You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Blazor页面切换时依赖注入失效,如何实现用户独立会话状态?

搞定Blazor用户会话状态的隔离与共享问题

先说说你遇到的两个坑

  • 用AddScoped时跳转页面状态就没了:在Blazor WebAssembly里,Scoped服务是每个组件实例单独一份,页面跳转等于加载新组件,之前存的状态自然就丢了;要是你用的Blazor Server还出现这问题,大概率是导航时加了强制刷新(forceLoad: true),直接重启了整个应用,Scoped实例肯定会重置。
  • 换AddSingleton又串号:Singleton是全局唯一实例,所有用户共用同一个对象,后面登录的用户自然会覆盖前面的状态,这肯定不符合需求。

分场景给你解决办法

如果你用的是Blazor Server(优先选这个)

Blazor Server里的AddScoped本来就是每个用户会话(也就是每个SignalR连接)单独一份,正常情况下不会丢状态。要是你那状态还是没了,按这几步改:

  1. 保持Program.cs里的Scoped注册不变:
builder.Services.AddScoped<SessionState>();
  1. 登录跳转时别加强制刷新:
state.id = int.Parse(dt.Rows[0]["iduser"].ToString());
state.verified = true;
// 就用默认的NavigateTo,别加forceLoad: true
NavigationManager.NavigateTo("home");
  1. 要是非得强制刷新(比如要加载新的静态资源),那得把状态存到HttpContext.Session里,让SessionState自己去读取:
    • 先在Program.cs里加Session支持:
      builder.Services.AddSession(options =>
      {
          options.IdleTimeout = TimeSpan.FromMinutes(30);
          options.Cookie.HttpOnly = true;
          options.Cookie.IsEssential = true;
      });
      builder.Services.AddHttpContextAccessor();
      
    • 然后修改你的SessionState类,让它和Session绑定:
      public class SessionState
      {
          private readonly IHttpContextAccessor _httpContextAccessor;
      
          public SessionState(IHttpContextAccessor httpContextAccessor)
          {
              _httpContextAccessor = httpContextAccessor;
              var session = _httpContextAccessor.HttpContext?.Session;
              if (session != null)
              {
                  id = int.TryParse(session.GetString("UserId"), out var userId) ? userId : 0;
                  verified = bool.TryParse(session.GetString("IsVerified"), out var verified) ? verified : false;
              }
          }
      
          private int _id;
          public int id
          {
              get => _id;
              set
              {
                  _id = value;
                  _httpContextAccessor.HttpContext?.Session.SetString("UserId", value.ToString());
              }
          }
      
          private bool _verified;
          public bool verified
          {
              get => _verified;
              set
              {
                  _verified = value;
                  _httpContextAccessor.HttpContext?.Session.SetString("IsVerified", value.ToString());
              }
          }
      }
      

如果你用的是Blazor WebAssembly

WebAssembly跑在浏览器里,没有服务器端的会话概念,得把状态存在浏览器的存储里,同时封装成Scoped服务让页面共享:

  1. 先安装NuGet包:Microsoft.AspNetCore.Components.WebAssembly.Storage。
  2. 修改SessionState类,用LocalStorage存状态:
public class SessionState
{
    private readonly ILocalStorageService _localStorage;
    private int _id;
    private bool _verified;

    public SessionState(ILocalStorageService localStorage)
    {
        _localStorage = localStorage;
        // 初始化时从LocalStorage读取之前的状态
        LoadStateAsync().Wait();
    }

    public int id
    {
        get => _id;
        set
        {
            _id = value;
            _localStorage.SetItemAsync("UserId", value).Wait();
        }
    }

    public bool verified
    {
        get => _verified;
        set
        {
            _verified = value;
            _localStorage.SetItemAsync("IsVerified", value).Wait();
        }
    }

    private async Task LoadStateAsync()
    {
        _id = await _localStorage.GetItemAsync<int>("UserId") ?? 0;
        _verified = await _localStorage.GetItemAsync<bool>("IsVerified") ?? false;
    }
}
  1. 在Program.cs里注册服务:
builder.Services.AddScoped<SessionState>();
builder.Services.AddLocalStorageServices();
  1. 登录代码还是你原来那样就行:
state.id = int.Parse(dt.Rows[0]["iduser"].ToString());
state.verified = true;
NavigationManager.NavigateTo("home");

备注:LocalStorage会一直存在浏览器里,就算关了标签页再打开还在;要是想关了浏览器就清状态,换成ISessionStorageService就行。

最后提俩注意点

  • 别往SessionState里存敏感信息,真要存得加密处理。
  • 不管哪种方案,确保页面里注入的是同一个Scoped实例——Blazor Server里是会话级,WebAssembly里是当前标签页级,都是每个用户单独一份的。

内容的提问来源于stack exchange,提问作者Kasra Ghavami

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 02:22:49