Using Multiple MvcSiteMaps

Kori picture Kori · Feb 24, 2012 · Viewed 7.3k times · Source

I've recently hit a road block trying to use the MvcSiteMapProvider.

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

So, when I'm:

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

I've tried the following:

Shared -> _AppLayout.cshtml

@Html.Partial("_Menu")

Shared -> _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 don't want to have to copy/paste the _AppLayout.cshtml content into a new master just for one area, I'd rather it select the right provider dynamically.

Answer

Cristi Todoran picture Cristi Todoran · Feb 28, 2012

Add something like this in 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>

Put this in your common masterpage (same thing 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 finaly create a sitemap file for each area.

It works for me. Hope it helps.