دسترسی به اطلاعات درخواست وب جاری در ASP.NET Core
برای دسترسی به اطلاعات درخواست جاری در ASP.NET Core، میتوان از طریق تزریق سرویس جدید IHttpContextAccessor اقدام کرد. این اینترفیس دارای تک خاصیت HttpContext است که به صورت پیش فرض جزو سرویسهای از پیش ثبت شدهی ASP.NET Core نیست و برای اینکه تزریق وابستگیها در اینجا به درستی صورت گیرد، طول عمر این سرویس باید به صورت singleton تنظیم شود:
public void ConfigureServices(IServiceCollection services) { services.AddMvc(); services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>(); }
- هر زمانیکه درخواست جدیدی برای پردازش فرا میرسد، IHttpContextFactory کار ایجاد یک HttpContext جدید را آغاز میکند.
- اگر سرویس IHttpContextAccessor پیشتر ثبت شده باشد، IHttpContextFactory کار مقدار دهی HttpContext آنرا نیز انجام میدهد.
- اینجا شاید این سؤال مطرح شود که طول عمر IHttpContextAccessor «باید» به صورت singleton ثبت شود. پس این سرویس چگونه میتواند HttpContextهای مختلفی را شامل شود؟ کلاس HttpContextAccessor که پیاده سازی کنندهی IHttpContextAccessor است، دارای یک خاصیت AsyncLocal است که از این خاصیت جهت ذخیره سازی اطلاعات Contextهای مختلف استفاده میشود. بنابراین کلاس HttpContextAccessor دارای طول عمر singleton است، اما خاصیت AsyncLocal آن دارای طول عمری محدود به یک درخواست (request scoped) میباشد.
بنابراین به صورت خلاصه:
- هرجایی که نیاز به اطلاعات HTTP context وجود داشت، از تزریق اینترفیس IHttpContextAccessor استفاده کنید.
- ثبت سرویس IHttpContextAccessor را در ابتدای برنامه فراموش نکنید.
- طول عمر سرویس ثبت شدهی IHttpContextAccessor باید singleton باشد.
یک نکته: اگر از ASP.NET Core Identity استفاده میکنید، متد services.AddIdentity کار ثبت سرویس IHttpContextAccessor را نیز انجام میدهد.
یک مثال: ذخیره سازی اطلاعاتی با طول عمر کوتاه در HttpContext و سپس دسترسی به آنها در کلاسهای دیگر برنامه
استفادهی از مجموعهی Items شیء HttpContext، یکی از روشهایی است که از آن میتوان جهت ذخیره سازی اطلاعات موقتی و محدود به طول عمر درخواست جاری استفاده کرد. برای مثال در یک کنترلر و اکشن متدی خاص، دو key/value جدید را به آن اضافه میکنیم:
public IActionResult ProcessForm() { HttpContext.Items["firstname"] = "Vahid"; HttpContext.Items["lastname"] = "N."; return View(); }
public class MyHelperClass { private readonly IHttpContextAccessor _contextAccessor; public MyHelperClass(IHttpContextAccessor contextAccessor) { _contextAccessor = contextAccessor; } public string DoWork() { string firstName = _contextAccessor.HttpContext.Items["firstname"].ToString(); string lastName = _contextAccessor.HttpContext.Items["lastname"].ToString(); return $"Hello {firstName} {lastName}!"; } }