SharePoint Branding Issues: Breadcrumb

Navigation can break or make your site, and more specifically, your site’s usability. One of the tools to achieve a good navigation experience is the breadcrumb. In opposite to a menu structure a breadcrumb is quite space saving. And this is, according to MSDN, because it displays a hierarchical path of hyperlinked page names that provides an escape up the hierarchy of pages from the current location.

Basicily, it shows the current node and all its parent nodes. For the sake of completeness, it’s also called an eyebrow. And I’m not making this stuff up.. :p All in all, I’m pretty sure you guys all know the beast. I, for one, find it pretty usefull… as long as it keeps consistency along the way.

Back to SharePoint now. A breadcrumb within ASP.NET is called a SiteMapPath. This is a control which uses an XML sitemap of your site structure to keep track of your every move. It then shows your progress in a nice little breadcrumb. To access the sitemap, we need to use a .NET object called SiteMapProvider. As this is an object in code, we can change the way such a SiteMapProvider works and feed him some custom links programmically in stead of using a XML scheme. This gives a whole lot of flexibility. And because of SharePoint’s inherent dynamic nature, this is why almost all SiteMapProviders within SharePoint are implemented this way.

WSS natively offers a couple of SiteMapProviders (SPNavigationProvider, SPSiteMapProvider, SPContentMapProvider and SPXmlContentMapProvider), each with its specific use within your site. MOSS adds about 10 more. And it’s in MOSS, the troubles begin. Say, you design your site and you have to choose the breadcrumb’s location. Done? Ok.. which SiteMapProvider will you use? The default.masterpage has two (event up to three) breadcrumbs integrated in its design, all with different SiteMapProviders. (I wonder why this design decision was made) The two providers used are:

  • SPContentMapProvider: the default WSS SiteMapProvider which shows nicely all different items and lists
  • CurrentNavSiteMapProviderNoEncode: a provider which parses pages, not as items in a Pages list, but as sections within the site, which is pretty clean.

My requirement was: I want both advantages: items and lists nicely shown and pages cleanly parsed. Unfortunately, the WSS SiteMapProvider does not know pages and the MOSS SiteMapProvider does not parse lists and items. So, I decided to develop my own SiteMapProvider.

A SiteMapProvider consists of two things. A class containing the logic and an entry in the web.config enabling the SiteMapProvider’s use in a masterpage. Let’s first start with the logic.
As this is a MOSS problem only, I created a class inheriting from a MOSS SiteMapProvider: CombinedNavSiteMapProvider. This one will show nice complete breadcrumbs, except of course for lists and items. The SiteMapPath control uses one particular property from the SiteMapProvider: CurrentNode. So this is the one to override. This is the code I came up with:

public override SiteMapNode CurrentNode
{
  get
  {
    SiteMapNode node = base.CurrentNode;
    SPListItem listItem = SPContext.Current.ListItem;
    string url = HttpContext.Current.Request.Url.AbsolutePath;
    bool isItemSelf = listItem != null && url.EndsWith(listItem.Url);
    if (!isItemSelf)
      node = SiteMap.Providers["SPContentMapProvider"].CurrentNode;
    return node;
  }
}

Two things to notice. I check if the url is a page by comparing the requested url with the current item’s url. If they both match, it’s a Page alright. Second thing, to parse with the default WSS provider, one can find the correct provider in the static property Providers from the type SiteMap.
The last piece of the puzzel is the entry in the web.config. This is pretty straight forward. Go to configuration.system.web.siteMap.providers and duplicate the entry of the provider you inherited from. Change the assembly details and you have yourself a working SiteMapProvider.

All in all, this was quite a challenging change to find a solution for and to implement it. But once up, it works like a charm and seems so easy. See you next time!

16 Responses to “SharePoint Branding Issues: Breadcrumb”

  1. Adee Says:

    Very nice. May be you could tell how and where to implement this code ?
    I am very new to SharePoint, fresh from school, and this was a very good article and solves my problem, but I don’t know what to do with the code.

  2. Shilpa Says:

    Is there a possibility to write a custom provider for the MySite navigation. MySite uses the MySiteMapProvider which is sealed and it ingerits from the SiteMapProvider. I have to add another node to the TopNavigationBar of the MySite and this should happen for all the users whenever they create the site.

    Thanks in advance,
    Shilpa

  3. YPG Says:

    Hello.
    Thank you for the information.
    You just helped me with this article.

  4. Tombo Says:

    Shilpa>
    I think so. As the MySiteMapProvider is sealed, you’ll have to mimic it’s behaviour by trial and error, I’m affraid. Also, you maybe will have to change the master page for the my sites, as you will have a custom provider.

    Good Luck! Let me know if it works :-)

  5. Ketul Says:

    SPSiteMapProvider and SPContentMapProvider are sealed classes which class did you inherit from?

  6. Itay Shakury Says:

    Excellent! Thank you so much.

  7. Andy Says:

    I’m with Ketul – what providers did you inherit from? Any chance of seeing all the code?

    Also, how does this deal with caching?

  8. novolocus.com » Creating a SiteMapProvider for SharePoint Says:

    [...] stuff about creating a SiteMapProvider on ‘Tomblog’ (but Tom [...]

  9. morphis Says:

    Please Tombo, can you tell us which class did you inherit from? I have search several times, but find nothing suitable.

  10. Tombo Says:

    I inherited from System.Web.SiteMapProvider. This is a standard .NET class.

    About caching: there is none implemented. The caching classes are all sealed or internal. So you’ll have to come up with your own caching procedures. On my project I didn’t implement it yet. However, I don’t have any performance issues. Just make sure you dispose your SPWeb and SPSite objects.

    Good Luck!
    Tombo

  11. morphis Says:

    So I tried to implement this, but everytime I added my SiteMapProvider to my web.conf I get an Exception: [HttpException (0x80004005): The DataSourceID of 'TopNavigationMenu' must be the ID of a control of type IHierarchicalDataSource. A control with ID 'topSiteMap' could not be found.]
    I added the following to my web.config:

  12. Tombo Says:

    Try using a asp:SiteMapDataSource datasource instead of a SharePoint one…

    Tombo

  13. def Says:

    morphis: I had the same problem and that link
    http://devel.pc-serwis.com/2009/01/custom-navigation-provider-in-sharepoint-gives-shity-errors-part-1/
    helped me

  14. Chris Says:

    New to SP. Where do I put the class?

  15. bhargavi Says:

    Hi,
    i have a requirement to change the user name in the breadcrumb for MySite. Generally the bread crumb displays the site collection admin name, is it possible to change?

    thanks in advance :)

    Bhargavi

  16. Eric Says:

    Thanks for figuring out such clean logic for determining if you’re on a web page or not! I have used this with great success, and just incorporated it into a more detailed post with a Feature receiver class and some more detailed info for folks new to SharePoint development:

    http://www.thesug.org/Blogs/ermurray/archive/2009/4/24/CreatingaHybridPublishingSiteMapProviderCustomBreadcrumbNavigationProvider.aspx

Leave a Reply