起因
这个是网友在官网论坛的提问:https://fineui.com/bbs/forum.php?mod=viewthread&tid=22237
重新问题
本着务实求真的态度,我们先来复现这个问题。首先页面截图是这样的:
类 MsStudentMajor 有两个非空属性 Major2 和 Desc2,如下所示:
public class MsStudentMajor { ////// 标识 /// public int Id { get; set; } /// /// Name /// public string Name { get; set; } /// /// 所学专业 /// [Required] public string Major2 { get; set; } [Required] public string Desc2 { get; set; } }
但是页面上只用到了 Major2,而没有用到 Desc2:
F.SimpleForm() .ID("SimpleForm1") .ShowBorder(false) .ShowHeader(false) .BodyPadding(10) .LabelWidth(180) .Items( F.TextBoxFor(m => m.Name) .Label("姓名"), F.HiddenFieldFor(m => m.Major) .Label("所学专业1"), F.DropDownListFor(m => m.StudentMajor.Major2) .ID("StudentMajor_Major2") //.Name("StudentMajor.Major2") .Label("所学专业2") .Items( F.ListItem() .Text("请选择") .Value(""), F.ListItem() .Text("计算机") .Value("计算机"), F.ListItem() .Text("物理") .Value("物理") ) .SelectedValue(Model.StudentMajor.Major2) //F.TextBoxFor(m => m.StudentMajor.Desc2) // .Label("描述") )
所以在后台的模型绑定验证时出错:
[HttpPost] [ValidateAntiForgeryToken] public ActionResult FormSubmit_btnSave_Click(MsStudent model) { if (ModelState.IsValid) { } return UIHelper.Result(); }
调试分析
遇到问题首先要调试,看下内部变量是否和预想的有出入。首先看下点击保存按钮时客户端提交的数据:
二级属性是以 StudentMajor.Major2 的形式提交的,后台接受到的数据:
一切都合情合理,二级属性也能正确绑定,只不过由于前台并未告知 StudentMajor.Desc2 的值,所以未能绑定,这也在情理之中。
对比测试老版本 FineUIMvc v5.3.0
由于网友在帖子里提到了老版本 FineUIMvc v5.3.0 是可以正常运行的,所以我们找来了老版本,同样测试如下:
和最新版不同的是,这里提交的二级属性名为 StudentMajor_Major2 ,很明显,后台模型绑定时不会自动识别这个字符串:
所以这里,模型绑定出来的 StudentMajor == null。自然而然,就不会提示模型绑定失败,因为未对二级属性进行有效的绑定处理!
很明显,这个应该是老版本的BUG。如果我们仔细看更新记录的话,可能看到相关的改进:https://fineui.com/mvc/version/
解决问题
既然这是老版本的BUG,而新版本没有问题。那该如何满足用户的这个需求呢?
其实很简单,ASP.NET MVC/Core提供了一种机制,可以在模型绑定时排除对某些属性的绑定,如下所示:
[HttpPost] [ValidateAntiForgeryToken] public ActionResult FormSubmit_btnSave_Click([Bind(Exclude = "StudentMajor")]MsStudent model) { if (ModelState.IsValid) { } return UIHelper.Result(); }
注意,这里的 [Bind(Exclude = "StudentMajor")] 就是告诉ASP.NET MVC/Core 框架在模型绑定时忽略 StudentMajor 属性。
万事皆有因,万般皆有果。