MVC问题:客户端新增记录无法提交至控制器
我来帮你排查这个问题,你遇到的核心是MVC模型绑定对动态新增列表项的命名规则有要求,再加上一个容易忽略的拼写错误,咱们一步步解决:
首先修复最明显的拼写错误
你的JavaScript代码里有个笔误:$("#dv_poeple")应该是$("#dv_people")(注意是people不是poeple),这个错误会导致新增的HTML元素根本没加到页面上的目标容器里,自然不会被表单提交。
核心问题:MVC模型绑定的列表命名规则
MVC默认的模型绑定器要正确识别List<person>,表单元素的name属性需要符合特定格式,同时还要保证索引的有效性,分两种场景处理:
场景1:不需要删除现有记录,保持索引连续
这种情况最简单,只需要让新增项的索引接着原有记录的索引往下走:
在视图中添加隐藏字段记录当前最大索引
在dv_people容器外添加一个隐藏字段,用来存储当前已有的记录数量(也就是下一个新增项的索引):<input type="hidden" id="currentIndex" value="@Model.people.Count()" /> <div id="dv_people"> @{ for (var c = 0; c < Model.people.Count(); c++) { @Html.EditorFor(m => Model.people[c].firstname); @Html.EditorFor(m => Model.people[c].lastname); @Html.HiddenFor(m => Model.people[c].ID); } } </div>修改JavaScript代码使用连续索引
移除uniqueIndex参数,改用隐藏字段里的索引值,新增后更新索引:function addPerson(firstname, lastname){ var currentIndex = parseInt($("#currentIndex").val()); var htm = '<input class="text-box single-line" id="people_' + currentIndex + '__firstname" name="people[' + currentIndex + '].firstname" type="text" value="' + firstname + '">' htm += '<input class="text-box single-line" id="people_' + currentIndex + '__lastname" name="people[' + currentIndex + '].lastname" type="text" value="' + lastname + '">' htm += '<input id="people_' + currentIndex + '__ID" name="people[' + currentIndex + '].ID" type="hidden" value="0">' // 新增记录ID通常设为0,后端处理时判断是新增 $("#dv_people").append(htm); // 更新索引,供下一次新增使用 $("#currentIndex").val(currentIndex + 1); }
场景2:需要支持删除中间记录(非连续索引)
如果你的页面允许删除现有记录,连续索引就会断裂,这时候需要用Index字段来标识每个列表项的唯一索引:
修改原有视图,添加Index隐藏字段
给每个现有记录加上people.Index的隐藏字段,告诉MVC这个项的索引:<div id="dv_people"> @{ for (var c = 0; c < Model.people.Count(); c++) { @Html.Hidden("people.Index", c) @Html.EditorFor(m => Model.people[c].firstname); @Html.EditorFor(m => Model.people[c].lastname); @Html.HiddenFor(m => Model.people[c].ID); } } </div>修改JavaScript代码,使用唯一索引并添加Index字段
用时间戳或UUID作为唯一索引,同时新增people.Index隐藏字段:function addPerson(firstname, lastname){ var uniqueIndex = Date.now(); // 用时间戳生成唯一索引 var htm = '<input type="hidden" name="people.Index" value="' + uniqueIndex + '">' htm += '<input class="text-box single-line" id="people_' + uniqueIndex + '__firstname" name="people[' + uniqueIndex + '].firstname" type="text" value="' + firstname + '">' htm += '<input class="text-box single-line" id="people_' + uniqueIndex + '__lastname" name="people[' + uniqueIndex + '].lastname" type="text" value="' + lastname + '">' htm += '<input id="people_' + uniqueIndex + '__ID" name="people[' + uniqueIndex + '].ID" type="hidden" value="0">' $("#dv_people").append(htm); }
最后检查ViewModel的属性访问权限
你的ViewModel里的people属性没有加public修饰符,模型绑定器无法访问和设置它的值,必须改成public:
public class person { public int ID { get; set; } public string firstname { get; set; } public string lastname { get; set; } } public class viewmodel { public List<person> people { get; set; } // 加上public修饰符 }
做完这些修改后,点击提交按钮,新增的记录应该就能正确绑定到ViewModel的people集合里了!
内容的提问来源于stack exchange,提问作者Matt

