Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Highlight Current Menu Item under MvcSiteMapProvider

0.00/5 (No votes)
13 Feb 2017 1  
Highlighting the current menu item in MVC using the MvcSiteMapProvider turned out to be somewhat of a challenge but with a little head scratching and several cups of coffee, this is what emerged.

The default MVC 5 setup gives you a horrendous menu to work with and I probably could have made it look half way decent but I remembered the old SiteMapProvider I had used many moons ago and wondered if there was anything like it available today. Turns out there is and it's available at https://github.com/maartenba/MvcSiteMapProvider. You can also do a package install...

Install-Package MvcSiteMapProvider.MVCx

...where x is the MVC version you are running.

Ok, so you got it configured and it looks pretty good but highlighting is a real PITA, I Googled for quite a while and the cleanest solution required is that you adorn one of the menu items with an 'selected' class attribute. Well, since you can't get to the element to add the said attribute, what can we do?

In the Mvc.sitemap file, the only thing that you are really allowed to set is the description field and when set, it overwrites the title field with what you entered in the description. So I got to thinking if I could get the current page and check it against the list of menu items and when I got a match, just set the menu items class to highlight the item.

So, given a very basic sitemap with just a few items:

<mvcSiteMapNode title="Home" controller="Home"
action="Index" description="selected">
  <mvcSiteMapNode title="Pricing"
  controller="Pricing" action="Index" />
  <mvcSiteMapNode title="Contact"
  controller="Home" action="Contact"/>
  <mvcSiteMapNode title="Testimonials"
  controller="Testimonials" action="Index"/>
  <mvcSiteMapNode title="About"
  controller="Home" action="About"/>
  <mvcSiteMapNode title="Admin"
  controller="Admin" action="Index" roles="Admin" />
</mvcSiteMapNode>

As you can see, I set the Home menu item to selected and as long as it is unique, this scheme will work.

Now in your _Layout.cshtml file, add the JavaScript to do the actual work:

<script>
    window.onload = function () {
        setPage();
    }
 
    function setPage() {
        hrefString = document.location.href ? document.location.href : document.location;
 
        if (document.getElementById("menu") != null)
            setActiveMenu(document.getElementById("menu").getElementsByTagName("a"), 
                             extractPageName(hrefString));
    }
 
    function extractPageName(hrefString)
    {
        var arr = hrefString.split('/');
        return  arr[arr.length-1].toLowerCase();
    }
 
    function setActiveMenu(arr, crtPage)
    {
        for (var i=0; i < arr.length; i++)
        {
            if (extractPageName($($(arr[i])[0]).attr('href')) == crtPage)
            {
                if (arr[i].parentNode.tagName == "LI")
                {
                    arr[i].className = "current";
                }
            }
        }
    }
</script>

Then in your styles page, set the current class to whatever highlighting you desire, mine looks like this:

.current{
    color: #eab34f !important;
}

I got the code above from a site, don't remember where but I had to modify it to key on the title field and the parsing needed some work, but a lot of it came from him. Sorry dude, don't remember!

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here