HiddenNetwork.com Banner
Showing posts with label SharePoint 2003. Show all posts
Showing posts with label SharePoint 2003. Show all posts

Monday, February 26, 2007

How to use the GetListItems web service?

Small tip for using the web service easily.
I posted this on the msdn forums a lot of times for people who had problems getting the web service to work.
The following are two functions that you can use after adding referances to Lists.asmx and SiteData.asmx (why sitedata? because I use it to get the WebID that is needed by lists.asmx)

private System.Xml.XmlNode GetItems(string webPath)

{

ListsOnLocalhost.Lists listsWS = new Sharepoint_Unit_Tests.ListsOnLocalhost.Lists();

listsWS.Url = webPath + "/_vti_bin/lists.asmx";

listsWS.UseDefaultCredentials = true;

System.Xml.XmlDocument doc = new System.Xml.XmlDocument();

doc.LoadXml("<Document><Query /><ViewFields /><QueryOptions /></Document>");

System.Xml.XmlNode listQuery = doc.SelectSingleNode("//Query");

System.Xml.XmlNode listViewFields = doc.SelectSingleNode("//ViewFields");

System.Xml.XmlNode listQueryOptions = doc.SelectSingleNode("//QueryOptions");

Guid g = GetWebID(webPath);

System.Xml.XmlNode items = listsWS.GetListItems(listName.Text, string.Empty, listQuery, listViewFields, string.Empty, listQueryOptions, g.ToString());

return items;

}

 

 

private Guid GetWebID(string webPath)

{

SiteDataWebService.SiteData siteDataWS = new SiteDataWebService.SiteData();

siteDataWS.UseDefaultCredentials = true;

SiteDataWebService._sWebMetadata webMetaData;

SiteDataWebService._sWebWithTime[] arrWebWithTime;

SiteDataWebService._sListWithTime[] arrListWithTime;

SiteDataWebService._sFPUrl[] arrUrls;

string roles; string[] roleUsers; string[] roleGroups; 

siteDataWS.Url = webPath + "/_vti_bin/sitedata.asmx";

uint i = siteDataWS.GetWeb(out webMetaData, out arrWebWithTime, out arrListWithTime, out arrUrls, out roles, out roleUsers, out roleGroups);

Guid g = new Guid(webMetaData.WebID);

return g;

}

Tuesday, August 29, 2006

Common (and simple) coding tasks in sharepoint

Well, everyone went to teched last week and I was left at work stuck with a project with a strict deadline. So out of boredom I decided that I will compile a small snippet database for beggining sharepoint developers.
I see a lot of people in the microsoft public sharepoint developer forums asking these questions over and over again, so I thought I will save everyone some time by answering these right here.
Some people may say these are RTFM questions, since the SDK contains all of these examples, but apperantly people dont bother with the SDK, or find it confusing to navigate through. So here is my 2 cents.

The purpose here is to give some code samples to common tasks like:

  • getting a reference to a site
  • Iterating over all lists in a site
  • getting a reference to a list
  • getting a reference to an item in a list
  • getting a reference to the item's properties
  • getting a reference to a document and its properties
  • adding a new item to a list
  • modifying an item in a list

If you feel I should add to this list, let me know and I will write some sample code. However, please remember this is for simple, common tasks and I wont start giving application samples here.

So, lets get down to it!

Getting a reference to a site

Ok, you have a sharepoint site in a URL "http://server/sites/site" and you want to get the object of the site from its URL. What do you do?

using(SPSite mySite = new SPSite("http://server/sites/site"))
{
   using(SPWeb myWeb = mySite.OpenWeb())
   {
   }
}

Now you have the SPWeb object, allowing you to get information about the site you used in the URL. For example, iterating all lists in the site:

using(SPSite mySite = new SPSite("http://server/sites/site"))
{
   using(SPWeb myWeb = mySite.OpenWeb())
   {
      string linksHtml = "";
      foreach(SPList list in myWeb.Lists)
      {           
         string listLink = "<a href='" + list.DefaultView.Url.ToString()          + "'>" + list.Title + "</a>(<b>"+list.Items.Count+"</b>)<br>";
         linksHtml += listLink;
      }
   }
}

The above example also showed how to get a reference to a list by iterating over the lists in a site. But what if you want a specific list called "contacts"? The following will show you how to get the object for a list that you know the name of:

using(SPSite mySite = new SPSite("http://server/sites/site"))
{
   using(SPWeb myWeb = mySite.OpenWeb())
   {
      SPList contactsList = myWeb.Lists["Contacts"];
   }
}

Now lets iterate through the items in the list and get item's properties:

using(SPSite mySite = new SPSite("http://server/sites/site"))
{
   using(SPWeb myWeb = mySite.OpenWeb())
   {
      SPList contactsList = myWeb.Lists["Contacts"];
      foreach (SPListItem contact in contactsList)
      {
         string contactLastName = contact["Last Name"].ToString();
      }
   }
}

Now some of you are saying - "what about documents?", to which I answer that document libraries are the same as lists (ok, there are some differences but we will leave that for future articles). To get to a document in a document library you can either use the code above to iterate through the library and its files, or, if you know the file's URL, you can do this:

using(SPSite mySite = new SPSite("http://server/sites/site"))
{
using(SPWeb myWeb = mySite.OpenWeb())
{
SPFile file = myWeb.GetFile("http://server/sites/site/library/folder/file");
}
}

File properties are available through its Item property. If you have for example a text field in the document library called "My Custom String Property", and you want to know the value for that field in a specific file, use the following code:

