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

.NET Core 6 Blazor Server中POST后作用域类注入控制器问题

问题解答

1. 控制器获取独立ITestClass实例的原因

Scoped服务在Blazor Server和MVC控制器中的作用域边界完全不同:

  • Blazor Server的Scoped服务绑定到客户端电路(Circuit):每个用户的浏览器连接会创建一个独立电路,电路内所有组件共享同一个ITestClass实例,这也是PageB修改值后Index页面能正常读取的原因。
  • MVC控制器的Scoped服务绑定到单个HTTP请求:你通过表单发起的POST是一个独立的HTTP请求,不属于Blazor的电路上下文,因此会创建全新的ITestClass实例,自然看不到PageB中设置的值。
  • 控制器修改值后返回Redirect,会触发新的HTTP请求加载Index页面,此时若页面刷新则会重新创建Blazor电路,之前修改的值也会丢失。

2. 刷新Index页面重置值的原因

Blazor Server中,页面刷新会终止当前客户端电路并创建全新的电路实例。由于Scoped服务是电路级别的,新电路会重新初始化ITestClass,导致之前设置的状态被重置。

3. 启动时输出两次"Created"的原因

这是Blazor Server默认启用预渲染导致的:

  • 预渲染阶段:服务器先渲染页面的静态版本,此时会创建第一个ITestClass实例(第一次输出"Created")。
  • 交互式初始化:客户端建立SignalR连接后,会创建新的Blazor电路,再次实例化ITestClass(第二次输出"Created")。

解决方案建议

若要在Blazor组件和MVC控制器之间共享用户专属状态,可参考以下方案:

  • 使用Session存储:将状态保存到Session中,组件和控制器通过Session读写数据。需先在Program.cs中配置Session服务:
    builder.Services.AddSession(options =>
    {
        options.IdleTimeout = TimeSpan.FromMinutes(30);
        options.Cookie.HttpOnly = true;
    });
    // 中间件添加app.UseSession();
    
  • 替换表单为Blazor HttpClient调用:避免传统HTTP请求脱离电路上下文,通过HttpClient传递状态参数,而非依赖Scoped实例共享:
    <!-- PageB中替换表单为Blazor按钮 -->
    <button @onclick="CallController">Controller</button>
    
    @code {
        [Inject] HttpClient Http { get; set; }
    
        private async Task CallController()
        {
            // 传递当前状态作为请求参数
            var content = new StringContent(TestClass.Name, System.Text.Encoding.UTF8, "application/json");
            await Http.PostAsync("/api/test", content);
            NavigationManager.NavigateTo("/");
        }
    }
    
  • 使用客户端存储:通过LocalStorage或SessionStorage持久化状态,刷新页面也不会丢失,但需注意敏感数据的安全性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 13:07:04