
在 .NET 6 Razor Pages 中,使用 JavaScript 动态添加含索引的表单控件(如 Participation.Participants[1].Prenom)时,若直接拼接 asp-for 标签助手,将导致模型绑定失败——因为服务端无法识别未正确渲染的 name 属性;必须手动设置符合模型绑定规范的 name 特性。
在 .NET 6 Razor Pages 中,使用 JavaScript 动态添加表单控件时,若直接拼接 asp-for 标签助手(如 asp-for="Participation.Participants[1].Prenom"),将导致模型绑定失败——因为服务端无法识别未正确渲染的 name 属性;必须手动设置符合模型绑定规范的 name 特性。
Razor 页面的模型绑定机制高度依赖 HTML 表单元素的 name 属性。当使用 asp-for 标签助手时,Razor 在服务端渲染阶段会自动将其转换为标准的 name="Participation.Participants[0].Prenom" 和 id="Participation_Participants_0__Prenom"(注意下划线转点、方括号转双下划线),同时注入当前模型值与验证信息。但JavaScript 运行在客户端,无法执行服务端标签助手逻辑——你拼接的 字符串会被浏览器原样解析为无效属性,既不生成 name,也不触发绑定。
✅ 正确做法是:在 JS 中显式构造符合 ASP.NET Core 模型绑定规则的 name 值。对于嵌套集合(如 List
name="ParentProperty.NestedCollection[Index].PropertyName"
其中索引必须为连续非负整数(0, 1, 2…),且不能跳号或重复。
以下是修正后的关键脚本片段(已适配你的结构):
@section Scripts
{
<script>
let rowCount = 1; // 初始为1,因第0行已在服务端静态渲染
$("#addRow").click(function () {
const html = `
<tr class="dynamic-row">
<td>
<input type="text"
class="form-control d-table-cell"
name="Participation.Participants[${rowCount}].Prenom"
id="Participation_Participants_${rowCount}__Prenom" />
<span class="text-danger field-validation-valid"
data-valmsg-for="Participation.Participants[${rowCount}].Prenom"
data-valmsg-replace="true">
<td>
<input type="text"
class="form-control d-table-cell"
name="Participation.Participants[${rowCount}].Nom"
id="Participation_Participants_${rowCount}__Nom" />
<span class="text-danger field-validation-valid"
data-valmsg-for="Participation.Participants[${rowCount}].Nom"
data-valmsg-replace="true">
<td>
<button type="button" class="btn btn-danger remove-row">Supprimer
`;
$('#newRow').append(html);
rowCount++;
});
// 使用事件委托处理动态按钮
$(document).on('click', '.remove-row', function () {
$(this).closest('.dynamic-row').remove();
// 注意:删除后无需递减 rowCount,避免索引错乱;实际绑定只认 name 属性值
});
</script>
}
? 关键注意事项:
- ✅ name 必须精确匹配模型路径(大小写敏感),且索引从 0 开始连续;
- ✅ id 和 data-valmsg-for 需同步更新,以支持客户端验证(如使用 jQuery Validation Unobtrusive);
- ❌ 禁用 asp-for、asp-validation-for 等服务端标签助手在 JS 字符串中出现;
- ⚠️ 删除行时不要修改 rowCount —— 因为模型绑定只依赖 name 的实际值,而非计数器;若需重排索引(如删除中间项后保持连续),应重新渲染整个表格或手动修正所有后续 name;
- ? 后端模型需确保 Participants 初始化(如在 PageModel 构造函数中 Participation = new() { Participants = new() }),否则空集合会导致绑定跳过。
? 进阶建议:
对复杂动态表单,推荐改用 FormData + Fetch API 提交 JSON 数据,并在 Handler 中手动映射(更可控);或采用 InputModel 分离绑定逻辑,避免深度嵌套绑定风险。
通过严格遵循 name 属性规范,即可让动态生成的表单项无缝参与 .NET 6 的默认模型绑定与验证流程。










