ASP.NET Core Razor Pages自定义可编辑Grid如何Post提交行Id
问题原因
现有代码无法正常完成行编辑保存,核心是两点不符合Razor Pages模型绑定和表单提交的规则:
- 用
foreach循环直接渲染集合项时,默认生成的表单字段name属性没有匹配的绑定前缀,且整个表格套在单个form中,点击任意保存按钮都会提交所有行的输入,无法区分要更新的具体行 TryUpdateModelAsync指定的"GridRow"前缀和实际提交的字段名不匹配,无法正确读取编辑后的值,同时提交按钮没有传递当前行的Id参数,后台查询不到要更新的记录
无JS实现方案
全程不需要任何JavaScript/jQuery代码,利用HTML原生特性和Razor Pages标签助手即可实现,按以下步骤修改:
- 调整页面表单结构
移除包裹整个表格的form标签,给每一行配置独立的提交表单,通过HTML5原生的form属性关联行内控件和对应表单,提交时只会上传当前行的数据,不会冗余提交其他行内容:
<table class="table"> <thead> <tr> <th>Text 1</th> <th>Text 2</th> <th>Text 3</th> <th>操作</th> </tr> </thead> <tbody> @foreach (var item in Model.GridRows) { // 每行对应独立表单,用行Id做唯一标识 <form method="post" asp-page-handler="SaveRow" id="row-form-@item.Id"></form> <tr> <td> <input type="hidden" asp-for="@item.Id" form="row-form-@item.Id" /> </td> <td> <input asp-for="@item.Text1" form="row-form-@item.Id" class="form-control" /> </td> <td> <input asp-for="@item.Text2" form="row-form-@item.Id" class="form-control" /> </td> <td> <input asp-for="@item.Text3" form="row-form-@item.Id" class="form-control" /> </td> <td> <button type="submit" form="row-form-@item.Id" class="btn btn-primary">Save</button> </td> </tr> } </tbody> </table>
如果对HTML结构校验有严格要求,可以把所有行的form标签统一移到table外层,只要保证form的id和行内控件的
form属性值一一对应即可,功能完全一致。所有现代浏览器都原生支持form属性,不需要额外兼容。
- 调整后台处理方法
修改Post处理方法的命名匹配表单指定的handler名称,去掉错误的绑定前缀,代码如下:
public async Task<IActionResult> OnPostSaveRowAsync(int id) { if (!ModelState.IsValid) { return Page(); } var gridRowUpdate = await _context.GridRows.FindAsync(id); if (gridRowUpdate == null) { return NotFound(); } // 单表单仅提交当前行字段,无需指定自定义前缀 if (await TryUpdateModelAsync<GridRow>(gridRowUpdate, g => g.Text1, g => g.Text2, g => g.Text3)) { await _context.SaveChangesAsync(); } return RedirectToPage("./Index"); }
注意事项
- 不要用
@Html.EditorFor生成控件,直接用asp-for标签助手生成输入框,会自动处理name、value属性的生成,避免命名不匹配导致的绑定失败 - 每个行表单提交时只会携带当前行的Id和三个文本字段,模型绑定器会自动把表单中的Id值绑定到方法的
id参数,不需要额外做参数解析 - 实现逻辑完全基于HTML原生表单提交和Razor Pages默认模型绑定规则,没有任何前端脚本依赖
内容的提问来源于stack exchange,提问作者denki
相关产品推荐
相关产品推荐

