1️⃣ با یک متد Use در کلاس WebApplication
شما میتوانید یک متد Use را روی کلاس WebApplication فراخوانی کنید تا یک middleware بسازید:
var builder = WebApplication.CreateBuilder(args);
builder.Logging.AddConsole();
var app = builder.Build();
app.Use(async (context, next) =>
{
Console.WriteLine("Request is starting...");
await next();
Console.WriteLine("Request has finished");
});
app.MapGet("/api/books", () =>
{
var books = SeedService.GetBooks(10);
return Results.Ok(books);
});
await app.RunAsync();
در این مثال هنگام فراخوانی یک endpoint به آدرس /api/books، ابتدا middleware تعریف شده در متد Use فراخوانی میشود. await next.Invoke() خودِ endpoint کتابها را فراخوانی میکند، اما قبل و بعد از آن ما یک پیام در کنسول لاگ کردهایم:
Request is starting...
Request has finished
میدلور ها به ترتیبی که به پایپلاین در آبجکت WebApplication اضافه شدهاند، اجرا میشوند. هر middleware میتواند عملیاتی را قبل و بعد از middleware بعدی انجام دهد:
🔹 قبل: اجرای عملیات قبل از فراخوانی middleware بعدی میتواند شامل تسکهایی مانند لاگینگ، احراز هویت، اعتبارسنجی و غیره باشد.
🔹 بعد: عملیات پس از فراخوانی middleware بعدی میتواند شامل تسکهایی مانند تغییر پاسخ یا مدیریت خطا باشد.
قدرت واقعی middlewareها این است که شما میتوانید آنها را آزادانه به هر ترتیبی که میخواهید، زنجیرهای کنید. برای متوقف کردن اجرای درخواست و short-cut کردن زنجیره middleware (متوقف کردن اجرای middlewareهای دیگر) - یک پاسخ را مستقیماً در HttpContext بنویسید به جای فراخوانی متد await next.Invoke():
await context.Response.WriteAsync("Some response here");2️⃣ با یک کلاس Middleware بر اساس قرارداد (By Convention)
شما میتوانید یک middleware را به یک کلاس جداگانه که از قرارداد خاصی پیروی میکند، استخراج کنید:
public class LoggingMiddleware
{
private readonly RequestDelegate _next;
public LoggingMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task InvokeAsync(HttpContext context)
{
Console.WriteLine($"Request: {context.Request.Method} {context.Request.Path}");
await _next(context);
Console.WriteLine($"Response: {context.Response.StatusCode}");
}
}
برای افزودن این middleware به پایپلاین، متد UseMiddleware را روی کلاس WebApplication فراخوانی کنید:
app.Use(async (context, next) =>
{
// Middleware از مثال قبلی
});
app.UseMiddleware<LoggingMiddleware>();
در نتیجه اجرای این middleware، موارد زیر هنگام اجرای یک endpoint به آدرس /api/books در کنسول لاگ خواهد شد:
Request is starting...
Request: GET /api/books
Response: 200
Request has finished
این رویکرد "بر اساس قرارداد" نامیده میشود، زیرا کلاس middleware باید از این قوانین پیروی کند:
✅ کلاس middleware باید یک متد InvokeAsync با یک آرگومان الزامی HttpContext داشته باشد.
✅ کلاس middleware باید یک RequestDelegate بعدی را در سازنده تزریق کند.
✅ کلاس middleware، delegate RequestDelegate بعدی را فراخوانی کرده و آرگومان HttpContext را به آن پاس دهد.