0Pricing
C# Academy · Lesson

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 — 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, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

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 JSON

Static 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 policies

CORS 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 pipeline

Real-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

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, and the C# Academy course includes 4 lessons in total. 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.

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; this is — lesson 4 of 4, so you can start here or from the beginning and move at your own pace.

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

  1. ASP.NET Core Pipeline Overview
  2. Writing Custom Middleware
  3. Short-Circuiting & Branching
  4. Middleware Ordering & Built-in Middleware
← Back to C# Academy