The Middleware Pipeline
Every HTTP request handled by an ASP.NET Core app passes through a chain of middleware components, small pieces of code that can inspect, modify, short-circuit, or pass along the request and response. Middleware is registered in Program.cs with app.Use... calls, and the order of those calls directly determines the order components run in for incoming requests, and the reverse order for the outgoing response.
Cricket analogy: It's like a ball passing through a fielding chain, wicketkeeper to slip to gully, each fielder gets a chance to intercept it before it reaches the boundary, and the sequence they're positioned in is exactly the order the ball is handled.
Ordering Determines Behavior
Because middleware forms a single ordered chain, placing app.UseAuthentication() before app.UseAuthorization() is required, authentication must establish who the user is before authorization can decide what they're allowed to do. Similarly, app.UseExceptionHandler() is typically registered early so it can catch exceptions thrown by anything downstream, while app.UseStaticFiles() is often placed before routing so static asset requests can short-circuit without ever reaching MVC.
Cricket analogy: It's like a bowler needing to complete their run-up before releasing the ball, the sequence of steps is non-negotiable, you can't deliver the ball and then run up afterward.
Short-Circuiting and app.Use vs app.Run
Middleware written with app.Use() receives a RequestDelegate 'next' parameter and can choose to call it to pass control down the chain, or skip it to short-circuit the pipeline and return a response immediately, for example, blocking a request that fails an IP allow-list check. Terminal middleware registered with app.Run() never calls next because it is meant to be the final handler in the chain, commonly used for a simple catch-all endpoint.
Cricket analogy: It's like a run-out appeal, if the fielder decides to appeal and the umpire raises the finger, the innings for that batter ends right there rather than continuing to the next ball.
app.Use(async (context, next) =>
{
if (!context.Request.Headers.ContainsKey("X-Api-Key"))
{
context.Response.StatusCode = StatusCodes.Status401Unauthorized;
await context.Response.WriteAsync("Missing API key");
return; // short-circuit: 'next' is never called
}
await next(context); // pass control to the next middleware
});
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run(async context =>
{
context.Response.StatusCode = StatusCodes.Status404NotFound;
await context.Response.WriteAsync("Not found");
});Registering app.UseAuthorization() before app.UseAuthentication() is a common mistake, authorization checks will run against an unauthenticated user context and either fail incorrectly or allow requests that should have been rejected.
- Middleware forms an ordered chain that every HTTP request passes through.
- Registration order in Program.cs is execution order for the request, and reverse order for the response.
- Authentication must be registered before Authorization for identity checks to be meaningful.
- app.Use() middleware can call next() to continue the chain or omit it to short-circuit.
- app.Run() registers terminal middleware that never calls next and ends the pipeline.
- app.UseStaticFiles() is typically placed early so static asset requests avoid unnecessary processing.
- Exception handling middleware is usually registered first so it can catch errors from everything downstream.
Practice what you learned
1. What determines the order in which middleware processes an incoming HTTP request?
2. Why must app.UseAuthentication() be registered before app.UseAuthorization()?
3. What does it mean for a piece of middleware to 'short-circuit' the pipeline?
4. What distinguishes middleware registered with app.Run() from middleware registered with app.Use()?
Was this page helpful?
You May Also Like
Project Structure and Program.cs
How a default ASP.NET Core project is laid out and how Program.cs bootstraps the host, services, and request pipeline.
Dependency Injection Basics
How ASP.NET Core's built-in dependency injection container registers and supplies services throughout your application.
What Is ASP.NET Core?
A cross-platform, open-source, high-performance framework from Microsoft for building web apps, APIs, and microservices on .NET.
Related Reading
Related Study Notes in Microsoft Technologies
Browse all study notesWindows 10 / UWP Development Study Notes
.NET · 30 topics
Microsoft TechnologiesWindows Batch Scripting Study Notes
Batch · 30 topics
Microsoft TechnologiesMFC (Microsoft Foundation Classes) Study Notes
C++ · 30 topics
Microsoft TechnologiesSilverlight Study Notes
.NET · 30 topics
Microsoft TechnologiesXAML Study Notes
.NET · 30 topics
Microsoft TechnologiesWPF (Windows Presentation Foundation) Study Notes
.NET · 30 topics