Thursday, July 12, 2012

ASP.net MVC Bread Crumbs

ASP.net WebForms has first class support for Breadcrumbs. Such first class treatment is missing when it comes to ASP.net MVC. You can either use MvcSiteMapProvider (recommended) or write custom code (put your reason here).

It is not all that difficult to write custom code to display bread crumbs on your pages served by ASP.net MVC.

You need to create Web.Sitemap in your root folder. Make sure the Url attribute is pointing to your controller

<?xml version="1.0" encoding="utf-8" ?>
<siteMap>
  <siteMapNode title="Home" url="~" >
    <siteMapNode title="Services" url="~/Services" >
      <siteMapNode title="Training" url="~/Training"/>
    </siteMapNode>
  </siteMapNode>
</siteMap>

Next you need to create a partial view that iterates the ancestry of the current node in reverse order (from the oldest to the newest including the current) and build the breadcrumbs as links and render them.

@using System.Text
@{
    var stack = new List<SiteMapNode>();
    var current = SiteMap.CurrentNode;
    
    while(current != null)
    {
        stack.Add(current);
        current = current.ParentNode;
    }

    var builder = new StringBuilder();
    foreach (var node in stack.Reverse<SiteMapNode>())
    {
        var tag = new TagBuilder("a");
        tag.MergeAttribute("href", node.Url);
        tag.InnerHtml = node.ToString();

        builder.AppendFormat("{0}>", tag.ToString());
    }
    
    ViewBag.SiteMap = MvcHtmlString.Create(builder.ToString());    
}

<h4>@ViewBag.SiteMap</h4>

Next use the partial view inside the pages or inside the _layout.cshtml using Html.Partial.

Disclaimer: The code in this article is experimental and does not reflect the way I write code in general. For example a lot of optimizations can be done to avoid the iteration of ancestral nodes by caching the results.