در نگارشهای دیگر ASP.NET، برای دسترسی به اطلاعات درخواست وب جاری، میتوان از خاصیت استاتیک System.Web.HttpContext.Current استفاده کرد. با حذف شدن System.Web از ASP.NET Core و همچنین بهبود طراحی آن جهت سازگاری کامل با مفاهیم تزریق وابستگیها، دیگر روش استفادهی مستقیم از خواص استاتیک توصیه نشده و بجای آن تزریق اینترفیس ویژهی IHttpContextAccessor توصیه میشود.
دسترسی به اطلاعات درخواست وب جاری در ASP.NET Core
برای دسترسی به اطلاعات درخواست جاری در ASP.NET Core، میتوان از طریق تزریق سرویس جدید IHttpContextAccessor اقدام کرد. این اینترفیس دارای تک خاصیت HttpContext است که به صورت پیش فرض جزو سرویسهای از پیش ثبت شدهی ASP.NET Core نیستو برای اینکه تزریق وابستگیها در اینجا به درستی صورت گیرد، طول عمر این سرویس باید به صورت singleton تنظیم شود:
روش کارکرد این سرویس نیز به صورت ذیل است:
- هر زمانیکه درخواست جدیدی برای پردازش فرا میرسد، 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 جدید را به آن اضافه میکنیم:
سپس جهت دسترسی به این اطلاعات در یک کلاس دیگر میتوان به صورت ذیل عمل کرد:
در اینجا در کلاسی قرار داریم که مستقیما ارتباطی به کنترلر جاری نداشته و دسترسی مستقیمی به خاصیت HttpContext آن ندارد. بنابراین برای دسترسی به اطلاعات موجود در HttpContext جاری میتوان سرویس IHttpContextAccessor را به سازندهی این کلاس تزریق کرد و سپس با کمک خاصیت contextAccessor.HttpContext آن، به اطلاعات مدنظر دسترسی یافت.
دسترسی به اطلاعات درخواست وب جاری در 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}!"; } }