Using Multiple MvcSiteMaps

前端 未结 4 1343
有刺的猬
有刺的猬 2020-12-20 15:55

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 curr

相关标签:
4条回答
  • 2020-12-20 16:12

    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.

    0 讨论(0)
  • 2020-12-20 16:14

    I'm using version 4, for which the named providers apparently doesn't work. The prescribed way to have multiple sitemaps in v4 frankly scared the bejeebus out of me and was way more work than I wanted.

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

    Step 1: add this setting to in web.config

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

    Step 2: pick 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, all of these are 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'll note, that the Reports, Downloads and Document links are available to both regular users and admin users, but since admin rarely uses these options, I wanted to put them in the Misc submenu.

    Step 3: in your _Layout.cshtml, decide 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 aren't I think you can just call @Html.MvcSiteMap().Menu(new { name = "MENUNAME" })

    0 讨论(0)
  • 2020-12-20 16:14

    Multiple Sitemaps in One Application explains how this is done in v4, which has changed quite a bit from the accepted answer - which was for v3 and prior.

    The primary difference is that now multiple sitemaps are configured with DI, and you need to implement ISiteMapCacheKeyGenerator and/or ISiteMapCacheKeyToBuilderSetMapper, which are small classes to tell MvcSiteMapProvider how to map the incoming HTTP requests to each sitemap.

    0 讨论(0)
  • 2020-12-20 16:17

    This is what I ended up doing (based on this question). it's a little simpler, hope it helps. I just named my 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>
    
    0 讨论(0)
提交回复
热议问题