如何在Asp.Net Core MVC控制器中使用特定的动作和控制器创建动态网址?

问题描述

我想动态生成导航菜单,该菜单遵循具有特定操作和控制器的应用程序的认路由。 我在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。

有什么主意吗?

解决方法

在核心中,您可以通过 IActionDescriptorCollectionProvider 获取所有路径。

如果要将所有路由都放入导航栏中,则需要向核心项目的startup添加自定义中间件,以将相应的html传递给{{ 1}}页。

这是完整的示例:

自定义中间件:

_layout

将此中间件添加到Configure方法:

  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); 
        } 
    }

在_Layout.cshtml中:

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

            app.UseStaticFiles();

            app.UseMiddleware<GetRoutingMiddleware>(); 

            app.UseRouting();

            //....

        }

我对样式进行了一些更改,您可以根据需要进行更改。

这是测试结果:

enter image description here