using(SPSite mySite = new SPSite("http://server/sites/site"))
{
using(SPWeb myWeb = mySite.OpenWeb())
{
SPFile file = myWeb.GetFile("http://server/sites/site/library/folder/file");
string filePropertyValue = file.Item["My Custom String Property"].ToString();
}
}

We now want to add a new item to a list:

using(SPSite mySite = new SPSite("http://server/sites/site"))
{
using(SPWeb myWeb = mySite.OpenWeb())
{
SPList contactsList = myWeb.Lists["Contacts"];
SPListItem newItem = contactsList.Items.Add();
newItem["First Name"] = "Ishai";
newItem["Last Name"] = "Sagi";
newItem.Update();
}
}

Lets change all items in the list to build the email address based on the first and last name (in the format of 'first.last@testing.com') :

using(SPSite mySite = new SPSite("http://server/sites/site"))
{
using(SPWeb myWeb = mySite.OpenWeb())
{
SPList contactsList = myWeb.Lists["Contacts"];
foreach(SPListItem existingItem in contactsList.Items)
{
existingItem["E-mail Address"] = existingItem["First Name"] + "." + existingItem["Last Name"] + "@testing.com";
newItem.Update();
}
}
}

Well, that's it. If you think of more snippets like that, let me know!

[Update 4/4/2007 : I have replaced the old samples to best practice format (using using)]

Wednesday, July 19, 2006

Great new search solution for WSS 2

I know I usually write about wss3 and sharepoint 2007, but this product just got released by KwizCom that I thought all my readers should be aware of.

The product is "WSS Cross Site Search" and it allows you to search in WSS as if you had portal (across sites, advanced search and more) and for cheap (current pricing stands on 560$)!

Now, I have seen some other products that do similar items, but what I liked about this one, is that it completely integrates into the wss framework. Take a look:

And check out the advanced search page:

I also like the sound of some of the items in the feature list:
  • Easy management of properties available for the advanced search
  • User can define that the search results page will be displayed on a new window
  • Clicking an Office 2003 document (Word, Excel, PPT) in the search results page opens it in Edit mode
  • Available both as a web part and as a custom control, enabling easy deployment both in WSS sites and WSS site definitions

How good is that???

I hope you find it as useful as I do. The guys from KwizCom did it again.

Link to the product page

kick it on SharePointKicks.com

Tuesday, May 16, 2006

Improving SharePoint Accessibility - adding 'ALT' attributes to bullet images

1. Introduction

Following a research in a customer site (see my last article aboutsharepoint portal server accessibility) some conclusions were made on the best practices of implementing a portal server so that it meets accessibility requirements. One of the findings was that the built in web parts that show a link list in a summarized view (bulleted list) do not add an “ALT” tag to the bullet images. This breaks one of the chief (Conformance Level A) requirements of WCAG and therefore needs to be fixed. Two possible workarounds for this were proposed:

  1. Use a different view – one that doesn’t include bullets. This method is not advisable due to the fact that bulleted lists are easier to read and enhance usability of the site.
  2. Use FrontPage 2003 to change the web part and add the “ALT” tags

1.1 Purpose

This article’s purpose is to describe how to use FrontPage 2003 to change the web part and add the “ALT” tags.

2. Walkthrough
2.1. CREATE A TEMPORARY WEB PART PAGE

Open the portal area that contains the link list you want to add to a page Click “Manage Content” and then “Create” Click “Web Part Page” (last choice in this screen)

Give the page a name (“temp” for example) and hit “OK”

2.2. ADDING THE LINKS WEB PART TO THE TEMPORARY PAGE

Browse through the web parts in the gallery and find the links list you want to add. This might have a different name (for example “other information” or “external links”)

Drag the list to the page (doesn’t matter where to)

Close the web part gallery (use the “X” button on the top of the pane) to view the page.

At this stage you should modify web part settings such as toolbar other settings. This is not compulsory, as these changes can be done in FrontPage in step 2.3, but it is easier to do it now using the web interface to change the web part’s properties.

2.3. MODIFY THE PAGE IN FRONTPAGE TO PRODUCE A WEB PART

Open the page in FrontPage (hit the “Edit in FrontPage” button in internet explorer)

Right click the links web part and select “Convert to XSLT Data View” from the menu

With the web part still selected, switch to code view (button in the bottom left of the screen)

Scroll down (or run a search) and find the line that says <img src="/_layouts/images/square.gif" />

Change the line to <img alt="””/" src="/_layouts/images/square.gif" /> Save the page and exit FrontPage

2.4. EXPORTING THE WEB PART

Using internet explorer, browse back to the page you have created (if you left the window open with it, you will need to refresh the page, and you will get a link telling you to refresh it again).

Open the web part’s drop down menu and hit “export”

Select the option to save the file

Save the file to a location on your machine

You can now safely delete the web part page (go to the document library where it was saved, select it and delete it)

2.5. IMPORTING THE WEB PART TO OTHER PAGES

Open the page you want the web part to appear in (for example the home page)

Click “Edit Page” and then open the drop down menu “Modify Shared Page” to select “add web parts” > “import” Click “View Page” to view the page correctly.

browse to the file you saved in step 2.4 and hit upload

drag and drop the web part to the location in the page where you want it

View the results

The new web part is not in the page, with all the bullets with an 'alt' tag. More options to cosider on this scenario is to create the data view using web services and not from the list view - that option will allow you to add the web part in every site (and server) and not just the site you designed the web part on.

Tuesday, May 02, 2006

SharePoint Portal Server Accessibility Research

1. INTRODUCTION

