Lesson 10 of 45 intermediate

Request Lifecycle and the Middleware Pipeline

Every request walks through a chain, and the order of the chain is the logic

Guess first

Pick an answer. You will see if you were right at the end of the lesson.

A middleware calls await next(context) and then logs elapsed time. When does the log line run?

Open interactive version (quiz + challenge)

Real-world analogy

Think of airport departures. You pass check-in, then security, then passport control, then the gate. Each desk can stop you and send you home. Swap two desks and the checks make no sense. Here you are the HTTP request and each desk is a middleware. The order of the desks is the order of the rules.

What is it?

The ASP.NET Core request pipeline is a chain of small components called middleware. Kestrel turns the incoming bytes into an HttpContext and passes it down the chain. Each component can inspect or change the request, call the next one, and then inspect or change the response on the way back. You build the chain in Program.cs, and the order of the lines is the order of execution.

Real-world relevance

A common production bug is a wrong order. If CORS runs after authorization, a 401 goes back without CORS headers. The browser then shows a confusing CORS error instead of the real one. If the exception handler is not first, errors thrown by earlier middleware are not caught. Teams also write small middleware for correlation ids, request timing and tenant lookup, because it runs for every request without touching controllers.

Key points

Quick check

Answer from memory — scrolling up first makes it stick less.

What does it mean when a middleware short-circuits the pipeline?

Why does the order of app.Use... lines matter?

Code example

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddProblemDetails();
builder.Services.AddAuthentication();
builder.Services.AddAuthorization();
var app = builder.Build();

app.UseExceptionHandler();            // first: catches errors from everything below
app.UseHttpsRedirection();

// Inline middleware that wraps the rest of the pipeline
app.Use(async (context, next) =>
{
    var watch = Stopwatch.StartNew();
    await next(context);              // everything below runs here
    watch.Stop();
    app.Logger.LogInformation("{Method} {Path} took {Elapsed} ms",
        context.Request.Method, context.Request.Path, watch.ElapsedMilliseconds);
});

app.UseAuthentication();              // who are you?
app.UseAuthorization();               // what may you do?

app.MapGet("/ping", () => "pong");
app.Run();

Line-by-line walkthrough

  1. 1. AddProblemDetails gives UseExceptionHandler a standard error body. It goes first, so an error thrown by any later middleware lands in it.
  2. 2. UseHttpsRedirection sends plain HTTP callers to the HTTPS address before any real work happens.
  3. 3. The app.Use lambda starts a stopwatch, then awaits next(context). Everything registered below it runs inside that await.
  4. 4. When next returns, the response is already built. The code after it stops the watch and logs method, path and milliseconds.
  5. 5. UseAuthentication reads the token and sets the user. UseAuthorization then decides if that user may continue, so it must come second.
  6. 6. MapGet is the endpoint at the end of the chain. Run starts listening.

Spot the bug

app.UseHttpsRedirection();
app.UseAuthorization();    // runs first
app.UseAuthentication();   // runs second

app.MapGet("/me", (ClaimsPrincipal user) => user.Identity?.Name)
   .RequireAuthorization();
Need a hint?
Authorization needs to know who the user is. Which middleware tells it?
Show answer
UseAuthorization runs before UseAuthentication, so no user has been identified yet. Every request looks anonymous and /me returns 401 even with a valid token. Fix: put app.UseAuthentication() before app.UseAuthorization().

Explain like I'm 5

Imagine a line of helpers passing a letter from hand to hand. Each helper can check the letter, stop it, or pass it on. On the way back, each helper can add a note before it reaches you.

Fun fact

Since .NET 6 WebApplication adds routing for you, so you rarely write UseRouting yourself. Since .NET 7 it also adds authentication and authorization when those services are registered. Once you write those lines yourself, their order is your job.

Hands-on challenge

Say it out loud in 30 seconds: "How does the ASP.NET Core request pipeline work, and why does middleware order matter?" Then check: did you mention the next delegate, running before and after the rest of the chain, and a concrete wrong-order example?

More resources

Open interactive version (quiz + challenge) Download the whole course as PDF / Word

Lock it in

← Back to course: .NET + React Playbook