首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何获取ASP.NET核心中所有路由的列表?

如何获取ASP.NET核心中所有路由的列表?
EN

Stack Overflow用户
提问于 2015-02-10 23:42:59
回答 5查看 28.9K关注 0票数 32

在ASP.NET核心中,有没有办法查看在启动中定义的所有路由的列表?我们使用IRouteBuilderMapRoute扩展方法来定义路由。

我们正在迁移一个较旧的项目WebAPI项目。在那里,我们可以使用GlobalConfiguration.Configuration.Routes来获取所有路由。

更具体地说,我们在操作过滤器中执行此操作。

代码语言:javascript
复制
public class MyFilter : ActionFilterAttribute
{      
    public override void OnActionExecuting(ActionExecutingContext actionContext)
    {
        base.OnActionExecuting(actionContext);

        // This no longer works
        // var allRoutes = GlobalConfiguration.Configuration.Routes;

        // var allRoutes = ???
    }
}
EN

回答 5

Stack Overflow用户

发布于 2016-03-02 22:40:36

要获取所有路由,您需要使用MVC的ApiExplorer部分。您可以使用属性标记所有操作,也可以使用如下约定:

代码语言:javascript
复制
public class ApiExplorerVisibilityEnabledConvention : IApplicationModelConvention
{
    public void Apply(ApplicationModel application)
    {
        foreach (var controller in application.Controllers)
        {
            if (controller.ApiExplorer.IsVisible == null)
            {
                controller.ApiExplorer.IsVisible = true;
                controller.ApiExplorer.GroupName = controller.ControllerName;
            }
        }
    }
}

在Startup.cs中,在ConfigureServices(...)中添加新的

代码语言:javascript
复制
public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc(
        options => 
        {
            options.Conventions.Add(new ApiExplorerVisibilityEnabledConvention());
            options.
        }
}

在您的ActionFilter中,您可以使用构造函数注入来获取ApiExplorer:

代码语言:javascript
复制
public class MyFilter : ActionFilterAttribute
{      
    private readonly IApiDescriptionGroupCollectionProvider descriptionProvider;

    public MyFilter(IApiDescriptionGroupCollectionProvider descriptionProvider) 
    {
        this.descriptionProvider = descriptionProvider;
    }

    public override void OnActionExecuting(ActionExecutingContext actionContext)
    {
        base.OnActionExecuting(actionContext);

        // The convention groups all actions for a controller into a description group
        var actionGroups = descriptionProvider.ApiDescriptionGroups.Items;

        // All the actions in the controller are given by
        var apiDescription = actionGroup.First().Items.First();

        // A route template for this action is
        var routeTemplate = apiDescription.RelativePath
    }
}

包含RelativePathApiDescription,它是该路由的路由模板:

代码语言:javascript
复制
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;
using System.Collections.Generic;
using Microsoft.AspNetCore.Mvc.Abstractions;
using Microsoft.AspNetCore.Mvc.ModelBinding;

namespace Microsoft.AspNetCore.Mvc.ApiExplorer
{
    public class ApiDescription
    {
        public string GroupName { get; set; }
        public string HttpMethod { get; set; }
        public IList<ApiParameterDescription> ParameterDescriptions { get; } = new List<ApiParameterDescription>();
        public IDictionary<object, object> Properties { get; } = new Dictionary<object, object>();
        public string RelativePath { get; set; }
        public ModelMetadata ResponseModelMetadata { get; set; }
        public Type ResponseType { get; set; }
        public IList<ApiRequestFormat> SupportedRequestFormats { get; } = new List<ApiRequestFormat>();
        public IList<ApiResponseFormat> SupportedResponseFormats { get; } = new List<ApiResponseFormat>();
    }
}
票数 28
EN

Stack Overflow用户

发布于 2021-02-07 18:06:16

如果您正在使用ASP.NET核心3.0+,这意味着您正在使用endpoint routing,那么您可以使用EndpointDataSource列出所有路由。

