ASP.NET MVC 动态新增分部视图地址表单提交时模型绑定失败如何解决
问题原因和解决方案
核心问题梳理
- 模型定义错误:
CustomerInfo中的CustomerAddresses是单个对象类型,无法绑定多个地址数据,且存在地址类名与属性类型不匹配的问题 - 表单字段命名不符合ASP.NET MVC集合绑定规则:动态生成的地址输入框
name属性没有集合索引前缀,MVC无法将多个地址字段映射到集合属性 - 提交JS逻辑错误:直接对jQuery表单对象执行
JSON.parse会抛出异常,提交逻辑重复混乱 - DOM ID重复:删除按钮使用固定ID,多次追加地址后ID重复,仅第一个删除按钮生效
- 分部视图模型类型不匹配:分部视图声明的模型与实际使用的地址模型类不一致
修复步骤
1. 修正模型定义
将地址属性改为集合类型,统一类名:
// 地址模型统一类名 public class CustomerAddress { public string Address { get; set; } } public class CustomerInfo { public CustomerModel CUSTOMER { get; set; } // 改为列表类型支持绑定多个地址 public List<CustomerAddress> CustomerAddresses { get; set; } }
2. 调整分部视图与加载逻辑
给动态生成的表单字段加上符合绑定规则的索引前缀:
首先修改分部视图Action,接收索引参数设置前缀:
public virtual PartialViewResult RegisterAddress(int index) { // 设置HTML字段前缀,生成符合绑定规则的name属性 ViewData.TemplateInfo.HtmlFieldPrefix = $"CustomerAddresses[{index}]"; return PartialView(MVC.Applications.Views.CustomerAddress); }
修改追加地址的JS,传递当前地址数量作为索引:
$(document).on('click', "#addAddressItem", function (e) { e.preventDefault(); // 统计当前已有地址数量作为新项的索引 var currentCount = $("#RegisterAddressId .address-item").length; $.ajax({ url: this.href + "?index=" + currentCount, cache: false, success: function (html) { $("#RegisterAddressId").append(html); } }); });
修改分部视图,添加地址项标识、将删除按钮ID改为类:
@model CustomerAddress <!-- 添加address-item类用于计数和查找 --> <table class="address-item"> <td class="personlistborder"> <div class="editor-label"> Address </div> <div class="editor-field"> @Html.EditorFor(model => model.Address, new { @class = "CustomerAddressField" }) @Html.ValidationMessageFor(model => model.Address) </div> </td> <td colspan="7"></td> <td> <!-- 将固定ID改为class,避免重复 --> <span class="deleteRegisterCustomerAddress outline ui-button ui-widget ui-state-default ui-corner-all" role="button" aria-disabled="false"> <span class="ui-icon-minusthick ui-icon"></span> </span> </td> </table>
3. 实现删除功能并修复索引
删除地址后重新整理所有字段的索引,避免索引断层导致绑定失败:
$(document).on('click', ".deleteRegisterCustomerAddress", function () { // 删除当前地址项 $(this).closest(".address-item").remove(); // 重排剩余地址项的索引 $("#RegisterAddressId .address-item").each(function (index) { // 修改输入框name属性 $(this).find("input[name*='Address']").attr("name", $"CustomerAddresses[{index}].Address"); // 同步修改验证提示的关联属性,保证表单验证正常生效 $(this).find("[data-valmsg-for*='Address']").attr("data-valmsg-for", $"CustomerAddresses[{index}].Address"); }); });
4. 修正提交JS逻辑
删除错误的JSON解析代码,直接提交验证通过的表单:
buttons: ({ "Save": { text: "save", id: "btnSubmitExamApp", click: function () { var form = $('form', this); var validator = $(form).validate(); if (validator.form()) { form.submit(); } } } })
5. 后端接收逻辑
提交的Action参数直接使用CustomerInfo类型即可自动绑定地址集合:
[HttpPost] public ActionResult SaveCustomer(CustomerInfo model) { // model.CustomerAddresses 即可获取所有提交的地址数据 // 后续业务逻辑 }
内容的提问来源于stack exchange,提问作者lekiniu
相关产品推荐
相关产品推荐

