<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      深入淺出 MVC 數據驗證 2.0 [附演示源碼]

      上次的文章得到了很多讀者的支持,所以感謝一下大家,特別感謝指出不足之處的幾位朋友,我在原文中已經進行了修改。

      P.S. 圖片中的 dozer.net.cn 其實打開后就是我博客園的地址,會自動跳轉,這個好記一點

       

      今天在這里給大家介紹一下MVC的數據驗證框架。

      在1.0版中,很多朋友提出了怎么使用客戶端驗證,今天找了一些資料,發現了客戶端驗證的方法。

       

       

      1、MVC中的數據驗證框架有何優點?

      在Asp.net時代,或者沒有使用MVC的驗證框架,一般是在BLL層中進行數據驗證,但是BLL層的返回值又只能返回一個東西,比如一個字符串,而實際情況中,數據驗證是很復雜的。

      這時候,BLL層和網站會分離的不徹底,因為很多代碼不得不在網站中寫。

       

      而在MVC的數據驗證框架中,甚至可以不用BLL層,而在比BLL層更底層的Model層書寫數據驗證的代碼。

      并且最后能在網頁上顯示出來。 

      此圖這就是最后的效果

       

      2、深入淺出?

      此框架有個優點,非常靈活,我這里用正常的三層架構來寫。

      因為靈活,我可以把數據驗證寫在任何一層。

       

      i)寫在Controller里:這是最簡單的方法,但是也是最不推薦的方法, 因為不能體現分層思想

      ii)寫在BLL中:如果對一個數據驗證的時候,需要牽扯到別的數據,就應該把驗證寫在這一層,比如一個Article Model的Category值是1,查詢這個分類是否存在

      iii)寫在Model中:一些底層的標準應該寫在這一層,因為這些標準在任何情況下都不能違反,比如帳號名長度不能超過20個字符

       

      下面,我會一步步講3中驗證方法介紹給大家

       

      3、前端和后端的結合

      完整地看過MVC教程的人應該都知道如何使用 ModelState,其實MVC驗證框架就是利用它,將驗證的結果顯示在頁面中。

       

      下面看一個例子:

      Controller
      [HttpPost]
      //如果表單中input的name屬性和Model的字段一樣,那可以直接以Model形式傳入一個Action
      public ActionResult Exp1(Models.UserModel user)
      {
      //判斷
      if (user.Name.Length > 20)
      {
      //如果錯誤,調用ModelState的AddModelError方法,第一個參數需要輸入出錯的字段名
      ModelState.AddModelError("Name", "名字不得超過20個字符");
      }
      //判斷ModelState中是否有錯誤
      if (ModelState.IsValid)
      {
      //如果沒錯誤,返回首頁
      return RedirectToAction("Index");
      }
      else
      {
      //如果有錯誤,繼續輸入信息
      return View(user);
      }
      }

      這里在Controller中一個Action中進行了數據驗證,并且把結果放入了ModelState中,那怎么在前端頁面顯示呢?

       

      如果不了解MVC的驗證框架,其實可以直接自動生成,看看標準做法

      在代碼上右擊,點Add View

      選擇創建強類型View,并且在內容中選擇Edit

       

      這是自動生成的View

       

       

      OK,下面我可以運行了。。。

       

      由于前端的頁面View是自動生成的,所以有些讀者可能沒看懂,為什么我剛剛在后端的數據驗證信息會顯示到前端去了呢?

      其實關鍵就是利用了這個:<%= Html.ValidationMessageFor(model => model.Name) %>

      不理解強類型方法、或還在使用MVC1.0的讀者可以看這個:<%= Html.ValidationMessage("Name") %>

      (除了ValidationMessage函數外,還有其它幾個函數,可以達到不同的效果,讀者可以自行研究下,這幾個函數都是以Validation開頭的)

       

      小結:在Controller中驗證數據,放入ModelState(其核心是一個字典),然后在利用函數讀取

      這樣,就達到了數據驗證時前端和后端相結合的效果。

       

       

      4、如何將數據驗證代碼放入業務邏輯層?

      上面那部分,我們看到了MVC數據驗證框架的核心,ModelState。

      只要在ModelState中添加錯誤就可以在前端頁面中顯示了。

       

      所以,這個部分的關鍵就是讓BLL操作ModelState

      這里,有2中方法可以參考,其中,第二種方案我是參考了xVal來實現的

       

      i)方案一:在調用BLL函數的時候直接傳入ModelState對象

      優點:這個是最好理解的,我直接傳入ModelState對象,讓BLL操作它不就可以了?

      缺點:BLL是業務邏輯層,它不應該知道自己被誰調用了,也就是說,BLL層中不應該出現任何MVC特有的東西(ModelState對象)

       

      下面就讓我來實現它:

       

      BLL
      using System;
      using System.Collections.Generic;
      using System.Linq;
      using System.Web;
      using System.Web.Mvc;

      namespace MvcApplication1.BLL
      {
      public static class UserBLL
      {
      public static void Edit(Models.UserModel user, ModelStateDictionary ModelState)
      {
      if (user.Name.Length > 20)
      {
      //如果錯誤,調用ModelState的AddModelError方法,第一個參數需要輸入出錯的字段名
      ModelState.AddModelError("Name", "名字不得超過20個字符");
      }
      if (ModelState.IsValid)
      {
      //在這里我可以寫一些代碼,因為完成了驗證,我就可以開始更新數據庫了
      }
      }
      }
      }

       

       

      Controller
      [HttpPost]
      public ActionResult Exp2(Models.UserModel user)
      {
      //調用BLL中的函數
      BLL.UserBLL.Edit(user, ModelState);

      if (ModelState.IsValid)
      {
      return RedirectToAction("Index");
      }
      else
      {
      //這里,前端頁面不用改,所以我直接利用第一個例子中的前端頁面
      return View("Exp1",user);
      }
      }

       

      OK,直接運行,結果和上一個方法一樣

       

      總結:在調用BLL的時候把ModelState傳入

       

       

      ii)方案二:通過錯誤捕捉,將BLL和Controller關聯起來

      如果使用方案一,會出現這樣一個問題:

      如果我的項目不用MVC了,要移植怎么辦?

      新的架構中也有類似于ModelState的東西。總不能把所有的BLL改一遍吧?

      所以,我們需要方案二。

       

      這里是通過編寫一個自定義Exception類,然后這個自定義Exception類有2個功能:

      1、加入錯誤

      2、把錯誤轉換到ModelState中(如果要轉移到別的架構,可以再寫一個新的轉移方法)

       

      下面的代碼就是這個自定義Exception類

       

      ModelExceptions
      //必須繼承自Exception
      public class ModelExceptions : Exception
      {
      //存放錯誤信息的List
      List<string[]> errors = new List<string[]>();

      //判斷是否有錯誤
      public bool IsValid
      {
      get
      {
      return errors.Count == 0 ? true : false;
      }
      }

      //增加錯誤信息
      public void AddError(string name, string message)
      {
      this.errors.Add(new string[] { name, message });
      }

      //填充ModelState
      public void FillModelState(ModelStateDictionary modelstate)
      {
      foreach (var e in this.errors)
      {
      modelstate.AddModelError(e[
      0], e[1]);
      }
      }
      }

       

       

       

      接下來是在Controller中的代碼

       

      Controller
      [HttpPost]
      public ActionResult Exp3(Models.UserModel user)
      {
      //用try來捕捉錯誤
      try
      {
      BLL.UserBLL.Edit(user);
      }
      catch (ModelExceptions e)
      {
      //如果發生了錯誤,就填充到ModelState中
      e.FillModelState(ModelState);
      }
      if (ModelState.IsValid)
      {
      return RedirectToAction("Index");
      }
      else
      {
      //這里,前端頁面不用改,所以我直接利用第一個例子中的前端頁面
      return View("Exp1", user);
      }
      }

       

       

       

      然后是在BLL中的代碼

       

      BLL
      public static void Edit(Models.UserModel user)
      {
      var e
      = new ModelExceptions();
      if (user.Name.Length > 20)
      {
      //如果錯誤,調用ModelState的AddModelError方法,第一個參數需要輸入出錯的字段名
      e.AddError("Name", "名字不得超過20個字符");
      }
      if (e.IsValid)
      {
      //在這里我可以寫一些代碼,因為完成了驗證,我就可以開始更新數據庫了
      }
      else
      {
      //如果有錯誤,就拋出錯誤
      throw e;
      }
      }

       

      總結:簡單的做法,在后期會反而會帶來很多麻煩,所以推薦方案二。而且方案二也不是很麻煩,反而讓人感覺很清晰

       

       

       

      5、如何將數據驗證代碼放入Model中?

      前面,在BLL中驗證數據已經很好了,但是又出現了一個問題

      一個Model,很多限制是固定的,比如長度不能超過20個字符

      但是我在BLL中有很多過程,比如修改,刪除等

      那我豈不是要在所有的過程中都多這個進行驗證?

      其實你也可以通過寫一個函數來解決這個問題

       

      但是,我(Model)的名字有沒有超過20個字符是我自己的事情,憑什么要你來鑒定?我自己說了算!

       

      插播笑話一則:在我家,大事我說了算,小事我老婆說了算~ 那什么是大事?什么是小事?像美國打不打伊拉克,這就是大事;別的都是小事……

       

      OK,言歸正傳…

       

      如何把數據驗證交給Model呢?這里需要引用一個DLL

       

      然后在Model中這樣做

       

      Model
      using System;
      using System.Collections.Generic;
      using System.Linq;
      using System.Web;
      using System.ComponentModel.DataAnnotations;

      namespace MvcApplication1.Models
      {
      public class UserModel
      {
      public string Name { get; set; }


      //屬性前加上Attribute
      [Required(ErrorMessage = "密碼不能為空")]
      [StringLength(
      20, ErrorMessage = "密碼長度不能超過20個字符")]
      public string Password { get; set; }
      }
      }

       

      引用 System.ComponentModel.DataAnnotations 命名空間,并且在Model屬性前加上Attribute(C# 新特性:特征),這樣就可以了

      請自行查看System.ComponentModel.DataAnnotations命名空間,看看可以有哪些驗證方法

      當然也可以自定義驗證,查看默認驗證的定義,看看它繼承了哪個類,自己仿寫就可以了

       

      我這里沒有取消掉BLL中的驗證,2種驗證可以混合使用

       

      OK,那在Controller和BLL中需要做什么?我們需要做一定的修改

       

      Controller
      [HttpPost]
      //MVC在傳入這個Model的時候已經進行了驗證,并且把錯誤放去了ModelState
      public ActionResult Exp4(Models.UserModel user)
      {
      try
      {
      //別的不變,除了這里,我們需要傳入ModelState.IsValid
      BLL.UserBLL.Edit(user,ModelState.IsValid);
      }
      catch (ModelExceptions e)
      {
      e.FillModelState(ModelState);
      }
      if (ModelState.IsValid)
      {
      return RedirectToAction("Index");
      }
      else
      {
      return View("Exp1", user);
      }
      }

       

       

      BLL
      public static void Edit(Models.UserModel user,bool IsValid)
      {
      var e
      = new ModelExceptions();
      if (user.Name.Length > 20)
      {
      e.AddError(
      "Name", "名字不得超過20個字符");
      }
      //別的不變,但在這里,我除了要判斷e中是否有錯誤外,還要判斷ModelState中是否有錯誤
      if (e.IsValid && IsValid)
      {
      //在這里我可以寫一些代碼,因為完成了驗證,我就可以開始更新數據庫了
      }
      else
      {
      throw e;
      }
      }

       

      我注釋了相對了上個例子改動的地方

       

       

      并且混合使用了2中驗證方法

      什么時候用Model驗證?  驗證Model固有的屬性

      什么時候用BLL驗證? 當需要驗證一些復雜關系的時候

       

       

      另外,為什么要把ModelState.IsValid傳入BLL?

      因為Model驗證是在這個Model傳入這個方法的時候就已經完成的

       如果不傳入,那BLL驗證中雖然沒錯誤,但不代表整個過程沒有錯誤。

      對數據庫的操作要知道完整的驗證信息,如果不傳入,會導致程序BUG

       

      總結:合理的根據情況來放置數據驗證代碼的位置才是王道

       

       

       

      6、如何更改錯誤提示的樣式?

      我這里用了MVC基本的那個例程,里面包含了CSS樣式表

      而默認情況下,雖然會出現譬如“名稱過長”這樣的文字信息,但是卻沒有樣式(默認是正常字體,正常顏色)

       

      那如何修改?

      其實打開MVC默認的CSS樣式表就不難發現,這些錯誤信息都有固定的class,所以只要寫一個CSS的class即可

       

      那怎么才能知道class名是什么呢? 最方便的方法,做好頁面后在瀏覽器中看一下即可

       

       

       

      7、Entity Framework中,如何在Model中編寫數據驗證?

      Entity Framework會自動生成Model,雖然是可以修改的,但是強烈建議不要直接修改Model原始代碼

      其實微軟早就想到這一點了,它生成的Model都是 partial class(部分類)

      也就是說,同一個類的代碼可以分幾部分,寫在不同的地方

       

      具體寫法如下,寫在不同的地方,但需要在同一個命名空間下

       

      User
      [MetadataType(typeof(UserMetaData))]
      public partial class User { }
      public class UserMetaData
      {
      [Required(ErrorMessage
      = "名字為空")]
      [StringLength(
      10, ErrorMessage = "名字長度不得超過10個字符")]
      public string Name { get; set; }

      [Required(ErrorMessage
      = "密碼為空")]
      [StringLength(
      20, ErrorMessage = "密碼長度不得超過20個字符")]
      public string Password { get; set; }

      [Required(ErrorMessage
      = "帳號為空")]
      [StringLength(
      10, ErrorMessage = "帳號長度不得超過10個字符")]
      public string Passport { get; set; }
      }

       

      這樣寫好后,便可以在Entity Framework中使用Model驗證了

       

       

      8、如何使用客戶端驗證

      任何平臺都可以靠js來實現客戶端驗證,但是我這里探討的是MVC的數據驗證。

      那MVC的客戶端數據驗證有什么不同呢?

       

      不同之處就在于,你可以不用寫一行javascript代碼!

      下面讓我們來實現它

       

      先添加3個javascript文件,請按順序添加:

       

       

      然后在View里添加一行代碼:(注意要添加在Form前)

       

      注意點:這里,其實是這個函數把Model驗證轉換成了javascript代碼,對!它只能轉換Model驗證,BLL驗證無法轉換,因為BLL驗證涉及到復雜的代碼,不可能全部轉換成javascript吧?并且BLL驗證很多還需要和數據庫交互。

      那如果想把BLL驗證也做成“客戶端”驗證怎么辦?(只有可能用ajax實現無刷新驗證,而不是真正的客戶端驗證)

      目前看來先只能手寫了

      如有收獲,我會繼續更新~

       

       

      9、Ending

      演示中的源碼(更新至2.0):下載

       

      如果感覺有收獲,那就點一下支持吧~

      如有疑問或者我文章中有不妥之處,請在下方留言,或者發送郵件到:dozer@dozer.net.cn

       

       

      Creative Commons License
      本作品采用知識共享署名-非商業性使用 3.0 Unported許可協議進行許可。

      posted @ 2010-04-12 03:27  Dozer  閱讀(12292)  評論(33)    收藏  舉報
      主站蜘蛛池模板: japanese边做边乳喷| 日本一区二区不卡精品| 日本韩无专砖码高清观看| 色综合色天天久久婷婷基地| 国产人妻大战黑人20p| 综合激情网一区二区三区| ww污污污网站在线看com| 无码熟妇人妻AV影音先锋| 亚洲精品日韩精品久久| 久久这里只精品热免费99| 精品熟女亚洲av在线观看| 亚洲自偷自偷在线成人网站传媒| 实拍女处破www免费看| 国产99在线 | 欧美| 国产精品日韩中文字幕| 中国亚洲女人69内射少妇| 国产无遮挡猛进猛出免费| 波多野结系列18部无码观看AV | 国模少妇无码一区二区三区| 国产精品福利一区二区久久| 国产成人精品亚洲午夜麻豆| 亚洲a成人片在线观看| 精品国产熟女一区二区三区| 亚洲a∨国产av综合av| 亚洲成人精品综合在线| 国产久爱免费精品视频| 吉川爱美一区二区三区视频| 国产啪视频免费观看视频 | 亚洲天堂av日韩精品| 亚洲欧洲精品日韩av| 久热视频这里只有精品6| 国产亚洲人成网站在线观看| 精品无码一区在线观看| 礼泉县| 亚洲五月天一区二区三区| 亚洲AV永久无码嘿嘿嘿嘿| 国产精品 欧美激情 在线播放| 日日碰狠狠添天天爽不卡| 久久成人影院精品777| 久久一夜天堂av一区二区| 国产精品自在线拍国产手机版|