IEnumerable<EndpointDataSource>注入您的控制器/端点,然后提取所需的任何内容。它既可以与控制器操作、端点一起使用,也可以部分与razor页面一起使用(razor页面似乎不会公开可用的HTTP方法)。

代码语言:javascript
复制
[Route("/-/{controller}")]
public class InfoController : Controller
{
    private readonly IEnumerable<EndpointDataSource> _endpointSources;

    public InfoController(
        IEnumerable<EndpointDataSource> endpointSources
    )
    {
        _endpointSources = endpointSources;
    }

    [HttpGet("endpoints")]
    public async Task<ActionResult> ListAllEndpoints()
    {
        var endpoints = _endpointSources
            .SelectMany(es => es.Endpoints)
            .OfType<RouteEndpoint>();
        var output = endpoints.Select(
            e =>
            {
                var controller = e.Metadata
                    .OfType<ControllerActionDescriptor>()
                    .FirstOrDefault();
                var action = controller != null
                    ? $"{controller.ControllerName}.{controller.ActionName}"
                    : null;
                var controllerMethod = controller != null
                    ? $"{controller.ControllerTypeInfo.FullName}:{controller.MethodInfo.Name}"
                    : null;
                return new
                {
                    Method = e.Metadata.OfType<HttpMethodMetadata>().FirstOrDefault()?.HttpMethods?[0],
                    Route = $"/{e.RoutePattern.RawText.TrimStart('/')}",
                    Action = action,
                    ControllerMethod = controllerMethod
                };
            }
        );
        
        return Json(output);
    }
}

当你访问/-/info/endpoints时,你会得到一个JSON格式的路由列表:

代码语言:javascript
复制
[
  {
    "method": "GET",
    "route": "/-/info/endpoints", // <-- controller action
    "action": "Info.ListAllEndpoints",
    "controllerMethod": "Playground.Controllers.InfoController:ListAllEndpoints"
  },
  {
    "method": "GET",
    "route": "/WeatherForecast", // <-- controller action
    "action": "WeatherForecast.Get",
    "controllerMethod": "Playground.Controllers.WeatherForecastController:Get"
  },
  {
    "method": "GET",
    "route": "/hello", // <-- endpoint route
    "action": null,
    "controllerMethod": null
  },
  {
    "method": null,
    "route": "/about", // <-- razor page
    "action": null,
    "controllerMethod": null
  },
]
票数 17
EN

Stack Overflow用户

发布于 2019-03-09 06:25:19

上面的不成功,因为我想要一个完整的url,我不必纠结于构建url的东西,而是让框架来处理解析。因此,从AspNetCore.RouteAnalyzer和无数的谷歌和搜索,我没有找到一个明确的答案。

以下内容适用于典型的家庭控制器和区域控制器:

代码语言:javascript
复制
public class RouteInfoController : Controller
{
    // for accessing conventional routes...
    private readonly IActionDescriptorCollectionProvider _actionDescriptorCollectionProvider;

    public RouteInfoController(
        IActionDescriptorCollectionProvider actionDescriptorCollectionProvider)
    {
        _actionDescriptorCollectionProvider = actionDescriptorCollectionProvider;
    }

    public IActionResult Index()
    {
        StringBuilder sb = new StringBuilder();

        foreach (ActionDescriptor ad in _actionDescriptorCollectionProvider.ActionDescriptors.Items)
        {
            var action = Url.Action(new UrlActionContext()
            {
                Action = ad.RouteValues["action"],
                Controller = ad.RouteValues["controller"],
                Values = ad.RouteValues
            });

            sb.AppendLine(action).AppendLine().AppendLine();
        }

        return Ok(sb.ToString());
    }

这将在我的简单解决方案中输出以下内容:

代码语言:javascript
复制
/
/Home/Error
/RouteInfo
/RouteInfo/Links
/Area51/SecureArea

上面的工作是使用dotnetcore 3预览版完成的,但我认为它应该适用于dotnetcore 2.2。此外,以这种方式获得url将考虑到已经实施的任何约定,包括在Scott Hanselman's Blog上公开的出色的slugify。

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28435734

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档