关键词:
【中文标题】如何获取 ASP.NET Core 中所有路由的列表?【英文标题】:How to get a list of all routes in ASP.NET Core? 【发布时间】:2015-04-10 17:24:11 【问题描述】:在 ASP.NET Core 中,有没有办法查看 Startup 中定义的所有路由的列表?我们使用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 = ???
【问题讨论】:
【参考方案1】:要获取所有路由,您需要使用 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
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>();
【讨论】:
我希望我能投票 100 次。在 AspNetCore 中很难找到有关 ApiExplorer 的文档,而且微软在 github 上的示例都已过时。谢谢! 为了清楚起见,这也是在 MVC 5 中使用全局RouteTable.Routes
的替代品吗?仅仅为了枚举应用程序的路由列表,这似乎是一件非常困难的事情。特别是因为路由很容易在启动代码中连续添加。
恐怕这是 .NET 团队的问题。这是一年前推荐给我的方法。
var apiDescription = actionGroup.First().Items;
使 apiDescription
类型为 IReadOnlyList<ApiDescription>
,因此 apiDescription.RelativePath
无效。
这是如何获取所有路由的?看起来这只是获取当前请求的路由。【参考方案2】:
如果您使用的是 ASP.NET Core 3.0+,这意味着您使用的是endpoint routing,那么您可以使用EndpointDataSource
s 列出所有路由。
将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
,
]
【讨论】:
非常简单又不错的解决方案! 谢谢!这个对我有用。我将方法的信号从public async Task<ActionResult> ListAllEndpoints()
更改为public IActionResult ListAllEndpoints()
为什么注入IEnumerable<EndpointDataSource>
而不仅仅是EndpointDataSource
? DI 容器(.Net 5/6)中只有一个EndpointDataSource
注册。
@Granger 是的。但 ASP.NET Core 旨在支持多个端点源。例如,您/一个库可以提供从数据库或上游服务生成端点的另一个源。使用IEnumerable<EndpointDataSource>
注入所有实现会更安全。见source.dot.net/#Microsoft.AspNetCore.Routing/…【参考方案3】:
你可以看看这个很棒的 GitHub 项目:
https://github.com/kobake/AspNetCore.RouteAnalyzer
项目自述文件
=========================
AspNetCore.RouteAnalyzer
查看 ASP.NET Core 项目的所有路由信息。
截取的截图
在您的 ASP.NET Core 项目中的使用
安装 NuGet 包
NuGet Gallery | AspNetCore.RouteAnalyzerPM> Install-Package AspNetCore.RouteAnalyzer
编辑 Startup.cs
在 Startup.cs 中插入代码 services.AddRouteAnalyzer();
和所需的 using
指令,如下所示。
using AspNetCore.RouteAnalyzer; // Add
public void ConfigureServices(IServiceCollection services)
services.AddMvc();
services.AddRouteAnalyzer(); // Add
案例1:在浏览器上查看路由信息
在 Startup.cs 中插入代码routes.MapRouteAnalyzer("/routes");
,如下所示。
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
....
app.UseMvc(routes =>
routes.MapRouteAnalyzer("/routes"); // Add
routes.MapRoute(
name: "default",
template: "controller/action=Index/id?");
);
然后你可以访问http://..../routes
的url,在你的浏览器上查看所有的路由信息。 (此网址/routes
可通过MapRouteAnalyzer()
自定义。)
案例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输出面板查看所有路由信息了。
【讨论】:
aspnet core 2.2 存在一个问题,您需要使用services.AddMvc(options => options.EnableEndpointRouting = false; );
禁用options.EnableEndpointRouting
。该项目似乎还可以,但不明白您是否有自定义路由属性。【参考方案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 preview 完成的,但我认为它应该适用于 dotnetcore 2.2。此外,以这种方式获取 url 将考虑任何已实施的约定,包括 Scott Hanselman's Blog
【讨论】:
这是我的首选解决方案。我首先尝试了 abdusco 的答案,效果很好,但由于具有内部构造函数的密封类(即没有 CreateInstance 恶作剧),我无法进行单元测试。模拟 IActionDescriptorCollectionProvider.ActionDescriptors 属性要简单得多。【参考方案5】:您可以通过以下方式从 HttpActionContext 获取 HttpRouteCollection:
actionContext.RequestContext.Configuration.Routes
RequestContext
HttpConfiguration
HttpRouteCollection
-- 问题更新后--
ActionExecutingContext 有一个从 ControllerContext 继承的 RouteData 属性,它公开了 DataTokens 属性(这是一个路由值字典)。它可能与您习惯使用的集合不同,但它确实提供了对该集合的访问:
actionContext.RouteData.DataTokens
DataTokens
【讨论】:
好的 - 在我的情况下这是一个空字典。 RouteData 似乎保存与当前路线有关的数据,而不是所有路线的列表。actionContext.RequestContext.Configuration.Routes
不存在了。【参考方案6】:
使用 iApplicationBuilder 'app' 对象,我编写了这个简单的代码 sn-p,您可以将其添加到 Startup 类中的 Configure 方法的末尾. 它应该检索(至少在 ASP.NET Core 3.1 中)可用的注册路由。它将它们存储到“theRoutes”列表中,您可以简单地在调试会话中进行检查(就像我所做的那样,因为这对我来说已经足够了),或者您可以记录它,等等。
// Put this code at the end of 'Configure' method in 'Startup' class (ASP.Net Core 3.1)
var theRoutes = new List<string>();
var v1 = app.Properties["__EndpointRouteBuilder"];
var v2 = (System.Collections.Generic.List<Microsoft.AspNetCore.Routing.EndpointDataSource>)(v1.GetType().GetProperty("DataSources").GetValue(v1, null));
foreach (var v3 in v2)
foreach (var v4 in v3.Endpoints)
var v5 = (Microsoft.AspNetCore.Routing.Patterns.RoutePattern) (v4.GetType().GetProperty("RoutePattern").GetValue(v4, null));
theRoutes.Add(v5.RawText);
【讨论】:
【参考方案7】:这仅对调试有用:
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 将包含路由和类型的字符串数组。
【讨论】:
如何使用 ASP.NET Core 获取当前路由名称?
】如何使用ASP.NETCore获取当前路由名称?【英文标题】:HowcanIgetthecurrentroutenamewithASP.NETCore?【发布时间】:2019-11-2302:59:35【问题描述】:我有一个基于ASP.NETCore2.2框架编写的应用程序。我有以下控制器publicclassTestController:Controller[R... 查看详情
ASP.Net Core 2.0 如何获取中间件中的所有请求标头? [复制]
】ASP.NetCore2.0如何获取中间件中的所有请求标头?[复制]【英文标题】:ASP.NetCore2.0Howtogetallrequestheadersinmiddleware?[duplicate]【发布时间】:2018-08-2418:06:34【问题描述】:在ASP.NetCore2.0中,我尝试在自定义中间件中验证传入的请求标头... 查看详情
如何在 ASP.NET Core 中强制执行小写路由?
】如何在ASP.NETCore中强制执行小写路由?【英文标题】:HowdoyouenforcelowercaseroutinginASP.NETCore?【发布时间】:2016-07-2109:40:38【问题描述】:在ASP.NET4中,这与应用程序的RegisterRoutes处理程序中的routes.LowercaseUrls=true;一样简单。我在ASP.... 查看详情
获取 ASP .Net Core WebAPI 中的所有身份角色
】获取ASP.NetCoreWebAPI中的所有身份角色【英文标题】:GetallIdentityrolesinASP.NetCoreWebAPI【发布时间】:2021-10-1002:54:22【问题描述】:我的任务是获取数据库中的所有身份角色。我使用下面的代码来获取所有角色。在Asp.Net核心WebAPI中U... 查看详情
如何在 ASP.NET Core 2.0 中根据路由配置服务身份验证
】如何在ASP.NETCore2.0中根据路由配置服务身份验证【英文标题】:HowtoConfigureServicesAuthenticationbasedonroutesinASP.NETCore2.0【发布时间】:2018-03-0922:06:40【问题描述】:在ASP.NETCore1.x中,我可以在Configure中使用身份验证方法,但现在在ASP... 查看详情
如何覆盖 .ASP.NET Core 5 中的路由?
】如何覆盖.ASP.NETCore5中的路由?【英文标题】:Howtooverrideroutein.ASP.NETCore5?【发布时间】:2021-06-2301:34:35【问题描述】:我想在ASP.NETCore5中覆盖路由我试过这个,但它不起作用varlastExistingRoute=routeBuilder.Routes.FirstOrDefault(x=>((Route)... 查看详情
如何在 ASP.NET Core API 控制器中获取多个表的记录
】如何在ASP.NETCoreAPI控制器中获取多个表的记录【英文标题】:HowtofetchrecordofmorethanonetableinASP.NETCoreAPIController【发布时间】:2020-06-2901:17:57【问题描述】:我想从数据库中获取3个表,只是从3个表中获取所有值。这个api在销售控... 查看详情
如何在 ocelot.json 路由 asp.net core 中发布 json body
】如何在ocelot.json路由asp.netcore中发布jsonbody【英文标题】:Howpostjsonbodyinocelot.jsonrouteasp.netcore【发布时间】:2021-09-0311:57:44【问题描述】:"DownstreamPathTemplate":"/ProceedToBuy/PostWishList","DownstreamScheme":"http","DownstreamHostAnd 查看详情
在 ASP.NET Core 3.x Endpoints 路由中,如何指定域名?
】在ASP.NETCore3.xEndpoints路由中,如何指定域名?【英文标题】:InASP.NETCore3.xEndpointsrouting,howtospecifydomainname?【发布时间】:2020-08-0705:22:20【问题描述】:我希望能够根据URL的域名路由到不同的控制器。比如当请求的URL是www.domain1.co... 查看详情
如何在asp.net core中获取当前用户
】如何在asp.netcore中获取当前用户【英文标题】:Howtogetcurrentuserinasp.netcore【发布时间】:2016-08-0702:00:32【问题描述】:我想获取当前用户,以便访问他们的电子邮件地址等字段。但我不能在asp.net核心中做到这一点。这是我的代... 查看详情
ASP.Net Core 如何在 EF Core 和 Identity 中获取用户角色
】ASP.NetCore如何在EFCore和Identity中获取用户角色【英文标题】:ASP.NetCorehowtogettheuserroleinEFCoreandIdentity【发布时间】:2018-01-0814:25:00【问题描述】:您好,我正在使用Identity和自定义用户类和EFCore构建API。我想获取属于用户的角色... 查看详情
如何在 ASP.NET Core 中获取 HttpContext.Current? [复制]
】如何在ASP.NETCore中获取HttpContext.Current?[复制]【英文标题】:HowtogetHttpContext.CurrentinASP.NETCore?[duplicate]【发布时间】:2016-11-2823:44:31【问题描述】:我们目前正在使用ASP.NETCore重写/转换我们的ASP.NETWebForms应用程序。尽量避免重新... 查看详情
ASP.NET Core 3.1 - 如何获取客户端的 IP 地址?
】ASP.NETCore3.1-如何获取客户端的IP地址?【英文标题】:ASP.NETCore3.1-HowdoIgetaclient\'sIPAddress?【发布时间】:2020-05-1609:44:32【问题描述】:我有一个Razor页面Web应用程序并正在记录用户的IP地址。出于某种原因,它返回的是IP地址,... 查看详情
如何在 ASP.NET Core MVC 中获取 Url Referrer?
】如何在ASP.NETCoreMVC中获取UrlReferrer?【英文标题】:HowcanIgetUrlReferrerinASP.NETCoreMVC?【发布时间】:2016-08-0416:08:21【问题描述】:我正在尝试将ASP.NETMVC网络表单迁移到ASP.NETCoreMVC。目前,我在使用Request.UrlReferrer课程时遇到了问题... 查看详情
如何在 ASP.NET Core 中获取我网站的 baseurl?
】如何在ASP.NETCore中获取我网站的baseurl?【英文标题】:HowcanIgetthebaseurlofmysiteinASP.NETCore?【发布时间】:2017-04-2017:56:06【问题描述】:假设我的网站托管在www.example.com的mywebsite文件夹中,我访问了https://www.example.com/mywebsite/home/abo... 查看详情
如何在 Asp.net Core 中获取用户浏览器名称(用户代理)?
】如何在Asp.netCore中获取用户浏览器名称(用户代理)?【英文标题】:HowtogetuserBrowsername(user-agent)inAsp.netCore?【发布时间】:2015-04-2405:52:15【问题描述】:能否告诉我如何获取客户端在MVC6、ASP.NET5中使用的浏览器名称?【问题讨... 查看详情
如何从 ASP.NET Core 的 Main() 中获取环境变量?
】如何从ASP.NETCore的Main()中获取环境变量?【英文标题】:HowtogetenvironmentvariablesfrominsideMain()inASP.NETCore?【发布时间】:2020-06-2618:56:18【问题描述】:我想知道代码是否是Dev/Stage,所以我需要得到它。我尝试了下面的代码,但它似... 查看详情
如何在 ASP.NET CORE 3.1 中获取客户端 IP 地址?
】如何在ASP.NETCORE3.1中获取客户端IP地址?【英文标题】:HowdoIgetclientIPaddressinASP.NETCORE3.1?【发布时间】:2020-04-2921:06:39【问题描述】:在WebAPI项目中编写代码时如何在ASP.NET3.1中获取客户端IP地址【问题讨论】:这能回答你的问题... 查看详情