Middleware Ordering & Built-in Middleware
Understand correct middleware ordering for authentication, routing, CORS, and exception handling.
Middleware Ordering & Built-in Middleware is a free C# Academy lesson on CoddyKit. This is lesson 4 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the C# Academy learning path, and your progress syncs across the web and the CoddyKit app. The C# Academy course includes 4 lessons in total.
Why Ordering Matters
ASP.NET Core middleware runs in the exact order it is registered. Wrong order causes security holes, performance issues, or broken behavior — for example, routing must come before authorization, which must come before endpoint execution.
The Recommended Middleware Order
Microsoft documents the recommended order. Deviating from it creates hard-to-debug issues. Here is the canonical order for a production ASP.NET Core API.
// Recommended order:
app.UseExceptionHandler(); // 1. Catch all exceptions
app.UseHsts(); // 2. HTTP Strict Transport Security
app.UseHttpsRedirection(); // 3. Redirect HTTP to HTTPS
app.UseStaticFiles(); // 4. Serve static assets
app.UseRouting(); // 5. Match route patterns
app.UseCors(); // 6. Cross-Origin
app.UseAuthentication(); // 7. Who are you?
app.UseAuthorization(); // 8. Are you allowed?
app.UseRateLimiter(); // 9. Throttle
app.UseOutputCache(); // 10. Cache responses
// Map endpoints here
app.MapControllers();
app.Run();Exception Handling First
Exception handling middleware must be first (outermost) so it catches exceptions from all subsequent middleware and endpoints.
// Development: detailed error page
if (app.Environment.IsDevelopment())
app.UseDeveloperExceptionPage();
else
{
// Production: generic error page + structured response
app.UseExceptionHandler("/error");
app.UseHsts();
}
// OR: use ProblemDetails globally (recommended .NET 8+)
builder.Services.AddProblemDetails();
app.UseExceptionHandler();
// All unhandled exceptions -> RFC 7807 ProblemDetails JSONStatic Files Before Routing
Static files (UseStaticFiles) should come before routing. Serving a static file short-circuits the pipeline — no need to run auth or routing for /css/main.css.
app.UseStaticFiles(); // serves wwwroot/* without going through auth
app.UseRouting(); // expensive: runs route matching
// If you put UseStaticFiles AFTER UseRouting, the route
// matcher runs unnecessarily for every .js/.css request.
// Serve static files first for better performance.Authentication Before Authorization
UseAuthentication must come before UseAuthorization. Authentication populates HttpContext.User; authorization checks that populated user against policies.
// WRONG ORDER — authorization runs before user is populated:
app.UseAuthorization(); // user is null → everything allowed!
app.UseAuthentication(); // too late
// CORRECT:
app.UseAuthentication(); // populates context.User
app.UseAuthorization(); // checks context.User against policiesCORS Before Authentication
CORS middleware must run before authentication so that pre-flight OPTIONS requests are handled without requiring authentication headers.
builder.Services.AddCors(opts =>
opts.AddPolicy("Frontend", p =>
p.WithOrigins("https://myapp.com")
.AllowAnyHeader()
.AllowAnyMethod()));
app.UseRouting();
app.UseCors("Frontend"); // before auth — handles OPTIONS pre-flight
app.UseAuthentication();
app.UseAuthorization();Common Built-In Middleware
ASP.NET Core ships many built-in middleware components. Knowing what each does helps you understand when and how to use them.
// Compression: compresses responses (must be before static files)
builder.Services.AddResponseCompression();
app.UseResponseCompression();
// Request localization: sets culture from Accept-Language header
builder.Services.AddLocalization();
app.UseRequestLocalization();
// Health checks: /health endpoint
builder.Services.AddHealthChecks();
app.MapHealthChecks("/health");
// Forwarded headers: trust X-Forwarded-For from reverse proxy
app.UseForwardedHeaders();Routing Middleware Deep Dive
UseRouting() matches the incoming request to a route pattern and stores the match in HttpContext. UseEndpoints() (or MapXxx()) then executes the matched endpoint.
app.UseRouting(); // matches route, stores in context
// Between UseRouting and Map*: middleware can read route data
app.Use(async (ctx, next) =>
{
var endpoint = ctx.GetEndpoint();
var routeName = endpoint?.DisplayName;
Console.WriteLine($"Matched: {routeName}");
await next(ctx);
});
// All auth and other middleware go here
app.UseAuthentication();
app.UseAuthorization();
// Execute the matched endpoint
app.MapControllers();
app.MapGet("/", () => "Home");Response Compression Placement
Response compression must come before static files and routing so compressed output is written before content is generated. Place it immediately after exception handling.
// Correct placement for response compression:
app.UseExceptionHandler();
app.UseResponseCompression(); // before static files
app.UseStaticFiles(); // compressed static files
app.UseRouting();
// ... rest of pipelineReal-World: Full Production Pipeline
A complete production pipeline combining all recommendations into a well-ordered, secure middleware stack.
var app = builder.Build();
if (app.Environment.IsDevelopment())
app.UseDeveloperExceptionPage();
else { app.UseExceptionHandler(); app.UseHsts(); }
app.UseResponseCompression();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseCors("AllowFrontend");
app.UseAuthentication();
app.UseAuthorization();
app.UseRateLimiter();
app.UseOutputCache();
app.MapHealthChecks("/health").AllowAnonymous();
app.MapControllers();
app.Run();Quick Check
Why must UseAuthentication come before UseAuthorization in the middleware pipeline?
Recap: Middleware Ordering & Built-In Middleware
Key takeaways:
- Exception handling first, static files before routing, auth before authorization, CORS before auth
- Response compression goes early (before static files) for maximum effect
- UseRouting + UseAuthorization + Map* — middleware between them can read route data
- Built-in: UseHsts, UseHttpsRedirection, UseStaticFiles, UseRateLimiter, UseOutputCache
- Check
ctx.GetEndpoint()between UseRouting and MapXxx to read matched route info
Learn C# with an AI tutor — free
Write and run real code in your browser, get instant help from a 24/7 AI tutor, and pick up where you left off on the web or in the app.
- Courses
- 93
- Lessons
- 346
Frequently Asked Questions
Is the “Middleware Ordering & Built-in Middleware” lesson free?
Yes — the full text of “Middleware Ordering & Built-in Middleware” is free to read here on the web. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the C# Academy course, upgrade to CoddyKit PRO. The C# Academy course includes 4 lessons in total.
What will I learn in “Middleware Ordering & Built-in Middleware”?
Understand correct middleware ordering for authentication, routing, CORS, and exception handling. You practise C# Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start C# Academy?
No prior experience is required. C# Academy on CoddyKit is structured for beginners through advanced learners, so you can start here or from the beginning and move at your own pace. This is lesson 4 of 4.
How long does the “Middleware Ordering & Built-in Middleware” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this C# Academy lesson?
Yes. Every C# Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- ASP.NET Core Pipeline Overview
- Writing Custom Middleware
- Short-Circuiting & Branching
- Middleware Ordering & Built-in Middleware