Blazor中IHttpContextAccessor注入后为空的问题求助
解决Blazor中IHttpContextAccessor注入为空的问题
核心问题
你在CustomStateProvider中使用[Inject]属性注入IHttpContextAccessor,但服务类(非Blazor组件)的依赖注入必须通过构造函数实现,[Inject]属性仅适用于Blazor组件类,这是导致属性为空的直接原因。
修改步骤
1. 重构CustomStateProvider的注入方式
移除[Inject]属性,将IHttpContextAccessor通过构造函数注入:
public class CustomStateProvider : AuthenticationStateProvider { private readonly IHttpContextAccessor _httpContextAccessor; private readonly IAuthService _authService; private CurrentUser _currentUser; // 通过构造函数注入两个依赖 public CustomStateProvider(IAuthService authService, IHttpContextAccessor httpContextAccessor) { _authService = authService; _httpContextAccessor = httpContextAccessor; } public override async Task<AuthenticationState> GetAuthenticationStateAsync() { var identity = new ClaimsIdentity(); try { var userInfo = GetCurrentUser(); if (userInfo.IsAuthenticated) { var claims = new[] { new Claim(ClaimTypes.Name, _currentUser.UserName) } .Concat(_currentUser.Claims.Select(c => new Claim(c.Key, c.Value))); identity = new ClaimsIdentity(claims, "Server authentication"); } } catch (HttpRequestException ex) { Console.WriteLine("Request failed:" + ex); } return new AuthenticationState(new ClaimsPrincipal(identity)); } public async Task Login(ConnexionModel loginParameters) { _authService.Login(loginParameters); var user = _authService.GetUser(loginParameters.UserName); _currentUser = user; var cookieOptions = new CookieOptions { Expires = DateTime.Now.AddDays(7), HttpOnly = true }; _httpContextAccessor.HttpContext.Response.Cookies.Append("CurrentUser", JsonConvert.SerializeObject(_currentUser), cookieOptions); NotifyAuthenticationStateChanged(GetAuthenticationStateAsync()); } public async Task Logout() { _currentUser = null; _httpContextAccessor.HttpContext.Response.Cookies.Delete("CurrentUser"); NotifyAuthenticationStateChanged(GetAuthenticationStateAsync()); } public async Task Register(InscriptionModel registerParameters) { _authService.Register(registerParameters); var user = _authService.GetUser(registerParameters.UserName); _currentUser = user; var cookieOptions = new CookieOptions { Expires = DateTime.Now.AddDays(7), HttpOnly = true }; _httpContextAccessor.HttpContext.Response.Cookies.Append("CurrentUser", JsonConvert.SerializeObject(_currentUser), cookieOptions); NotifyAuthenticationStateChanged(GetAuthenticationStateAsync()); } public CurrentUser GetCurrentUser() { if (_currentUser != null && _currentUser.IsAuthenticated) { return _currentUser; } else { var cookie = _httpContextAccessor.HttpContext.Request.Cookies["CurrentUser"]; if (cookie != null) { return JsonConvert.DeserializeObject<CurrentUser>(cookie); } } return new CurrentUser(); } }
2. 确认Program.cs的服务注册(你的配置无需修改)
当前的服务注册逻辑是正确的,保持顺序即可:
builder.Services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>(); builder.Services.AddScoped<CustomStateProvider>(); builder.Services.AddScoped<AuthenticationStateProvider>(s => s.GetRequiredService<CustomStateProvider>());
额外注意事项
- 若你使用的是Blazor WebAssembly,
IHttpContextAccessor本身不可用,因为WebAssembly运行在浏览器环境中,没有服务器端的HttpContext,此时需改用浏览器本地存储(如localStorage)保存用户信息。 - 在Blazor Server中,
HttpContext仅在初始请求或SignalR交互的上下文内可用,若在后台线程中调用GetAuthenticationStateAsync,可能会出现HttpContext为空的情况,建议将用户信息缓存到服务内部,减少对HttpContext的直接依赖。
内容的提问来源于stack exchange,提问作者Armure
相关产品推荐
相关产品推荐

