Получить список всех маршрутов
В 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 = ???
}
}
Ответы
Ответ 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 будет содержать строковый массив маршрутов и типов.