Following a 1 day research in a customer site, some conclusions were made on the best practices of implementing a portal server so that it meets accessibility requirements. This document will summarize these conclusions and offer a review of the steps needed to be implemented to achieve the goal of a more accessible portal.

1.1 PURPOSE
This document’s purpose is to outline the steps that are necessary to perform to get SharePoint Portal Server as compatible as possible with WCAG 1.0 specifications for web sites, with a focus on Conformance Level A. The document will describe the methods of research taken by the author and his recommendations for future enhancements to improve accessibility in a customer’s SharePoint Portal Server site.

1.2. AUDIENCES
This document is meant for the people in charge of SharePoint Portal Server deployment in accessibility aware companies, to be used as a “best practices” guideline when deploying the portal and extending it by developing new web parts. The recommendation section of this document is meant for technical people only – and includes details of how to work around and improve SharePoint Portal Server accessibility.

1.3. DEFINITIONS, ACRONYMS AND ABBREVIATIONS

WSS Windows SharePoint Services.
A platform for creating sites that hold information and provide users a graphical interface to access that information and to add more.

SPS SharePoint Portal Server.
A platform that extends Windows SharePoint Services, and allows creating portal sites that hold information in a structure based on “Areas”. Additional capabilities of the platform include:

  • Better search engine
  • Dynamic structure of sites
  • Listings mechanism to add data to several sites at once.
  • Personalization features including
  • Audiences mechanism to target data to people
  • ‘My Site’ – a personal site for each user

Web parts
Blocks of information that can be added to Windows SharePoint Services and SharePoint Portal Server sites.
These blocks may be written by a 3rd party or be a built in from Microsoft. Web parts can be used to display lists (such as links, document libraries, events and so on) or external information (for example weather)

Templates & Site Definitions
Folders and files on the SharePoint server under the folder “C:\Program Files\Common Files\Microsoft Shared\web server extensions\60\TEMPLATE\1033”

  1. If a change is made to an “.aspx” file, the change will affect all existing sites and areas in SharePoint Portal Server and Windows SharePoint Services sites.
  2. If a change is made to an “.xml” file, the change will affect only newly created sites and areas.

WCAG
Web Content Accessibility Guidelines. W3C guidelines that explain how to make web content accessible to people with disabilities.

Bobby
Watchfire® Bobby ™ An application that analyses a web site and produces a report of errors and warnings for that site’s accessibility, based on the WCAG. This document refers to evaluation version 5.30.0.47 of Watchfire® Bobby ™

Conformance Level A
Priority 1 Guidelines represent a base level of accessibility and include problems that seriously affect the web page's usability by people with disabilities. This is referred in ‘Bobby’ as “Priority 1”

Conformance Level AA
Priority 2 Guidelines include problems that, although not as vital as Priority 1, are important for access and should be corrected. This is the preferred conformance level for an accessible site. This is referred in ‘Bobby’ as “Priority 2”

Conformance Level AAA
Priority 3 Priority 3 guidelines include issues that you should also consider correcting. This is referred in ‘Bobby’ as “Priority 3”

2. RESEARCH METHOD

To test SharePoint Portal Server compatibility with WCAG conformance level A, I used Bobby to scan an out-of-the-box portal set up for testing purposes to check the default portal before any modifications were made. I also checked the customer’s portal to check the impact of additional 3rd party and customized web parts will have on the accessibility. The test was focused on the home page of the portal, but also included:

  1. The search page (both with and without search results)
  2. List pages
  3. Document libraries pages
The research only focused on the output from the “Bobby” application, and there are things that application cannot check. For example, high contrast colours and font sizes. This was ignored in the test, and assumed fixable by a graphic designer.

3. RESEARCH RESULTS

3.1. RESULTS FROM A DEFAULT PORTAL (Out of the box)

The default SharePoint Portal Server Portal shows no Conformance Level A (Priority 1 in Bobby) errors. This means that the default portal is accessible enough for most companies. However, there were a few (10) warnings for level A, which I will specify here, and give my opinion on how they should be regarded. The warnings for Conformance Level A are:

  1. Warning: Provide extended description for images with important information. (58 instances)
    My Response:
    On a default SharePoint Portal Server home page there are no images with important information.
    This warning can be ignored.

  2. Warning: If you use colour to convey information, make sure the information is also represented another way.
    My Response: On a default SharePoint Portal Server portal, colours are not used to convey information.
    This warning should be checked with new 3rd party or customized web parts introduced into the system
  3. Warning: Identify any changes in the document's language.
    My Response: On a default SharePoint Portal Server portal, there are no changes in document’s language.
    This warning can be ignored.
  4. Warning: If this is a data table (not used for layout only), identify headers for the table rows and columns
    My Response: Most web parts comply with this guideline, including all of Microsoft’s built-in web parts
    This warning should be checked with new 3rd party or customized web parts introduced into the system
  5. Warning: If a table has two or more rows or columns that serve as headers, use structural markup to identify their hierarchy and relationship.
    My Response: On a default SharePoint Portal Server portal, there are no instances of the above.
    This warning should be checked with new 3rd party or customized web parts introduced into the system
  6. Warning: If style sheets are ignored or unsupported, ensure that pages are still readable and usable.
    My Response: The default SharePoint Portal Server portal pages were tested, and were found to be readable and usable.
    See Image below for example.

    This warning can be ignored.
  7. Warning: Make sure pages are still usable if programmatic objects do not function
    My Response: This cannot be achieved in a SharePoint Portal Server site. The site relies heavily on JavaScript objects for functionality. However, most links will still be usable for readers but not for editors in the SharePoint Portal Server site
    This warning can be ignored if the person viewing the portal is a reader and not a content editor.
    If the user is a content editor in the portal, there are some ways to overcome this warning by customizing some of the problematic views that require scripts. This will be discussed later in this document.
  8. Warning: Make sure that the page does not cause the screen to flicker rapidly.
    My Response: Default SharePoint Portal Server pages do not cause the screen to flicker.
    This warning can be ignored.
  9. Warning: Provide accessible alternatives to the information in scripts, applets, or objects
    My Response: This cannot be achieved in a SharePoint Portal Server site. SharePoint Portal Server page require scripts to work. Browsers that don’t allow scripts will not be able to open the site.
    This warning can be ignored.
  10. Warning: Use the simplest and most straightforward language that is possible.
    My Response: This depends on the content authors
    This warning can be ignored.


