1. Install MvcSiteMapProvider MVC5 NuGet package. This package is a SiteMapProvider implementation for the ASP.NET MVC 5 framework.
2. In web.config, downsize the MvcSiteMapProvider configuration to the minimal. Keep it simple, stupid. (KISS)
<system.web> <siteMap defaultProvider="MvcSiteMapProvider"> <providers> <clear /> <add name="MvcSiteMapProvider" type="MvcSiteMapProvider.DefaultSiteMapProvider, MvcSiteMapProvider" siteMapFile="~/Mvc.Sitemap" /> </providers> </siteMap> </system.web>
3. Modify the ~\Mvc.sitemap file as the following.
<?xml version="1.0" encoding="utf-8" ?> <mvcSiteMap xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://mvcsitemap.codeplex.com/schemas/MvcSiteMap-File-4.0" xsi:schemaLocation="http://mvcsitemap.codeplex.com/schemas/MvcSiteMap-File-4.0 MvcSiteMapSchema.xsd"> <mvcSiteMapNode title="Home" controller="Home" action="Index"> <mvcSiteMapNode title="About" controller="Home" action="About" /> <mvcSiteMapNode title="Contact" controller="Home" action="Contact" /> <mvcSiteMapNode title="Administration" clickable="false"> <mvcSiteMapNode title="User Mgmt" controller="Home" action="UserMgmt" /> <mvcSiteMapNode title="Role Mgmt" controller="Home" action="RoleMgmt" /> </mvcSiteMapNode> <mvcSiteMapNode title="Profile" clickable="false"> <mvcSiteMapNode title="Change Password" controller="Home" action="ChangePassword" /> <mvcSiteMapNode title="Separator" clickable="false" /> <mvcSiteMapNode title="Sign Off" controller="Home" action="SignOff" /> </mvcSiteMapNode> </mvcSiteMapNode> </mvcSiteMap>
4. To support submenu inside a dropdown menu, append the following CSS to ~/Content/Site.css
/* Bootstrap Dropdown Submenu */ .dropdown-submenu { position: relative; } .dropdown-submenu > .dropdown-menu { top: 0; left: 100%; margin-top: -6px; margin-left: -1px; -webkit-border-radius: 0 6px 6px 6px; -moz-border-radius: 0 6px 6px 6px; border-radius: 0 6px 6px 6px; } .dropdown-submenu:hover > .dropdown-menu { display: block; } .dropdown-submenu > a:after { display: block; content: " "; float: right; width: 0; height: 0; border-color: transparent; border-style: solid; border-width: 5px 0 5px 5px; border-left-color: #cccccc; margin-top: 5px; margin-right: -10px; } .dropdown-submenu:hover > a:after { border-left-color: #ffffff; } .dropdown-submenu.pull-left { float: none; } .dropdown-submenu.pull-left > .dropdown-menu { left: -100%; margin-left: 10px; -webkit-border-radius: 6px 0 6px 6px; -moz-border-radius: 6px 0 6px 6px; border-radius: 6px 0 6px 6px; } .navbar-nav .divider-vertical { height: 40px; margin: 0 9px; border-left: 1px solid #f2f2f2; border-right: 1px solid #ffffff; }
5. The MvcSiteMapProvider renders a menu as a unordered list which doesn’t fit the Bootstrap’s Navbar component. We need to create a partial view to fill this gap. Add a partial view file BootstrapMenuHelperModel.cshtml under ~\Views\Shared\DisplayTemplates
@model MvcSiteMapProvider.Web.Html.Models.MenuHelperModel @using System.Web.Mvc.Html @using MvcSiteMapProvider.Web.Html.Models @helper TopMenu(List<SiteMapNodeModel> nodeList) { <nav class="navbar navbar-default" role="navigation"> <div class="container-fluid"> <div class="collapse navbar-collapse"> <ul class="nav navbar-nav"> @foreach (SiteMapNodeModel node in nodeList) { string url = node.IsClickable ? node.Url : "#"; if (!node.Children.Any()) { <li><a href="@url">@node.Title</a></li> } else { <li class="dropdown"><a class="dropdown-toggle" data-toggle="dropdown">@node.Title <span class="caret"></span></a>@DropDownMenu(node.Children)</li> } if (node != nodeList.Last()) { <li class="divider-vertical"></li> } } </ul> </div> </div> </nav> } @helper DropDownMenu(SiteMapNodeModelList nodeList) { <ul class="dropdown-menu" role="menu"> @foreach (SiteMapNodeModel node in nodeList) { if (node.Title == "Separator") { <li class="divider"></li> continue; } string url = node.IsClickable ? node.Url : "#"; if (!node.Children.Any()) { <li><a href="@url">@node.Title</a></li> } else { <li class="dropdown-submenu"><a href="@url">@node.Title</a>@DropDownMenu(node.Children)</li> } } </ul> } @TopMenu(Model.Nodes)
Notes: 2 value-added features worth mention in the above code snippet. a) Handle multi-level site map using Bootstrap’s Dropdowns component (This post shows 2 levels site map, I tested with 4 levels site map); b) Support adding Separator in the menu (Refer to above ~\Mvc.sitemap snippet in step 4).
6. Edit the _Layout.cshtml file again to render the MvcSiteMap’s menu using the Bootstrap menu partial view.
...... <body> <div class="container"> <div class="row"> <div class="span12"> <nav> @Html.MvcSiteMap().Menu("BootstrapMenuHelperModel") </nav> </div> </div> <!-- //row --> <div class="row"> <div class="span12 body-content"> @RenderBody() <hr /> <footer> <p>© @DateTime.Now.Year - My ASP.NET Application</p> </footer> </div> </div> <!-- //row --> </div> ...... </body> ......
7. Completed!!!


You can download the code sample here.
References