在ASP.NET核心中,有没有办法查看在启动中定义的所有路由的列表?我们使用IRouteBuilder
的MapRoute
扩展方法来定义路由。
我们正在迁移一个较旧的项目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 = ???
}
}
发布于 2016-03-02 22:40:36
要获取所有路由,您需要使用MVC的ApiExplorer部分。您可以使用属性标记所有操作,也可以使用如下约定:
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
}
}
包含RelativePath
的ApiDescription
,它是该路由的路由模板:
// 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>();
}
}
发布于 2021-02-07 18:06:16
如果您正在使用ASP.NET核心3.0+,这意味着您正在使用endpoint routing,那么您可以使用EndpointDataSource
列出所有路由。
将IEnumerable<EndpointDataSource>
注入您的控制器/端点,然后提取所需的任何内容。它既可以与控制器操作、端点一起使用,也可以部分与razor页面一起使用(razor页面似乎不会公开可用的HTTP方法)。
[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格式的路由列表:
[
{
"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
},
]
发布于 2019-03-09 06:25:19
上面的不成功,因为我想要一个完整的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将考虑到已经实施的任何约定,包括在Scott Hanselman's Blog上公开的出色的slugify。
https://stackoverflow.com/questions/28435734
复制相似问题