TL;DR
  • Middleware order in ASP.NET Core defines your app’s security, performance, and request handling correctness.
  • Recommended order: exception handling → HSTS → HTTPS redirection → static files → routing → CORS → authentication → authorization → endpoint mapping.
  • Incorrect order can break authentication, CORS, or routing, and expose your app to security issues.
  • Follow the “onion model”: outer middleware runs first on requests, last on responses.
  • Always test your middleware pipeline after changes to prevent subtle bugs and security risks.

Getting your middleware pipeline right in ASP.NET Core is crucial for security, performance, and correctness. The order in which you register middleware defines the order it executes on a request and the reverse order it executes on a response. A wrong sequence can cause anything from broken authentication to security vulnerabilities.

Let’s cut to the chase. Here is the recommended, battle-tested middleware order for most modern ASP.NET Core applications.

Think of the request pipeline as a series of gates. A request must pass through each one in the correct sequence. Here’s a typical Program.cs setup that demonstrates this flow:

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

// --- The Recommended Middleware Order ---

// 1. Exception Handling: Catches exceptions thrown in later middleware.
// Should be first so it can handle errors from everything that runs after it.
if (app.Environment.IsDevelopment())
{
    app.UseDeveloperExceptionPage();
}
else
{
    app.UseExceptionHandler("/Error");
    // 2. HSTS: Enforces HTTPS in production.
    app.UseHsts();
}

// 3. HTTPS Redirection: Redirects HTTP requests to HTTPS.
app.UseHttpsRedirection();

// 4. Static Files: Serves static files (JS, CSS, images) and short-circuits.
// Placed early to avoid unnecessary processing for static content.
app.UseStaticFiles();

// 5. Routing: Determines which endpoint to execute.
app.UseRouting();

// 6. CORS: Must come after UseRouting and before UseAuthorization.
// This allows policy evaluation based on the selected endpoint's metadata.
app.UseCors();

// 7. Authentication: Identifies the user. Who are you?
app.UseAuthentication();

// 8. Authorization: Checks if the user has permission. Are you allowed?
app.UseAuthorization();

// 9. Endpoint Mapping: Executes the endpoint selected by routing.
// This is where your app.MapGet(), app.MapPost(), etc., are executed.
app.MapControllers(); // Or app.MapRazorPages(), app.MapGet(...), etc.

app.Run();

Why This Order Matters

This sequence isn’t arbitrary. It’s designed for efficiency and correctness:

  • Diagnostics First: Exception handlers are at the top to catch anything that goes wrong down the line.
  • Short-Circuiting Early: UseStaticFiles and UseHttpsRedirection can handle requests and stop the pipeline immediately, saving resources.
  • Auth After Routing: A common pitfall is placing UseAuthentication or UseAuthorization before UseRouting. This is inefficient because you don’t even know which endpoint the user is trying to access yet. Routing needs to happen first so the system can identify the endpoint and any associated authorization policies.

A Quick Mental Model

Think of middleware as wrapping layers, like an onion. The first middleware added is the outermost layer, it sees the request first and the response last. The last middleware is the innermost layer. This “first in, last out” model helps ensure that concerns like security and error handling wrap the core application logic correctly.

FAQ

Why does middleware order matter in ASP.NET Core?

Middleware order determines how requests and responses flow through your application. Placing middleware in the wrong order can break authentication, CORS, routing, or error handling, leading to security vulnerabilities and hard-to-debug issues.

What is the recommended order for middleware in ASP.NET Core?

Start with exception handling, then HSTS (in production), HTTPS redirection, static files, routing, CORS, authentication, authorization, and finally endpoint mapping. This order ensures each concern is handled at the right stage of the pipeline.

Why should exception handling middleware come first?

Exception handling should be first so it can catch errors from all subsequent middleware. This ensures consistent error responses and prevents unhandled exceptions from leaking sensitive information.

Where should CORS middleware be placed?

Place CORS after routing and before authentication/authorization. This allows CORS policies to be evaluated based on endpoint metadata and ensures preflight requests are handled correctly.

What happens if authentication or authorization is registered before routing?

Registering authentication or authorization before routing is inefficient and can cause issues, as the endpoint and its policies are not yet determined. Always route first, then authenticate and authorize.

Can static files middleware be placed anywhere in the pipeline?

No, static files middleware should be early in the pipeline to short-circuit requests for static content, improving performance and avoiding unnecessary processing.

How does middleware order affect security?

Incorrect order can expose endpoints to unauthenticated users, skip CORS checks, or miss error handling, creating security holes. Proper order ensures each security layer is applied as intended.

What is the “onion model” of middleware?

The onion model means the first middleware added is the outermost layer, seeing requests first and responses last. Each subsequent middleware wraps the next, ensuring correct layering of concerns.

How can you debug middleware order issues?

Use logging, breakpoints, or tools like MiddlewareAnalysis to trace the pipeline. Check for misplaced middleware if you see unexpected authentication, CORS, or routing behavior.

Is the recommended order always required?

The recommended order covers most scenarios, but some apps may need adjustments for custom middleware or advanced requirements. Always test thoroughly when changing the pipeline.
See other aspnet-core posts