Asp.net
嵌套 ViewModel 的驗證
我有兩個 ViewModel(簡化):
public class ParentViewModel { public ParentViewModel { Content = new ChildViewModel(); } public ChildViewModel Content { get; set, } } public class ChildViewModel { [Required] public string Name1 { get; set, } [Required] public string Name2 { get; set, } }以及以下控制器發布操作:
[HttpPost] public ActionResult Create(ParentViewModel viewModel) { if (ModelState.IsValid) { // process viewModel -> write something into database return RedirectToAction("Index"); } return View(viewModel); }現在,我將發布請求正文中的以下表單值發送到與該操作對應的 URL(在 Fiddler 請求生成器中手動):
- 內容.名稱1=X
這工作正常,
Name1屬性已填寫viewModel.Content,Name2isnull並且模型狀態無效,因為Name2是必需的。因此,驗證按預期失敗。
- Xontent.Name1=X或Name1= X或其他任何東西都不會綁定到
viewModel現在
viewModel.Content不是null(因為我在建構子中實例化它)而是所有屬性Name1和Name2是null. 這是意料之中的。我沒想到的是模型狀態是有效的,所以它通過了驗證(後來導致數據庫異常,因為有不可為空的列)。如何改進此程式碼,以便驗證也適用於第二種情況?
我做了三個實驗:
- 我已經刪除了
Content建構子中的實例化ParentViewModel,然後Content在null上面的第二個範例中,但驗證仍然通過。- 我已經為屬性添加了一個
[Required]屬性Content(但沒有刪除建構子中的實例化Content)ParentViewModel。這根本沒有影響,上面兩個測試的描述行為是相同的。- 我已經為屬性添加了一個屬性
[Required]並刪除了建構子中的實例化。這似乎可以按我的意願工作:在第二個測試中,由於該屬性,驗證失敗。它看起來像這樣:Content``Content``ParentViewModel``Content``null``[Required]public class ParentViewModel { [Required] public ChildViewModel Content { get; set, } } public class ChildViewModel { [Required] public string Name1 { get; set, } [Required] public string Name2 { get; set, } }我現在可以得出結論,
Content在建構子中實例化子屬性ParentViewModel是問題的根源,並且模型綁定器本身必須實例化子屬性(或者如果請求中沒有匹配的表單欄位,則不實例化)才能正確地工作伺服器端驗證。我在其他幾個視圖模型建構子中有子屬性實例化,直到現在才注意到這個問題。那麼,這通常是一種不好的做法嗎?還有其他方法可以解決問題嗎?
第三種解決方案很好:
public class ParentViewModel { [Required] public ChildViewModel Content { get; set, } } public class ChildViewModel { [Required] public string Name1 { get; set, } [Required] public string Name2 { get; set, } }我現在在幾個地方使用它,沒有發現任何問題。
ModelState.IsValid 告訴您是否已將任何模型錯誤添加到 ModelState。
預設模型綁定器將為基本類型轉換問題添加一些錯誤,例如為“int”傳遞非數字。您可以根據您使用的任何驗證系統更充分地填充 ModelState。我建議查看數據註釋以驗證 ViewModel,因為它執行良好。
此語法可能錯誤或陳舊。ModelState.AddModelError(“鍵”,異常)