Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Middleware

Khái niệm

Middleware là các component nằm trong pipeline xử lý request/response. Mỗi middleware có thể:

  • Xử lý request trước khi chuyển cho middleware tiếp theo
  • Xử lý response sau khi các middleware trước đó đã xử lý
  • Quyết định không chuyển request cho middleware tiếp theo (short-circuit)

Pipeline Execution Order

┌────────────────────────────────────────────────────────────────────┐
│                        REQUEST PIPELINE                           │
├────────────────────────────────────────────────────────────────────┤
│                                                                    │
│  ┌──────────┐    ┌──────────┐    ┌──────────┐    ┌──────────┐    │
│  │  Logging │───▶│ Routing  │───▶│ Auth     │───▶│ Endpoint │    │
│  │ Middleware   │ Middleware   │ Middleware   │ (Controller) │    │
│  └──────────┘    └──────────┘    └──────────┘    └──────────┘    │
│       ▲                                                    │       │
│       │                                                    ▼       │
│       │                   ┌──────────┐    ┌──────────┐           │
│       └───────────────────│ Response │◀───│ Error    │           │
│                           │ Middleware   │ Middleware   │           │
│                           └──────────┘    └──────────┘           │
│                                                                    │
└────────────────────────────────────────────────────────────────────┘

Thứ tự quan trọng

  1. Exception Handling - Đầu tiên để bắt exceptions
  2. Security (CORS, Authentication, Authorization)
  3. Static Files - Nếu cần
  4. Routing - Xác định endpoint
  5. Endpoints - Controller/Action
  6. Custom Middleware

Cách viết Custom Middleware

1. Conventional Middleware Class

public class RequestTimingMiddleware
{
    private readonly RequestDelegate _next;
    private readonly ILogger<RequestTimingMiddleware> _logger;

    public RequestTimingMiddleware(
        RequestDelegate next, 
        ILogger<RequestTimingMiddleware> logger)
    {
        _next = next;
        _logger = logger;
    }

    public async Task InvokeAsync(HttpContext context)
    {
        var stopwatch = Stopwatch.StartNew();
        
        // Before next middleware
        _logger.LogInformation("Request started: {Path}", context.Request.Path);
        
        await _next(context); // Call next middleware
        
        // After next middleware
        stopwatch.Stop();
        _logger.LogInformation(
            "Request completed in {ElapsedMs}ms", 
            stopwatch.ElapsedMilliseconds);
    }
}

// Extension method để dễ đăng ký
public static class RequestTimingMiddlewareExtensions
{
    public static IApplicationBuilder UseRequestTiming(
        this IApplicationBuilder builder)
    {
        return builder.UseMiddleware<RequestTimingMiddleware>();
    }
}

// Đăng ký trong Program.cs
var app = builder.Build();
app.UseRequestTiming();

2. Inline Middleware (Minimal API)

var app = builder.Build();

app.Use(async (context, next) =>
{
    var stopwatch = Stopwatch.StartNew();
    
    await next();
    
    stopwatch.Stop();
    Console.WriteLine($"Request took {stopwatch.ElapsedMilliseconds}ms");
});

app.MapGet("/", () => "Hello World");
app.Run();

3. Middleware with Dependencies

public class CustomMiddleware
{
    private readonly RequestDelegate _next;
    private readonly IConfiguration _config;

    public CustomMiddleware(
        RequestDelegate next,
        IConfiguration config)
    {
        _next = next;
        _config = config;
    }

    public async Task InvokeAsync(HttpContext context)
    {
        // Sử dụng injected dependencies
        var timeout = _config.GetValue<int>("App:Timeout");
        
        await _next(context);
    }
}

Middleware vs Filters

Middleware

  • Hoạt động trên toàn bộ request pipeline
  • Thực thi trước khi routing xác định endpoint
  • Phù hợp cho: Logging, Authentication, CORS, Error handling

Filters (MVC/Web API)

  • Chỉ hoạt động cho MVC/Razor Pages actions
  • Có access đến ActionContext
  • Phù hợp cho: Model validation, Result caching, Exception handling cụ thể

Ví dụ so sánh

// Middleware - Cho toàn bộ app
app.Use(async (context, next) =>
{
    // Log mọi request
    await next();
});

// Filter - Chỉ cho MVC actions
public class ActionLogFilter : IActionFilter
{
    public void OnActionExecuting(ActionExecutingContext context)
    {
        // Log trước khi action chạy
    }

    public void OnActionExecuted(ActionExecutedContext context)
    {
        // Log sau khi action chạy
    }
}