How do I access HttpContext in Server-side Blazor?
It depends what you want to access the HttpContext
for.
Should you want to access authentication or user info, consider using the AuthenticationStateProvider
instead:
@page "/"
@using System.Security.Claims
@using Microsoft.AspNetCore.Components.Authorization
@inject AuthenticationStateProvider AuthenticationStateProvider
<h3>ClaimsPrincipal Data</h3>
<button @onclick="GetClaimsPrincipalData">Get ClaimsPrincipal Data</button>
<p>@_authMessage</p>
@if (_claims.Count() > 0)
{
<ul>
@foreach (var claim in _claims)
{
<li>@claim.Type – @claim.Value</li>
}
</ul>
}
<p>@_surnameMessage</p>
@code {
private string _authMessage;
private string _surnameMessage;
private IEnumerable<Claim> _claims = Enumerable.Empty<Claim>();
private async Task GetClaimsPrincipalData()
{
var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync();
var user = authState.User;
if (user.Identity.IsAuthenticated)
{
_authMessage = $"{user.Identity.Name} is authenticated.";
_claims = user.Claims;
_surnameMessage =
$"Surname: {user.FindFirst(c => c.Type == ClaimTypes.Surname)?.Value}";
}
else
{
_authMessage = "The user is NOT authenticated.";
}
}
}
blazor.Sever to Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddServerSideBlazor<Client.Startup>();
// HttpContextAccessor
services.AddHttpContextAccessor();
services.AddScoped<HttpContextAccessor>();
}
blazor.Shared
public class HttpContextAccessor
{
private readonly IHttpContextAccessor _httpContextAccessor;
public HttpContextAccessor(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
public HttpContext Context => _httpContextAccessor.HttpContext;
}
blazor.Client to App.cshtml
@inject blazor.Shared.HttpContextAccessor HttpContext
<Router AppAssembly=typeof(Program).Assembly />
@functions
{
protected override void OnInit()
{
HttpContext.Context.Request.Cookies.**
// Or data passed through middleware in blazor.Server
HttpContext.Context.Features.Get<T>()
}
}
Credits: https://github.com/aspnet/Blazor/issues/1554
Please note that the documentation explicitly states that IHttpContextAccessor should not be used for Blazor apps: https://docs.microsoft.com/en-us/aspnet/core/fundamentals/http-context?view=aspnetcore-3.1#blazor-and-shared-state
(This does not mean that in your particular case it will not work for a particular scenario. But as you are anyway only able to get the cookie from the first request - once SignalR takes over the are no cookies anymore - you should maybe get the value when _Host.cshtml is renderend, and pass it on as a string value to the Blazor components from there.)
Add the following to Blazor.Web.App.Startup.cs:
services.AddHttpContextAccessor();
You also need this in <component-name>.cshtml
@using Microsoft.AspNetCore.Http
@inject IHttpContextAccessor httpContextAccessor
Note: At the time when this answer was written, accessing the HttpContext was done as described above. Since then, Blazor has been under rapid development, and has fundamentally changed. It is definitely deprecated the usage described above, but alas, you can still do the above, which is legitimate and right, if you access the HttpContext from a .cshtml page. This has not changed... Thus the only place from which you can access the HttpContext, without even adding the IHttpContextAccessor to the DI container, is the _Host.cshtml file, which is a Razor Pages file, with the .cshtml extension. When the code in this file is executed, Blazor is still not born, and the execution of this file will be serving the Blazor Server App. Please, see this answer as to how to do it properly...
Hope this helps...