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.
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 PageActionDescriptor
s, 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;
// ...
});
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
.Include() VS .Load() Performance in Entityframework
How to Route Images Using ASP.NET MVC Routing
Binding Objects Defined in Code-Behind
What Is the Efficiency and Performance of Linq and Lambda Expression in .Net
When Is Finally Run If You Throw an Exception from the Catch Block
Iis Wcf Service Hosting VS Windows Service
C# - Volatile Keyword Usage VS Lock
Is Configurationmanager.Appsettings Available in .Net Core 2.0
How to Know the Size of the String in Bytes
Cannot Implicitly Convert Type 'Int' to 'T'
Ascending/Descending in Linq - Can One Change the Order via Parameter
Are 2 Dimensional Lists Possible in C#
Self Referencing Loop Detected - Getting Back Data from Webapi to the Browser
Hot Unload/Reload of a Dll Used by an Application
Return/Consume Dynamic Anonymous Type Across Assembly Boundaries