EndPoint Routing is the new way to implement the Routing in ASP.NET Core. It splits up the old routing middleware into two separate middleware’s and also decouples the MVC from the Routing Middleware. Learn what is Endpoint is and how to register these routing middleware’s using the UseRouting
& UseEndpoints
methods in the Configure method of the startup class.
The Article Applies to ASP.NET Core 3.0 or later. For Previous Version of the ASP.NET core check the article Routing in ASP.NET Core 2.0
Table of Contents
What is Endpoint Routing in ASP.NET Core
The Endpoint Routing is the Process by which ASP.NET Core inspects the incoming HTTP requests and maps them to applications executable Endpoint. We define the Endpoint during the application startup. The Routing Module then matches the incoming URL to an Endpoint and dispatches the request to it.
The Endpoint Routing Module also decouples the route matching functions and endpoint dispatching functions using the two separate middleware’s.
- The
EndPointRoutingMiddleware
resolves the HTTP request to an Endpoint (route matching). - The
EndpointMiddleware
invokes the Endpoint (endpoint dispatching).
Before ASP.NET Core 3.0
Before ASP.NET Core 3.0 the Route resolution & invoking of the Route were part of the MVC Middleware. We defined the routes while configuring the MVC is using the app.UseMvc
as shown below
1 2 3 4 5 6 | app.UseMvc(routes => { routes.MapRoute("default", "{controller}/{action}"); }); |
- When a new request arrives, the routing middleware parses the incoming URL.
- A matching route is searched in the RouteCollection.
- If a matching route is found, control is passed to the RouteHandler
- If a matching route is not found, the next middleware is invoked.
What is an Endpoint
An Endpoint is an object that contains everything that you need to execute the incoming Request. The Endpoint object contains the following information
- Metadata of the request.
- The delegate (Request handler) that ASP.NET core uses to process the request.
We define the Endpoint at the application startup using the UseEndpoints
method.
The ASP.NET Core routing is now not tied up only to the MVC Endpoints. You can define an Endpoint, which can also hit a Razor page, SignalR etc.
The following are the the Endpoints that you can configure in ASP.NET Core app.
- MVC Controller Action Method
- Web API Controller Action Method
- Razor page
- SignalR
- gRPC Services
- Blazer on the server
- Endpoint defined in an middleware
- Delegates and lambdas registered with routing.
How Endpoint Routing Works
The Endpoint Routing has three components
- Defining the Endpoints.
- Route matching & Constructing an Endpoint (
UseRouting
). - Endpoint Execution (
UseEndpoints
).
To understand how it works, Create a new ASP.NET Core application in VS 2019 ( Min Version 16.9.1 ) and .NET 5.0. Choose the Web Application (Model-View-Controller) Template.
Open the startup class.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseExceptionHandler("/Home/Error"); // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. app.UseHsts(); } app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); }); } |
Configure the Endpoint
We configure the Endpoint in the app.UseEndpoints
method.
The following method adds the default MVC Conventional route using the MapControllerRoute method. The following adds the default
conventional route to MVC Controllers using a pattern.
1 2 3 4 5 | endpoints.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); |
To setup an attribute based Routing use the method MapControllers. We use the attribute based Routing to create a route to Rest API (Web API Controller Action Method). You can also use it to create a route to MVC Controller action method.
1 2 3 | endpoints.MapControllers(); |
MapControllerRoute
& MapControllers
methods hides all the complexities of setting up the Endpoint from us. Both sets up the Endpoint to Controller action methods
You can also create an Endpoint to a custom delegate using MapGet
method. MapGet
accepts two argument. One is Route Pattern (/
in the example) and a request delegate.
1 2 3 4 5 6 | endpoints.MapGet("/", async context => { await context.Response.WriteAsync("Hello World"); }); |
UseRouting
The EndPointRoutingMiddleware
resolves the incoming HTTP requests and constructs an Endpoint.
We register it very early in the middleware pipeline using the UseRouting
method.
Its purpose is to
- Parse the incoming URL
- Resolve the URL and construct the Endpoint.
- Updates the HTTP Context object with the endpoint using the SetEndpoint method.
The Endpoint objects are immutable and cannot be modified after creation.
The Middleware running after UseRouting
can access the endpoint from the HTTP Context and take action. For example, an authorization middleware can query the metadata of the endpoint and apply the correct authorization policy based on that information.
1 2 3 4 5 6 7 8 9 | //All Middleware till here cannot access the Endpoint // Add the EndpointRoutingMiddleware app.UseRouting(); // All middleware from here onwards can access the Endpoint from the HTTP Context |
UseEndpoints
The EndpointMiddleware
is responsible for execution the Endpoint. We register the it using the UseEndpoints
method. It reads the Endpoint, which was selected by the Route Matching middleware and runs the delegate associated with it.
Remember, we also configure the endpoints in the UseEndpoints
method
1 2 3 4 5 6 | app.UseEndpoints(endpoints => { // Define endpoint here }); |
- The
EndpointMiddleware
middleware is terminal Middleware when a match is found - The middleware after
UseEndpoints
execute only when no match is found.
Endpoint Routing in Action
In the following example, we are using the MapGet to create two custom Endpoints
MapGet is an extension method, on EndpointRouteBuilder
and accepts two arguments.
The first argument is route pattern as string. The second argument is a request delegate, which will be executed when the Endpoint is matched.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { //All Middleware till here cannot access the Endpoint app.UseRouting(); //All middleware from here onwards can access the Endpoint from the HTTP Context app.UseEndpoints(endpoints => { endpoints.MapGet("/", async context => { await context.Response.WriteAsync("Hello World"); }); endpoints.MapGet("/hello", async context => { await context.Response.WriteAsync(helloWorld()); }); }); } private string helloWorld() { return "Hello World from a Method"; } |
The Code above defines two Endpoints. One is root URL /
and the other one is /hello
.
Request delegates in both the Endpoints print Hello World
to the response stream. The second delegate uses the the method helloWorld()
to do so.
When the app starts, UseRouting
registers the Route Matching Middleware EndPointRoutingMiddleware
. UseEndpoints
method registers the Endpoint execution middleware EndpointMiddleware
. UseEndpoints
also configures the Endpoints.
When the request arrives to root URL /
or to the /hello
URL, the Route Matching Middleware will construct the Endpoint and updates the context. The later in the middleware the EndpointMiddleware
reads the Endpoint from the context and executes its delegate.
Any request other than the above, will not have any Endpoints, and hence will throw the 404 error. Also note that MapGet
maps to HTTP GET requests only. Any other request like POST, PUT etc returns 404 status code.
Reading Endpoints in Middleware
Any Middleware between the UseRouting
and UseEndpoints
can access the the Endpoint from the context using the GetEndpoint
mehod.
In the following code adds a custom middleware after UseRouting. If Endpoint is not null, it extracts the DisplayName
, RoutePattern
& metdata
from the Endpoint and writes it to the response stream.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { //All Middleware till here cannot access the Endpoint app.UseRouting(); app.Use(async (context, next) => { var endpoint = context.GetEndpoint(); if (endpoint != null) { await context.Response.WriteAsync("<html> Endpoint :" + endpoint.DisplayName + " <br>"); if (endpoint is RouteEndpoint routeEndpoint) { await context.Response.WriteAsync("RoutePattern :" + routeEndpoint.RoutePattern.RawText + " <br>"); } foreach (var metadata in endpoint.Metadata) { await context.Response.WriteAsync("metadata : " + metadata + " <br>"); } } else { await context.Response.WriteAsync("End point is null"); } await context.Response.WriteAsync("</html>"); await next(); }); app.UseEndpoints(endpoints => { endpoints.MapGet("/", async context => { await context.Response.WriteAsync("Hello World"); }); endpoints.MapGet("/hello", async context => { await context.Response.WriteAsync(helloWorld()); }); }); } |
Set a breakpoint to inspect the properties of the Endpoint.
Defining the Endpoints
As shown earlier, we configure the Endpoint in the app.UseEndpoints
method.
The ASP.NET Core supports many scenarios in developing apps. They include web apps like MVC, Razor Pages & Blazor. You can also build Web APIs or real time Apps using SignalR. Use gRPC to build Remote Procedure call apps, etc.
The ASP.NET Core provides several extension methods to setup & configure the Endpoints.
You can create endpoint to custom delegates using the map methods like MapGet
, MapPost
, MapPut
, MapDelete
, & Map
Use MapRazorPages to adds all the required Endpoints which maps to Razor Pages
1 2 3 | endpoints.MapRazorPages(); |
Similarly, you can use the MapHub to configure the SignalR endpoint
1 2 3 | endpoints.MapHub<ChatHub>("/chathub"); |
Use MapGrpcService
to Create Endpoint to a gRPC service.
1 2 3 | endpoints.MapGrpcService<SomeGrpcService>(); |
Routing to Controller Action
MVC & Web API require us to setup Endpoint to each controller action methods. There are two different ways by which we can set up routes.
- Convention-based routing
- Attribute routing
Convention-based routing
Conventional based routing is typically used with the controllers and views. It creates routes based on a series of conventions. We define it using the endpoints.MapControllerRoute
method.
1 2 3 4 5 6 7 8 | app.UseEndpoints(endpoints => { endpoints.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); }); |
In the above example, the MapControllerRoute
creates a single route, which is named as default
and the URL Pattern of the route is {controller=Home}/{action=Index}/{id?}
You can read more about Convention based routing in ASP.NET Core
Attribute routing
The attribute routing uses the attributes defined directly on the controller action to define the routes. Attribute routing gives you more control over the URLs in your web application.
To make use of the attribute routing use the MapControllers
method.
1 2 3 | endpoints.MapControllers(); |
You can read more about attribute routing in ASP.NET Core