Portal in a browser with CSS disabled is still readable

 
Bobby results for a default (out of the box) Portal shows no errors for priority 1


Bobby results for the search page shows no errors for priority 1

 

3.2. RESULTS FOR A DEFAULT PORTAL WITH A LINK LIST

After testing the default portal installation, I added some web parts to test the default, built-in web parts that come from Microsoft. The results were the same as described in the previous test, except for the link list.

A link list web part has a special view – summarized view that shows the list of links in a bulleted list. This makes the list of links more usable – more readable to users, and is the recommended way to display the list in a portal page.

However, it turned out in the test that this view breaks WCAG Conformance Level A - since the bullet images do not have an ‘alt’ tag as required.


Bobby results for the a portal home page that has a bulleted link list shows errors for priority 1

4. RECOMMENDATIONS & BEST PRACTICES

4.1. MAKE SURE ALL 3RD PARTY WEB PARTS CONFORM TO LEVEL A

When installing or developing a web part (such as ABC news) makes sure all Level A requirements are met when the web part gets rendered.
This includes giving an ‘alt’ tag to every image, not using colors to convey information and giving names to frames.
Every web part developed or downloaded should be first checked in the development environment and tested with Bobby for Conformity level A errors.

4.2. CHANGING DEFAULT LIST VIEWS TO INCLUDE THE “EDIT” ICON

By changing the views of the lists to include the “edit” icon, it will be possible for people who can’t use the scripted drop down menus to edit list items.
Existing lists will have to be modified manually (or by writing a script) to include this icon, but new lists can be made to have it by default by changing the lists templates in the site definitions.
It is recommended that this change is taken, and that the edit icon is present in every view that also has the drop down menu.
The location of this icon should be right after the file name column so that when a user tabs through the links, the link to edit will be near the file name.

4.3. USING XSLT DATAVIEWS OR A TABLE VIEW FOR A LINK LIST

During research it turned out that the built-in web parts that show a list of links in a summarized view (bulleted view) the bullet images do not have an ‘alt’ attribute assigned to them.
Since this breaks WCAG Conformance Level A, it is recommended to change the view to one of the following two options:
 

  1. Don’t use the summarized view. Instead, use a regular view of the link list that doesn’t show bullets, and does show a header for the hyperlink column.
    This option is easiest to implement and only lacks in reduced usability of the site since bulleted lists are easier for the human eye to follow.
  2. Transform the summarized view to an xslt data view using Microsoft FrontPage 2003. This will allow changing the xsl code to include an empty ‘alt’ tag to the bullet image.
     

4.4. IMPLEMENT THE TIPS FROM THE MSDN ARTICLE ON ENHANCING ACCESSIBILITY

In their article “Tips for Enhancing the Accessibility of SharePoint Web Sites”, Samer Sawaya and Les W. Smith define some methods for enhancing SharePoint. It is recommended that these steps are taken, to enhance the CDDP portal, especially:

  1. Add skip-to-main-content link
  2. Add submit buttons to bottom of forms
  3. Don’t use the built-in image web part. Instead use the content editor web part to add an image with the necessary tags (‘alt’ and ‘longdesc’)

I also recommend that in addition to a “skip to content link” another improvement on the article is to add a “skip to navigation” link. This link will allow the user to skip all links and get to the navigation section of the page (the section that shows the sub sites, and the actions the user can do in the page).

4.5. MODIFY THE CSS FOR THE PORTAL SITE

Some more research is needed to evaluate if it will be possible to use two different CSS files, based on the user’s preferences. It is recommended that this research is done, and if possible that thisdevelopment task gets developed since that will allow developing a high contrast/large fonts style sheet that will be used only by certain people and will not affect all of the users in the organization.
However, it is still possible to change the current CSS file of theportal to have higher contrast. This may need the study of a graphical designer.

5. SUMMARY

It turns out that SharePoint is almost completely compliant with WCAG conformance level 1 as it is out of the box. To get it to be fully conforming there are some things that need to be done.

One can only hope that future versions will at least keep the current status and high standard, and even improve to comply with level 2 (which was not discussed in this document).

Tuesday, April 11, 2006

Search highlighing in WSS free code

In his tip in msd2d Igor Goldstaub from KWizCom explain how to add search string highlighting to WSS search. This is free!!! KWizCom does have a better product that supports both wss and sps and highlights words inside documents (see one of my previous posts) but getting wss highlighting for free is as cool as it gets... Thanks KWizCom!

Monday, March 27, 2006

How to show a picture library as links using frontpage and web services

I saw the request for this in MSD2D and people are always asking for similar stuff, so I guess I can start with some code samples, and if anyone wants something more specific they can ask...

The request was to make a view of a picture library, but have every picture point to a different url. this can be to the picture itself or to a url in the intranet\internet.

