Подтвердить что ты не робот

Получить список всех маршрутов

В ASP.NET Core, есть ли способ увидеть список всех маршрутов, определенных в Startup? Мы используем метод расширения MapRoute для IRouteBuilder для определения маршрутов.

Мы переносим старый проект WebAPI проекта. Там мы могли бы использовать GlobalConfiguration.Configuration.Routes для получения всех маршрутов.

В частности, мы делаем это в рамках фильтра действий.

public class MyFilter : ActionFilterAttribute
{      
    public override void OnActionExecuting(ActionExecutingContext actionContext)
    {
        base.OnActionExecuting(actionContext);

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

        // var allRoutes = ???
    }
}
4b9b3361

Ответ 1

Чтобы добраться на всех маршрутах, вам нужно использовать часть ApiExplorer MVC. Вы можете либо отметить все свои действия атрибутом, либо использовать соглашение, подобное этому:

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(...)

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc(
        options => 
        {
            options.Conventions.Add(new ApiExplorerVisibilityEnabledConvention());
            options.
        }
}

В ActionFilter вы можете использовать инсталляцию конструктора для получения ApiExplorer:

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

ApiDescription, который имеет RelativePath, который является шаблоном маршрута для этого маршрута:

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

Ответ 2

Вы можете взглянуть на этот удивительный проект GitHub:

https://github.com/kobake/AspNetCore.RouteAnalyzer

Readme из проекта

=======================

AspNetCore.RouteAnalyzer

Просмотр всей информации о маршруте для проекта ASP.NET Core.

Снятый скриншот

screenshot

Использование в вашем основном проекте ASP.NET

Установить пакет NuGet

PM> Install-Package AspNetCore.RouteAnalyzer

Изменить Startup.cs

Вставьте код services.AddRouteAnalyzer(); и требуемую директиву using в файл Startup.cs следующим образом.

'' 'CS использование AspNetCore.RouteAnalyzer;//Добавить

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();
    services.AddRouteAnalyzer(); // Add
}

Case1: просмотр информации о маршруте в браузере

Вставьте код routes.MapRouteAnalyzer("/routes"); в файл Startup.cs следующим образом.

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    ....
    app.UseMvc(routes =>
    {
        routes.MapRouteAnalyzer("/routes"); // Add
        routes.MapRoute(
            name: "default",
            template: "{controller}/{action=Index}/{id?}");
    });
}

Затем вы можете получить доступ к URL-адресу http://..../routes, чтобы просмотреть всю информацию о маршруте в вашем браузере. (Этот URL /routes можно настроить с помощью MapRouteAnalyzer().)

screenshot

Случай 2: Печать маршрутов на панели вывода VS

Вставьте блок кода, как показано ниже, в Startup.cs.

public void Configure(
    IApplicationBuilder app,
    IHostingEnvironment env,
    IApplicationLifetime applicationLifetime, // Add
    IRouteAnalyzer routeAnalyzer // Add
)
{
    ...

    // Add this block
    applicationLifetime.ApplicationStarted.Register(() =>
    {
        var infos = routeAnalyzer.GetAllRouteInformations();
        Debug.WriteLine("======== ALL ROUTE INFORMATION ========");
        foreach (var info in infos)
        {
            Debug.WriteLine(info.ToString());
        }
        Debug.WriteLine("");
        Debug.WriteLine("");
    });
}

Затем вы можете просмотреть всю информацию о маршруте на панели вывода VS.

screenshot

Ответ 3

Вы можете получить HttpRouteCollection из HttpActionContext с помощью:

actionContext.RequestContext.Configuration.Routes

RequestContext

HttpConfiguration

HttpRouteCollection

- После обновления вопроса -

ActionExecutingContext имеет свойство RouteData, которое он наследует от ControllerContext, который предоставляет свойство DataTokens (которое является словарем значения маршрута). Это, вероятно, не та же коллекция, с которой вы привыкли работать, но она обеспечивает доступ к этой коллекции:

actionContext.RouteData.DataTokens

DataTokens

Ответ 4

Не удалось выполнить вышесказанное, так как я хотел получить полный URL-адрес, который мне не нужно было возиться с вещами для создания URL-адреса, но вместо этого позволил платформе обработать разрешение. Поэтому, следуя AspNetCore.RouteAnalyzer и бесчисленному поиску и поиску, я не нашел однозначного ответа.

Следующее работает для меня типичный домашний контроллер и контроллер области:

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

Это выведет следующее в моем простом решении:

/
/Home/Error
/RouteInfo
/RouteInfo/Links
/Area51/SecureArea

Выше было сделано с использованием предварительного просмотра dotnetcore 3, но я думаю, что он должен работать с dotnetcore 2.2. Кроме того, при получении URL-адреса таким образом будут учитываться все принятые соглашения, в том числе отличное описание, как было показано на блоге Скотта Хансельмана.

Ответ 5

Это полезно только для отладки:

var routes = System.Web.Http.GlobalConfiguration.Configuration.Routes;
var field = routes.GetType().GetField("_routeCollection", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
var collection = field.GetValue(routes) as System.Web.Routing.RouteCollection;
var routeList = collection
    .OfType<IEnumerable<System.Web.Routing.RouteBase>>()
    .SelectMany(c => c)
    .Cast<System.Web.Routing.Route>()
    .Concat(collection.OfType<System.Web.Routing.Route>())
    .Select(r => $"{r.Url} ({ r.GetType().Name})")
    .OrderBy(r => r)
    .ToArray();

routeList будет содержать строковый массив маршрутов и типов.