使用多个MvcSiteMaps

时间:2012-02-24 19:00:32

标签: c# asp.net-mvc mvcsitemapprovider

我最近遇到了试图使用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内容复制/粘贴到一个区域的新主服务器中,我宁愿它动态选择合适的提供程序。

4 个答案:

答案 0 :(得分:8)

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

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

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

答案 1 :(得分:6)

我正在使用版本4,其中指定的提供商显然不起作用。 prescribed way to have multiple sitemaps in v4坦率地害怕了我的bejeebus,并且比我想要的工作更多。

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

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

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

第2步:选择不同&#34;菜单的名称&#34;并将它们应用于每个节点上的visibility属性。在我的情况下,我有&#34;常规&#34;和&#34;管理员&#34;。同样,所有这些都在同一个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" })

答案 2 :(得分:5)

Multiple Sitemaps in One Application解释了如何在v4中完成此操作,这已经从接受的答案中改变了很多 - 这是针对v3和之前的。

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

答案 3 :(得分:2)

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

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