The following is an example of how the result will look like (I used sample icons instead of nifty looking gifs...sorry - I am not a graphical designer). The two images each link to different pages. The web part links to the picture library in a site - either a remote one or the current one.

What I suggest to people who dont want to write their own web parts using Visual Studio is to use frontpage data views and connect them using web services. This is usefull to show the data from the list in another site as well (so you can have a picture library in a master site and web parts in other sites showing it as a link list or a picture list).

The recommended best practice for this is to create a stub web part page to be edited frontpage so that no important page gets unghosted. then you can export the web part to a dwp file and import it into every page you want. If you want more information, search the internet (I will post some links when I have more time)

anyway, here is the process:

First, create an image list for your images.

If you want to use that as a link list, you will have to add a column that will hold the link each picture will point to:

  1. Go into “modify settings and columns” and click “add a new column”
  2. Name the new field and set the type to hyperlink
  3. Go back to the list.
  4. Upload a few images and set the hyperlinks so that they point to different sites.

Now, to create the view for the list (or the web part if you will).

  1. Create a dummy site or a web part page (to pervent unghosting)
  2. Open the page in frontpage and stand on a web part zone (otherwise frotnpage will just embed the new view into the page instead of having it as web part that is movable...I made that mistake preparing the screen shots - dont follow my lead on this one!)
  3. Expand the "data" menu and select "Insert Data View"
  4. Click "Add to Catalog" (we need to add the image list as a data source) select "web services" (and not sharepoint list. that option wont allow the web part to work from remote sites).
  5. Write the path to the site with the list, followed by "_vti_bin/lists.asmx" and click "connect"
  6. From the operations list select "GetListItems"
  7. Double click the "listname" variable
  8. Set the value to the name of the list you created and click ok twice to go back to the frontpage main page.
  9. In the pane you now see the new data source. open the menu for the source and choose "Show Data"
  10. Select the colunms you want to show. in this example I selected the column that holds the link to the image and the one that holds the link we entered seperatly. If you want the click on the image to open the image, you can select only the one field.
  11. In my example I first clean up the headers of the table. You dont have to do that, but at the very least you are going to want to change the text there as by default it shows the field's internal name (ows_something). Switch to code view, and run a search for the field name. We are looking for where it is inside a "<th>" tag. if you find it, delete the entire bit as shown in the following image.

    You should save the page and then open it in internet explorer to make sure the change took effect and the headers are gone with no error.
  12. Next, is the actual change to the code to make the image a link. Switch to code view again, and scroll down in the page to located the xsl code that renders the data. This may vary, depending on the style frontpage selects for you when you inserted the data view. Basically what you have to look for is a tag (a row) with some tags inside and a "<?xml:namespace prefix = xsl />xsl:value-of"
  13. Change the text inside to render each image as a link. the following are two examples for how to do that - in one the image is a link to itself, and in the other it is a link to the page the link field we added is pointing at.

Code Example 1 - Image is a thumbnail pointing to the bigger image

<xsl:variable select="@ows_link_x0020_to_x0020_open" name="linkText"></xsl:variable>
<xsl:variable select="@ows_RequiredField" name="linkImage"></xsl:variable>
<tr>
 <td class="ms-vb">
  <a>
   <?xml:namespace prefix = xsl />
   <xsl:attribute name="href">
    <xsl:value-of select="substring-before($linkText,', ')"></xsl:value-of>
   </xsl:attribute>
   <xsl:attribute name="title">
    <xsl:value-of select="substring-after($linkText,', ')"></xsl:value-of>
   </xsl:attribute>
   <img border="0" />
    <xsl:attribute name="src">http://demo02:8081/<xsl:value-of select="substring(string-length(substring-before($linkImage,substring(normalize-space($linkImage),1,1)))+1)">
    </xsl:value-of>
    </xsl:attribute>
   </img>
  </a>
 </td>
</tr>
Code Example 2 - Image is a link to a page specified in the custom field

 <tr style="display:{$GroupStyle}">
 <td class="ms-vb">
  <a>
   <xsl:variable name="linkText" select="@ows_link_x0020_to_x0020_open"/>
   <xsl:variable name="linkImage" select="@ows_RequiredField"/>
   <xsl:attribute name="href">
    <xsl:value-of xmlns:xsl="http://www.w3.org/1999/XSL/Transform" select="substring-before($linkText,', ')"/>
   </xsl:attribute>
   <xsl:attribute name="title">
    <xsl:value-of xmlns:xsl="http://www.w3.org/1999/XSL/Transform" select="substring-after($linkText,', ')"/>
   </xsl:attribute>
   <img border="0">
    <xsl:attribute name="src">http://demo02:8081/<xsl:value-of xmlns:xsl="http://www.w3.org/1999/XSL/Transform" select="substring(
$linkImage,
string-length(substring-before($linkImage,substring(normalize-space($linkImage),1,1)))+1)"/>
    </xsl:attribute>
   </img>
  </a>
 </td>
</tr>

Liked the tip? kick it on SharePointKicks.com

Tuesday, March 21, 2006

Content index is stuck with no (or few) documents

