【问题标题】:ASP.NET - Determine which menu item is selectedASP.NET - 确定选择了哪个菜单项
【发布时间】:2016-05-17 21:53:59
【问题描述】:

这有点抽象:

我有一个用 ASP.NET MVC 编写的网站。最终用户可以创建一个 Menu 对象,该对象将在站点的菜单中移动。这看起来像这样:

public class Menu
{
    public string Caption { get; set; }
    public string Address { get; set; }

    public Menu(string Caption, string Address)
    {
        this.Caption = Caption;
        this.Address = Address;
    }
}

public Menu Menu1 = new("Home", "/");
public Menu Menu2 = new("Events", "/events");
public Menu Menu3 = new("Specific Event", "/event/13");

当一个请求进来时,我需要能够确定哪个菜单项是“活动的”。此外,如果请求是针对未明确命名的项目的“子页面”,则菜单项也应标记为活动的(例如,如果请求是针对“/event/95/checkout”,则 Menu2 将是标记为活动)。

我正在考虑尝试将相对 URL 与 URL 的地址进行比较,以确定哪个字符匹配最多,从字符串的开头开始 - 但我该怎么做呢?有没有更好的办法?

【问题讨论】:

  • 这看起来像是在与 MVC 作斗争。你为什么不使用Url.Action()之类的东西?
  • 是的 - 我知道你的意思 - 问题是我让用户在菜单上创建他们想要的任何链接 - 而不仅仅是与特定动作/控制器相关的东西
  • 我认为具有贪婪捕获的正则表达式(即尝试匹配尽可能多的字符)将起作用(忽略所有其他可能的替代方案,例如使用路由表,如 @itsme86 所述)。

标签: c# asp.net


【解决方案1】:

我们的代码中有类似的东西。我们的母版页在左侧有一个菜单,但一个菜单项可以关联到一系列子页面。

我们采用的解决方案是为每个菜单项保存一个正则表达式列表。

我会给你一堆我们的代码的sn-ps。这不是一个独立的解决方案,但可能会给你一些想法......

我们将使用构建器模式定义我们的菜单(注意方法UrlMatchPattern

var builder = new SiteMapBuilder();
builder.Add
       .Title("Home")
       .LaunchUrl("~/Home/Index")
       .IconUrl("~/Images/menuIcons/home.png")
       .UrlMatchPattern("~/Home/Index/?.*"); 
builder.Add
        .Title("Network")
        .IconUrl("~/Images/menuIcons/network.png")
        .Children(b => 
                    {
                        b.Add.Title("Companies")
                            .LaunchUrl("~/Company")
                            .UrlMatchPattern("~/Company");
                        b.Add.Title("Groups")
                            .LaunchUrl("~/PlayerGroup")
                            .UrlMatchPattern("~/PlayerGroup")
                            .LimitToRoles(
                                            CmsUserRoleId.Administrators, 
                                            CmsUserRoleId.Support
                                          );
                        b.Add.Title("Players")
                            .LaunchUrl("~/Player/index")
                            .UrlMatchPattern(
                                                @"~/\bPlayer\b", 
                                                "~/Player/Index", 
                                                @"~/Admin/PlayerDiagnostics\.aspx"
                                            ); 

这个构建器会在每个页面请求上动态重建菜单,生成一堆导航面板节点:

     internal NavPanelNode GenerateNode(IWebContext webContext, ...)
     {
            return new NavPanelNode
            {
                Title = _title,
                Url = _url,
                Children = _childNodeBuilder == null ? Enumerable.Empty<NavPanelNode>() : _childNodeBuilder.GenerateNodeHierachy(webContext, userContext),
                IsSelected = _urlMatchPattern.Any(pattern => webContext.MatchesPath(pattern)),
                IconUrl = _iconUrl
            };
   }

还有我的MatchesPath 方法:

    public static bool MatchesPath(this IWebContext webContext, System.Text.RegularExpressions.Regex matchPattern)
    {
        string appRelativePath = webContext.CurrentRequestContext.GetAppRelativePath();
        return matchPattern.IsMatch(appRelativePath);
    }

如前所述,我们的匹配逻辑是通过正则表达式实现的。 当然,如果您要让这个最终用户可配置,您将不得不让他们配置匹配逻辑。我不知道您将如何做到这一点 - 这取决于您正在创建的用户界面。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-20
    • 1970-01-01
    • 2021-10-08
    • 2020-02-18
    • 1970-01-01
    相关资源
    最近更新 更多