Using Multiple MvcSiteMaps

I recently hit the road block while trying to use MvcSiteMapProvider .

In my application, I have three different areas: Landing, Application and Administration. I have currently implemented MvcSiteMapProvider and it works amazingly, but now I am trying to use the Html MvcSiteMap Helper and specify a different map provider depending on the area I am in.

So when I:

  • In the "Admin" area - I want to use a provider named "AdminSiteMapProvider".
  • In the "Application" area - I want to use a provider named "AppSiteMapProvider".

I tried the following:

General -> _AppLayout.cshtml

@Html.Partial("_Menu") 

General → _Menu.cshtml

 @{ if (HttpContext.Current != null && HttpContext.Current.Handler is System.Web.Mvc.MvcHandler) { var handler = HttpContext.Current.Handler as System.Web.Mvc.MvcHandler; var currentArea = handler.RequestContext.RouteData.Values["area"] ?? string.Empty; if (!string.IsNullOrEmpty(currentArea.ToString())) { <text>@Html.MvcSiteMap("AppSiteMapProvider").Menu()</text> } else if (currentArea.ToString() == "Admin") { <text>@Html.MvcSiteMap("AdminSiteMapProvider").Menu()</text> } } 

}

Any suggestions? I do not want to copy / paste the contents of _AppLayout.cshtml into the new wizard for only one area, I would prefer that he select the correct provider dynamically.

+8
c # asp.net-mvc mvcsitemap mvcsitemapprovider
source share
4 answers

