Category Archives: Tips and Tricks

FAST Search Tip #1: Enabling Stemming in PowerShell

Recently, I’ve been working with FAST Search for SharePoint 2010 and, although it’s a great search platform with pretty impressive features, I believe there are still too many manual installation and configurations steps, and too many of those features are only accessible through PowerShell. Don’t get me wrong, PowerShell is great and, by far, the best way to deploy your solution to the client’s environment, but a little more graphical UI wouldn’t hurt.

According to FAST Search’s TechNet documentation, you can use the Set-FASTSearchMetadataManagedProperty cmdlet to configure the main settings of a managed property. Among other things, you can enable stemming for a specific managed property. Here’s how it’s done:

$title = Get-FASTSearchMetadataManagedProperty –Name title
Set-FASTSearchMetadataManagedProperty –ManagedProperty $title –StemmingEnabled $true

The problem is that this doesn’t work. The StemmingEnabled argument is actually ignored by the cmdlet so, we need to use a different approach. This is the right way:

$title = Get-FASTSearchMetadataManagedProperty –Name title
$title.StemmingEnabled = 1
$title.update()

Although Microsoft is yet to update TechNet’s documentation, it has published a support article in its knowledge base (KB2468430) which describes this very solution.

SharePoint Tip #27: Choice Columns and DataSheet Views

Using features to create Choice site columns is pretty straightforward (check this post for additional information). See below a sample feature element for that purpose.

<Field

    ID="{538c71e4-8650-4ce7-b021-920effa66346}"

    Type="Choice"

    Name="Publishing_x0020_Status"

    StaticName="Publishing_x0020_Status"

    DisplayName="Publishing Status"

    Required="FALSE

    Format="Dropdown"

    FillInChoice="FALSE"

    Group="Custom Columns">

    <Default>Not Published</Default>

    <CHOICES>

       <CHOICE>

          Not Published

       </CHOICE>

       <CHOICE>

          Pending

       </CHOICE>

       <CHOICE>

          Published

       </CHOICE>

       <CHOICE>

          Error

       </CHOICE>

    </CHOICES>

</Field>

Although the XML is well formed and all the attributes and values are correct, this field definition has a problem. If you create a site column using this definition, here is what happens:

  • If you check the site column configuration in SharePoint, everything will look fine
  • If you add this site column to a list (either through a content type, or directly) and you edit an item using the default list forms, everything will work as expected.
  • If you try to edit the list items using a DataSheet View, you won’t be able to select any value from this choice field and SharePoint will always throw a validation error.

The problem here are the invisible characters (spaces, newlines and tabs) between the <CHOICE> and </CHOICE> tags and their inner values. Apparently, when using list forms these characters are trimmed from the valid choices, but when using the datasheet view they are not, causing a strange behavior when editing an item in that view.

The correct definition for this field would be:

<Field

    ID="{538c71e4-8650-4ce7-b021-920effa66346}"

    Type="Choice"

    Name="Publishing_x0020_Status"

    StaticName="Publishing_x0020_Status"

    DisplayName="Publishing Status"

    Required="FALSE

    Format="Dropdown"

    FillInChoice="FALSE"

    Group="Custom Columns">

    <Default>Not Published</Default>

    <CHOICES>

       <CHOICE>Not Published</CHOICE>

       <CHOICE>Pending</CHOICE>

       <CHOICE>Published</CHOICE>

       <CHOICE>Error</CHOICE>

    </CHOICES>

</Field>

SharePoint Tip #26: Comments in Content Type Definition

There is an issue with SharePoint 2010’s CAML parser that causes SharePoint to ignore fields in a Content Type definition. When defining a Content Type feature element, avoid placing comments inside the <fieldrefs> element as that will cause SharePoint to create the Content Type disregarding all the fields, even though the XML is well formed.

<?xml version="1.0" encoding="utf-8" ?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <ContentType
    ID="0x0100C5647A362F236548B218C15302286758"
    Name="MyCT"
    Description="Simple Custom Content Type" 
    Inherits="TRUE"
    Overwrite="TRUE"
    Version="0">
    <Folder TargetName=”_cts/MyCT” />
    <FieldRefs>
      <FieldRef ID="{fa564e0f-0c70-4ab9-b863-0177e6ddd247}" Name="Title" />

      <!-- This is a comment –->   
      <FieldRef ID="{b402db15-ee44-4ec4-89e3-23e10a8fc64c}" Name="My_x0200_Field" />
      <FieldRef ID="{538c71e4-8650-4ce7-b021-920effa66346}" Name="Status" />
    </FieldRefs>
  </ContentType>
</Elements>

The Content Type feature element above will cause the Content Type to be created with only the Title field, which is inherited from the parent Content Type. All the fields referenced in this Content Type definition will be ignored.