Just had a problem in a customer site, where the search index for non_portal_content was always on 3 documents, even though the customer had about 17 site collections, all with documents and lists with items. No matter how many times I reset the index, or tried setting up new ones, nothing was added to the index! If this happens to you, I recommend the following troubleshooting stages:

  1. Check that the sites are crawled. In "Site Settings" > "Manage crawls of Site Directory" make sure the sites you want are approved. didnt help me - they were all approved.
  2. Make sure you are running SPS SP2. Some search issues are resolved after installing SP2. To determine you are running SP2, go to the "control panel" > "add\remove programs" and check the "about" of SPS. the version should be 11.0.8126.0 (for the english version anyway). this improved matters for me - the portal index suddenly worked better, but still empty non_portal_contents
  3. Do a "Hard Reset" of the index Ok - last resort: 3.1. First stop the "Microsoft SharePointPS Search" service. 3.2. Now, go to where you installed sharepoint (or if you set the indexes to be in a different location) for example - "C:\Program Files\SharePoint Portal Server\DATA\01b905a4-6f4b-4f3b-bab9-0702d5d86968" and you should see there the "Non_Portal_Content" folder. 3.3. Rename the "Non_Portal_Content" folder to "Non_Portal_Content_Old". 3.4. Start the "Microsoft SharePointPS Search" service again. 3.5 Go to the search administration screen and make sure the index is starting a crawl

Thats it! the last thing solved my problem. the "stuck" index was fully crawled and search works as expected.

Hopes this helps anyone...if not - dont blame me!

Monday, March 13, 2006

Search Highlighting

Hey, I just have to let everyone know about this one. You know how google (and other search engines) highlights the words you searched for in the results? well, now you can do that in sharepoint! I wrote this application for Kwizcom (friends of mine). Its a sharepoint portal server search that highlights the searched words in the search page and inside the documents (doc, rtf and pdf). You also can configure how the highlighting will appear (bold? blue? blinking? just configure your own!) and how it will work (case sensative? search whole word or part of a word?). Oh yeah... a bonus feature (one that customers always ask me for) is that when you click a word document from the search results - it will open up in word and not in the internet explorer window (which is annoying!). Now your users dont have to click "back" to get from the word document back to the search results. I find it fantastic value... check it out!

Thursday, March 09, 2006

Automatically applying a theme to a site when it is created

WSS site definitions dont support setting a default theme. This leave the administrator with three options, none of them recommended:

  1. Have users manually set a theme after creating a site (ugly!)
  2. Set the company theme to a site, and save it as template and deploy the template globaly in the server (complicated, and also disconnects the sites from the file system templates, making it hard to change in the future)
  3. Change the default css files and not use the theme (extremely ugly - why are the themes for??? also does not support multiple templates with different themes)

The solution I found for the problem (thanks to Kalmberg) is to add in the site definition a link to a custom page that will run code when the site is created. the code will apply the theme to the new site.

Kalmberg example was instructive, but allow me to take you through the proccess step by step:

Step 1 - Changing The Site Definition

  1. Create the site definition that you want
  2. Go into the "xml" folder and open the "onet.xml" file in notepad or visual studio (or any editor)
  3. Find the "Configurations" tag at the bottom, and for every configuration you want to change add the following in the "Configuration" tag (where it says "THEMENAMEHERE" write your theme name. This may be case sensative): <ExecuteUrl Url="_layouts/1033/ThemeSetter.aspx?Theme=THEMENAMEHERE" />

Step 2 - Creating the ThemeSetter ASPX Page

  1. Open "C:\Program Files\Common Files\Microsoft Shared\web server extensions\60\TEMPLATE\LAYOUTS\1033"
  2. Create a new text file, rename it to "ThemeSetter.aspx"
  3. Open the file for editing, and paste the following code into it:
    <html dir="ltr">
    <%@ Page Language="C#" ValidateRequest="False" %>
    <%@ Import Namespace="Microsoft.SharePoint.ApplicationPages" %>
    <%@ Register Tagprefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=11.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
    <%@ Register Tagprefix="Utilities" Namespace="Microsoft.SharePoint.Utilities" Assembly="Microsoft.SharePoint, Version=11.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
    <%@ Import Namespace="Microsoft.SharePoint" %>
    <%
    
    SPWeb myNewWeb = SPControl.GetContextWeb(Context);
    myNewWeb.AllowUnsafeUpdates = true;
    myNewWeb.ApplyTheme(this.Page.Request["Theme"].ToString());
    myNewWeb.Update();
    Response.Redirect(myNewWeb.Url);
    
    %>
    </html>

Step 3 - Reset the IIS

for the changes to take affect, you will need to reset the IIS.

Now, create a site from the site definition, and the site should automatically be with the theme.

Liked it? kick it on SharePointKicks.com

Wednesday, March 01, 2006

Formatting links properly in a frontpage dataview

When creating a dataview for a list using the getlistitems function of the “lists” web service you can display a list from a remote site in your site, without having to develop a custom web part. However, inserting a link list from a web service shows the links in full text - for example : "www.msd2d.com, msd2d" This is because sharepoint stores the link's title and link in a single field with a comma and a space seperating the title and the link. What you need to do to solve this, is change the xsl of the dataview so that the link will only show the title, while the link will include only the link. In frontpage, click the dataview and switch to code view. The selected area is the entire dataview defenition. You will need to scroll down and locate the tag definition inside (location may change depending on your list and view). Change the tag using xsl “substring-before” and “substring-after” functions: Add an xsl variable that will hold the full link text : Change the xml of the href attribute to insert the text before the comma: Change the xml of the text to insert the text after the comma and the text: This can be confusing, so use my sample code below - just copy and paste it over the existing tag. You should note that the link field may be named differrently in your list. in a default links list it is named “ows_URL” but in your list you may need to check what the name is. just look in the dataview code before pasting over it. Code Sample:

<a> <xsl:variable name="linktext" select="@ows_URL"/> <xsl:attribute name="href"> <xsl:value-of select="substring-before($linktext,', ')"/> </xsl:attribute> <xsl:value-of select="substring-after($linktext,', ')"/> </a>