Add something like this to your web.config file (a new provider for each area):

 <siteMap defaultProvider="AppSiteMapProvider" enabled="true"> <providers> <clear /> <add name="AppSiteMapProvider" type="MvcSiteMapProvider.DefaultSiteMapProvider, MvcSiteMapProvider" siteMapFile="~/Mvc.Sitemap" securityTrimmingEnabled="true" cacheDuration="5" enableLocalization="true" scanAssembliesForSiteMapNodes="true" includeAssembliesForScan="" excludeAssembliesForScan="" attributesToIgnore="visibility" nodeKeyGenerator="MvcSiteMapProvider.DefaultNodeKeyGenerator, MvcSiteMapProvider" controllerTypeResolver="MvcSiteMapProvider.DefaultControllerTypeResolver, MvcSiteMapProvider" actionMethodParameterResolver="MvcSiteMapProvider.DefaultActionMethodParameterResolver, MvcSiteMapProvider" aclModule="MvcSiteMapProvider.DefaultAclModule, MvcSiteMapProvider" siteMapNodeUrlResolver="MvcSiteMapProvider.DefaultSiteMapNodeUrlResolver, MvcSiteMapProvider" siteMapNodeVisibilityProvider="MvcSiteMapProvider.DefaultSiteMapNodeVisibilityProvider, MvcSiteMapProvider" siteMapProviderEventHandler="MvcSiteMapProvider.DefaultSiteMapProviderEventHandler, MvcSiteMapProvider" /> <add name="AdminSiteMapProvider" type="MvcSiteMapProvider.DefaultSiteMapProvider, MvcSiteMapProvider" siteMapFile="~/Areas/Admin/Mvc.Sitemap" securityTrimmingEnabled="true" cacheDuration="5" enableLocalization="true" scanAssembliesForSiteMapNodes="true" includeAssembliesForScan="" excludeAssembliesForScan="" attributesToIgnore="visibility" nodeKeyGenerator="MvcSiteMapProvider.DefaultNodeKeyGenerator, MvcSiteMapProvider" controllerTypeResolver="MvcSiteMapProvider.DefaultControllerTypeResolver, MvcSiteMapProvider" actionMethodParameterResolver="MvcSiteMapProvider.DefaultActionMethodParameterResolver, MvcSiteMapProvider" aclModule="MvcSiteMapProvider.DefaultAclModule, MvcSiteMapProvider" siteMapNodeUrlResolver="MvcSiteMapProvider.DefaultSiteMapNodeUrlResolver, MvcSiteMapProvider" siteMapNodeVisibilityProvider="MvcSiteMapProvider.DefaultSiteMapNodeVisibilityProvider, MvcSiteMapProvider" siteMapProviderEventHandler="MvcSiteMapProvider.DefaultSiteMapProviderEventHandler, MvcSiteMapProvider" /> </providers> </siteMap> nodeKeyGenerator = "MvcSiteMapProvider.DefaultNodeKeyGenerator, MvcSiteMapProvider" controllerTypeResolver = "MvcSiteMapProvider.DefaultControllerTypeResolver, MvcSiteMapProvider" actionMethodParameterResolver = "MvcSiteMapProvider.DefaultActionMethodParameterResolver, MvcSiteMapProvider" aclModule = "MvcSiteMapProvider.DefaultAclModule, MvcSiteMapProvider" siteMapNodeUrlResolver = "MvcSiteMapProvider.DefaultSiteMapNodeUrlResolver <siteMap defaultProvider="AppSiteMapProvider" enabled="true"> <providers> <clear /> <add name="AppSiteMapProvider" type="MvcSiteMapProvider.DefaultSiteMapProvider, MvcSiteMapProvider" siteMapFile="~/Mvc.Sitemap" securityTrimmingEnabled="true" cacheDuration="5" enableLocalization="true" scanAssembliesForSiteMapNodes="true" includeAssembliesForScan="" excludeAssembliesForScan="" attributesToIgnore="visibility" nodeKeyGenerator="MvcSiteMapProvider.DefaultNodeKeyGenerator, MvcSiteMapProvider" controllerTypeResolver="MvcSiteMapProvider.DefaultControllerTypeResolver, MvcSiteMapProvider" actionMethodParameterResolver="MvcSiteMapProvider.DefaultActionMethodParameterResolver, MvcSiteMapProvider" aclModule="MvcSiteMapProvider.DefaultAclModule, MvcSiteMapProvider" siteMapNodeUrlResolver="MvcSiteMapProvider.DefaultSiteMapNodeUrlResolver, MvcSiteMapProvider" siteMapNodeVisibilityProvider="MvcSiteMapProvider.DefaultSiteMapNodeVisibilityProvider, MvcSiteMapProvider" siteMapProviderEventHandler="MvcSiteMapProvider.DefaultSiteMapProviderEventHandler, MvcSiteMapProvider" /> <add name="AdminSiteMapProvider" type="MvcSiteMapProvider.DefaultSiteMapProvider, MvcSiteMapProvider" siteMapFile="~/Areas/Admin/Mvc.Sitemap" securityTrimmingEnabled="true" cacheDuration="5" enableLocalization="true" scanAssembliesForSiteMapNodes="true" includeAssembliesForScan="" excludeAssembliesForScan="" attributesToIgnore="visibility" nodeKeyGenerator="MvcSiteMapProvider.DefaultNodeKeyGenerator, MvcSiteMapProvider" controllerTypeResolver="MvcSiteMapProvider.DefaultControllerTypeResolver, MvcSiteMapProvider" actionMethodParameterResolver="MvcSiteMapProvider.DefaultActionMethodParameterResolver, MvcSiteMapProvider" aclModule="MvcSiteMapProvider.DefaultAclModule, MvcSiteMapProvider" siteMapNodeUrlResolver="MvcSiteMapProvider.DefaultSiteMapNodeUrlResolver, MvcSiteMapProvider" siteMapNodeVisibilityProvider="MvcSiteMapProvider.DefaultSiteMapNodeVisibilityProvider, MvcSiteMapProvider" siteMapProviderEventHandler="MvcSiteMapProvider.DefaultSiteMapProviderEventHandler, MvcSiteMapProvider" /> </providers> </siteMap> = "visibility" nodeKeyGenerator = "MvcSiteMapProvider.DefaultNodeKeyGenerator, MvcSiteMapProvider" controllerTypeResolver = "MvcSiteMapProvider.DefaultControllerTypeResolver, MvcSiteMapProvider" actionMethodParameterResolver = "MvcSiteMapProvider.DefaultActionMethodParameterResolver, MvcSiteMapProvider" aclModule = "MvcSiteMapProvider.DefaultAclModule, MvcSiteMapProvider" siteMapNodeUrlResolver = <siteMap defaultProvider="AppSiteMapProvider" enabled="true"> <providers> <clear /> <add name="AppSiteMapProvider" type="MvcSiteMapProvider.DefaultSiteMapProvider, MvcSiteMapProvider" siteMapFile="~/Mvc.Sitemap" securityTrimmingEnabled="true" cacheDuration="5" enableLocalization="true" scanAssembliesForSiteMapNodes="true" includeAssembliesForScan="" excludeAssembliesForScan="" attributesToIgnore="visibility" nodeKeyGenerator="MvcSiteMapProvider.DefaultNodeKeyGenerator, MvcSiteMapProvider" controllerTypeResolver="MvcSiteMapProvider.DefaultControllerTypeResolver, MvcSiteMapProvider" actionMethodParameterResolver="MvcSiteMapProvider.DefaultActionMethodParameterResolver, MvcSiteMapProvider" aclModule="MvcSiteMapProvider.DefaultAclModule, MvcSiteMapProvider" siteMapNodeUrlResolver="MvcSiteMapProvider.DefaultSiteMapNodeUrlResolver, MvcSiteMapProvider" siteMapNodeVisibilityProvider="MvcSiteMapProvider.DefaultSiteMapNodeVisibilityProvider, MvcSiteMapProvider" siteMapProviderEventHandler="MvcSiteMapProvider.DefaultSiteMapProviderEventHandler, MvcSiteMapProvider" /> <add name="AdminSiteMapProvider" type="MvcSiteMapProvider.DefaultSiteMapProvider, MvcSiteMapProvider" siteMapFile="~/Areas/Admin/Mvc.Sitemap" securityTrimmingEnabled="true" cacheDuration="5" enableLocalization="true" scanAssembliesForSiteMapNodes="true" includeAssembliesForScan="" excludeAssembliesForScan="" attributesToIgnore="visibility" nodeKeyGenerator="MvcSiteMapProvider.DefaultNodeKeyGenerator, MvcSiteMapProvider" controllerTypeResolver="MvcSiteMapProvider.DefaultControllerTypeResolver, MvcSiteMapProvider" actionMethodParameterResolver="MvcSiteMapProvider.DefaultActionMethodParameterResolver, MvcSiteMapProvider" aclModule="MvcSiteMapProvider.DefaultAclModule, MvcSiteMapProvider" siteMapNodeUrlResolver="MvcSiteMapProvider.DefaultSiteMapNodeUrlResolver, MvcSiteMapProvider" siteMapNodeVisibilityProvider="MvcSiteMapProvider.DefaultSiteMapNodeVisibilityProvider, MvcSiteMapProvider" siteMapProviderEventHandler="MvcSiteMapProvider.DefaultSiteMapProviderEventHandler, MvcSiteMapProvider" /> </providers> </siteMap> MvcSiteMapProvider.DefaultSiteMapNodeVisibilityProvider, MvcSiteMapProvider" siteMapProviderEventHandler = "MvcSiteMapProvider.DefaultSiteMapProviderEventHandler, MvcSiteMapProvider" <siteMap defaultProvider="AppSiteMapProvider" enabled="true"> <providers> <clear /> <add name="AppSiteMapProvider" type="MvcSiteMapProvider.DefaultSiteMapProvider, MvcSiteMapProvider" siteMapFile="~/Mvc.Sitemap" securityTrimmingEnabled="true" cacheDuration="5" enableLocalization="true" scanAssembliesForSiteMapNodes="true" includeAssembliesForScan="" excludeAssembliesForScan="" attributesToIgnore="visibility" nodeKeyGenerator="MvcSiteMapProvider.DefaultNodeKeyGenerator, MvcSiteMapProvider" controllerTypeResolver="MvcSiteMapProvider.DefaultControllerTypeResolver, MvcSiteMapProvider" actionMethodParameterResolver="MvcSiteMapProvider.DefaultActionMethodParameterResolver, MvcSiteMapProvider" aclModule="MvcSiteMapProvider.DefaultAclModule, MvcSiteMapProvider" siteMapNodeUrlResolver="MvcSiteMapProvider.DefaultSiteMapNodeUrlResolver, MvcSiteMapProvider" siteMapNodeVisibilityProvider="MvcSiteMapProvider.DefaultSiteMapNodeVisibilityProvider, MvcSiteMapProvider" siteMapProviderEventHandler="MvcSiteMapProvider.DefaultSiteMapProviderEventHandler, MvcSiteMapProvider" /> <add name="AdminSiteMapProvider" type="MvcSiteMapProvider.DefaultSiteMapProvider, MvcSiteMapProvider" siteMapFile="~/Areas/Admin/Mvc.Sitemap" securityTrimmingEnabled="true" cacheDuration="5" enableLocalization="true" scanAssembliesForSiteMapNodes="true" includeAssembliesForScan="" excludeAssembliesForScan="" attributesToIgnore="visibility" nodeKeyGenerator="MvcSiteMapProvider.DefaultNodeKeyGenerator, MvcSiteMapProvider" controllerTypeResolver="MvcSiteMapProvider.DefaultControllerTypeResolver, MvcSiteMapProvider" actionMethodParameterResolver="MvcSiteMapProvider.DefaultActionMethodParameterResolver, MvcSiteMapProvider" aclModule="MvcSiteMapProvider.DefaultAclModule, MvcSiteMapProvider" siteMapNodeUrlResolver="MvcSiteMapProvider.DefaultSiteMapNodeUrlResolver, MvcSiteMapProvider" siteMapNodeVisibilityProvider="MvcSiteMapProvider.DefaultSiteMapNodeVisibilityProvider, MvcSiteMapProvider" siteMapProviderEventHandler="MvcSiteMapProvider.DefaultSiteMapProviderEventHandler, MvcSiteMapProvider" /> </providers> </siteMap> 