SharePoint Tips #25: Beware of User Profile Import

Among SharePoint 2007’s User Profile features, one of the most useful is the Profile Import. This feature allows you to import existing user accounts from Active Directory, an LDAP server or the Business Data Catalog, to the User Profile Store. Even better, it allows you to map the User Profile properties to user account properties (from Active Directory, for instance) so that they’re automatically imported. Additionally, you can schedule regular imports so that SharePoint’s User Profile is kept in sync with Active Directory’s user account.

Needless to say, this can save you a lot of time, especially if you already have a large base of users with a few populated properties on Active Directory. This is, however, a one way process, that is, only from the Directory to SharePoint, never the other way around.

One question you might be asking is: what if I update a User Profile on SharePoint, putting new data on a mapped property and then a Profile Import occurs?

The answer to this is not straightforward, because it depends on your answer to one or two questions.

Question 1: In Active Directory (or LDAP server), does the mapped property have a value?

If so, then the value in SharePoint’s User Profile property will get overwritten by the one in the directory’s user account property. No need to check Question 2.

If not, then check Question 2.

Question 2: Did you update the User Profile using SharePoint’s UI, or using the API?

If you used the SharePoint’s UI then the User Profile property will retain the value, since the mapped property in the directory service has no value to replace it.

If you used the API, the Profile Import will clear the value of the mapped property on SharePoint’s User Profile. I cannot explain why this difference exists, but I have seen it happen.

Conclusion: If you are updating User Profile properties by using SharePoint’ API, make sure you remove their mappings (to directory services’ properties) to prevent you from losing data when the Profile Import executes.

SharePoint Tip #24: Changing a Web Site’s Navigation Settings

Changing a web site’s navigation settings is pretty easy using the SharePoint user interface. You just click the Site Actions button, select the Site Settings option, and click on Navigation. But how do you do it programmatically?

Most navigation options on a SharePoint web site are manipulated through the SPWeb object’s property bag. Set the following properties to configure a web site’s navigation settings:

  • __IncludeSubSitesInNavigation: Set this property to True to show the subsites of the current site on the global and current navigation menus. Set it to False to hide the subsites.
  • __IncludePagesInNavigation: Set this property to True to show the pages on the global and current navigation menus. Set it to False to hide the pages.
  • __InheritCurrentNavigation: Set this property to True to display the same navigations items as the parent site in the current navigation menu. Set it to False to display only items from the current site and subsites.
  • __NavigationShowSiblings: Set this property to True to display the navigation items below the current site and the current site’s siblings, in the current navigation menu.
  • __NavigationOrderingMethod: Set this property to one of the following values:
    • 0: Sort the navigation items automatically
    • 1: Sort the subsites manually but the pages automatically
    • 2: Sort the navigation items manually
  • __NavigationAutomaticSortingMethod: When using automatic ordering, set this property to one of the following values:
    • 0: Sort by Title
    • 1: Sort by Created Date
    • 2: Sort by Last Modified Date
  • __NavigationSortAscending: When using automatic ordering, set this property to True if the automatic sorting of the navigation items should be done in ascending order. Set it to False to use descending order.

Note: there are two underscore characters (_) in each property name.

Example
In the example below, I’m setting the navigation options to:

  • Show only the current site’s navigation items in the global navigation
  • Show the current site’s sub sites in the global navigation
  • Don’t show the pages in the global navigation
  • Show only the current site’s navigation items in the current navigation
  • Don’t show the current site’s siblings in the current navigation
  • Sort the navigation items manually
// break inheritance of global navigation
web.Navigation.UseShared = false;

// show subwebs but don't show pages in global navigation
web.AllProperties["__IncludeSubSitesInNavigation"] = "True";
web.AllProperties["__IncludePagesInNavigation"] = "False";

// show only current site's navigation items in current navigation
web.AllProperties["__InheritCurrentNavigation"] = "False";
web.AllProperties["__NavigationOrderingMethod"] = "2";
web.AllProperties["__NavigationShowSiblings"] = "False";
web.Update();

SharePoint Tip #23: Creating a Personal Site

