Understanding Custom Site Navigation

Concept

In a standard SharePoint site, users have two types of navigation:

  • Global navigation (this is also named the Top Navigation menu). This begins at the top-level site.
  • Current navigation (this is also named Quick Launch). This starts at the current site.

These types of navigation are based on the site hierarchy and on the pages within each site in a site collection. If you want users to have other options, such as navigating through a hierarchical structure of product categories, you must create some custom navigation.

For example, the Partner Portal application uses the Business Data Catalog (BDC) to expose information from a product catalog system. These categories are stored hierarchically, but the BDC uses a single profile page to display data about a particular category. The profile pages are distinguished from each other by query string parameters in the URL.

The Partner Portal application uses custom navigation to display the catalog hierarchy of the products as partners browse the site. These sites are displayed as a series of links at the top of the Web page. Displaying a hierarchy is sometimes referred to as bread crumbing. A common example of bread crumbing in Windows is the path you see in the address bar when you look at the contents of a folder. The links go from the root, such as Computer, to your present location.

The following figure illustrates an example of a Web page that displays the catalog hierarchy.

Contoso catalog page with bread crumb navigation

Ff649108.4ebad19b-fc89-4ffd-952b-6a9c0466c4b8(en-us,PandP.10).png

The custom navigation shows the root category, then the dental equipment category, and then the x-ray category. To implement the custom navigation, a custom site map provider supplies data to an ASP.NET control, which displays the data as a sequence of links at the top of the Web page.

Implementation Details

The following procedure shows the general steps required to implement a breadcrumb user interface (UI).

To implement custom navigation

  1. Create a custom class that inherits from the SiteMapProvider class. Implement override methods in your SiteMapProvider class to create site map nodes for the custom breadcrumb UI that you want to display. The methods to override are FindSiteMapNode and GetParentNode. See Creating the Custom Site Map Provider Class and Building the Navigation Path for an URL later in this topic.
  2. Configure and register the custom site map provider. See Configuring and Registering the Site Map Provider later in this topic.
  3. Display the ASP.NET SiteMapPath control. See Displaying the ASP.NET SiteMapPath Control later in this topic.

Each of these steps is explained in the following sections.

Creating the Custom Site Map Provider Class

The Partner Portal application includes the BusinessDataCatalogSiteMapProvider class to implement custom navigation. This class inherits from a .NET Framework class that is named SiteMapProvider. Override the methods of this class to create a custom class. Unlike the HierarchicalConfigSiteMapProvider class, the BusinessDataCatalogSiteMapProvider does not store the navigation structure in memory.

Building the Navigation Path for a URL

The SiteMapPath control runs each time a partner clicks on a category page. The control invokes the FindSiteMapNode method of the BusinessDataCatalogSiteMapProvider class. The raw URL of the page that is displayed is the method's argument. The method returns an object of type SiteMapNode because this is the type that the site map path control requires to construct the breadcrumb UI.

Each component of the breadcrumb path corresponds to a SiteMapNode object. Each SiteMapNode object has a display string and an associated target URL. In the case of nodes that are created by the custom site map provider, the URL represents a category profile page URL with a particular ID as a query string parameter.

When the ASP.NET SiteMapPath control calculates the sequence of SiteMapNode objects for the Web page that is displayed, it begins by finding the site map node for the current page. To do this, it calls the FindSiteMapNode method to obtain a SiteMapNode object that is created from the raw URL of the current page. This method is in the BusinessDataCatalogSiteMapProvider.cs file that is located in the folder \Source\PartnerPortal\Contoso.PartnerPortal.ProductCatalog\Navigation.

The FindSiteMapNode method extracts the category ID from the query string of the currently requested page and calls into the repository to retrieve the corresponding category record from the BDC. The resulting site map node includes the category ID, the raw URL, and the name that corresponds to the category ID.

Note

