Click here to Skip to main content
Click here to Skip to main content

Breadcrumbs in WebMatrix Web Pages

By , 8 Apr 2012
Rate this:
Please Sign up or sign in to vote.

Introduction

Breadcrumbs are often an important aid in user interface, allowing users to know their position in the site they are navigating.

One of the most common ways of creating a breadcrumb in ASP.NET sites is based on an XML file named web.sitemap, that is located in the site root directory.

The web.sitemap collects site pages in hierarchical order, where each page is referenced by a siteMapNode and siteMapNodes are nested to reproduce the site structure.

In Web Forms there’s a siteMapPath control that lets insert a breadcrumb easily into any page of the site, based on the contents of web.sitemap.

Controls are not allowed in ASP.NET Web Pages, therefore a different solution must be implemented to achieve the same goal.

The Sitemap Helper

Carlos Aguilar Mares, in his blog, suggests a simple solution based on an helper that I have just improved a little adding three optional parameters that set the separators before, after and between the links.

@helper 

Sitemap(string prev = "", string sep = " > ", string post = "") 
{
@*  Helper Syntax:
    Sitemap(prev, sep, post)
    Sitemap()
    Creates and displays a bredcrumb as unordered list based on web.sitemap.
    The breadcrumb is preceded by "prev", followed by "post" and with items
    divided by "sep".
    The default values for parameters are an empty string for "prev" and 
    "post" and the greater-than sign for "sep".
    
    Parameters
    prev:   string added before the breadcrumb (optional)
    sep:    string added between items (optional)
    post:   string added after the breadcrumb (optional)
*@
   
    @* Retrive current node *@
    SiteMapNode currentNode = SiteMap.CurrentNode;
    
    @* Build breadcrumb *@
    <nav> 
        <ul class="siteMap">
            <li><span id="prev">@Html.Raw(prev)</span></li>
            
            @* If current node exist in web.sitemap *@
            @if (currentNode != null) {
                
                @* Push parent nodes into a stack to reverse them *@
                var node = currentNode;
                var nodes = new Stack<SiteMapNode>();
                while (node.ParentNode != null) {
                    nodes.Push(node.ParentNode);
                    node = node.ParentNode;
                }
                
                @* Pop parent nodes from the stack *@
                while (nodes.Count != 0) {
                    SiteMapNode n = nodes.Pop();
                    
                    @* Add a parent node's link to the breadcrumb *@
                    <li><a href="@n.Url" title="@n.Description">@n.Title</a><span id="sep">@Html.Raw(sep)</span></li> 
                }
                
                @* Add current node title to the breadcrumb *@
                <li><span>@currentNode.Title</span></li>
            }
            
            @* If current node don't exist in web.sitemap *@
            else {
                
                @* Replace breadcrumb with page title *@
                <li><span>@Page.Title</span></li>
            }
            <li id="post">@Html.Raw(post)</li>
        </ul>
    </nav>
}

The simple helper proposed by Carlos Aguilar Mares retrieves the current node through the SiteMap.CurrentNode property and reverses its parent nodes pushing them into a stack.

Then it builds the breadcrumb popping each parent node and adding its link to an unordered list.

Another addition that I have made to the original helper it’s the possibility of displaying the title of the page instead of the breadcrumb in case the helper isn’t able of identify the current node.

The breadcrumb look can be defined adding the right styles to the css file, as the example in the following:

.siteMap { 
 font-size:14px;
 color:#888;
 display:inline;
}
.siteMap li {
 float:left;
 list-style-type:none;
 padding-left:0px;
 border-width:0px;
}
.siteMap span {
 font-weight:bold;
}
.siteMap #prev {
 color:blue;
 font-weight:normal;
}
.siteMap #post {
 color:blue;
 font-weight:normal;
}
.siteMap #sep {
 color:blue;
 font-weight:normal;
}
.siteMap a,a.Visited {
 color:#888;
 text-decoration:none;
} 

The appropriate position for the helper call is from the site’s Layout page.

The extension-less problem

ASP.NET 4 applications can handle requests for extensionless URLs in IIS 7.0 and IIS 7.5, so you can access default.cshtml just typing default. However, if in web.sitemap the files are reported without the extension, typing their name with the extension doesn’t let recognize the siteMapNode.

This problem can be solved implementing URL rewriting with the Application_BeginRequest event in Global.asax:

void Application_BeginRequest(object sender, EventArgs e)
{
 string currentUrl = Request.FilePath.ToLower();
 
 if(currentUrl.Length > 6) {
  if ((currentUrl.Substring(currentUrl.Length - 7)) == ".cshtml") {
   var originalUrl = currentUrl.Substring(0, currentUrl.Length - 7);
   Context.RewritePath(originalUrl);
  }
 } 
}

The code I’ve used is pretty simple: if the actual URL contains the .cshtml extension, the Application_BeginRequest event redirects to the same URL without extension, permitting the identification of the right siteMapNode.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Gianmaria Gregori
Chief Technology Officer Federfarma Pavia
Italy Italy
No Biography provided
Follow on   Twitter

Comments and Discussions

 
QuestionIs it possible to generate a sitemap.cshtml in Webmatrix? PinmemberMember 1013209628-Jun-13 21:15 
AnswerRe: Is it possible to generate a sitemap.cshtml in Webmatrix? PinmemberMember 1013209629-Jun-13 4:08 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web03 | 2.8.140421.2 | Last Updated 9 Apr 2012
Article Copyright 2012 by Gianmaria Gregori
Everything else Copyright © CodeProject, 1999-2014
Terms of Use
Layout: fixed | fluid