ASP.NET MVC/Core表單提交後臺模型二級屬性驗證問題
起因
這個是網友在官網論壇的提問:https://fineui.com/bbs/forum.php?mod=viewthread&tid=22237
重新問題
本著務實求真的態度,我們先來複現這個問題。首先頁面截圖是這樣的:
類 MsStudentMajor 有兩個非空屬性 Major2 和 Desc2,如下所示:
public class MsStudentMajor { /// <summary> /// 標識 /// </summary> public int Id { get; set; } /// <summary> /// Name /// </summary> public string Name { get; set; } /// <summary> /// 所學專業 /// </summary> [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 屬性。
萬事皆有因,萬般皆有果。