The repository that holds the category information is cached to improve the performance of the data lookups. By default, BDC does not cache any data. Whenever data is requested through the BDC, it always calls the external system. This can cause considerable performance degradation when many users are navigating through the categories.

The following code shows how the FindSiteMapNode method obtains a SiteMapNode object.

public override SiteMapNode FindSiteMapNode(string rawUrl)
{
   SiteMapNode node = null;

   string queryString = rawUrl.Split("?".ToCharArray())[1];
   string[] query = queryString.Split("&".ToCharArray());
   string[] queryParts = query[0].Split("=".ToCharArray());
   string categoryId = queryParts[1];

   Category category = this.productCatalogRepository.GetCategoryById(categoryId);
   if (category != null)
   {
       node = new SiteMapNode(this, categoryId, rawUrl, category.Name);
   }

   return node;
}

After the SiteMapPath control has the SiteMapNode object for the currently displayed page, it iteratively calls the GetParentNode method of the current node, backtracking until it discovers the breadcrumb trail from the current page to the root page. It then formats and displays links for each element of this hierarchy, starting with the root node and proceeding to the site map node for the current page. The GetParentNode method is in the BusinessDataCatalogSiteMapProvider.cs file located in the folder \Source\PartnerPortal\Contoso.PartnerPortal.ProductCatalog\Navigation.

The following code shows how the GetParentNode method constructs a navigation path.

public override SiteMapNode GetParentNode(SiteMapNode node)
{
    SiteMapNode parentNode = null;

    Category currentCategory = 
                 this.productCatalogRepository.GetCategoryById(node.Key);
    if (currentCategory != null)
    {
        Category parentCategory =
this.productCatalogRepository.GetCategoryById(currentCategory.ParentId);
        if (parentCategory != null)
        {
           parentNode = new SiteMapNode(this,
                                parentCategory.CategoryId,
                                string.Format(this.profileUrl, 
                                                     parentCategory.CategoryId),
                                parentCategory.Name);

           if (parentCategory.CategoryId == "0")
                    {
                        this.rootNode = parentNode;
                    }
                }
            }

            return parentNode;
        }

Any category that has the ID of 0 is a root category node. After the method finds a category with an ID of 0, it stops calling the GetParentNode method.

For more information about the SiteMapNode class, see SiteMapNode Class on MSDN.

Configuring and Registering the Site Map Provider

The new site map provider is registered in the Web.config file of the current Web application. It is associated with the symbolic name CategorySiteMapProvider that is referenced by the site map's ASP.NET control.

The WebFeatureReceiver class defines the modification to the Web.config using an instance of SPWebConfigModification.

public WebFeatureReceiver()
{
    sPWebConfigModification = new 
        SPWebConfigModification("add[@name=\"CategorySiteMapProvider\"]",
        "configuration/system.web/siteMap/providers");
    sPWebConfigModification.Owner = GetType().Assembly.GetName().ToString();
    sPWebConfigModification.Type = 
        SPWebConfigModification.SPWebConfigModificationType.EnsureChildNode;
    sPWebConfigModification.Value = @"<add name=""CategorySiteMapProvider""    
description=""Provider for category navigation using Business Data Catalog"" type=""Contoso.PartnerPortal.ProductCatalog.Navigation.BusinessDataCatalogSiteMapProvider, Contoso.PartnerPortal.ProductCatalog, Version=1.0.0.0, Culture=neutral, PublicKeyToken=0dcd9137292eac97"" />";
}

For more information about using the SPWebConfigModification class to modify the Web.config file, see Managing Application Configuration.

The FeatureActivated method of the WebFeatureReceiver class registers the provider during deployment. The method is declared in the WebFeatureReceiver.cs file of the Contoso.PartnerPortal.ProductCatalog project.

[SharePointPermission(SecurityAction.LinkDemand, ObjectModel = true)]
public override void FeatureActivated(SPFeatureReceiverProperties properties)
{ 
   /// ...
   web.Site.WebApplication.WebConfigModifications.Add(sPWebConfigModification);
                 
   web.Site.WebApplication.Update();                
   web.Site.WebApplication.WebService.ApplyWebConfigModifications();
}

