【问题标题】:Using MvcSiteMapProvider to show part of a node level使用 MvcSiteMapProvider 显示部分节点级别
【发布时间】:2014-04-02 03:16:01
【问题描述】:

我正在为 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。它不应该显示所有这些。

Edit 2: Using Structure Map for external DI,我添加了这一行,但我不确定它是否正确:

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

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

编辑 4:我通过从 web.config 中删除内部 DI 设置修复了前两次编辑的问题。现在我又开始展示我想要展示的内容了。

【问题讨论】:

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


    【解决方案1】:

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

    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”或其他自定义参数的路由。

    【讨论】:

    • 这应该会有所帮助。我的规则很简单——菜单 X 应该对所有人可见,菜单 Y 应该基于角色可见。而且我已经了解到 MvcSiteMapProvider 可以很好地处理“基于角色”。
    • 我更新并更正了我的答案以包含外部 DI 的示例。确保将 VisibilityAffectsDescendants 设置为 false(我之前的示例显示为 true),否则您的菜单将始终隐藏不可见节点的后代节点。此外,请参阅更新后的第 3 项以始终显示面包屑跟踪中的项目。
    • 现在测试。顺便说一句,visibilityAffectsDescendants 有什么用?
    • visibilityAffectsDescendants 由 Menu、SiteMap 和 /sitemap.xml 端点使用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多