Client
↓ Reverse Proxy (optional)
↓ Kestrel Web Server
↓ ASP.NET Core Hosting Layer
↓ Middleware Pipeline
↓ Endpoint Routing
↓ Endpoint Execution (Controller / Minimal API)
↓ Middleware (Response Flow)
↓ Kestrel
↓ Client Response CODE_BLOCK: Client
↓ Reverse Proxy (optional)
↓ Kestrel Web Server
↓ ASP.NET Core Hosting Layer
↓ Middleware Pipeline
↓ Endpoint Routing
↓ Endpoint Execution (Controller / Minimal API)
↓ Middleware (Response Flow)
↓ Kestrel
↓ Client Response CODE_BLOCK: Client
↓ Reverse Proxy (optional)
↓ Kestrel Web Server
↓ ASP.NET Core Hosting Layer
↓ Middleware Pipeline
↓ Endpoint Routing
↓ Endpoint Execution (Controller / Minimal API)
↓ Middleware (Response Flow)
↓ Kestrel
↓ Client Response CODE_BLOCK: app.Use(async (context, next) => { var logger = context.RequestServices .GetRequiredService<ILoggerFactory>() .CreateLogger("RequestLogger"); logger.LogInformation("Request started: {Path}", context.Request.Path); await next(); logger.LogInformation("Response finished with status {StatusCode}", context.Response.StatusCode); }); CODE_BLOCK: app.Use(async (context, next) => { var logger = context.RequestServices .GetRequiredService<ILoggerFactory>() .CreateLogger("RequestLogger"); logger.LogInformation("Request started: {Path}", context.Request.Path); await next(); logger.LogInformation("Response finished with status {StatusCode}", context.Response.StatusCode); }); CODE_BLOCK: app.Use(async (context, next) => { var logger = context.RequestServices .GetRequiredService<ILoggerFactory>() .CreateLogger("RequestLogger"); logger.LogInformation("Request started: {Path}", context.Request.Path); await next(); logger.LogInformation("Response finished with status {StatusCode}", context.Response.StatusCode); }); CODE_BLOCK: Request → Middleware → Endpoint Response ← Middleware ← Endpoint CODE_BLOCK: Request → Middleware → Endpoint Response ← Middleware ← Endpoint CODE_BLOCK: Request → Middleware → Endpoint Response ← Middleware ← Endpoint CODE_BLOCK: app.Use(async (context, next) => { if (!context.User.Identity?.IsAuthenticated ?? true) { context.Response.StatusCode = StatusCodes.Status401Unauthorized; return; } await next(); }); CODE_BLOCK: app.Use(async (context, next) => { if (!context.User.Identity?.IsAuthenticated ?? true) { context.Response.StatusCode = StatusCodes.Status401Unauthorized; return; } await next(); }); CODE_BLOCK: app.Use(async (context, next) => { if (!context.User.Identity?.IsAuthenticated ?? true) { context.Response.StatusCode = StatusCodes.Status401Unauthorized; return; } await next(); }); CODE_BLOCK: app.UseRouting(); CODE_BLOCK: app.UseRouting(); CODE_BLOCK: app.UseRouting(); CODE_BLOCK: app.UseAuthentication(); CODE_BLOCK: app.UseAuthentication(); CODE_BLOCK: app.UseAuthentication(); CODE_BLOCK: app.UseAuthorization(); CODE_BLOCK: app.UseAuthorization(); CODE_BLOCK: app.UseAuthorization(); CODE_BLOCK: app.UseExceptionHandler(); CODE_BLOCK: app.UseExceptionHandler(); CODE_BLOCK: app.UseExceptionHandler(); CODE_BLOCK: app.UseAuthorization(); app.UseAuthentication(); CODE_BLOCK: app.UseAuthorization(); app.UseAuthentication(); CODE_BLOCK: app.UseAuthorization(); app.UseAuthentication(); CODE_BLOCK: app.UseAuthentication(); app.UseAuthorization(); CODE_BLOCK: app.UseAuthentication(); app.UseAuthorization(); CODE_BLOCK: app.UseAuthentication(); app.UseAuthorization(); CODE_BLOCK: app.MapGet("/products/{id}", (int id) => { return Results.Ok($"Product {id}"); }); CODE_BLOCK: app.MapGet("/products/{id}", (int id) => { return Results.Ok($"Product {id}"); }); CODE_BLOCK: app.MapGet("/products/{id}", (int id) => { return Results.Ok($"Product {id}"); }); CODE_BLOCK: GET /products/10 CODE_BLOCK: GET /products/10 CODE_BLOCK: GET /products/10 CODE_BLOCK:
[HttpPost] public IActionResult CreateOrder(OrderDto order) CODE_BLOCK:
[HttpPost] public IActionResult CreateOrder(OrderDto order) CODE_BLOCK:
[HttpPost] public IActionResult CreateOrder(OrderDto order) CODE_BLOCK: public class OrderDto {
[Required] public string CustomerEmail { get; set; } } CODE_BLOCK: public class OrderDto {
[Required] public string CustomerEmail { get; set; } } CODE_BLOCK: public class OrderDto {
[Required] public string CustomerEmail { get; set; } } CODE_BLOCK: return Ok(order); CODE_BLOCK: return Ok(order); CODE_BLOCK: return Ok(order); CODE_BLOCK: app.Use(async (context, next) => { var stopwatch = Stopwatch.StartNew(); await next(); stopwatch.Stop(); var logger = context.RequestServices .GetRequiredService<ILoggerFactory>() .CreateLogger("Performance"); logger.LogInformation("Request completed in {Elapsed} ms", stopwatch.ElapsedMilliseconds); }); CODE_BLOCK: app.Use(async (context, next) => { var stopwatch = Stopwatch.StartNew(); await next(); stopwatch.Stop(); var logger = context.RequestServices .GetRequiredService<ILoggerFactory>() .CreateLogger("Performance"); logger.LogInformation("Request completed in {Elapsed} ms", stopwatch.ElapsedMilliseconds); }); CODE_BLOCK: app.Use(async (context, next) => { var stopwatch = Stopwatch.StartNew(); await next(); stopwatch.Stop(); var logger = context.RequestServices .GetRequiredService<ILoggerFactory>() .CreateLogger("Performance"); logger.LogInformation("Request completed in {Elapsed} ms", stopwatch.ElapsedMilliseconds); }); CODE_BLOCK: Request Flow Summary Client
↓ Kestrel
↓ Middleware Pipeline
↓ Routing
↓ Endpoint Execution
↓ Middleware (response)
↓ Client CODE_BLOCK: Request Flow Summary Client
↓ Kestrel
↓ Middleware Pipeline
↓ Routing
↓ Endpoint Execution
↓ Middleware (response)
↓ Client CODE_BLOCK: Request Flow Summary Client
↓ Kestrel
↓ Middleware Pipeline
↓ Routing
↓ Endpoint Execution
↓ Middleware (response)
↓ Client
- Listen for incoming HTTP requests
- Parse HTTP messages
- Forward the request into the ASP.NET Core application pipeline
- Azure App Service infrastructure
- Builds the dependency injection container
- Configures logging
- Loads configuration
- Constructs the middleware pipeline
- Inspect the request
- Modify the request
- Stop the request from continuing
- Pass the request to the next component
- Modify the response before it leaves
- The request enters the middleware
- Code before await next() runs
- The request moves to the next middleware
- Eventually an endpoint executes
- The response travels back through middleware
- Code after await next() runs - authentication checks - rate limiting - request filtering
- CORS (UseCors)
- Response compression (UseResponseCompression)
- HTTPS redirection (UseHttpsRedirection)
- Rate limiting (UseRateLimiter)
- HTTP method (GET, POST, etc.) - request path - route parameters - a controller action - a minimal API handler - a Razor page - a gRPC service - request body - route values - query parameters - database queries - calling services - performing calculations - invoking external APIs - objects → JSON - status codes → HTTP response codes - headers → HTTP headers - modify response headers - compress responses - log execution time - transform output