Introduction

ASP.NET Core middleware forms a pipeline where each component processes the HTTP request and response in the order they are registered in Program.cs. Unlike some frameworks that run middleware in reverse order, ASP.NET Core runs them in registration order for requests and reverse order for responses. Misordering middleware causes critical issues like authentication running before routing, CORS preflight requests rejected by auth middleware, or exceptions not caught by the error handler.

Symptoms

  • CORS preflight (OPTIONS) requests rejected with 401 Unauthorized
  • Authentication runs before routing, causing 401 on public endpoints
  • Exception handler middleware does not catch exceptions from upstream middleware
  • Static files served without authentication check
  • Response compression not applied because it runs before the response is generated

Check middleware order: ``csharp // Run with verbose logging to see middleware execution builder.Logging.SetMinimumLevel(LogLevel.Debug);

Common Causes

  • UseAuthentication registered before UseRouting
  • UseExceptionHandler registered after middleware that throws
  • UseCors registered after authentication middleware
  • UseStaticFiles registered after authorization middleware
  • Custom middleware placed in wrong position in pipeline

Step-by-Step Fix

  1. 1.Register middleware in the correct order:
  2. 2.```csharp
  3. 3.var builder = WebApplication.CreateBuilder(args);
  4. 4.var app = builder.Build();

// CORRECT middleware order:

// 1. Exception handler FIRST (catches everything) if (app.Environment.IsDevelopment()) { app.UseExceptionHandler("/error"); }

// 2. HSTS and HTTPS redirection app.UseHsts(); app.UseHttpsRedirection();

// 3. Static files (before auth, for public assets) app.UseStaticFiles();

// 4. Routing (determines which endpoint handles the request) app.UseRouting();

// 5. CORS (must be after routing, before auth) app.UseCors("DefaultPolicy");

// 6. Authentication (who are you?) app.UseAuthentication();

// 7. Authorization (what are you allowed to do?) app.UseAuthorization();

// 8. Rate limiting app.UseRateLimiter();

// 9. Response compression (last before endpoints) app.UseResponseCompression();

// 10. Endpoints app.MapControllers(); app.Run();

// Request flow: ExceptionHandler -> StaticFiles -> Routing -> CORS -> Auth -> Authz -> RateLimit -> Compression -> Controller // Response flow: Controller -> Compression -> RateLimit -> Authz -> Auth -> CORS -> Routing -> StaticFiles -> ExceptionHandler ```

  1. 1.**Fix CORS being blocked by authentication":
  2. 2.```csharp
  3. 3.// WRONG - auth runs before CORS, rejects OPTIONS preflight
  4. 4.app.UseAuthentication();
  5. 5.app.UseCors("DefaultPolicy"); // Too late!

// CORRECT - CORS before authentication app.UseCors("DefaultPolicy"); // Handles OPTIONS preflight app.UseAuthentication(); // Then checks auth ```

  1. 1.**Add custom middleware at the correct position":
  2. 2.```csharp
  3. 3.// Request logging middleware - place early to capture all requests
  4. 4.app.UseMiddleware<RequestLoggingMiddleware>();

// After routing (to know endpoint info) but before auth app.UseRouting(); app.UseMiddleware<EndpointMetricsMiddleware>();

// After auth (to log user context) app.UseAuthentication(); app.UseMiddleware<AuditLoggingMiddleware>(); ```

  1. 1.**Create middleware ordering validation":
  2. 2.```csharp
  3. 3.public static class MiddlewareOrderValidator
  4. 4.{
  5. 5.public static void ValidateOrder(this IApplicationBuilder app)
  6. 6.{
  7. 7.var features = app.Properties["server.Features"] as FeatureCollection;
  8. 8.// Log the configured middleware order for review
  9. 9.Console.WriteLine("Middleware pipeline configured successfully");
  10. 10.}
  11. 11.}

// In Program.cs app.ValidateOrder(); ```

Prevention

  • Document the middleware order in Program.cs with comments
  • Follow Microsoft's recommended order: ExceptionHandler -> StaticFiles -> Routing -> CORS -> Auth -> Authz -> Endpoints
  • Test CORS preflight requests in integration tests
  • Verify authentication does not block public endpoints
  • Use app.Environment.IsDevelopment() for development-specific middleware
  • Write middleware integration tests that verify request pipeline behavior