ترتیب middlewareها 🧱
در این دیاگرام کل pipeline پردازش درخواست در ASP.NET Core MVC و Razor Pages را نشان میدهد.
میتوانید ببینید که در یک اپلیکیشن معمولی، middlewareهای موجود چه ترتیبی دارند و middlewareهای سفارشی کجا اضافه میشوند.
شما کنترل کامل دارید که middlewareهای موجود را جابهجا کنید یا middleware جدید تزریق کنید، متناسب با سناریوهای خودتان. 🔧
ءEndpoint middleware در دیاگرام بالا، filter pipeline مربوط به نوع اپلیکیشن (MVC یا Razor Pages) را اجرا میکند.
ءRouting middleware در دیاگرام بالا بعد از Static Files نشان داده شده است.
این همان ترتیبی است که قالبهای پیشفرض پروژه با فراخوانی صریح app.UseRouting پیادهسازی میکنند.
اگر app.UseRouting را صدا نزنید، Routing middleware بهصورت پیشفرض در ابتدای pipeline اجرا میشود.
برای اطلاعات بیشتر، بخش Routing را ببینید.
ترتیبی که middlewareها در فایل Program.cs اضافه میشوند، دقیقاً ترتیب اجرای آنها روی request و ترتیب معکوس برای response را مشخص میکند.
این ترتیب برای امنیت، کارایی و عملکرد صحیح کاملاً حیاتی است. ⚠️
ترتیب پیشنهادی middlewareهای امنیتی
کد زیر در Program.cs middlewareهای مربوط به امنیت را در ترتیب توصیهشده اضافه میکند:
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using WebMiddleware.Data;
var builder = WebApplication.CreateBuilder(args);
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection")
?? throw new InvalidOperationException("Connection string 'DefaultConnection' not found.");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(connectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<ApplicationDbContext>();
builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseMigrationsEndPoint();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
// app.UseCookiePolicy();
app.UseRouting();
// app.UseRateLimiter();
// app.UseRequestLocalization();
// app.UseCors();
app.UseAuthentication();
app.UseAuthorization();
// app.UseSession();
// app.UseResponseCompression();
// app.UseResponseCaching();
app.MapRazorPages();
app.MapDefaultControllerRoute();
app.Run();
در کد بالا: middlewareهایی که هنگام ساخت یک وباپ با حساب کاربری فردی اضافه نمیشوند، کامنت شدهاند.
همهی middlewareها دقیقاً در همین ترتیب ظاهر نمیشوند، اما بسیاری از آنها همینطور هستند. برای مثال:
قوانین مهم ترتیب middlewareها 📌
ءUseCors، UseAuthentication و UseAuthorization باید دقیقاً به همین ترتیب باشند.
ءUseCors در حال حاضر باید قبل از UseResponseCaching قرار بگیرد. این الزام در GitHub issue شماره dotnet/aspnetcore #23218 توضیح داده شده است.
ءUseRequestLocalization باید قبل از هر middlewareای باشد که ممکن است culture درخواست را بررسی کند، مثلاً ()app.UseStaticFiles
وقتی rate limiting بهصورت endpoint-specific استفاده میشود (مثلاً با [EnableRateLimiting])، باید UseRateLimiter بعد از UseRouting صدا زده شود.
اگر فقط global limiterها استفاده شوند، میتوان UseRateLimiter را قبل از UseRouting هم صدا زد.
ترتیبهای جایگزین در برخی سناریوها
در بعضی سناریوها ترتیب middleware متفاوت است.
مثلاً ترتیب caching و compression وابسته به سناریو است و چندین ترتیب معتبر وجود دارد. برای مثال:
app.UseResponseCaching();
app.UseResponseCompression();
در این حالت، مصرف CPU ممکن است کاهش پیدا کند چون response فشردهشده cache میشود،
اما ممکن است چند نسخهی مختلف از یک resource با الگوریتمهای فشردهسازی متفاوت مثل Gzip یا Brotli در cache ذخیره شوند. 📦