تصور کنید یک کارخانه تولیدی را که در آن مواد اولیه از یک سری ایستگاههای کاری عبور میکنند تا در نهایت به محصول نهایی تبدیل شوند. در ASP.NET Core MVC، Pipeline پردازش درخواست HTTP دقیقاً همین نقش را ایفا میکند. این Pipeline مجموعهای از اجزای نرمافزاری به نام Middleware است که به ترتیب خاصی در کنار یکدیگر قرار گرفتهاند و هر کدام وظیفه خاصی را در طول چرخه حیات یک درخواست HTTP ورودی انجام میدهند.
هنگامی که یک کاربر از طریق مرورگر خود یک درخواست (Request) به سرور ASP.NET Core ارسال میکند، این درخواست ابتدا وارد Pipeline میشود. سپس، این درخواست از میان هر یک از Middlewareهای موجود در Pipeline عبور میکند. هر Middleware میتواند عملیات خاصی را بر روی درخواست (و یا پاسخ نهایی) انجام دهد، مانند:
در نهایت، پس از عبور درخواست از تمامی Middlewareهای موجود در Pipeline (یا در صورت وجود، قبل از رسیدن به انتهای Pipeline)، درخواست به Endpoint نهایی برنامه میرسد. در یک برنامه ASP.NET Core MVC، این Endpoint معمولاً یک Action Method در یک Controller است که منطق اصلی پردازش درخواست و تولید پاسخ را بر عهده دارد. پس از اینکه Action Method پاسخ (Response) را تولید کرد، این پاسخ نیز مجدداً از طریق Pipeline و به صورت معکوس از میان همان Middlewareها عبور میکند تا قبل از ارسال به کاربر، پردازشهای لازم (مانند افزودن هدرها، فشردهسازی و غیره) بر روی آن انجام شود.
Middleware در ASP.NET Core MVC، یک جزء نرمافزاری مستقل و قابل استفاده مجدد است که میتواند برای انجام وظایف خاص در طول پردازش درخواست و پاسخ HTTP به Pipeline اضافه شود. هر Middleware به عنوان یک حلقه در زنجیره Pipeline عمل میکند و مسئول انجام یک عمل خاص است.
Middlewareها معمولاً به صورت کلاسهایی پیادهسازی میشوند که دارای یک متد به نام InvokeAsync (یا Invoke) هستند. این متد دو پارامتر اصلی دریافت میکند:
HttpContext: که شامل اطلاعات مربوط به درخواست HTTP جاری (مانند متد، هدرها، بدنه درخواست و غیره) و همچنین اطلاعات مربوط به پاسخ HTTP در حال ساخت است.
RequestDelegate next: که نماینده (Delegate) Middleware بعدی در Pipeline است.
نحوه عملکرد یک Middleware به این صورت است که ابتدا منطق مربوط به خود را بر روی HttpContext اعمال میکند. سپس، میتواند تصمیم بگیرد که آیا درخواست را به Middleware بعدی در Pipeline ارسال کند یا خیر. اگر Middleware متد next را فراخوانی کند، درخواست به Middleware بعدی منتقل میشود. اگر Middleware متد next را فراخوانی نکند، پردازش Pipeline متوقف شده و Middleware میتواند پاسخ نهایی را تولید و ارسال کند (اصطلاحاً به این عمل Short-circuiting یا میانبُر زدن Pipeline گفته میشود).
علاوه بر پیادهسازی به صورت کلاس، Middlewareها میتوانند به صورت Anonymous Middleware یا Middlewareهای درونخطی نیز تعریف شوند. این نوع Middlewareها معمولاً برای انجام وظایف ساده و کوتاه استفاده میشوند و به صورت یک Delegate در هنگام پیکربندی Pipeline تعریف میگردند.
Middlewareها در ASP.NET Core MVC طیف وسیعی از وظایف را بر عهده دارند و نقش بسیار مهمی در عملکرد و قابلیتهای برنامههای وب ایفا میکنند. برخی از مهمترین کارکردهای Middlewareها عبارتند از:
عملکرد Pipeline و Middleware در ASP.NET Core MVC به صورت یک زنجیره متصل از اجزا صورت میگیرد. هنگامی که یک درخواست HTTP وارد برنامه میشود، مراحل زیر به ترتیب انجام میشوند:
نکته کلیدی در عملکرد Pipeline، ترتیب قرارگیری Middlewareها است. ترتیبی که Middlewareها در Pipeline پیکربندی میشوند، تأثیر مستقیمی بر نحوه پردازش درخواست و پاسخ دارد. برای مثال، Middleware احراز هویت باید قبل از Middleware مجوزدهی قرار گیرد، زیرا ابتدا باید هویت کاربر مشخص شود تا بتوان مجوز دسترسی او را بررسی کرد. به همین ترتیب، Middleware مدیریت خطا معمولاً در ابتدای Pipeline قرار میگیرد تا بتواند هرگونه خطای احتمالی در طول پردازش درخواست توسط سایر Middlewareها یا Endpoint را مدیریت کند.
Pipeline در ASP.NET Core MVC در متد Configure کلاس Startup.cs پیکربندی میشود. شیء IApplicationBuilder که به این متد تزریق میشود، برای افزودن Middlewareها به Pipeline استفاده میشود. متدهای Extension مختلفی بر روی IApplicationBuilder وجود دارند که برای افزودن Middlewareهای مختلف به کار میروند. برخی از رایجترین این متدها عبارتند از:
مثال ساده از پیکربندی Pipeline در Startup.cs:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseSession();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
}
در این مثال، Middlewareها به ترتیب زیر به Pipeline اضافه شدهاند:
توسعهدهندگان میتوانند Middlewareهای سفارشی خود را برای انجام منطق خاص مورد نیاز برنامه ایجاد کنند. برای ایجاد یک Middleware سفارشی، معمولاً یک کلاس ایجاد میشود که دارای شرایط زیر است:
کلاس باید دارای یک متد به نام InvokeAsync باشد.
متد InvokeAsync باید دو پارامتر دریافت کند: HttpContext و RequestDelegate next.
کلاس Middleware میتواند از طریق سازنده (Constructor Injection) به سرویسهای مورد نیاز خود دسترسی پیدا کند.
مثال از یک Middleware سفارشی برای ثبت زمان پردازش درخواست:
public class RequestTimeMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger _logger;
public RequestTimeMiddleware(RequestDelegate next, ILogger logger)
{
_next = next;
_logger = logger;
}
public async Task InvokeAsync(HttpContext context)
{
var startTime = Stopwatch.StartNew();
await _next(context); // فراخوانی Middleware بعدی
startTime.Stop();
_logger.LogInformation($"Request to {context.Request.Path} took {startTime.ElapsedMilliseconds} ms");
}
}
برای استفاده از این Middleware سفارشی، باید آن را در متد Configure به Pipeline اضافه کنیم:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
// سایر Middlewareها...
app.UseMiddleware(); // افزودن Middleware سفارشی
// سایر Middlewareها...
}
همچنین، میتوان یک Middleware سفارشی را به صورت یک Middleware درونخطی (Anonymous Middleware) تعریف کرد:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
// سایر Middlewareها...
app.Use(async (context, next) => {
var startTime = Stopwatch.StartNew();
await next(); // فراخوانی Middleware بعدی
startTime.Stop();
Log.Information($"Request to {context.Request.Path} took {startTime.ElapsedMilliseconds} ms");
});
// سایر Middlewareها...
}
ASP.NET Core دارای مجموعهای از Middlewareهای داخلی است که برای انجام وظایف رایج استفاده میشوند. در اینجا به برخی از مهمترین آنها اشاره میکنیم:
Middlewareها نقش اساسی در معماری ASP.NET Core MVC ایفا میکنند و مزایای متعددی را برای توسعهدهندگان فراهم میکنند:
برای استفاده موثر از Middleware در ASP.NET Core، رعایت برخی از بهترین روشها توصیه میشود:
Pipeline و Middleware مفاهیم اساسی در ASP.NET Core MVC هستند که نحوه پردازش درخواستهای HTTP را تعیین میکنند. Middlewareها اجزای قابل استفاده مجددی هستند که میتوانند برای افزودن قابلیتهای مختلف به Pipeline استفاده شوند. درک صحیح این مفاهیم برای هر توسعهدهنده ASP.NET Core ضروری است، زیرا به آنها امکان میدهد برنامههای وب ماژولار، انعطافپذیر و کارآمد را بسازند. با استفاده از Middlewareهای داخلی و سفارشی، توسعهدهندگان میتوانند به راحتی منطق مورد نیاز خود را به برنامههای خود اضافه کرده و عملکرد و امنیت آنها را بهبود بخشند.
2 نظر