A Semi-Dynamic Sitemap Solution

I was creating a website which had pages with multiple views. I wanted a fairly simple sitemap solution, without creating any custom sitemap provider, which could show the current view name in the breadcrumb trail like this -

Home » Parent Page » Current Page » Current View 1
Home » Parent Page » Current Page » Current View 2

So here’s what I did to achieve that -

MasterPage.Master:

<%@ Master Language="C#" AutoEventWireup="true" CodeFile="MasterPage.master.cs" Inherits="MasterPage" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>CMS ::</title>
</head>
<body>
    <form id="form1" runat="server">
        <div>
            <asp:SiteMapPath ID="SiteMapPath1" runat="server" OnPreRender="SiteMapPath1_PreRender" PathSeparator=" :  " RenderCurrentNodeAsLink="True">
            </asp:SiteMapPath>
        </div>
        <div>
            <asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server">
            </asp:ContentPlaceHolder>
        </div>
    </form>
</body>
</html>

MasterPage.master.cs:

using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Collections.Generic;

public partial class MasterPage : System.Web.UI.MasterPage
{
    private string _currentViewName = string.Empty;
    public string CurrentViewName
    {
        get { return _currentViewName; }
        set { _currentViewName = value; }
    }
    protected void Page_Load(object sender, EventArgs e)
    {
        SiteMap.SiteMapResolve += new SiteMapResolveEventHandler(SiteMap_SiteMapResolve);
    }
    protected void SiteMapPath1_PreRender(object sender, EventArgs e)
    {
        //If there is a current view name defined then add a child node to the breadcrumb trail.
        if (!string.IsNullOrEmpty(CurrentViewName))
        {
            SiteMapNodeItem sepItem = new SiteMapNodeItem(-1, SiteMapNodeItemType.PathSeparator);
            ITemplate sepTemplate = SiteMapPath1.PathSeparatorTemplate;
            if (sepTemplate == null)
            {
                Literal separator = new Literal();
                separator.Text = SiteMapPath1.PathSeparator;
                sepItem.Controls.Add(separator);
            }
            else
            {
                sepTemplate.InstantiateIn(sepItem);
            }
            sepItem.ApplyStyle(SiteMapPath1.PathSeparatorStyle);

            SiteMapNodeItem viewItem = new SiteMapNodeItem(-1, SiteMapNodeItemType.Current);
            Literal viewName = new Literal();
            viewName.Text = CurrentViewName;
            viewItem.Controls.Add(viewName);
            viewItem.ApplyStyle(SiteMapPath1.CurrentNodeStyle);

            SiteMapPath1.Controls.AddAt(-1, sepItem);
            SiteMapPath1.Controls.AddAt(-1, viewItem);
        }
        else //...if not then don't show the current node as a link.
        {
            SiteMapPath mySMP = (SiteMapPath)sender;
            mySMP.RenderCurrentNodeAsLink = false;
            mySMP.DataBind();
        }
    }
    private SiteMapNode SiteMap_SiteMapResolve(Object sender, SiteMapResolveEventArgs e)
    {
        SiteMapNode currentNode = SiteMap.CurrentNode.Clone(true);         

        //If there is a current view defined then set the URLs in the breadcrumb trail 
        //so that they point to the correct view. For example:
        //Home (Home.aspx) > News (News.aspx?View=0) > Edit (News.aspx?View=1)
        if (!string.IsNullOrEmpty(CurrentViewName))
        {
            string currentRequest = e.Context.Request.UrlReferrer.PathAndQuery;

            if (currentNode != null)
                currentNode.Url = currentRequest;
        }

        return currentNode;
    }
}

Now you are all set. To put this code in action, just declare a curent view name like this in your pages wherever needed:

((MasterPage)this.Master).CurrentViewName = "News Listing";

This solution was inspired by this blog post.

If you liked this post, 🗞 subscribe to my newsletter and follow me on 𝕏!