The new node registers a site map provider that is named CategorySiteMapProvider. This provider is mapped to the BusinessDataCatalogSiteMapProvider class and used in the Category.aspx page.

For more information about the SPWebConfigModification class, see SPWebConfigModification Class (Microsoft.SharePoint.Administration) on MSDN.

Displaying the ASP.NET SiteMapPath Control

The ASP.NET SiteMapPath control is a UI control that displays a sequence of links, from a root page to the currently displayed page. To display the links, the SiteMapPath control must be included on the category page. It must also be associated with the BusinessDataCatalogSiteMapProvider class that calculates the breadcrumb links, which are based on the BDC category information. The SiteMapPath control retrieves these links from the site map provider.

In the Partner Portal application, the category page includes a site map path control that references the site map registration that was added to the Web.config file. The following XML code includes the SiteMapPath control and associates it with the BusinessDataCatalogSiteMapProvider. It uses the symbolic name CategorySiteMapProvider that was registered as part of the configuration process. The code is located in the \Source\PartnerPortal\Contoso.PartnerPortal.ProductCatalog\WebPartPages\Category\Category.aspx file in the Contoso.PartnerPortal.ProductCatalog project.

 <tr>
    <td>
       <asp:SiteMapPath 
            SiteMapProvider="CategorySiteMapProvider" 
             
            ID="SiteMapPath1" 
            NodeStyle-CssClass="ms-sitemapdirectional" />
     </td>
</tr>

The SiteMapPath control uses the Web.config file to look up the type (this is the BusinessDataCatalogSiteMapProvider class) for the site map provider that is named CategorySiteMapProvider. It then instantiates the class and calls the methods that are on that class. For more information about the SiteMapPath control, see SiteMapPath Class on MSDN.

An Example of Constructing a Navigation Path

Here is an example that demonstrates how breadcrumbing works, using food as an example. The catalog has a simple hierarchy that has the following structure: food, fruit, apples, Jonathan apples. The repository is a table that relates the category IDs, names, and parent nodes. Food is the root node and has a category ID of 0. The following table shows the repository.

Category ID

Name

Parent node

2

Jonathan apples

3

3

Apples

5

5

Fruit

1

1

Food

Null

For example, Jonathan apples have a category ID of 2 and the parent node has a category ID of 3, which has the name Apples.

A user has bookmarked the page for Jonathan apples. The URL for the page is https://localhost/category.aspx?categoryID=2. The SiteMapPath control calls the FindSiteMapNode method with this URL. The method parses it to extract the category ID value 2. It then calls into the repository with the ID and retrieves the corresponding name, Jonathan apples. It creates an instance of SiteMapNode with fields that contain the raw URL, the name, and the category ID.

After the SiteMapPath control has the current site map node, it attempts to find the parent node that corresponds to the next more general category in the breadcrumb hierarchy. To do this, the SiteMapPath control calls the GetParentNode method of the current site map node. The GetParentNode method calls into the repository, locates the record for the site node, and finds the parent node. It then constructs the URL for the parent node by substituting the category ID of the parent node for the category ID of the child page.

This process is repeated until the SiteMapPath control reaches a node with no parent. This is indicated by a null return value from the call to GetParentNode.

After the SiteMapPath control has all the site map nodes beginning with the root category down to the current page, it constructs the breadcrumb UI and renders it to the HTML page.

Additional Overridden Methods

To complete the implementation of a class that is derived from the SiteMapProvider class, the following properties and method are required:

  • RootNode property. This returns the top-most node in the custom navigation hierarchy.
  • GetChildNodes method. This returns a collection of all nodes that have as their parent node the node provided as an argument to the GetChildNodes method.
  • GetRootNodeCore property. This is the same as the RootNode property.

Home page on MSDN | Community site