Let’s say you do something fancy with your publishing site that changes the page hierarchy and would like the Bread Crumbs to account for those changes. You could create your own Bread Crumbs control but there is a quicker and more supported way that will allow your changes to affect the OOB Bread Crumbs control.
ASP.Net and thus SharePoint provides the provider model allowing you as a developer to override the delivered provider and insert your own allowing you to change the data presented to the OOB controls.
As MSDN documentation explains, you need 3 components to make a custom navigation provider: web.config entry, change in the master page, and a custom provider class. As usual the MSDN example is somewhat basic and is missing some of the key information for this scenario.
Custom Provider Class
MSDN tells you to override the GetChildNodes() method, but actually for the breadcrumb you need to override GetParentNode. For my current solution we had a recursive look up for parent in the pages library that we wanted to include in the navigation. Below is my custom navigation provider:
public class PageNavProvider : PortalSiteMapProvider { public override SiteMapNode GetParentNode(SiteMapNode node) { SPListItem listItem = SPContext.Current.ListItem; SiteMapNode parentnode = getParentNode(listItem); if (parentnode == null) { parentnode = base.GetParentNode(node); } return parentnode; } private SiteMapNode getParentNode(SPListItem listItem) { if (listItem["Parent"] != null) { SPFieldLookupValue parentVal = new SPFieldLookupValue(listItem["Parent"].ToString()); SPListItem parentListItem = SPContext.Current.List.GetItemById(parentVal.LookupId); if (parentListItem != null) { PortalSiteMapProvider portalProvider = PortalSiteMapProvider.CurrentNavSiteMapProviderNoEncode; // Look up the node for the given Web site URL. string serverRelativeUrl = parentListItem.Web.ServerRelativeUrl; if (serverRelativeUrl.Length > 1) { serverRelativeUrl = serverRelativeUrl + "/" + parentListItem.Url; } else { serverRelativeUrl = serverRelativeUrl + parentListItem.Url; } SiteMapNode parentNode = portalProvider.FindSiteMapNode(serverRelativeUrl); SiteMapNode grandparentNode = getParentNode(parentListItem); if (grandparentNode != null) { parentNode.ParentNode = grandparentNode; } return parentNode; } } return null; } }
Change in the Master Page
The MSDN article says to update the masterpage and change the bread crumbs provider on ListSiteMapPath1. This will only update the global bread crumbs pop out menu ( the little folder next to site actions) to get the bread crumbs control to work on the OOB layout pages or on your custom pages with the bread crumbs control you need to set your site map provider as the default provider. From my testing this has not had any adverse affects but you will want to test your site after making this change to ensure that none of the navigation is affected. .
Changes in the web.config
You need to make the following changes to the web.config in configuration/system.web/siteMap/providers:
<add name=’ProviderName’ type='NameSpace.ClassName, AssemblyName, Version=1.0.0.0, Culture=neutral, PublicKeyToken= publicKeyToken' NavigationType='Current' EncodeOutput='false' Version='14' />
At configuration/system.web/siteMap replace the default provider attribute with your custom provider name.
These changes should be made using a Web Application scoped feature receiver! See this post on why and how.