The User Profile is the central concept behind the personalization features of SharePoint (MOSS only). In addition to the User Profile, each user can have a My Site. A My Site is composed of:

  • A Profile Page that shows the user profile data, according to the user viewing it and the privacy options of each profile field. You can find that page (Person.aspx) in the root web site of the My Site host site collection (e.g http://mysites/Person.aspx?accountname=domain\username).
  • A Personal Site which is a site collection where you can show personal and public information and documents.

The Personal Site is automatically provisioned for you when you try to access your My Site (using the My Site link or clicking your username). However, you might want to create it programmatically for one or more users, before they even try to access it. See below an example of how to do it.

// open a site collection
using (SPSite site = new SPSite("http://myportal"))
{
    // get the server context
    ServerContext context = ServerContext.GetContext(site);

    // create the profile manager object
    UserProfileManager profileManager = new UserProfileManager(context);

    // get the user profile
    UserProfile profile = profileManager.GetUserProfile("domain\\username");

    // create the user's personal site
    profile.CreatePersonalSite();
}

The really important line of code here is the last one. There rest was already explained in one of my previous posts (WSS Tip #20: Get User Profile).

SharePoint Tip #22: Create a User Profile

The best way to create SharePoint User Profiles is to import them from somewhere (Active Directory for instance). This is specially true if you want to create a lot of them at once. However, if you really want to do it manually, one at a time, you can. Just do it like in the snippet below.

// open a site collection
using (SPSite site = new SPSite("http://myportal"))
{
    // get the server context
    ServerContext context = ServerContext.GetContext(site);

    // create the profile manager object
    UserProfileManager upm = new UserProfileManager(context);

    // create the user profile
    UserProfile profile = upm.CreateUserProfile("domain\\username");
}

Just like getting a User Profile from the User Profile Store, to create one you need a UserProfileManager object. After that, you just need to call the CreateUserProfile method and pass it the user account name (including the domain).

Attention: User Profiles are a MOSS only feature. You cannot use them with WSS.

SharePoint Tip #21: Importing User Profiles

One of the best things of SharePoint's User Profiles, is that the profile data can be imported from several data sources (Active Directory or other LDAP directories, Databases and web services). It gets even better since you can schedule these imports to be performed automatically every given period of time.

But what if you want to start a profile import programmatically, without having to wait for the next scheduled import? Well, that can be done using the following code snippet.

// open a site collection
using (SPSite site = new SPSite("http://myportal"))
{
    // get the server context
    ServerContext context = ServerContext.GetContext(site);

    // create the profile configuration manager object
    UserProfileConfigManager upcm = new UserProfileConfigManager(context);

    // check if there is already an import in progress
    if (!upcm.IsImportInProgress())
    {
        // if not, start a new one
        // pass "true" as a parameter, if the import is incremental
        // pass "false" as a parameter, if you want a full import
        upcm.StartImport(true);
    }
}

The profile import process is managed using the UserProfileConfigManager object, which can be created using a ServerContext object. Before starting an import, using the StartImport method, you should always check if there is already an import in progress (using the IsImportInProgress method).

The StartImport method accepts a single boolean parameter which specifies if you want an incremental import (true) or a full import (false).

If necessary, you can build a while cycle to wait for the import to be over, testing the IsImportInProgress return value, until it returns false.

Attention: User Profiles are a MOSS only feature. You cannot use them with WSS.

SharePoint Tip #20: Get User Profile

User Profiles are a central concept to Office SharePoint Server 2007. They store all the information about the SharePoint users in a central location, the User Profile Store, allowing that information to be indexed and searched. The User Profile store can be populated and synchronized with several data sources:

  • Active Directory directory services
  • LADP Directory (other than Active Directory)
  • Databases and web services, via Business Data Catalog
  • Custom sources, via the User Profiles object model

You can also add users to it manually. Additionally, you can add custom properties to the User Profile and map some of them to the data sources you have. This great flexibility allows a multitude of scenarios. In this post I'll show you how you can get access a User Profile programmatically.

Everything is starts with the UserProfileManager object. Here is how you use it to get a UserProfile object.

// open a site collection
using (SPSite site = new SPSite("http://myportal"))
{
    // get the server context
    ServerContext context = ServerContext.GetContext(site);

    // create the profile manager object
    UserProfileManager profileManager = new UserProfileManager(context);

    // get the user profile
    UserProfile profile = profileManager.GetUserProfile("domain\\username");
}

There constructor for the UserProfileManager class is overloaded, which means there are other ways to create an instance but this is the way I usually do it. The GetUserProfile method is also overloaded, allowing you to get a user profile using its ID or just getting the current user's profile.

Attention: User Profiles are a MOSS only feature. You cannot use them with WSS.

SharePoint Tip #19: Using JavaScript in Body OnLoad Event

When developing web parts or other controls that use JavaScript, it's quite common to need to call some function on the Body OnLoad event of the web page. The problem with this is that, in SharePoint, the Body element is in the master page and not in the control, so doing this is can be tricky.

Fortunately, the SharePoint team gave the developers a way to do this easily, using a special array called _spBodyOnLoadFunctionNames. The only thing you have to do is push your function's name to this array and it will get called in the OnLoad event of the window.

Example:

_spBodyOnLoadFunctionNames.push("MyFunction");

function MyFunction() {
    setTimeout('MyFunction()', 1000);
}