ASP.NET MVC如何从视图向控制器提交List类型自定义类对象
问题根因
ASP.NET MVC的模型绑定器对集合类型的参数有严格的命名约定,你当前输出的表单输入项name属性不符合绑定规则,无法映射到PostQuestionnaireViewModel下的List<PostViewModel> Post属性,所以拿到的值为null。
解决步骤
1. 调整分部视图的模型类型与控制器返回值
分部视图需要支持下标索引访问,所以将IQueryable改为IList类型:
- 分部视图
_GetAnswerResponse顶部的模型声明改为:
@model IList<CRM.ViewModel.Questionnaire.IndexQuestinaryViewModel>
GetResponse控制器方法返回时将IQueryable转为List:
[HttpGet] public ActionResult GetResponse() { var CurentId = User.Identity.GetUserId<int>(); var GetAllQuestion = _userService.GetAnswerResponse(CurentId); // 转为List支持索引访问 return PartialView("_GetAnswerResponse", GetAllQuestion.ToList()); }
2. 调整表单渲染逻辑,生成符合绑定规则的name属性
将foreach循环改为带索引的for循环,使用强类型HTML助手自动生成正确的name属性,前缀要和接收模型的集合属性名Post对应:
修改后的分部视图完整代码:
@model IList<CRM.ViewModel.Questionnaire.IndexQuestinaryViewModel> <table class="table"> <thead> </thead> <tbody> @for (int i = 0; i < Model.Count; i++) { <tr> <td> @* 自动生成 name="Post[i].属性名" 格式的输入项 *@ @Html.HiddenFor(m => m[i].UserId) @Html.HiddenFor(m => m[i].QuestionId) @Html.HiddenFor(m => m[i].TextQuestion) @Model[i].TextQuestion </td> <td> @Html.TextBoxFor(m => m[i].TextResponses) </td> </tr> } </tbody> </table>
原理说明
强类型助手会自动为输入项生成符合绑定规则的name属性,比如第1个问题的输入项会生成:
<input type="hidden" name="Post[0].UserId" value="xxx"><input type="hidden" name="Post[0].QuestionId" value="xxx"><input type="text" name="Post[0].TextResponses" value="xxx">
MVC模型绑定器会自动把相同索引下的所有字段封装为一个PostViewModel对象,最终组装成List<PostViewModel> Post集合,你在控制器就能直接拿到关联好的对象列表了。
注意事项
- 索引必须从0开始且连续不中断,否则中断位置之后的项无法绑定
- 如果不需要保存
TextQuestion字段,可以去掉对应的隐藏域,减少提交的数据量 - 不需要修改你当前的接收模型结构,现在的
PostQuestionnaireViewModel和PostViewModel定义是正确的
内容的提问来源于stack exchange,提问作者Boris
相关产品推荐
相关产品推荐

