Exercise 3: Custom Middleware
Objective
Create custom middleware to log requests and measure response times.
Implementation
public class RequestLoggingMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger<RequestLoggingMiddleware> _logger;
public RequestLoggingMiddleware(
RequestDelegate next,
ILogger<RequestLoggingMiddleware> logger)
{
_next = next;
_logger = logger;
}
public async Task InvokeAsync(HttpContext context)
{
var startTime = DateTime.UtcNow;
var requestId = Guid.NewGuid().ToString();
_logger.LogInformation(
"[{RequestId}] {Method} {Path} started",
requestId,
context.Request.Method,
context.Request.Path);
await _next(context);
var elapsed = DateTime.UtcNow - startTime;
_logger.LogInformation(
"[{RequestId}] {Method} {Path} completed in {ElapsedMs}ms with status {StatusCode}",
requestId,
context.Request.Method,
context.Request.Path,
elapsed.TotalMilliseconds,
context.Response.StatusCode);
context.Response.Headers.Add("X-Response-Time", elapsed.TotalMilliseconds.ToString());
context.Response.Headers.Add("X-Request-Id", requestId);
}
}
// Extension method
public static class MiddlewareExtensions
{
public static IApplicationBuilder UseRequestLogging(
this IApplicationBuilder builder)
{
return builder.UseMiddleware<RequestLoggingMiddleware>();
}
}
// Usage
app.UseRequestLogging();
Challenge Tasks
- Add API key validation middleware
- Create exception handling middleware
- Implement rate limiting middleware (simple counter)
- Add request/response body logging
Expected Outcome
- Custom middleware that logs all requests
- Response time header added to responses
- Understanding of middleware execution order