更新(2021 年 1 月 24 日)
有一种更简单的方法可以直接通过HttpContext 检索RoutePattern。
FilterContext filterContext;
var endpoint = filterContext.HttpContext.GetEndpoint() as RouteEndpoint;
var template = endpoint?.RoutePattern?.RawText;
if (template is null)
throw new Exception("No route template found, that's absurd");
Console.WriteLine(template);
GetEndpoint()是EndpointHttpContextExtensions类在Microsoft.AspNetCore.Http命名空间中提供的扩展方法
旧答案(工作量太大)
一个 ASP.NET Core 应用程序(至少对于 3.1)的所有路由构建器都是通过 IEndpointRouteBuilder 公开和注册的,但不幸的是,这没有在 DI 容器中注册,因此您无法直接获取它。我看到这个接口暴露的唯一地方是中间件。
因此,您可以使用其中一个中间件构建集合或字典,然后将其用于您的目的。
例如
程序.cs
扩展类来构建你的端点集合/字典
internal static class IEndpointRouteBuilderExtensions
{
internal static void BuildMap(this IEndpointRouteBuilder endpoints)
{
foreach (var item in endpoints.DataSources)
foreach (RouteEndpoint endpoint in item.Endpoints)
{
/* This is needed for controllers with overloaded actions
* Use the RoutePattern.Parameters here
* to generate a unique display name for the route
* instead of this list hack
*/
if (Program.RouteTemplateMap.TryGetValue(endpoint.DisplayName, out var overloadedRoutes))
overloadedRoutes.Add(endpoint.RoutePattern.RawText);
else
Program.RouteTemplateMap.Add(endpoint.DisplayName, new List<string>() { endpoint.RoutePattern.RawText });
}
}
}
public class Program
{
internal static readonly Dictionary<string, List<string>> RouteTemplateMap = new Dictionary<string, List<string>>();
/* Rest of things */
}
Startup.cs
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
/* all other middlewares */
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
//Use this at the last middlware exposing IEndpointRouteBuilder so that all the routes are built by this point
endpoints.BuildMap();
});
}
然后您可以使用该字典或集合,从 FilterContext 中检索路由模板。
FilterContext filterContext;
Program.RouteTemplateMap.TryGetValue(filterContext.ActionDescriptor.DisplayName, out var template);
if (template is null)
throw new Exception("No route template found, that's absurd");
/* Use the ActionDescriptor.Parameters here
* to figure out which overloaded action was called exactly */
Console.WriteLine(string.Join('\n', template));
为了解决重载动作的情况,路由模板使用字符串列表(而不仅仅是字典中的字符串)
您可以将ActionDescriptor.Parameters 与RoutePattern.Parameters 结合使用,为该路线生成唯一的显示名称。