Saturday, February 11, 2006

Global Templates Explained

This is an answer I gave in MSD2D forum for a question that is frequently asked. Original question is preety confused, but here it is: "I'm a Sharepoint newbie and am having some problems understanding the relationship between WSS and SPS. We have created a Sharepoint Portal which provides a tab for sites. I also have been able to create Sharepoint sites directly from within the SPS. However, I would like to add some site templates other than the ones shown. When I am in WSS mode, I am given the ability to Manage Site Templates. I can't find the equivalent within the SPS environment. I was given a suggestion to use stsadm.exe for this, but it strikes me as odd to have to use a command-line utility for what I would expect to be a built-in option like WSS provides." And here is my answer: The advice you were given was accurate up to a point. there are actually two ways to do what you want, and I prefer the second way. Let me explain: Quick overeview: WSS is built in the form of a "Site collection" that hold "webs". what you see as a site is actually a "web" inside the "site collection". The root site is the top level "web" in the site collection. It may or may not have sub webs under it. This is true when the wss sites are under a portal. every site you create from the portal is actually a different "site collection" with a root "web". The portal itself is a site collection on its own, with the "home" area as its root level "web". The fact that you create sites from the portal doesnt mean they are actually under the portal. they are infact stand alone site collections with root webs. WSS site collections have a template gallery you can upload templates to and then use those templates in all webs under the site collection, but you cant use them in other site collections on the same machine unless you install the template globally. How to install templates globaly If you have a template you want to be available globaly there are two ways to achive your goal: Save the web you want using the method you described ("save as template" in the site settings) and then download the stp file to the hard drive and install it with the stsadm command line utility (stsadm -o addtemplate) Create the new template as a site definition. Option number two is harder, since you dont get to just create a site, change it to look like you want and just save it. Instead, you have to manipulate aspx and xml files on the hard drive, and define everything manually. The benefit of the second option over the first is that the sites you will create from the new definition will stay connected to that definition. This means you will be able to change all sites at once if you want to change something in the way they look (not add or remove web parts, but change the layout of the home page). It is also easier to change the template itself when needed. I suggest you read about it in the link above, and ask here if more info is required.

Saturday, December 31, 2005

How to add a better “Send Document Link By Mail” menu item to document libraries

