ASP.NET - Endpoint Routing Internals
Endpoint routing decides which code runs for an incoming request. It separates route discovery from execution so routes are collected once at startup and then matched efficiently during requests.
Route Collection
At startup, calls like MapGet, MapPost and attribute routes create Endpoint objects. Each holds the pattern, HTTP method and delegate that should run. These are stored in EndpointDataSource, forming the routing table used for request matching.
Request Matching
When a request arrives, routing middleware examines the path and HTTP verb. It compares them against all registered endpoints and selects the best match. Once found, metadata and route values are attached to HttpContext for the rest of the pipeline.
Metadata Usage
Metadata is attached to endpoints to define rules such as authorization, CORS, and naming. Middleware reads this metadata to decide what conditions apply before executing the handler. This keeps cross-cutting concerns separate from business logic.
Delegate Execution
After routing picks the correct endpoint and middleware approves it, the delegate runs. It receives injected services, processes input and sends a response back to the client.
Why This Design Matters
Endpoint routing works for Minimal APIs, MVC, Razor Pages and gRPC. It improves performance by caching routes and allows flexible policies through metadata.
Example
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/hello", () => "Hello");
app.MapGet("/hello/{name}", (string name) => $"Hi {name}");
app.MapGet("/secure", () => "Protected")
.WithMetadata(new AuthorizeAttribute());
var data = app.Services.GetRequiredService<EndpointDataSource>();
foreach (var ep in data.Endpoints)
{
Console.WriteLine(ep.DisplayName);
}
app.Run();
Console:
GET /hello
GET /hello/{name}
GET /secure