Get All Registered Routes in ASP.NET Core

Get all registered routes in ASP.NET Core

I've created the NuGet package "AspNetCore.RouteAnalyzer" that provides a feature to get all route information.

  • NuGet Gallery | AspNetCore.RouteAnalyzer ... Package on NuGet Gallery
  • kobake/AspNetCore.RouteAnalyzer ... Usage guide

Try it if you'd like.

Usage

Package Manager Console

PM> Install-Package AspNetCore.RouteAnalyzer

Startup.cs

using AspNetCore.RouteAnalyzer; // Add
.....
public void ConfigureServices(IServiceCollection services)
{
....
services.AddRouteAnalyzer(); // Add
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
....
app.UseMvc(routes =>
{
routes.MapRouteAnalyzer("/routes"); // Add
....
});
}

Browse

Run project and you can access the url /routes to view all route information of your project.
Sample Image

Get all registered routes in ASP.NET Core 3.0

I just want to print them all out.

So, I guess this is for debugging purposes?

In that case, this will get you started:

public HomeController(IActionDescriptorCollectionProvider provider)
{
this.provider = provider;
}

public IActionResult Index()
{
var urls = this.provider.ActionDescriptors.Items
.Select(descriptor => '/' + string.Join('/', descriptor.RouteValues.Values
.Where(v => v != null)
.Select(c => c.ToLower())
.Reverse()))
.Distinct()
.ToList();

return Ok(urls);
}

This will return response in the following format:

[
"/post/delete",
"/users/index/administration",
"/users/details/administration",
]

If you need more information, the IActionDescriptorCollectionProvider has plenty of it.

ASP.net core MVC catch all route serve static file

If you're already in the routing stage, you've gone past the point where static files are served in the pipeline. Your startup will look something like this:

app.UseStaticFiles();

...

app.UseMvc(...);

The order here is important. So your app will look for static files first, which makes sense from a performance standpoint - no need to run through MVC pipeline if you just want to throw out a static file.

You can create a catch-all controller action that will return the content of the file instead. For example (stealing the code in your comment):

public IActionResult Spa()
{
return File("~/index.html", "text/html");
}

Asp.Net Core GetRoutes per assembly or namespace or project

You cannot retrieve the runtime type info for Razor pages before ASP.NET Core 6. You only have access to PageActionDescriptors, but sadly they don't provide type info.

With ASP.NET Core 6, this is changed, and now you can get CompiledPageActionDescriptor for Razor pages, which does include the reflection info.

var host = CreateHostBuilder(args).Build();
var provider = host.Services.GetRequiredService<IActionDescriptorCollectionProvider>();
var pageEndpoints = provider.ActionDescriptors.Items.OfType<CompiledPageActionDescriptor>()
.Select(e => {
var modelType = e.ModelTypeInfo;
var route = e.DisplayName;
// ...
});

reflection

How to hook into the Asp.Net Core 6 MVC route system to customize urls generation

Amir's answer put me on track to find a solution (bounty award for him). Creating a custom UrlHelper was the way to go, but not with a UrlHelper derived class. For enpoint routing, the framework is using the sealed EndpointRoutingUrlHelper class. So I just needed to derive from UrlHelperBase, paste the code from EndpointRoutingUrlHelper and add my customizations. I was lucky that there were no internal pieces of code in there...

Here is the solution. Note that:

  • the term "segment" mentioned in the original question is replaced by what I actually have in my code i.e. "lang".
  • HttpContext.Items["lang"] is set by a middleware.
using Microsoft.AspNetCore.Mvc.Routing;
using Microsoft.AspNetCore.Mvc;

// The custom UrlHelper is registered with serviceCollection.AddSingleton<IUrlHelperFactory, LanguageAwareUrlHelperFactory>();
public class LanguageAwareUrlHelperFactory : IUrlHelperFactory
{
private readonly LinkGenerator _linkGenerator;
public LanguageAwareUrlHelperFactory(LinkGenerator linkGenerator)
{
_linkGenerator = linkGenerator;
}

public IUrlHelper GetUrlHelper(ActionContext context)
{
return new LanguageAwareUrlHelper(context, _linkGenerator);
}
}

// Source code is taken from https://github.com/dotnet/aspnetcore/blob/main/src/Mvc/Mvc.Core/src/Routing/EndpointRoutingUrlHelper.cs
// and modified to inject the desired route value
public class LanguageAwareUrlHelper : UrlHelperBase
{
private readonly LinkGenerator _linkGenerator;

public LanguageAwareUrlHelper(ActionContext actionContext, LinkGenerator linkGenerator) : base(actionContext)
{
if (linkGenerator == null)
throw new ArgumentNullException(nameof(linkGenerator));

_linkGenerator = linkGenerator;
}

public override string? Action(UrlActionContext urlActionContext)
{
if (urlActionContext == null)
throw new ArgumentNullException(nameof(urlActionContext));

var values = GetValuesDictionary(urlActionContext.Values);

if (urlActionContext.Action == null)
{
if (!values.ContainsKey("action") && AmbientValues.TryGetValue("action", out var action))
values["action"] = action;
}
else
values["action"] = urlActionContext.Action;

if (urlActionContext.Controller == null)
{
if (!values.ContainsKey("controller") && AmbientValues.TryGetValue("controller", out var controller))
values["controller"] = controller;
}
else
values["controller"] = urlActionContext.Controller;

if (!values.ContainsKey("lang") && ActionContext.HttpContext.Items.ContainsKey("lang"))
values["lang"] = ActionContext.HttpContext.Items["lang"];

var path = _linkGenerator.GetPathByRouteValues(
ActionContext.HttpContext,
routeName: null,
values,
fragment: urlActionContext.Fragment == null ? FragmentString.Empty : new FragmentString("#" + urlActionContext.Fragment));

return GenerateUrl(urlActionContext.Protocol, urlActionContext.Host, path);
}

public override string? RouteUrl(UrlRouteContext routeContext)
{
if (routeContext == null)
throw new ArgumentNullException(nameof(routeContext));

var langRouteValues = GetValuesDictionary(routeContext.Values);
if (!langRouteValues.ContainsKey("lang") && ActionContext.HttpContext.Items.ContainsKey("lang"))
langRouteValues.Add("lang", ActionContext.HttpContext.Items["lang"]);

var path = _linkGenerator.GetPathByRouteValues(
ActionContext.HttpContext,
routeContext.RouteName,
langRouteValues,
fragment: routeContext.Fragment == null ? FragmentString.Empty : new FragmentString("#" + routeContext.Fragment));

return GenerateUrl(routeContext.Protocol, routeContext.Host, path);
}
}


Related Topics



Leave a reply



Submit