MVC动态加载分部视图后,SubModel保存时无法更新的问题
这个问题的核心在于Ajax重新加载分部视图时,表单字段的name属性没有带上Details前缀,导致ASP.NET MVC的模型绑定无法将提交的字段值映射到Model.Details上,所以保存时SubModel还是默认值。
为什么会出现这个问题?
你最初用@Html.PartialFor(m => m.Details, "~/Features/_SubModel.cshtml")渲染分部视图时,MVC会自动给表单字段加上Details前缀(比如生成<input name="Details.Id" ...>),因为它知道这个分部视图对应的是Model.Details。
但当你通过Ajax调用GetSubModel方法返回分部视图时,你直接把SubModel实例传给了视图,此时视图的模型是SubModel而不是Model的一部分,所以生成的字段name是Id而不是Details.Id。表单提交时,MVC找不到对应Details.Id的字段值,就会用默认的SubModel实例填充。
解决方法:给分部视图添加字段前缀
最简单的修复方式是在返回分部视图时,通过ViewData指定字段前缀,让MVC生成正确的name属性:
修改你的控制器代码:
[HttpPost] [Route("GetSubModel")] public async Task<ActionResult> GetSubModel( Query query ) { var subModel = await GetSubModel(query); // 添加字段前缀,让分部视图生成带有Details.的name属性 var viewData = new ViewDataDictionary(this.ViewData) { TemplateInfo = new TemplateInfo { HtmlFieldPrefix = "Details" } }; return PartialView("_SubModel.cshtml", subModel ?? new SubModel(), viewData); }
这样,当分部视图重新渲染时,所有表单字段的name都会带上Details前缀(比如Details.Id),和你最初用PartialFor渲染的效果完全一致。表单提交时,MVC就能正确将字段值绑定到Model.Details上了。
验证方法
修改后,你可以通过浏览器的开发者工具查看重新加载后的输入框源码,确认name属性是Details.Id而不是Id,这样就说明配置正确了。
内容的提问来源于stack exchange,提问作者Dragonalighted