Post update: my good friends in KWizCom have developed a menu editor for sharepoint. This makes implementing and deploying this article a piece of cake! Description: In his article Extending SharePoint 2003 Context Menus, Mark Bower explains how to add a “send link by email” menu item to SharePoint document libraries drop down menus. However, Bower uses a regular mailto link as the mechanism to create the mail item. This method has the advantage that it will work on most browsers and mail applications without any special configurations, but also the disadvantage that if the link has a space in it (for example http://server/document%20library/file%20name.doc) the link will be broken in the email (http://server/document library/file name.doc) which is not a good behavior.

An alternative approach is to use outlook activeX control to create the message and the link, thereby preserving the full link. The disadvantage of this method is that it requires Microsoft Outlook (any version, but not outlook express) and that it requires that the browser allows running activeX controls on the site (register the site as a safe site on the clients). Although it has drawbacks, it is my belief that most SharePoint users have outlook, and it is a recommended best practice to register the company internal portal as safe anyway. With this in mind, attached is my recommended version of code to accomplish the task.

Sample Code: *Before changing the ows.js file, please back it up. The following code is to be inserted into the ows.js file of the SharePoint machine (either WSS only or SPS machine). This causes all document libraries to have the new menu item. The code sample needs to be inserted into the AddDocLibMenuItems function. The exact location can change – depending on where you want the menu item to be. It should be after the line that starts with “var currentItemEscapedFileUrl”.

//Add the "send mail" link strDisplayText = "Send Link By Email"; strImagePath = ""; // parse the URL out of the itemTable var URL = ""; var index = itemTable.innerHTML.indexOf("href="); if (index > 0) { var str = itemTable.innerHTML.substr(index + 6); index = str.indexOf('"'); if (index > 0) { URL = str.substr(0, index); URL = URL.replace(" "," "); } } if (URL != "") { //The following is the original action – using the “mailto” //strAction = 'window.navigate("mailto:%20?subject=Take a look at this document...&body=' + URL + '")'; //Add the action to open outlook and a new message with a set subject and a link to the document strAction = "try{var olApp;olApp = new ActiveXObject('outlook.application');var oItem = olApp.CreateItem(0);oItem.Subject = 'Take a look at this document';oItem.HTMLBody = '" + URL + "';oItem.display(true);}catch(e){alert('Couldnt use the outlook object. Please make sure the current sharepoint site is trusted by your browser and activeX are allowed to run');}"; // Add menu item CAMOpt(m, strDisplayText, strAction, strImagePath); // add a separator to the menu CAMSep(m); }

Sample Code 2: *Before changing the ows.js file, please back it up. If you are unsure how and where to insert the code above, just copy the code below to replace the AddDocLibMenuItems function in your ows.js file. This will be simpler if you are unsure what to do.

function AddDocLibMenuItems(m, ctx) { if (typeof(Custom_AddDocLibMenuItems) != "undefined") { if (Custom_AddDocLibMenuItems(m, ctx)) return; } var RootFolder = GetRootFolder(ctx); setupMenuContext(ctx); if (currentItemFileUrl == null) currentItemFileUrl = itemTable.ServerUrl; if (currentItemFSObjType == null) currentItemFSObjType = itemTable.FSObjType; var currentItemEscapedFileUrl = escapeProperly( unescapeProperly(currentItemFileUrl)); strDisplayText = "Send Link By Email"; strImagePath = ""; // parse the URL out of the itemTable var URL = ""; var index = itemTable.innerHTML.indexOf("href="); if (index > 0) { var str = itemTable.innerHTML.substr(index + 6); index = str.indexOf('"'); if (index > 0) { URL = str.substr(0, index); URL = URL.replace(" "," "); } } if (URL != "") { ////strAction = 'window.navigate("mailto:%20?subject=Take a look at this document...&body=' + URL + '")'; strAction = "try{var olApp;olApp = new ActiveXObject('outlook.application');var oItem = olApp.CreateItem(0);oItem.Subject = 'Take a look at this document';oItem.HTMLBody = '" + URL + "';oItem.display(true);}catch(e){alert('Couldnt use the outlook object. Please make sure the current sharepoint site is trusted by your browser and activeX are allowed to run');}"; // Add menu item CAMOpt(m, strDisplayText, strAction, strImagePath); // add a separator to the menu CAMSep(m); } if (currentItemFSObjType != 1) { strDisplayText = L_ViewProperties_Text; strAction = "STSNavigate('" + ctx.displayFormUrl+"?ID="+ currentItemID + "&Source=" + GetSource() + RootFolder + "')"; strImagePath = ""; CAMOpt(m, strDisplayText, strAction, strImagePath); } strDisplayText = L_EditProperties_Text; strAction = "STSNavigate('" + ctx.editFormUrl+"?ID="+ currentItemID + "&Source=" + GetSource() + RootFolder + "')"; strImagePath = ctx.imagesPath + "edititem.gif"; CAMOpt(m, strDisplayText, strAction, strImagePath); if (currentItemFSObjType != 1) { if (ctx.isWebEditorPreview == 0) { if (ctx.listTemplate == LISTTEMPLATE_IMAGE_LIBRARY && itemTable.IsImage == "1") { strDisplayText = L_EditInOIS_Text; strAction = "EditSingleImage('" + currentItemID + "')"; strImagePath = ctx.imagesPath + "oisweb.gif"; CAMOpt(m, strDisplayText, strAction, strImagePath); } else { setDocType(); if (currentItemAppName != "" && currentItemOpenControl != "") { strDisplayText = StBuildParam(L_EditIn_Text, currentItemAppName); strAction = "editDocumentWithProgID2('" + currentItemFileUrl + "', '" + currentItemProgId + "', '" + currentItemOpenControl + "')"; strImagePath = ctx.imagesPath + currentItemIcon; CAMOpt(m, strDisplayText, strAction, strImagePath); } } } } strDisplayText = L_DeleteDocItem_Text; strAction = "DeleteDocLibItem('" + ctx.HttpPath + "&Cmd=Delete&List=" + ctx.listName + "&ID=" + currentItemID + "&owsfileref=" + currentItemEscapedFileUrl + "&NextUsing=" + GetSource() + "')"; strImagePath = ctx.imagesPath + "delitem.gif"; CAMOpt(m, strDisplayText, strAction, strImagePath); if (ctx.isModerated == true) { strDisplayText = L_ModerateItem_Text; strAction = "STSNavigate('" + ctx.editFormUrl+"?ID="+ currentItemID + "&ChangeApproval=TRUE&Source=" + GetSource() + RootFolder + "')"; strImagePath = ""; CAMOpt(m, strDisplayText, strAction, strImagePath); } if (currentItemFSObjType != 1 && ctx.listTemplate == LISTTEMPLATE_IMAGE_LIBRARY) { strAction = "DownloadOriginalImage(" + currentItemID + ")"; strImagePath = ctx.imagesPath + "download.gif"; strDisplayText = L_DownloadOriginal_Text; CAMOpt(m, strDisplayText, strAction, strImagePath); } if (currentItemFSObjType != 1) { CAMSep(m); AddCheckinCheckoutMenuItem(m, ctx, currentItemEscapedFileUrl); AddVersionsMenuItem(m, ctx, currentItemEscapedFileUrl); CAMSep(m); if (ctx.PortalUrl != null) { strDisplayText = L_AddToMyLinks_Text; strAction = "Portal_Tasks('PinToMyPage')"; ; strImagePath = ""; CAMOpt(m, strDisplayText, strAction, strImagePath); strDisplayText = L_AddToCategory_Text; strAction = "Portal_Tasks('Categorize')"; ; strImagePath = ""; CAMOpt(m, strDisplayText, strAction, strImagePath); CAMSep(m); } } strDisplayText = L_Subscribe_Text; strAction = "NavigateToSubNewAspx('" + ctx.HttpRoot + "', 'List=" + ctx.listName + "&ID=" + currentItemID + "')"; strImagePath = ""; CAMOpt(m, strDisplayText, strAction, strImagePath); if (currentItemFSObjType != 1) { strDisplayText = L_Discuss_Text; strAction = "STSNavigate('" + ctx.HttpPath + "&Cmd=COMMFRMS&amp;URL="; if (ctx.isWebEditorPreview == 0) strAction += currentItemEscapedFileUrl; strAction += "')"; strImagePath = ctx.imagesPath + "icdisc.gif"; CAMOpt(m, strDisplayText, strAction, strImagePath); if (ctx.listTemplate != LISTTEMPLATE_IMAGE_LIBRARY) AddWorkspaceMenuItem(m, ctx); } // add a separator to the menu CAMSep(m); }

Acknowledgments:My thanks to Mark Bower and\or to Alan Smithee who published the original document in Microsoft’s site.