Put this on your general main page (same for the menu):

 var currentArea = (string)ViewContext.RouteData.DataTokens["area"]; if (string.IsNullOrWhiteSpace(currentArea)) { <text>@Html.MvcSiteMap("AppSiteMapProvider").SiteMapTitle()</text> } else if (currentArea.ToString() == "Admin") { <text>@Html.MvcSiteMap("AdminSiteMapProvider").SiteMapTitle()</text> } 

And finally create a sitemap for each area.

This works for me. Hope this helps.

+8
source share

Several Sitemaps in one application explain how this is done in version v4, which has slightly changed from the accepted answer - which was for v3 and earlier.

The main difference is that now several Sitemaps are configured using DI, and you need to implement ISiteMapCacheKeyGenerator and / or ISiteMapCacheKeyToBuilderSetMapper, which are small classes to tell MvcSiteMapProvider how to map incoming HTTP requests to each sitemap.

+5
source share

I am using version 4, for which the named providers do not seem to work. The prescribed way to have multiple sitemaps in v4 was frankly scared of bejeebus from me and there was a lot more work than I wanted.

In the commentary on @ NightOwl888's comment about his own answer, I used the named helpers option in v4. I still have one mvc.sitemap file, but I have mutually exclusive visibility options.

Step 1: add this parameter to the web.config file

 <add key="MvcSiteMapProvider_DefaultSiteMapNodeVisibiltyProvider" value="MvcSiteMapProvider.FilteredSiteMapNodeVisibilityProvider, MvcSiteMapProvider"/> 

