Blazor数组元素表单绑定异常:提交时获取旧值
问题描述
熟悉C#但刚接触Blazor,需开发从数据库加载数据并支持编辑的页面。按自身思路实现后出现问题:修改输入字段内容并点击提交按钮,控制台输出的仍是旧值,尝试多种方法未解决。疑惑是遗漏关键配置还是实现思路错误?
相关代码
AppVersion类
using System.ComponentModel.DataAnnotations; namespace Domain.Entities; public class AppVersion: BaseEntity { [Required] public string? VersionNumber { get; set; } }
页面代码
@page "/version" @using Service @using Domain.Entities @inject AppVersionService AppVersionService <PageTitle>App Versions</PageTitle> <div> @if (Appversions == null) { <p>Loading...</p> } else { @foreach (var appVersion in Appversions) { var formName = appVersion.Id.ToString(); <EditForm Model="appVersion" OnValidSubmit="@ValidUpdateFormSubmitted" OnInvalidSubmit="@InvalidFormSubmitted" FormName="@formName"> <DataAnnotationsValidator/> <ValidationSummary/> <span>VersionNumber</span> <input type="text" placeholder="" @bind="appVersion.VersionNumber"/> <button type="submit"> Save </button> </EditForm> } } </div> @code { private AppVersion NewAppVersion { get; set; } = new(); private IList<AppVersion>? Appversions { get; set; } protected override async Task OnInitializedAsync() { Appversions = await AppVersionService.GetAllAsync(); } private async Task ValidUpdateFormSubmitted(EditContext editContext) { var appVersion = editContext.Model as AppVersion; Console.WriteLine($"Appversion number in Blazor page: {appVersion.VersionNumber}"); await AppVersionService.UpdateAsync(appVersion); } }
补充排查信息
经排查发现仅开启@rendermode InteractiveServer时才生效,但仍不理解原因,打算在GitHub提交bug报告。另外即使开启该模式,bind-value也完全无法工作。测试代码如下:
@page "/test" @* @rendermode InteractiveServer *@ @using System.ComponentModel.DataAnnotations <PageTitle>App Versions</PageTitle> <div> @foreach (var appVersion in Appversions) { var formName = appVersion.Id.ToString(); @appVersion.VersionNumber <EditForm Model="appVersion" OnValidSubmit="@ValidUpdateFormSubmitted" FormName="@formName"> <DataAnnotationsValidator/> <ValidationSummary/> <span>VersionNumber</span> <input type="text" placeholder="" class="bg-slate-700" @bind="appVersion.VersionNumber"/> <button type="submit"> Save </button> </EditForm> } </div> @code { public class AppVersion //: BaseEntity { public int Id { get; set; } [Required] public string? VersionNumber { get; set; } } private IList<AppVersion>? Appversions { get; set; } protected override void OnInitialized() { Appversions = new List<AppVersion> { new() { Id = 1, VersionNumber = "1.0.0" }, new() { Id = 2, VersionNumber = "1.0.1" }, new() { Id = 3, VersionNumber = "1.0.2" } }; } private void ValidUpdateFormSubmitted(EditContext editContext) { var appVersion = editContext.Model as AppVersion; Console.WriteLine($"Appversion number in Blazor page: {appVersion?.VersionNumber}"); } }
解决方案与原因分析
核心原因:渲染模式差异
Blazor的静态服务器渲染(SSR)模式下,页面仅在服务器端渲染一次,发送给浏览器的是纯静态HTML,没有交互逻辑。用户修改输入框内容时,不会同步更新服务器端的组件状态,提交表单时只会发送初始渲染的旧值,因此控制台输出旧数据。
而开启@rendermode InteractiveServer后,页面会通过SignalR建立服务器与浏览器的实时连接,所有交互操作都会同步到服务器端的组件实例,双向绑定功能才会正常生效,提交时能获取到最新的输入值。
关于bind-value失效的问题
bind-value写法错误,Blazor双向绑定的正确语法是@bind(简写)或@bind-Value(注意Value首字母大写),正确代码应为:
<input type="text" @bind-Value="appVersion.VersionNumber" />
优化实现建议
- 指定交互式渲染模式:对于需要交互的页面,必须在页面顶部添加:
也可在项目全局配置中设置默认交互式渲染模式。@rendermode InteractiveServer - 隔离编辑状态:循环中直接绑定集合元素可能引发状态跟踪问题,建议为每个编辑项创建独立的视图模型,或使用独立的
EditContext实例确保状态隔离。 - 完善验证逻辑:提交前调用
editContext.Validate(),确保模型验证通过后再执行更新操作。
内容的提问来源于stack exchange,提问作者TeaDrinkingProgrammer
相关产品推荐
相关产品推荐

