دستیابی به HttpContext در Blazor Server
اندازه‌ی قلم متن
تخمین مدت زمان مطالعه‌ی مطلب: دو دقیقه

در Asp.net core توسط IHttpContextAccessor  می‌توان به‌راحتی به HttpContext در هرجای برنامه دسترسی داشت و اطلاعات مورد نیاز را از قبیل نام کاربری، کوکی‌ها، توکن‌ها و ... به دست آورد. اما در Blazor Server برای استفاده از این قبیل اطلاعات توصیه شده‌است که اکیدا از IHttpContextAccessor در هرجایی از برنامه استفاده نشود؛ زیرا هیچ تضمینی وجود ندارد که در حالت‌های مختلف، مقدار HttpContext معتبر باشد. برای کسب اطلاعات بیشتر در این باب می‌توانید به Blazor and shared state و Accessing HttpContext.Items fails on WebKit browsers مراجعه نمایید. درکل Blazor Server خارج از چارچوب خط لوله ASP.NET Core اجرا می‌شود. اما اگر به هر دلیلی به دنبال اطلاعات خاصی از HttpContext در کامپوننت‌ها باشیم چطور؟ آیا هیچ راهی وجود ندارد؟
برای دستیابی به HttpContext در Blazor Server فقط باید در زمان رندر شدن Host.cshtml_ مقدار(های) مدنظر را از HttpContext دریافت کرده و داخل متغیری ذخیره کنیم و در ادامه‌ی برنامه از آن متغیر در قالب Cascading Parameters در کامپوننت‌ها استفاده نماییم.
روش کار به اینصورت است که ابتدا فایل Host.cshtml_ را به شکل زیر اصلاح می‌کنیم. در اینجا ما به دنبال اطلاعات توکن access_token می‌باشیم.
 @{ 
        var token = await HttpContext.GetTokenAsync("access_token");
    }

 <component type="typeof(App)" render-mode="ServerPrerendered" param-AccessToken="token" />
همانطور که ملاحظه می‌نمایید اطلاعات توکن access_token را داخل متغیر token ریخته و آن‌را به param-AccessToken کامپوننت منتسب می‌کنیم.
سپس به فایل App.razor رفته و متغیر AccessToken را به عنوان یک Cascading Value تعریف می‌کنیم. به شکل زیر:
<CascadingValue Name="AccessToken" Value="AccessToken">
    <CascadingAuthenticationState>
        <Router AppAssembly="@typeof(Program).Assembly">
            <Found Context="routeData">
                <AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
            </Found>
            <NotFound>
                <LayoutView Layout="@typeof(MainLayout)">
                    <p>Sorry, there's nothing at this address.</p>
                </LayoutView>
            </NotFound>
        </Router>
    </CascadingAuthenticationState>
</CascadingValue>
@code{
    [Parameter]
     public string AccessToken { get; set; }
}
در پایان، هر کامپوننتی که نیاز به مقدار AccessToken را داشته باشد فقط کافیست آن‌را به عنوان یک Cascade Parameter تعریف کند. برای مثال یک کامپوننت را به نام ShowToken.razor ایجاد می‌کنیم و کدهای آن‌را مانند زیر قرار می‌دهیم.
@page "/showtoken"

<p>This is part of the access token @(AccessToken != null ? AccessToken.Substring(0,30) : "(null)")</p>


@code {
    [CascadingParameter(Name = "AccessToken")] public string AccessToken { get; set; }
}
بدیهی است که اطلاعات دیگری نیز می‌توان از HttpContext استخراج کرد. برای مثال شاید شما بخواهید که در یک کامپوننت، بدون استفاده از <AuthorizeView> نام کاربری شخصی که لاگین کرده است را به دست آورید (برای زمانی که از اعتبارسنجی مبتنی بر کوکی‌ها در ASP.NET Core 2.0 بدون استفاده از سیستم Identity استفاده می‌کنید). تنها کافیست بخش Host.cshtml_ را مانند زیر تغییر دهید.
var userName = await HttpContext.User.Identity.Name;
یا برای مثال اگر به دنبال اطلاعات یک کوکی خاص می‌باشید:
var khasCookie = HttpContext.Request.Cookies["khas"];
  • #
    ‫۱ سال و ۸ ماه قبل، یکشنبه ۱۳ آذر ۱۴۰۱، ساعت ۱۶:۱۴
    برای استفاده از مقادیر کوکی در کلاس هایی نظر DbContext چکاری باید انجام داد؟ مثلا میخواهیم مقدار یک کوکی را بخوانیم تا در Gloabl Query Filter استفاده کنیم. در این حالت این اتفاق زیاد رخ میدهد که کانتکسی در دسترس نیست
    • #
      ‫۱ سال و ۸ ماه قبل، دوشنبه ۱۴ آذر ۱۴۰۱، ساعت ۱۶:۵۴
      اگر می‌خواهید اطلاعاتی نظیر کاربر را دریافت کنید آنگاه می‌توانید AuthenticationStateProvider را در DbContext تزریق کنید. یک نمونه پیاده سازی در  SO.
      اما دسترسی به HttpContext در هیچ کجای برنامه Blazor Server غیر از Host.cshtmlـ مقدار تضمین شده درستی را در بر نخواهد داشت. همچنین می‌توانید با اضافه کردن خط زیر در استارت آپ برنامه، با تزریق وابستگی، به HttpContext، در سرویس‌ها به آن دسترسی داشته باشید. ()Services.AddHttpContextAccessor
      • #
        ‫۱ سال و ۷ ماه قبل، شنبه ۱۷ دی ۱۴۰۱، ساعت ۱۳:۰۸
        همچنین می‌توانید با اضافه کردن خط زیر در استارت آپ برنامه، با تزریق وابستگی، به HttpContext، در سرویس‌ها به آن دسترسی داشته باشید. ()Services. AddHttpContextAccessor
        این قسمت از متن پاسخ بنده صحیح نمی‌باشد. در این حالت ممکن است مقدار HttpContext نامعتبر باشد. راهکار همان دوخط اول می‌باشد.
        • #
          ‫۱ سال و ۷ ماه قبل، شنبه ۱۷ دی ۱۴۰۱، ساعت ۱۴:۳۴
          بنا بر گفته یکی از دوستان که از این روش استفاده کرده بود و نتیجه خوبی گرفته بود.من این  نوع متغیر رو بدون استفاده از تزریق وابستگی در کلاس کانتکس new دستی کردم و تو این مدت باهاش کار کردیم به درستی جواب داده.
          • #
            ‫۱ سال و ۷ ماه قبل، شنبه ۱۷ دی ۱۴۰۱، ساعت ۱۴:۴۷
            روش توصیه شده‌ی برای برنامه‌های Blazor Server، کار با GetAuthenticationStateAsync جهت دسترسی به اطلاعات کاربر است و عدم استفاده از HttpContext برای این موارد.
          • #
            ‫۱ سال و ۵ ماه قبل، شنبه ۶ اسفند ۱۴۰۱، ساعت ۱۸:۳۴
            البته یک نکته در این رابطه هست که در iis مربوطه حتما قابلیت webSocket باید نصب شده باشد.
  • #
    ‫۱ سال و ۶ ماه قبل، سه‌شنبه ۲ اسفند ۱۴۰۱، ساعت ۰۰:۲۷
    سلام؛ آیا باید با تزریق IHttpContextAccessor در لایه سرویس پروژه Wasm اطلاعات مورد نیاز را از قبیل نام کاربری، بدست بیاوریم یا باید اطلاعات کاربری را از لایه UI توسط  AuthenticationStateProvider  استخراج و به لایه سرویس ارسال کنیم؟