Step 2: select the names of your different “menus” and apply them to the visibility attribute on each node. In my case, I had "Regular" and "Admin." Again, they are all in the same mvc.sitemap file.

 <mvcSiteMapNode title="Reports" controller="Report" action="List" visibility="Regular,!*"/> <mvcSiteMapNode title="Downloads" controller="Download" action="List" visibility="Regular,!*"/> <mvcSiteMapNode title="Documents" controller="Document" action="List" visibility="Regular,!*"/> <mvcSiteMapNode title="Users" controller="User" action="List" visibility="Admin,!*"/> <mvcSiteMapNode title="Projects" controller="Project" action="List" visibility="Admin,!*"/> <mvcSiteMapNode title="Misc" clickable="false" visibility="Admin,!*"> <mvcSiteMapNode title="Reports" controller="Report" action="List" visibility="Admin,!*"/> <mvcSiteMapNode title="Downloads" controller="Download" action="List" visibility="Admin,!*"/> <mvcSiteMapNode title="Documents" controller="Document" action="List" visibility="Admin,!*"/> </mvcSiteMapNode> 

You will notice that the “Reports”, “Downloads” and “Document” links are available both for regular users and for admin users, but since the administrator rarely uses these parameters, I wanted to put them in the Misc submenu.

Step 3: in your _Layout.cshtml, determine which menu you want to display.

 @if(User.IsInRole("Admin")) { @Html.MvcSiteMap().Menu("BootstrapMenuHelperModel", false, new { name = "Admin" }) } else { @Html.MvcSiteMap().Menu("BootstrapMenuHelperModel", false, new { name = "Regular" }) } 

I used this bootstrap / sitemap tutorial if you don’t think you can just call @Html.MvcSiteMap().Menu(new { name = "MENUNAME" })

+5
source share

This is what I ended up doing (based on this question). this is a little easier hope it helps. I simply called the site map provider after the area or "default."

 <ul id="menu"> @{ // gets a different sitemap for each area (or the default one) var _siteMap = ViewContext.RouteData.DataTokens["area"] as string ?? "Default"; var sm = Html.MvcSiteMap(_siteMap); @sm.Menu(sm.Provider.RootNode, true, true, 2); } </ul> 
+2
source share

All Articles