【问题标题】:How to make dynamic Url with specific Action and Controller in Asp.Net Core MVC controller?如何在 Asp.Net Core MVC 控制器中使用特定的 Action 和 Controller 制作动态 Url?
【发布时间】:2020-08-17 17:09:08
【问题描述】:

我想动态生成导航菜单,该菜单遵循我的应用程序的默认路由以及特定的操作和控制器。 我在 MVC5 中发现了它,但我不知道如何在 .Net Core MVC 应用程序中做同样的事情。

我在 MVC5 中的尝试如下:

查看模型:

public class MenuViewModel
{
    // other props
    public string Link
    {
        get
        {
            UrlHelper url = new UrlHelper(HttpContext.Current.Request.RequestContext);
            return url.Action(this.Action != null ? this.Action : "StaticPage", this.Controller != null ? this.Controller : "StaticPage", new { pageName = this.PageTitle });
        }
    }
}

Global.asax:

public static List<MenuViewModel> SetMenuHeads()
{
    return
        General.DataModel.Menus
        .Where(m => m.IsHead)
        .Select(MenuViewModel.Set)
        .ToList();
}

General.cs:

public static string SubMenuGenerator(MenuViewModel menu)
{
    string subMenus = "";

    var subMenusList =
        DataModel.Menus
        .Where(m => m.ParentId == menu.ID)
        .Select(MenuViewModel.Set)
        .ToList();

    if (subMenusList.Count == 0)
        subMenus += "<li><a href=\"" + menu.Link + "\" class=\"external\"><span>" + menu.RenderTitle + "</span></a></li>";
    else
    {
        subMenus += "<li><a href=\"#\" class=\"external\"><span>" + menu.Title + "</span></a>";
        subMenus += "<ul>";
        foreach (var mnu in subMenusList)
        {
            subMenus += SubMenuGenerator(mnu);
        }
        subMenus += "</ul>";
        subMenus += "</li>";
    }

    return subMenus;
}

_Layout.cshtml:

<nav id="main-nav">
    <ul id="main-menu" class="sm-clean">
        <li><a href="@Url.Action("Index", "Home")" class="external"><span>Home</span></a></li>
        @{
            string menu = "";
            foreach (var menuItem in global_asax.SetMenuHeads())
            {
                menu += General.SubMenuGenerator(menuItem);
            }
        }
        
        @Html.Raw(menu)
    </ul>
</nav>

现在我想尝试在 .net 核心中做同样的事情,但在 .net 核心中没有像 HttpContext.Current.Request.RequestContext 这样的类来使用其操作和控制器创建一个 url。

有什么想法吗?

【问题讨论】:

标签: c# asp.net-core model-view-controller asp.net-core-mvc


【解决方案1】:

在core中,可以通过IActionDescriptorCollectionProvider获取所有路径。

如果想让所有路由都变成导航栏,那么需要在核心项目的startup添加一个自定义中间件,将对应的html传递给_layout页面.

这是完整的例子:

自定义中间件:

  public class GetRoutingMiddleware
    {
        private readonly RequestDelegate _next;
        private readonly IActionDescriptorCollectionProvider _actionDescriptorCollectionProvider;
        public GetRoutingMiddleware(RequestDelegate next, IActionDescriptorCollectionProvider actionDescriptorCollectionProvider)
        {
            _next = next;
            _actionDescriptorCollectionProvider = actionDescriptorCollectionProvider;
        }

        public async Task InvokeAsync(HttpContext context)
        {
             
            var allMenuList = _actionDescriptorCollectionProvider.ActionDescriptors.Items.Select(x => new
            {
                Action = x.RouteValues["Action"],
                Controller = x.RouteValues["Controller"],
                Name = x.AttributeRouteInfo != null ? x.AttributeRouteInfo.Name : "",
                Template = x.AttributeRouteInfo != null ? x.AttributeRouteInfo.Template : x.RouteValues["Controller"] + "/" + x.RouteValues["Action"],
            }).ToList(); 

            var menu = allMenuList.GroupBy(x => x.Controller).ToList();
            var subMenus = "";
            foreach (var subMenuList in menu)
            {
                if (subMenuList.Count() > 0)
                {
                    subMenus += "<li class=\"nav-item dropdown\"><a href=\"#\" class=\"nav-link dropdown-toggle\" role=\"button\" data-toggle=\"dropdown\" aria-haspopup=\"true\" aria-expanded=\"false\"><span>" + subMenuList.Key + "</span></a>";
                    subMenus += "<div class=\"dropdown-menu\" arialabelledby=\"navbarDropdown\">";
                    foreach (var mnu in subMenuList)
                    {
                        subMenus += "<a class=\"dropdown-item\" href=\"/" + mnu.Template + "\">" + mnu.Action + "</a>";
                    }
                    subMenus += "</div>";
                    subMenus += "</li>";
                }
                else
                {
                    subMenus += "<li class=\"nav-item\"><a href=\"/" + subMenuList.FirstOrDefault().Template + "\" class=\"nav-link\"><span>" + subMenuList.Key + "</span></a></li>";
                }
            }
            context.Items.Add("routeMenu", subMenus);
            await _next.Invoke(context); 
        } 
    }

将此中间件添加到配置方法:

   public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            //...

            app.UseStaticFiles();

            app.UseMiddleware<GetRoutingMiddleware>(); 

            app.UseRouting();

            //....

        }

在_Layout.cshtml中:

@{
    var menus = Context.Items["routeMenu"];
}

 <nav class="navbar navbar-expand-lg navbar-light bg-light">
            <div class="collapse navbar-collapse" id="navbarSupportedContent">
                <ul class="navbar-nav mr-auto">
                    @Html.Raw(menus)
                </ul>
            </div>
        </nav>

我对样式做了一些修改,大家可以根据自己的需要进行修改。

这是测试结果:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-02-17
    • 1970-01-01
    • 2011-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多