نوشتن Middleware سفارشی در ASP.NET Core 🧩
ءMiddleware نرمافزاری است که در قالب یک pipeline داخل برنامه کنار هم قرار میگیرد تا درخواستها (requests) و پاسخها (responses) را مدیریت کند.
ءASP.NET Core مجموعهی غنیای از middlewareهای داخلی (built-in) را ارائه میدهد، اما در بعضی سناریوها ممکن است بخواهید یک middleware سفارشی (custom middleware) بنویسید.
کلاس Middleware
ءMiddleware معمولاً داخل یک کلاس کپسوله میشود و از طریق یک extension method در دسترس قرار میگیرد. مثال زیر یک middleware درونخطی (inline) را نشان میدهد که culture مربوط به درخواست جاری را از روی query string تنظیم میکند:
using System.Globalization;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.UseHttpsRedirection();
app.Use(async (context, next) =>
{
var cultureQuery = context.Request.Query["culture"];
if (!string.IsNullOrWhiteSpace(cultureQuery))
{
var culture = new CultureInfo(cultureQuery);
CultureInfo.CurrentCulture = culture;
CultureInfo.CurrentUICulture = culture;
}
// Call the next delegate/middleware in the pipeline.
await next(context);
});
app.Run(async (context) =>
{
await context.Response.WriteAsync(
$"CurrentCulture.DisplayName: {CultureInfo.CurrentCulture.DisplayName}");
});
app.Run();
ءMiddleware درونخطی بالا برای نمایش نحوهی ساخت یک middleware با استفاده از متد Microsoft.AspNetCore.Builder.UseExtensions.Use استفاده شده است. این متد، یک delegate تعریفشده بهصورت درونخطی را به pipeline درخواستهای برنامه اضافه میکند.
متدهای Use
دو overload برای متد Use وجود دارد:
یکی که HttpContext و <Func<Task میگیرد. در این حالت <Func<Task بدون پارامتر فراخوانی میشود.
دیگری که HttpContext و RequestDelegate میگیرد. در این حالت RequestDelegate با ارسال HttpContext فراخوانی میشود.
استفاده از overload دوم ترجیح داده میشود چون باعث صرفهجویی در دو allocation داخلی در هر درخواست میشود. ⚡️
تست Middleware
میتوانید middleware را با ارسال culture تست کنید. مثلاً:
https://localhost:5001/?culture=es-es
انتقال Middleware به یک کلاس
کد زیر همان middleware قبلی را داخل یک کلاس قرار میدهد:
using System.Globalization;
namespace Middleware.Example;
public class RequestCultureMiddleware
{
private readonly RequestDelegate _next;
public RequestCultureMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task InvokeAsync(HttpContext context)
{
var cultureQuery = context.Request.Query["culture"];
if (!string.IsNullOrWhiteSpace(cultureQuery))
{
var culture = new CultureInfo(cultureQuery);
CultureInfo.CurrentCulture = culture;
CultureInfo.CurrentUICulture = culture;
}
// Call the next delegate/middleware in the pipeline.
await _next(context);
}
}
الزامات کلاس Middleware
کلاس middleware باید شامل موارد زیر باشد:
• یک constructor عمومی با پارامتر از نوع RequestDelegate
• یک متد عمومی به نام Invoke یا InvokeAsync که:
• مقدار بازگشتی آن Task باشد
• اولین پارامتر آن از نوع HttpContext باشد
پارامترهای اضافی در constructor و متد Invoke/InvokeAsync از طریق Dependency Injection (DI) مقداردهی میشوند. 💉
Extension Method برای Middleware
معمولاً یک extension method ساخته میشود تا middleware از طریق IApplicationBuilder قابل استفاده باشد: