愛上MVC3~實體級標準驗證
在MVC架構中,底層數據源一般為linq to sql或者entity frameworks,可能還有少數團隊使用自己的ORM工具,但對于實體級的數據驗證來說都是必須要干的事,你可能在viewmodel中重復的寫一些驗證規則,你可能在用ctrl+C和ctrl+V的同時,也知道自己違背了DRY原則,但你可能會說:“這樣干容易,簡單!“,”我的邏輯復雜,我要分情況去考慮幼!”,呵呵,這些對于我來說,都是借口,違背就是違背,可能有些時候需要去違背原則,就像SQL非范式一樣,但今天要說的是,如何為一個實體對象,設計一個完整統一的驗證規則,我之前寫過一些實體驗證的東西,而今天說(shuo)的,主要還是使用“attribute"來實現這個驗證!
對于linq to sql,ef的開發者來說,實體對象會(hui)為我(wo)(wo)們自己(ji)生(sheng)成,而(er)我(wo)(wo)們對實體的驗證(zheng)不可能寫在生(sheng)成的實體中,因為只要實體要去從數據庫更新,你所作(zuo)的修改(gai)就徒(tu)勞了(le),呵(he)呵(he) ,還要小(xiao)微早就為我(wo)(wo)們考慮到了(le),所以,所有的實體類(lei)都(dou)是partial class,我(wo)(wo)們喜歡(huan)叫它(ta)“分(fen)部(bu)類(lei)”。
一些的效果為:
而一(yi)(yi)般我(wo)們的作法是把驗(yan)證信(xin)息寫(xie)在ViewModel里,即一(yi)(yi)個View寫(xie)一(yi)(yi)個Model,再添(tian)加一(yi)(yi)些驗(yan)證信(xin)息,而這(zhe)認為(wei)這(zhe)需(xu)要具(ju)體問(wen)題具(ju)體分(fen)析了,我(wo)們不應(ying)該將(jiang)所以業務(wu)都去重新抽象,這(zhe)樣無疑加大了代(dai)碼量,也破(po)壞了實(shi)體完整性,一(yi)(yi)個東西為(wei)何(he)拆(chai)成多個?
事實上,數據驗證這種事,我們往往應該把它放在數據模型層去干這事,即Entity(Model)層,它體現了數據庫的抽象,包括DATA層在內的所有層都可以去引用它,它只是數據庫的映射與數據有效性的驗證,不存在數據的操作,而操作這種事我們留給了DATA層,而根據業務去組合操作這種事我們交給了BLL(Service)層!
OK,我們來看一(yi)下,我在(zai)Entity層對實體的設(she)計:
1 namespace Role.Entity 2 { 3 /// <summary> 4 /// WorkFlow_Info數據(ju)有效(xiao)性驗證 5 /// </summary> 6 public class WorkFlow_Info_Meta 7 { 8 public int ID { get; set; } 9 public Nullable<int> PrevNode { get; set; } 10 public Nullable<int> NextNode { get; set; } 11 [Required(ErrorMessage = "請填(tian)寫工(gong)作流名稱")] 12 [Display(Name = "工作流名(ming)稱(cheng)")] 13 public string Name { get; set; } 14 public string Info { get; set; } 15 } 16 /// <summary> 17 /// 工作流實體 18 /// </summary> 19 [MetadataType(typeof(WorkFlow_Info_Meta))] 20 public partial class WorkFlow_Info 21 { 22 #region 導航屬性 23 /// <summary> 24 /// 是否為首(shou)結點(dian) 25 /// </summary> 26 public bool IsFirstNode 27 { 28 get 29 { 30 return this.PrevNode == null; 31 } 32 } 33 /// <summary> 34 /// 是否為尾(wei)結點 35 /// </summary> 36 public bool IsEndNode 37 { 38 get 39 { 40 return this.NextNode == null; 41 } 42 } 43 44 #endregion 45 } 46 /// <summary> 47 /// 工作量實體擴展 48 /// </summary> 49 public class WorkFlow_Info_Ext : WorkFlow_Info 50 { 51 } 52 }
好了(le),而(er)對(dui)于前臺提交表單時,只要調用(yong)ModelState對(dui)象的IsValid屬性即可驗證前臺模型了(le),呵(he)呵(he)!
1 [HttpPost] 2 public ActionResult Edit(WorkFlow_Info entity) 3 { 4 if (ModelState.IsValid) 5 { 6 repository.Update(entity); 7 return RedirectToAction("Index"); 8 } 9 return View(); 10 }