MVC 3 資料驗證 Model Validation 詳解
繼續我們前面所說的知識點進行下一個知識點的分析,這一次我們來說明一下資料驗證。其實這是個很容易理解並掌握的地方,但是這會浪費大家狠多的時間,所以我來總結整理一下,節約一下大家寶貴的時間。
在MVC 3中 資料驗證,已經應用的非常普遍,我們在web form時代需要在View端通過js來驗證每個需要驗證的控制元件值,並且這種驗證的可用性很低。但是來到了MVC 新時代,我們可以通過MVC提供的資料驗證Attribute來進行我們的資料驗證。並且MVC 提供了客戶端和伺服器端 雙層的驗證,只有我們禁用了客戶端js以後,也會執行服務端驗證,所以大大提高了我們的開發進度。今天我們就一起以一個初學者的身份來進入資料驗證的殿堂。
首先,要使MVC 資料驗證在客戶端生效,我們必須匯入必要的js庫。其中我在一篇部落格中專門介紹了通過jquery.validate.js進行鏈式驗證的方式。
1 <script src="@Url.Content("~/Scripts/jquery-1.5.1.min.js")" type="text/javascript"></script> 2 <script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script> 3 <script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
然後我們就需要新增對應的Model ,其實在MVC中Model層對應的不一定是實體類,還可以是領域模型。這個區別還是存在的。我們新增一個簡單的User類,
1 namespace MvcApplication4.Models 2 { 3 public class UserInfo 4 { 5 //ID編號 6 [ScaffoldColumn(false)] 7 [Required(AllowEmptyStrings = false, ErrorMessage = "使用者ID不能為空")] 8 [Display(Name = "記錄編號", Order = 20000)] 9 public int ID { get; set; } 10 11 [Display(Order = 15000)] 12 [Required(AllowEmptyStrings = false, ErrorMessage = "使用者名稱不能為空")] 13 [StringLength(20, MinimumLength = 6, ErrorMessage = "使用者名稱不能大於{2} 且要小於{1}")] 14 [Remote("User", "Validate", HttpMethod = "post", ErrorMessage = "使用者名稱已經存在")] 15 public string UserName { get; set; } 16 17 18 [Display(Name="password")] 19 [DataType(DataType.Password)] 20 [Required(AllowEmptyStrings = false, ErrorMessage = "密碼不能為空")] 21 [StringLength(60, MinimumLength = 20, ErrorMessage = "密碼必須在{2} 和{1}之間")] 22 public string UserPassword { get; set; } 23 24 [Required(AllowEmptyStrings = false, ErrorMessage = "郵箱必填")] 25 [RegularExpression(@"[A-Za-z0-9._%+-][email protected][A-Za-z0-9]+\.[A-Za-z]{2,4}", ErrorMessage = "{0}的格式不正確")] 26 public string Email { get; set; } 27 28 [Compare("Email", ErrorMessage = "郵箱要相同")] 29 public string TEmail { get; set; } //compare 大小寫要相同 否則不會觸發 驗證 30 31 32 [Display(Name = "身份證號碼")] 33 [RegularExpression(@"\d{17}[\d|x]|\d{15}", ErrorMessage = "身份證號碼格式錯誤")] 34 public string IdentityNo { get; set; } 35 36 [Required(AllowEmptyStrings = false, ErrorMessage = "年齡必填")] 37 [Range(10, 100, ErrorMessage = "年齡不能大於{2} 不能小於{1}")] 38 public int Age { get; set; } 39 40 [ReadOnly(true)] 41 [DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:c}")] 42 [Required(ErrorMessage = "金額不能為空")] 43 [Range(typeof(decimal), "20.0", "30.0", ErrorMessage = "金額在{1}和{2}之間")] 44 public decimal Money { get; set; } 45 } 46 }
在Model 層UserInfo類中,我們定義了一個User應該具有的屬性,以及需要為每個屬性新增的不同驗證。設定好了Model,我們就需要通過Controller來顯示對應的View層。
其實Controller不需要做任何的處理,只需要選擇一個合適的View進行頁面顯示。最重要的是在View層。
1 @{ 2 Layout = null; 3 } 4 @model MvcApplication4.Models.UserInfo 5 <!DOCTYPE html> 6 <html> 7 <head> 8 <title>Index</title> 9 </head> 10 <body> 11 <script src="@Url.Content("~/Scripts/jquery-1.5.1.min.js")" type="text/javascript"></script> 12 <script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script> 13 <script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script> 14 <div> 15 @using (Html.BeginForm()) 16 { 17 @Html.ValidationSummary(true) 18 <fieldset> 19 <legend>UserInfo</legend> 20 21 22 23 <div class="editor-label"> 24 @Html.LabelFor(t => t.UserPassword) 25 </div> 26 <div class="editor-field"> 27 @Html.EditorFor(model => model.UserPassword) 28 @Html.ValidationMessageFor(model => model.UserPassword) 29 </div> 30 <div class="editor-label"> 31 @Html.LabelFor(t => t.IdentityNo) 32 </div> 33 <div class="editor-field"> 34 @Html.EditorFor(model => model.IdentityNo) 35 @Html.ValidationMessageFor(model => model.IdentityNo) 36 </div> 37 <div class="editor-label"> 38 @Html.LabelFor(t => t.Email) 39 </div> 40 <div class="editor-field"> 41 @Html.EditorFor(model => model.Email) 42 @Html.ValidationMessageFor(model => model.Email) 43 </div> 44 45 <div class="editor-label"> 46 @Html.LabelFor(t => t.Age) 47 </div> 48 <div class="editor-field"> 49 @Html.EditorFor(model => model.Age) 50 @Html.ValidationMessageFor(model => model.Age) 51 </div> 52 53 <div class="editor-label"> 54 @Html.LabelFor(t => t.Money) 55 </div> 56 <div class="editor-field"> 57 @Html.EditorFor(model => model.Money) 58 @Html.ValidationMessageFor(model => model.Money) 59 </div> 60 61 <div class="editor-label"> 62 @Html.LabelFor(t => t.TEmail) 63 </div> 64 <div class="editor-field"> 65 @Html.EditorFor(model => model.TEmail) 66 @Html.ValidationMessageFor(model => model.TEmail) 67 </div> 68 69 @Html.EditorForModel() 70 71 </fieldset> 72 <input type="submit" value="提交" /> 73 } 74 </div> 75 </body> 76 </html>
我在View層中定義了兩種顯示Model資料的方式,一種是通過html.EditorFor(model)來分別顯示每個不同的屬性,另外一個簡潔的方式就是通過html.EditorForModel()進行,這個方法會提供錯誤資訊顯示等。
Model 、View、Controller都設定好了,下面我們來看一下最終執行的效果。
在效果圖中,我們看到了兩個相同的部分,這是我採用兩個不同的顯示方式顯示的效果。其中有兩個Age,這兩個只要一個驗證通過,就會驗證通過。根本原因就是它們的ID值是相同的。
看到了實際效果,我們來逐個分析一下每個驗證Attribute的實現方式 極其注意方式。
Required 必填項 表示的是這個欄位值是必填的。
[Required(AllowEmptyStrings = false, ErrorMessage = "使用者名稱不能為空")]
Display 欄位顯示的名稱 表示該欄位顯示的是Name值,而不是欄位本身的名稱
[Display(Name="password")]
StringLength 表示的是驗證字串的長度。我們可以設定最小長度和最大長度,如果不在這個範圍內,則會提示錯誤資訊
[StringLength(20, MinimumLength = 6, ErrorMessage = "使用者名稱不能大於{2} 且要小於{1}")]
其中我們看到ErrorMessage中有佔位符存在,其實這個佔位符很容易理解,就是{0}表示的是欄位本身的名稱,{1}表示它前面的第一個引數,{2}表示它前面的第二個引數。
ScaffoldColumn 表示的是是否採用MVC框架來處理 設定為true表示採用MVC框架來處理,如果設定為false,則該欄位不會在View層顯示,裡面定義的驗證也不會生效。
[ScaffoldColumn(false)]
Remote 表示的是進行遠端驗證,這個相當於我們採用ajax方式來非同步的請求伺服器,並返回資訊。最常用的就是驗證使用者名稱是否重複。下面這個驗證是非同步呼叫ValidateController下面的User Action 並且返回結果為json值。
[Remote("User", "Validate", HttpMethod = "post", ErrorMessage = "使用者名稱已經存在")]
DataType 表示的是欄位的資料型別 這個會影響到欄位在View層的顯示效果。如果設定為password,則輸入時會用*替換。
[DataType(DataType.Password)]
RegularExpression 正則表示式驗證。正則表示式我曾經在我的一篇部落格中有所介紹。正則表示式是驗證字串的利器,我們必須掌握的。前面是驗證模式,後面是出錯顯示的錯誤資訊。
[RegularExpression(@"[A-Za-z0-9._%+-][email protected][A-Za-z0-9]+\.[A-Za-z]{2,4}", ErrorMessage = "{0}的格式不正確")]
Compare 比較兩個欄位值是否相同,這個如果我們採用js進行驗證的話,最少需要三行,這還只是客戶端驗證。那麼在MVC中就比較容易實現了。
[Compare("Email", ErrorMessage = "郵箱要相同")]
在Compare 驗證中有一個地方需要注意,就是第一個引數,它是另一個欄位的名稱,我們一定要注意大小寫正確,如果錯誤的話,驗證就不會通過的。
Range 表示的大小資料的大小驗證。這個Attribute可以驗證int,double,decimal等資料型別的值的大小範圍。 表示的是在10和100之間,包括10和100
[Range(10, 100, ErrorMessage = "年齡不能大於{2} 不能小於{1}")]
ReadOnly 表示欄位是否只讀。 這個在View層我有時測試會沒有執行。具體原因還未知。
DisplayFormat 表示的資料顯示的樣式。其實這個不屬於資料驗證特性,而應該屬於資料格式。如果要啟用格式設定,第一個引數一定要設定為true,第二個就和我們toString()方法後面的引數一樣。
[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:c}")]
UiHint 告訴MVC 指定的模版。
HiddenInput 隱藏域顯示
其實我個人是將資料驗證的這些特性分為兩類,一類是真正的進行驗證,Required,Range,StringLength,Display,Remote,RegularExpression,Compare,Range。這些特性是真正會進行驗證的Attribute。另外幾個Display,ReadOnly,DataType,DisplayFormat,ScaffoldColumn等和欄位的顯示有關,沒有真正的和伺服器端進行驗證。
我們可以使用MVC提供的各種驗證特性,那麼我們是否可以自己來定義自定義特性驗證呢。MVC有著巨大的可擴充套件性,我們也可以自己進行擴充套件,有兩種擴充套件方式,一種就是可以重複使用的和MVC框架中驗證,只要繼承自ValidationAttribute 就可以實現重複使用的驗證特性,另一種就是內包含的模式,它是隻驗證特定的Model,繼承自IValidatableObject可以實現字包含的驗證。
可重複使用的驗證特性,繼承自ValidationAttribute。
1 public class MaxWordsAttribute : ValidationAttribute 2 { 3 4 public MaxWordsAttribute(int maxWords) 5 : base("{0} 字串過長") 6 { 7 _maxWords = maxWords; 8 } 9 private readonly int _maxWords; 10 11 protected override ValidationResult IsValid(object value, ValidationContext validationContext) 12 { 13 if (value != null) 14 { 15 var valueAsString = value.ToString(); 16 if (valueAsString.Split(' ').Length > _maxWords) 17 { 18 var errorMessage = FormatErrorMessage( 19 validationContext.DisplayName); 20 return new ValidationResult(errorMessage); 21 } 22 } 23 return ValidationResult.Success; 24 } 25 }
MVC 驗證特性提高了我們開發的效率以及穩定性,值得我們學習。還是那句話,每天學一學,自己常進步,世界更美好。
MVC 的驗證擴充套件特性 以及全球化,我們在以後有機會在一起學習。
相關推薦
MVC 3 資料驗證 Model Validation 詳解
繼續我們前面所說的知識點進行下一個知識點的分析,這一次我們來說明一下資料驗證。其實這是個很容易理解並掌握的地方,但是這會浪費大家狠多的時間,所以我來總結整理一下,節約一下大家寶貴的時間。 在MVC 3中 資料驗證,已經應用的非常普遍,我們在web form時代需要在View端通過js來驗證每個需要驗證的控制
MVC,MVP 和 MVVM 的詳解
name one control ember 模式 hash 改名 主動性 主動 一、MVC MVC模式的意思是,軟件可以分成三個部分。 視圖(View):用戶界面。 控制器(Controller):業務邏輯 模型(Model):數據保存 各部分之間的通信方式如下
springMVC引入Validation詳解
note get string getter abi res @override success temp 本文簡單介紹如何引入validation的步驟,如何通過自定義validation減少代碼量,提高生產力。特別提及:非基本類型屬性的valid,GET方法的處理,va
實戰 :Spring MVC + 註解 +SqlServer 框架搭建及詳解
原始碼下載:http://download.csdn.NET/detail/u010469432/6786687 https://blog.csdn.net/u010469432/article/details/17587699 先說一下Spring3 MVC的優點: spring&nb
Linux下多資料夾編寫Makefile詳解
分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!  
jdbc:oracle:thin:@192.168.3.98:1521:orcl(詳解)
原文章:點選開啟連結 整理自網際網路 一、 jdbc:oracle:thin:@192.168.3.98:1521:orcljdbc:表示採用jdbc方式連線資料庫oracle:表示連線的是oracle資料庫thin:表示連線時採用thin模式(oracle中有兩種模式)jdbc:oralce
sk buff封裝和解封裝網路資料包的過程詳解
分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!  
python 基本資料型別--字串例項詳解
字串(str) :把字元連成串. 在python中⽤', ", ''', """引起來的內容被稱為字串 。 注意:python中沒有單一字元說法,統一稱叫字串。 一、切片和索引 1、索引:索引就是下標,從0開始 str= "我是字串" print("str[0]=",st
JAVA基本資料型別、引用資料型別-引數傳遞詳解
1:基本型別的引數傳值 對於基本資料型別,修改這個值並不會影響作為引數傳進來的那個變數,因為你修改的是方法的區域性變數,是一個副本。實參的精度級別應等於或低於形參的精度級別,否則報錯。 class JB{ void f(int x, int y){ x=x+1;
Docker(3):Dockerfile配置詳解
FROM : 指定base映象 MAINTAINER :設定映象的作者,可以是任意的字串 COPY :將檔案從build context 複製到映象 COPY 支援兩種形式:CO
VC常用資料型別使用轉換詳解
分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!  
sk_buff封裝和解封裝網路資料包的過程詳解
可以說sk_buff結構體是Linux網路協議棧的核心中的核心,幾乎所有的操作都是圍繞sk_buff這個結構體進行的,它的重要性和BSD的mbuf類似(看過《TCP/IP詳解 卷2》的都知道),那麼sk_buff是什麼呢?  
Tensorflow官網CIFAR-10資料分類教程程式碼詳解
標題 概述 對CIFAR-10 資料集的分類是機器學習中一個公開的基準測試問題,本教程程式碼通過解決CIFAR-10資料分類任務,介紹了Tensorflow的一些高階用法,演示了構建大型複雜模型的一些重要技巧,著重於建立一個規範的網路組織結構,訓練並進行評估,為建立更大規模更加複雜的
kaggle 入門題 Tatanic | top_5%解法及資料分析常用技巧詳解
Titanic: 身為女性且來自頭等艙的ROSE存活率高達95%,身為男性且來自二等艙的Jack存活率不足10%。悲劇似乎在他們上船的那一刻就已經註定了。 姓名:李子羽 學號:2015300009 日期:2018/10/07 1.任務簡介 泰坦尼克號的沉沒是歷
JDBC元資料操作-- DatabaseMetaData介面詳解
package com.util; import java.sql.CallableStatement; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.DriverMana
5.3 以太坊原始碼詳解3
一、轉賬的概念和交易的基本流程 使用者輸入轉入的地址和金額 系統用轉賬地址的私鑰對交易進行簽名(確保這筆交易是由發起交易的所有人) 對交易進行驗證 存入交易快取池 廣播交易 二、交易的資料 type
mysql資料備份匯入匯出詳解
1、mysqldump 命令工具說明 引數註解: mysqldump 是採用SQL 級別的備份機制,它將資料表導成 SQL 指令碼檔案,在不同的 MySQL 版本之間升級時相對比較合適,這也是最
Unity3d中特殊資料夾以及作用詳解
1.Editor Editor資料夾可以在根目錄下,也可以在子目錄裡,只要名子叫Editor就可以。比如目錄:/xxx/xxx/Editor 和 /Editor 是一樣的,無論多少個叫Editor的資料夾都可以。Editor下面放的所有資原始檔或者指令碼檔案都不會被打進發
Apache Hadoop1.1.1+Apache Oozie3.3.2搭建安裝過程詳解(親測)
寫在前面: 最近需要定製的原因,需要將原來Cloudera版本的Hadoop更改為Apache版本的Hadoop和Oozie,對官方文件的學習,發現Hadoop1.1.1和Oozie3.3.2的組合比較好,所以,經過幾天的搭建,終於成功了,現在把心得分享出來,希望給需要的朋
[三]基礎資料型別之Integer詳解
Integer 基本資料型別int 的包裝類 Integer 型別的物件包含一個 int 型別的欄位 屬性簡介 值為 2^31-1 的常量,它表示 int 型別能夠表示的最大值 @Native public static final int