使用MvcSiteMapProvider显示节点级别的一部分

时间:2014-03-31 18:33:43

标签: asp.net-mvc-4 razor mvcsitemapprovider

我正在使用MVC4的MvcSiteMapProvider(v4.6.1)来处理面包屑和菜单。我已经完成了有关安装,配置和使用@Html.MvcSiteMap().Menu()的100级教程。

我现在想要一个显示顶级部分的菜单。目前,我的顶级节点包括Home,Profile,Login,Thing 1,Thing 2和Thing 3.借鉴this SOf answer,我制作了一个菜单,在水平行中显示所有这些项目。我还确定,一旦系统包含授权,无法访问Thing 3的用户就不会在他们的菜单上看到这一点。

但我想要的只是展示一些项目:Home和Login必须显示在面包屑中但不得出现在菜单中。请注意,它们在当前站点地图中不是连续的。

您有什么建议吗?

我目前的观点,从链接的答案批发:

@model MvcSiteMapProvider.Web.Html.Models.MenuHelperModel
@using MvcSiteMapProvider.Web.Html.Models

<div class="nav navbar-nav navbar-left">
    <ul class="nav navbar-nav">
        @foreach (var node in Model.Nodes) { 
            <li>@Html.DisplayFor(m => node)</li>
        }
    </ul>
</div>

我从菜单视图到此视图的当前通话:

@Html.MvcSiteMap().Menu("MenuHelper", 0, true, false, 1)

当然,我可以制作一个新的菜单助手来过滤掉我不想表达的那些。

编辑:Mvc.sitemap:

  <mvcSiteMapNode title="Home" controller="Home" action="Index" visibility="MainMenu,!*">
    <mvcSiteMapNode title="About" controller="Home" action="About"/>
    <mvcSiteMapNode title="Profile" controller="Home" action="UpdateProfile" visibility="MainMenu,!*"/>
    <mvcSiteMapNode title="Login" controller="SGAccount" action="Login">
      <mvcSiteMapNode title="Register" controller="SGAccount" action="Register">  
      </mvcSiteMapNode>
    </mvcSiteMapNode>
    <mvcSiteMapNode title="Thing1" controller="Thing1" action="Index" visibility="MainMenu,!*">
      <mvcSiteMapNode title="Thing1-action1" controller="Thing1" action="action1" visibility="RoleMenu,!*"/>
      <mvcSiteMapNode title="Thing1-action2" controller="Thing1" action="action2" visibility="RoleMenu,!*"/>
    </mvcSiteMapNode>
    <mvcSiteMapNode title="Thing2" controller="Thing2" action="Index" visibility="MainMenu,!*">
    </mvcSiteMapNode>
  </mvcSiteMapNode>

MainMenu显示Home,About,Profile,Login,Thing1和Thing2。它不应该显示所有这些。

编辑2:对外部DI使用结构图,我添加了这一行,但我不确定它是否正确:

x.For<ISiteMapNodeVisibilityProviderStrategy>().Use<SiteMapNodeVisibilityProviderStrategy>();

编辑3:我的面包屑@Html.MvcSiteMap().SiteMapPath()停止了工作。这也需要修复。

编辑4:我修复了前两个编辑&#39;通过从web.config删除内部DI设置来解决问题。现在我回过头来展示我想要展示的内容。

1 个答案:

答案 0 :(得分:4)

实现此目的的最佳方法是将named HTML helpers与ISiteMapNodeVisibilityProvider一起使用。框中有一个FilteredSiteMapNodeVisibilityProvider,可以通过为每个菜单命名来显示某些菜单实例上的节点。

1)将VisibilityAffectsDescendants设置为false,将默认可见性提供程序设置为FilteredSiteMapNodeVisibilityProvider

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

对于外部DI,这些设置需要由DI容器提供。以下是在StructureMap中如何做到这一点。

// Near the top of the DI module 
// (this setting is provided to the constructor of SiteMapBuilderSet)
bool visibilityAffectsDescendants = false;

// Visibility Providers
this.For<ISiteMapNodeVisibilityProviderStrategy>().Use<SiteMapNodeVisibilityProviderStrategy>()
    .Ctor<string>("defaultProviderName").Is("MvcSiteMapProvider.FilteredSiteMapNodeVisibilityProvider, MvcSiteMapProvider");

2)通过sourceMetaData参数

为每个菜单命名
@Html.MvcSiteMap().Menu(new { name = "TopMenu" })
@Html.MvcSiteMap().Menu(new { name = "SideMenu" })
@Html.MvcSiteMap().Menu(new { name = "BottomMenu" })

3)按照here所述设置每个节点的可见性属性。请记住,您也可以按HTML帮助程序类型进行过滤。

<mvcSiteMapNode title="Home" controller="Home" action="Index" visibility="TopMenu,BottomMenu,SiteMapPathHelper,!*">
    <mvcSiteMapNode title="About" controller="Home" action="About" visibility="SideMenu,BottomMenu,SiteMapPathHelper,!*"/>
    <mvcSiteMapNode title="Contact" controller="Home" action="Contact" visibility="TopMenu,SiteMapPathHelper,!*"/>
</mvcSiteMapNode>

如果您有更复杂的可见性规则,您甚至可以implement your own ISiteMapNodeVisibilityProvider

请注意,可见性也受security trimming影响,但安全修整始终隐藏隐藏节点的所有后代节点。启用安全修整后,每个节点都必须在安全性方面可访问且根据可见性提供程序可见,以便在UI上可见。

如果没有与当前页面匹配的节点,则会自动隐藏基于级别的痕迹路径和菜单。阅读How to Make MvcSiteMapProvider Remember a User's Position以深入了解匹配行为。这仅适用于具有“id”或其他自定义参数的路由。