Overview
UseRouting
— adds route matching to the pipeline; looks at endpoints defined in the app and selects the best match.
UseRouting
works by calling the SetEndpoint method to attach the endpoint to the current context.
UseEndpoints
— adds endpoint execution to the pipeline; runs the delegate associated with each the selected endpoint.
UseEndpoints
is terminal when a match is found.UseEndpoints
uses GetEndpoint to retrieve the endpoint and then invokes its RequestDelegate property.
WebApplicationBuilder
configures UseRouting
and UseEndpoints
.
Endpoints
- Endpoints in ASP.NET are executable (have a
RequestDelegate
), extensible (have aMetadata
collection), selectable (with routing information), and enumerable (the collection of endpoints can be listed fromEndpointDataSource
in DI). - Endpoints that can be matched and executed are configured in
UseEndpoints.
To connect ASP.NET framework features to the routing system use:
MapRazorPages
for Razor PagesMapControllers
for controllersMapHub<T>
for SignalRMapGrpcService<T>
for gRPC
Route Templates
Route templates configure how an endpoint is matched. Consider:
app.MapGet("/hello/{name:alpha}", (string name) => $"Hello {name}!");
/hello/{name:alpha}
is the route template. This templates matches/hello/
followed by a sequence of alphabetic characters.alpha
is a route constraint.name
binds the second segment of the URL path to the name parameter and stores it inHttpRequest.RouteValues
.
Endpoint Metadata
Consider:
app.UseAuthentication();
app.UseAuthorization();
app.MapHealthChecks("/healthz").RequireAuthorization(); // This endpoint is chained with RequireAuthorization. The endpoint now contains metadata.
app.MapGet("/", () => "Hello World!");
Metadata can be of any .NET type and can be processed by routing-aware middleware.
Terminal Middleware vs. Routing Endpoints
Consider:
// Approach 1: Terminal Middleware.
app.Use(async (context, next) =>
{
if (context.Request.Path == "/") // When a match is found…
{
await context.Response.WriteAsync("Terminal Middleware."); // …execute some functionality…
return; // …and return to terminate.
}
await next(context);
});
app.UseRouting();
// Approach 2: Routing.
app.MapGet("/Routing", () => "Routing."); // Endpoints are always terminal.
Other considerations:
- Positioning — Terminal middleware can be positioned anywhere in the pipeline. Routing endpoints will execute wherever
UseEndpoints
is called. - Matching — Terminal middleware allows for custom matching logic.
- Interfacing with other middleware — Routing endpoints interface automatically with other middleware like
UseAuthorization
andUseCors.
Terminal middleware requires manual interfacing.
Prefer routing endpoints over terminal middleware.