Section 4 of 5
Middleware Ordering
π― What You'll Learn
- Why middleware order matters
- The recommended middleware order
- Common ordering mistakes
- How order affects behavior
- Special ordering considerations
- Debugging order issues
- InvenTrack pipeline organization
Why Order Matters
Middleware executes in the order it's registered. The order determines:
- What runs first: Early middleware sees all requests
- What can short-circuit: Early middleware can stop the pipeline
- What modifies requests/responses: Order affects transformations
- Security: Authentication must come before authorization
β οΈ Wrong Order = Broken App
Incorrect middleware order can cause:
- Security vulnerabilities (authorization before authentication)
- 404 errors (routing after static files)
- Missing CORS headers
- Unhandled exceptions
Recommended Middleware Order
Microsoft recommends this order for ASP.NET Core applications:
Recommended Order
C#
var app = builder.Build();
// 1. Exception Handling (catch all errors)
if (app.Environment.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/error");
app.UseHsts();
}
// 2. HTTPS Redirection (force HTTPS early)
app.UseHttpsRedirection();
// 3. Static Files (short-circuit for static content)
app.UseStaticFiles();
// 4. Routing (match endpoints)
app.UseRouting();
// 5. CORS (after routing, before auth)
app.UseCors();
// 6. Authentication (identify user)
app.UseAuthentication();
// 7. Authorization (check permissions)
app.UseAuthorization();
// 8. Custom Middleware (business logic)
app.UseRequestTiming();
// 9. Endpoints (controllers, minimal APIs)
app.MapControllers();
app.Run();
Visual Representation
Pipeline Flow
Text
Request
β
βββββββββββββββββββββββββββββββββββ
β 1. Exception Handler β β Catches all errors
βββββββββββββββββββββββββββββββββββ€
β 2. HTTPS Redirection β β Redirect HTTP β HTTPS
βββββββββββββββββββββββββββββββββββ€
β 3. Static Files β β Serve CSS/JS/images
β β (may short-circuit)
βββββββββββββββββββββββββββββββββββ€
β 4. Routing β β Match request to endpoint
βββββββββββββββββββββββββββββββββββ€
β 5. CORS β β Add CORS headers
βββββββββββββββββββββββββββββββββββ€
β 6. Authentication β β Identify user
βββββββββββββββββββββββββββββββββββ€
β 7. Authorization β β Check permissions
βββββββββββββββββββββββββββββββββββ€
β 8. Custom Middleware β β Your logic
βββββββββββββββββββββββββββββββββββ€
β 9. Endpoint β β Controller/API
βββββββββββββββββββββββββββββββββββ
β
Response
Critical Ordering Rules
1. Exception Handler First
β
Correct
C#
app.UseExceptionHandler("/error"); // First!
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
β Wrong
C#
app.UseAuthentication();
app.UseExceptionHandler("/error"); // Too late!
app.MapControllers();
// Problem: Exceptions in authentication won't be caught!
2. Authentication Before Authorization
β
Correct
C#
app.UseAuthentication(); // First: Identify user
app.UseAuthorization(); // Then: Check permissions
β Wrong
C#
app.UseAuthorization(); // Can't check permissions without knowing who the user is!
app.UseAuthentication();
3. CORS After Routing
β
Correct
C#
app.UseRouting();
app.UseCors(); // After routing
app.UseAuthentication();
β Wrong
C#
app.UseCors(); // Before routing - may not work!
app.UseRouting();
4. Static Files Early
β
Correct
C#
app.UseStaticFiles(); // Early - short-circuit for static files
app.UseRouting();
app.UseAuthentication();
app.MapControllers();
β Wrong
C#
app.UseRouting();
app.UseAuthentication();
app.MapControllers();
app.UseStaticFiles(); // Too late - static files won't be served!
Common Mistakes
Mistake 1: Authorization Before Authentication
Problem
C#
app.UseAuthorization();
app.UseAuthentication(); // Wrong order!
// Result: Authorization fails because user is not identified yet
Mistake 2: Custom Middleware Before Authentication
Problem
C#
app.Use(async (context, next) =>
{
var userId = context.User.FindFirst("sub")?.Value; // null!
await next();
});
app.UseAuthentication(); // User not set yet!
Mistake 3: Exception Handler Too Late
Problem
C#
app.UseAuthentication();
app.UseExceptionHandler("/error"); // Too late!
// Result: Exceptions in authentication middleware are not caught
Special Considerations
Response Compression
Compression Placement
C#
app.UseResponseCompression(); // Before static files
app.UseStaticFiles();
// Why? Static files can be compressed too
Response Caching
Caching Placement
C#
app.UseResponseCaching(); // Before authentication
app.UseAuthentication();
// Why? Cached responses can be served without authentication
Session Middleware
Session Placement
C#
app.UseRouting();
app.UseSession(); // After routing, before endpoints
app.MapControllers();
Complete InvenTrack Pipeline
Program.cs (Production-Ready)
C#
var builder = WebApplication.CreateBuilder(args);
// Configure services
builder.Services.AddControllers();
builder.Services.AddDbContext<InvenTrackDbContext>();
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer();
builder.Services.AddAuthorization();
builder.Services.AddCors(options =>
{
options.AddPolicy("AllowFrontend", policy =>
policy.WithOrigins("https://inventrackapp.com")
.AllowAnyMethod()
.AllowAnyHeader());
});
builder.Services.AddResponseCompression();
var app = builder.Build();
// ============================================
// MIDDLEWARE PIPELINE (ORDER MATTERS!)
// ============================================
// 1. Exception Handling (FIRST - catch all errors)
if (app.Environment.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/error");
app.UseHsts();
}
// 2. HTTPS Redirection
app.UseHttpsRedirection();
// 3. Response Compression (before static files)
app.UseResponseCompression();
// 4. Static Files (early - can short-circuit)
app.UseStaticFiles();
// 5. Routing
app.UseRouting();
// 6. CORS (after routing, before auth)
app.UseCors("AllowFrontend");
// 7. Custom Middleware - Correlation ID
app.UseCorrelationId();
// 8. Custom Middleware - Request Timing
app.UseRequestTiming();
// 9. Authentication (identify user)
app.UseAuthentication();
// 10. Authorization (check permissions)
app.UseAuthorization();
// 11. Custom Middleware - API Key (after auth)
app.UseApiKey();
// 12. Endpoints (LAST)
app.MapControllers();
app.Run();
Why This Order?
| Position | Middleware | Reason |
|---|---|---|
| 1 | Exception Handler | Catch all errors from any middleware |
| 2 | HTTPS Redirection | Force HTTPS before any processing |
| 3 | Response Compression | Compress all responses (including static files) |
| 4 | Static Files | Short-circuit early for performance |
| 5 | Routing | Match request to endpoint |
| 6 | CORS | Add CORS headers after routing |
| 7-8 | Custom (Correlation, Timing) | Track requests before auth |
| 9 | Authentication | Identify user |
| 10 | Authorization | Check permissions (after auth) |
| 11 | Custom (API Key) | Additional security after auth |
| 12 | Endpoints | Execute controller/API logic |
Debugging Order Issues
Add Logging Middleware
Debug Middleware Order
C#
app.Use(async (context, next) =>
{
Console.WriteLine($"[1] Before: {context.Request.Path}");
await next();
Console.WriteLine($"[1] After: {context.Response.StatusCode}");
});
app.UseAuthentication();
app.Use(async (context, next) =>
{
Console.WriteLine($"[2] User: {context.User.Identity?.Name ?? "Anonymous"}");
await next();
});
Check User Identity
Verify Authentication Order
C#
app.Use(async (context, next) =>
{
if (context.User.Identity?.IsAuthenticated == true)
{
Console.WriteLine("User is authenticated");
}
else
{
Console.WriteLine("User is NOT authenticated");
}
await next();
});
Key Takeaways
- Order matters: Middleware executes in registration order
- Exception handler first: Catch all errors
- Authentication before authorization: Can't check permissions without knowing the user
- CORS after routing: Routing must happen first
- Static files early: Short-circuit for performance
- Custom middleware placement: Depends on what it needs (user, routing, etc.)
- Endpoints last: Final destination
- Wrong order = broken app or security issues
- Use logging to debug order issues
- Follow Microsoft's recommended order
π― Next Steps
You now understand middleware ordering! In the final section, we'll explore Exception Handling Middlewareβcreating robust error handling, custom error pages, logging exceptions, and building a production-ready error handling strategy for InvenTrack.