.NET › ASP.NET Core Middleware & Request Pipeline

How do you write a custom middleware component as a reusable class instead of an inline lambda?

Intermediate

Answer

A class-based middleware implements a constructor accepting RequestDelegate next (and typically other injected services), and an InvokeAsync (or Invoke) method containing the actual per-request logic, then calling await next(context) to pass control to the next middleware. It's registered via a custom `app.UseMiddleware<T>()` call or, more idiomatically, an extension method wrapping that call.
public class RequestTimingMiddleware {
    private readonly RequestDelegate _next;
    public RequestTimingMiddleware(RequestDelegate next) => _next = next;

    public async Task InvokeAsync(HttpContext context) {
        var sw = Stopwatch.StartNew();
        await _next(context);
        Console.WriteLine($"{context.Request.Path} took {sw.ElapsedMilliseconds}ms");
    }
}

// Registration
app.UseMiddleware<RequestTimingMiddleware>();
Real-world example A team extracts an inline logging lambda into a proper RequestTimingMiddleware class once it grows complex enough to need dependency injection (like an ILogger) and unit testing, which inline lambdas can't easily support.

Common follow-ups: Why is a class-based middleware constructed once per app lifetime rather than per request?;How do you inject scoped services into middleware given this singleton-like construction?