ASP.NET Middleware Standards
Before reviewing: Read .planning/CONVENTIONS.md for the repository's middleware conventions. Follow the established patterns for pipeline configuration.
Hard Rules for Review
Must Flag as Critical
- •Wrong middleware ordering — Authentication after Authorization, exception handler not first, routing after endpoints
- •Missing centralized exception handling — No
UseExceptionHandleror equivalent, allowing raw exceptions to reach clients - •No correlation ID — Requests processed without generating or propagating a correlation ID
- •Missing health checks — No health check endpoints for dependent services (database, message bus)
Must Flag as Important
- •
next()called multiple times — Middleware invokingnext(context)more than once, causing double-processing - •Missing CancellationToken propagation — Custom middleware not respecting
context.RequestAborted - •Logging sensitive data — Request/response logging that captures authentication tokens, PII, or financial details
- •Synchronous I/O in middleware — Blocking calls in the request pipeline
Pipeline Order
The order of middleware registration matters. Follow this ordering:
code
Request | +- 1. Exception Handler <- Catches all downstream exceptions +- 2. HSTS <- Strict transport security headers +- 3. HTTPS Redirection <- Redirect HTTP to HTTPS +- 4. Correlation ID <- Generate/read correlation ID (custom) +- 5. Request Logging <- Log request summary (custom) +- 6. Routing <- Match request to endpoint +- 7. Rate Limiting <- Throttle requests +- 8. Authentication <- Identify the caller +- 9. Authorization <- Check permissions +- 10. Custom Middleware <- Business-specific middleware +- 11. Endpoints <- Execute matched endpoint | Response
csharp
var app = builder.Build();
// 1. Exception handling — MUST be first
app.UseExceptionHandler();
// 2-3. Transport security
if (!app.Environment.IsDevelopment())
{
app.UseHsts();
}
app.UseHttpsRedirection();
// 4-5. Observability (custom middleware)
app.UseCorrelationId();
app.UseRequestLogging();
// 6. Routing
app.UseRouting();
// 7. Rate limiting
app.UseRateLimiter();
// 8-9. Auth
app.UseAuthentication();
app.UseAuthorization();
// 10. Health checks (before endpoints, after auth if health checks need auth)
app.MapHealthChecks("/health/ready", new HealthCheckOptions
{
Predicate = check => check.Tags.Contains("ready")
});
app.MapHealthChecks("/health/live", new HealthCheckOptions
{
Predicate = _ => false // Liveness = "is the process running?"
});
// 11. Endpoints
app.MapControllers();
Resilience & Auditability Rules
- •Correlation IDs are mandatory — Every request must have a correlation ID generated or propagated. This is non-negotiable for tracing operations across services
- •Health checks for all dependencies — Database, Service Bus, external APIs. Use readiness checks (
/health/ready) for load balancer decisions and liveness checks (/health/live) for container orchestration - •No internal details in error responses — Exception middleware must strip stack traces, SQL errors, and internal paths in non-development environments
- •Rate limiting on mutation endpoints — Payment and transfer endpoints must be rate-limited to prevent abuse
- •PII masking in request logs — Never log request/response bodies for endpoints that handle PII or sensitive data. Log path, method, status code, and duration only
Review Checklist
Pipeline Order
- • Exception handler is the first middleware registered?
- • Authentication before Authorization?
- • Routing before Auth middleware?
- • HTTPS redirection and HSTS configured for production?
Exception Handling
- • Centralized exception handler configured (UseExceptionHandler)?
- • ProblemDetails returned for all errors?
- • Stack traces excluded in non-development environments?
- • Correlation ID included in error responses?
Observability
- • Correlation ID middleware registered early in pipeline?
- • Correlation ID read from header or generated?
- • Correlation ID propagated to response headers?
- • Request logging captures method, path, status, duration?
- • Sensitive paths excluded from detailed logging?
Health Checks
- • Readiness endpoint (
/health/ready) checks all dependencies? - • Liveness endpoint (
/health/live) exists (minimal check)? - • Database health check configured?
- • Service Bus health check configured (if used)?
Custom Middleware
- •
next()called exactly once? - • Scoped services injected via
InvokeAsyncparameters (not constructor)? - •
context.RequestAbortedrespected for long operations? - • Middleware registered in correct pipeline position?
Resilience & Auditability
- • Correlation IDs on all requests?
- • Rate limiting on mutation endpoints?
- • PII excluded from request logs?
- • No internal details in production error responses?