【问题标题】:Using Multiple MvcSiteMaps使用多个 MvcSiteMap
【发布时间】:2023-03-10 11:40:01
【问题描述】:

我最近在尝试使用MvcSiteMapProvider 时遇到了障碍。

在我的申请中,我有三个不同的区域:登陆、申请和管理。我目前已经实现了 MvcSiteMapProvider,它的效果非常好,但我现在要做的是使用 Html MvcSiteMap Helper 并根据我所在的区域指定不同的地图提供者。

所以,当我:

  • 在“管理”区域 - 我想使用名为“AdminSiteMapProvider”的提供程序。
  • 在“应用程序”区域 - 我想使用名为“AppSiteMapProvider”的提供程序。

我尝试了以下方法:

共享 -> _AppLayout.cshtml

@Html.Partial("_Menu")

共享 -> _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>    
    }
}    

}

有什么建议吗?我不想只为一个区域将 _AppLayout.cshtml 内容复制/粘贴到新的母版中,我宁愿它动态选择正确的提供者。

【问题讨论】:

  • 你试过使用mvcSiteMapNode的area属性吗?
  • 这只改变了生成的链接(我目前使用“区域”,用于管理链接)。我希望生成一组完全不同的链接,这些链接实际上位于单独的文件 (admin.sitemap) 中,具体取决于我当前是否在“管理”区域中浏览。

标签: c# asp.net-mvc mvcsitemapprovider


【解决方案1】:

在您的 web.config 文件中添加类似这样的内容(每个区域的新提供程序):

<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>

把它放在你的通用母版页中(菜单也是一样的):

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>
}

最后为每个区域创建一个站点地图文件。

它对我有用。希望对您有所帮助。

【讨论】:

    【解决方案2】:

    我使用的是第 4 版,命名的提供者显然对此不起作用。 prescribed way to have multiple sitemaps in v4 坦率地说把我吓坏了,而且工作量比我想要的要多。

    根据@NightOwl888 对他自己的回答的建议评论,我使用了 v4 中的命名助手选项。我仍然只有一个 mvc.sitemap 文件,但我有互斥的可见性选项。

    第 1 步:将此设置添加到 web.config 中

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

    第 2 步:选择不同“菜单”的名称并将它们应用于每个节点上的 visibility 属性。就我而言,我有“常规”和“管理员”。同样,所有这些都在同一个 mvc.sitemap 文件中。

    <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>
    

    您会注意到,普通用户和管理员用户都可以使用“报告”、“下载”和“文档”链接,但由于管理员很少使用这些选项,我想将它们放在“杂项”子菜单中。

    第 3 步:在您的 _Layout.cshtml 中,决定要显示哪个菜单。

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

    我用过这个bootstrap/sitemap tutorial,如果你不是我想你可以打电话给@Html.MvcSiteMap().Menu(new { name = "MENUNAME" })

    【讨论】:

    • 多么好的简单的做事方式啊。我也同意 DI 方法是矫枉过正,坦率地说是荒谬的。使用了你的方法,对我来说效果很好。
    【解决方案3】:

    Multiple Sitemaps in One Application 解释了这是如何在 v4 中完成的,这与已接受的答案相比发生了很大变化 - 这是针对 v3 及之前的版本。

    主要区别在于现在多个站点地图都配置了 DI,并且您需要实现 ISiteMapCacheKeyGenerator 和/或 ISiteMapCacheKeyToBuilderSetMapper,它们是告诉 MvcSiteMapProvider 如何将传入的 HTTP 请求映射到每个站点地图的小类。

    【讨论】:

    • DI 蝙蝠侠的圣母,有没有简单的方法可以使用两个站点地图文件?
    • 抱歉,罗宾,目前没有。不过,现在有更多解决方法,例如使用具有高级可见性的“命名”HTML 帮助程序,因此在很多情况下不需要它们。
    • 谢谢 - 我最终只使用了一个。现实情况是,另一个站点地图只是一个“主页、关于、联系方式、常见问题解答”,它是正面的,每个人都可以看到。没有理由为此提供站点地图。
    【解决方案4】:

    这就是我最终要做的(基于这个问题)。比较简单,希望对您有所帮助。我只是在区域之后命名我的站点地图提供者,或“默认”。

    <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>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-09-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-21
      相关资源
      最近更新 更多