Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get a list of all routes in ASP.NET Core?

In ASP.NET Core, is there a way to see a list of all the routes defined in Startup? We are using the MapRoute extension method of IRouteBuilder to define the routes.

We are migrating an older project WebAPI project. There we could use GlobalConfiguration.Configuration.Routes to get all the routes.

More specifically, we are doing this within an action filter.

public class MyFilter : ActionFilterAttribute {           public override void OnActionExecuting(ActionExecutingContext actionContext)     {         base.OnActionExecuting(actionContext);          // This no longer works         // var allRoutes = GlobalConfiguration.Configuration.Routes;          // var allRoutes = ???     } } 
like image 767
clhereistian Avatar asked Feb 10 '15 15:02

clhereistian


People also ask

What is App UseRouting ()?

UseRouting adds route matching to the middleware pipeline. This middleware looks at the set of endpoints defined in the app, and selects the best match based on the request. UseEndpoints adds endpoint execution to the middleware pipeline. It runs the delegate associated with the selected endpoint.

What is routing and how can you define routes in ASP.NET Core?

In ASP.NET, routing is the process of directing the HTTP requests to the right controller. The MVC middleware must decide whether a request should go to the controller for processing or not. The middleware makes this decision based on the URL and some configuration information.

How many routes can be defined in MVC?

Every ASP.NET MVC application must configure (register) at least one route in the RouteConfig class and by default, the ASP.NET MVC Framework provides one default route. But you can configure as many routes as you want.

What is route in core in asp net?

Inside the call to UseEndpoints() , we use the MapControllerRoute() method to create a route by giving the name default . MVC configures the default route template as {controller=Home}/{action=Index}/{id?} . This will match the Index() method in HomeController with an optional parameter id by default.


2 Answers

If you're on ASP.NET Core 3.0+, that means you're using endpoint routing, then you can list all routes with EndpointDataSources.

Inject IEnumerable<EndpointDataSource> to your controller/endpoint then extract anything you need. It works with both controller actions, endpoints, and partially with razor pages (razor pages don't seem to expose available HTTP methods).

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

when you visit /-/info/endpoints, you'll get a list of routes as 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   }, ] 
like image 34
abdusco Avatar answered Sep 16 '22 14:09

abdusco


To get at all the routes, you need to use the ApiExplorer part of MVC. You can either mark all your actions with an attribute or use a convention like this one:

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

In Startup.cs, add your new in ConfigureServices(...)

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

In your ActionFilter you can then use constructor injection to get the 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, which has the RelativePath, which is the route template for that route:

// 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>();     } } 
like image 159
Dr Rob Lang Avatar answered Sep 18 '22 14:09

Dr Rob Lang