Saturday, June 23, 2012

SharePoint Publishing Site Map Providers and Navigation

Configuring the navigation of SharePoint 2010 publishing sites and subsites can be a bit confusing, also when configuring the navigation from code or from your web templates (or even old school site definitions). Add to that the UI that changes based on which settings you chose combined with what site or subsite context you're currently in. Plus the quite large number of site map providers defined in the web.config when using the PortalSiteMapProvider from code.

This post is about how the UI settings can be repeated in your site provisioning code, that is: first configure the navigation settings in your prototype to make it work according to your navigation concept, then package the settings into feature code.

The PortalSiteMapProvider works in combination with the PublishingWeb navigation settings, and of course with the top and current navigation controls used to render the navigation as HTML. The latter needs to look at the publishing web's PortalNavigation settings when querying the portal site map provider for the CurrentNode or when getting a set of navigation nodes to render. The navigation controls' code use the PortalSiteMapProvider properties IncludeSubSites, IncludePages, IncludeAuthoredLinks and IncludeHeadings to set the filtering applied to GetChildNodes when rendering nodes. These filter properties are typically set to IncludeOption.PerWeb to reflect the navigation settings of the current site or subsite.

The navigation settings UI tries to show the effects of your navigation settings (upper half) by rendering a preview of what nodes GetChildNodes would return for the *current* site (lower half) from the applicable site map provider. The PortalSiteMapProvider exposes several of the providers defined in web.config as static properties, but only two of them are typically used: CombinedNavSiteMapProvider and CurrentNavSiteMapProvider. The former is what feeds the top navigation, the latter feeds the current (left, local) navigation.


Note that when inheriting global navigation, the UI won't show the global navigation container as it only supports configuring the navigation of the current site. The term "parent site" in the UI refers to the top-level site of the site-collection, which is not the direct parent of a subsite beyond level 1 children.


Configuring the navigation settings from your site provisioning feature is quite simple once you've got a working prototype of your navigation concept. Use the mapping shown in the above figure to program the configuration settings for both global navigation (InheritGlobal, GlobalIncludeSubSites, GlobalIncludePages) and current navigation (InheritCurrent, CurrentIncludeSubSites, CurrentIncludePages, ShowSiblings).

The only little pitfall is for "Display the current site, the navigation items below the current site, and the current site's siblings" which requires a combination of InheritCurrent = false and ShowSiblings = true. Use this setting to show the same local navigation for a section of your web-site and all its child sites. A typical example is for the Quality Management section (level 1 subsite) and its QMS areas (level 2 subsites) to have a shared navigation experience. The QMS section would not use ShowSiblings while all the child areas would have ShowSiblings turned on.

Implementing a custom navigation concept is as simple as writing your own navigation rendering controls, and inheriting the PortalSiteMapProvider to override the logic for CurrentNode and GetChildNodes to suit your needs by applying the applicable node filtering properties to control which nodes are returned and rendered in which context. I've also used this approach for reading the navigation items from a central SharePoint list to get common cross site-collection top-navigation.

I hope this helped you understand how to realize your navigation concept from code, and that you're not totally confused by all the available site map providers and how they are used anymore.