ASP.NET沒有魔法_ASP.NET MVC 模型驗(yàn)證方法
在前面的文章中介紹了用戶的注冊及登錄功能,在注冊用戶時(shí)可以通過代碼的形式限制用戶名及密碼的格式,如果不符合要求那么就無法完成操作,如下圖:
該功能的原理是Identity基于的Entity Framework組件在添加用戶之前對(duì)用戶提交數(shù)據(jù)進(jìn)行校驗(yàn)后給出的錯(cuò)誤信息?! ?/p>
數(shù)據(jù)校驗(yàn)功能在每一個(gè)軟件系統(tǒng)中都是非常必要的,為了避免用戶輸入無效或非法數(shù)據(jù)導(dǎo)致的系統(tǒng)錯(cuò)誤,需要在數(shù)據(jù)進(jìn)行處理或持久化之前對(duì)其進(jìn)行驗(yàn)證確保數(shù)據(jù)的正確、有效性。
本文將從以下幾點(diǎn)來介紹ASP.NET MVC中的模型驗(yàn)證機(jī)制:
● 輸入驗(yàn)證
● .NET 的驗(yàn)證簡介
● ASP.NET MVC的后端模型驗(yàn)證
● ASP.NET MVC的客戶端模型驗(yàn)證
● 關(guān)于ASP.NET MVC的客戶端驗(yàn)證
● 自定義ASP.NET MVC中的模型驗(yàn)證
輸入驗(yàn)證
輸入驗(yàn)證的目的就是用來判斷一個(gè)變量是否能夠滿足規(guī)定的要求,這里既然提到了“判斷”那么使用程序來實(shí)現(xiàn)時(shí)最直接的方式就是通過判斷語句來完成,如:
但是在.Net中是否有一種統(tǒng)一的方式來實(shí)現(xiàn)數(shù)據(jù)的驗(yàn)證呢?否則每次通過判斷語句來寫驗(yàn)證代碼既不能重用又影響閱讀。
.NET 的驗(yàn)證簡介
在.Net中提供了一種基于特性的數(shù)據(jù)類型標(biāo)記(DataAnnotations)、驗(yàn)證機(jī)制。
1、數(shù)據(jù)類型的標(biāo)記:
.Net中有一個(gè)名為system.componentmodel.dataannotations的類庫,里面包含了很多特性(Attribute)。這些特性用于標(biāo)記.Net類型中的屬性的數(shù)據(jù)類型信息。比如數(shù)據(jù)長度、格式、能否為空等等。
下圖為該類庫中的部分類型,從中可以看到如信用卡、郵件地址、最大/最小長度等特性類型:
數(shù)據(jù)標(biāo)記特性(Data Annotation attributes)有三種類型,分別是:
● 驗(yàn)證特性:用于執(zhí)行驗(yàn)證規(guī)則,如郵箱地址、數(shù)據(jù)類型、數(shù)據(jù)長度、數(shù)字區(qū)間、正則表達(dá)式等驗(yàn)證特性。
● 展示特性:用于指定被標(biāo)記的類型或?qū)傩匀绾卧赨I上展示。
● 模型關(guān)系特性:用于指定類成員與其它類型的關(guān)系,如外鍵特性等。
下圖是通過特性對(duì)一個(gè)實(shí)體類型的name屬性進(jìn)行標(biāo)記的結(jié)果,從標(biāo)記的名稱可以輕易看出該name屬性是必填的并且最大長度為30,展示的名稱為“名稱”。
但需要注意的是system.componentmodel.dataannotations所提供的特性僅僅是一種描述,它不會(huì)因?yàn)槟阆拗屏艘粋€(gè)字符串的長度就無法給它賦值超出限制的字符串,它必須手動(dòng)調(diào)用驗(yàn)證方法或者在ASP.NET MVC、EF中使用。(可參考:https://stackoverflow.com/questions/6496705/how-do-data-annotations-work)
關(guān)于dataannotations提供的特性類型可參考:https://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.aspx
2、數(shù)據(jù)類型的驗(yàn)證
當(dāng)使用數(shù)據(jù)特性標(biāo)記對(duì)類型完成標(biāo)記后,還需要通過專門的驗(yàn)證類型才可以完成驗(yàn)證,該類型同樣存在于system.componentmodel.dataannotations程序集中名為Validator,下圖是Validator的定義,從其描述來看該類用于對(duì)使用ValidationAttribute特性標(biāo)記的類型、屬性、方法進(jìn)行驗(yàn)證:
3、類型驗(yàn)證示例
通過一個(gè)Console程序來演示如何使用.Net中的數(shù)據(jù)驗(yàn)證:
首先創(chuàng)建一個(gè)Console程序,并添加System.ComponentModel.DataAnnotations程序集的引用,然后編寫以下代碼:
運(yùn)行后將輸出以下錯(cuò)誤信息:
添加顯示特性后:
優(yōu)化了驗(yàn)證提示信息:
4、自定義驗(yàn)證方式:
系統(tǒng)內(nèi)置的數(shù)據(jù)驗(yàn)證特性均是繼承至ValidationAttribute類型,下面就通過繼承該類型來實(shí)現(xiàn)一個(gè)自己的數(shù)據(jù)驗(yàn)證方式:
首先添加一個(gè)繼承ValidationAttribute的類型,并重寫其IsValid方法,該方法中包含數(shù)據(jù)驗(yàn)證的邏輯,并設(shè)置相應(yīng)的錯(cuò)誤信息:
然后在相應(yīng)的類屬性上應(yīng)用該特性:
驗(yàn)證結(jié)果:
關(guān)于自定義驗(yàn)證特性可參考:https://msdn.microsoft.com/en-us/library/cc668224.aspx
ASP.NET MVC的模型驗(yàn)證
ASP.NET MVC中提供了基于特性標(biāo)記的模型驗(yàn)證的功能,既只要在用做action參數(shù)的類型屬性上添加對(duì)應(yīng)的數(shù)據(jù)驗(yàn)證特性,那么ASP.NET MVC在進(jìn)行模型綁定時(shí)就會(huì)自動(dòng)對(duì)被標(biāo)記的屬性進(jìn)行驗(yàn)證。驗(yàn)證的結(jié)果通過Controller中的ModelState的IsValid屬性體現(xiàn)?! ?/p>
下面就介紹如何在ASP.NET MVC中為Model添加數(shù)據(jù)驗(yàn)證:
1.使用特性為Model的屬性進(jìn)行標(biāo)記,如必填、密碼類型及屬性間的比較等:
2.在Action代碼中添加ModelState.IsValid判斷,當(dāng)出現(xiàn)錯(cuò)誤時(shí),將錯(cuò)誤信息通過ModelState對(duì)象的AddModelError方法攜帶至View中:
3、在View中使用Html.ValidationSummary方法輸出驗(yàn)證信息:
注:如果View中有用于客戶端驗(yàn)證的代碼需要先注釋掉@Scripts.Render("~/bundles/jqueryval"),該文件用于客戶端驗(yàn)證,客戶端驗(yàn)證在后面介紹。
4、在頁面上使用Html對(duì)象根據(jù)模型生成對(duì)應(yīng)的html標(biāo)簽
5、運(yùn)行程序
輸入空的用戶名和不匹配的兩個(gè)密碼,點(diǎn)擊提交后:
顯示驗(yàn)證未通過:
頁面上輸出的內(nèi)容:
6、使用display特性來優(yōu)化屬性名稱的輸出:
執(zhí)行結(jié)果:
ASP.NET MVC的客戶端模型驗(yàn)證
前面介紹的是ASP.NET MVC服務(wù)端的模型驗(yàn)證,當(dāng)數(shù)據(jù)提交到服務(wù)器時(shí)進(jìn)行驗(yàn)證的方式,雖然能夠在業(yè)務(wù)邏輯之前過濾數(shù)據(jù)無效的請求,但是仍然需要將請求發(fā)送到服務(wù)器,當(dāng)請求過多時(shí)這些無效的請求會(huì)占用大量的服務(wù)器資源,所以如果能夠在客戶端完成相應(yīng)的驗(yàn)證,那么對(duì)于客戶來說提升了響應(yīng)速度,而對(duì)于服務(wù)器來說減少了壓力,ASP.NET MVC就結(jié)合Jquery Validation插件提供了瀏覽器端的數(shù)據(jù)驗(yàn)證功能。
接下來就在上面代碼的基礎(chǔ)上,通過在頁面中引入驗(yàn)證相關(guān)javascript實(shí)現(xiàn)在客戶端驗(yàn)證:
1、添加以下代碼,引入驗(yàn)證相關(guān)Js代碼:
2、使用Html對(duì)象的ForXXX方法在View上生成Model對(duì)應(yīng)標(biāo)記的Html代碼:
3、運(yùn)行效果:
結(jié)果與服務(wù)端驗(yàn)證一致,但是點(diǎn)擊注冊按鈕時(shí)不再去發(fā)送Post請求到服務(wù)器,而是通過js代碼在瀏覽器完成的數(shù)據(jù)驗(yàn)證。
關(guān)于ASP.NET MVC的客戶端驗(yàn)證Jquery Validation
Jquery Validation是一個(gè)Jquery的插件,它提供了強(qiáng)大的表單數(shù)據(jù)驗(yàn)證功能,可以簡單快速的為Web應(yīng)用添加一些常用的數(shù)據(jù)驗(yàn)證,如必填、數(shù)字、郵箱、電話號(hào)碼、正則表達(dá)式等常用格式驗(yàn)證。 它的驗(yàn)證功能是通過在表單的標(biāo)簽中添加一些屬性或設(shè)置其類型來完成的,如下圖所示,該代碼來自官方文檔,它提供了長度限制、必填、Email格式、Url格式的驗(yàn)證:
更多關(guān)于Jquery Validation的內(nèi)容可參考文檔:https://jqueryvalidation.org/documentation/
Unobtrusive Javascript
Unobtrusive Javascript可以譯為非侵入式的Javascript,其目的就是為了分離HTML和Javascript,換句話說HTML中沒有JavaScript代碼,它們只有引用關(guān)系。這樣做既可以避免代碼混亂,又可以避免不同瀏覽器之間的兼容問題?! ?/p>
而ASP.NET MVC是通過在HTML中的標(biāo)簽上插入data-val*等屬性,對(duì)相應(yīng)的標(biāo)簽進(jìn)行標(biāo)記,然后引入的js通過讀取這些特殊標(biāo)記來完成特定的功能,以下是通過Html.TextBoxFor方法生成HTML:
從代碼中可以看到除了input標(biāo)簽正常的屬性外還生成了data-val為前綴的相關(guān)屬性,這些屬性將用于輔助js代碼完成數(shù)據(jù)驗(yàn)證。
關(guān)于@Scripts.Render("~/bundles/jqueryval"):
首先Scripts對(duì)象的Render方法是用于將指定的腳本文件路徑添加到頁面中,而它的參數(shù)是一個(gè)字符串?dāng)?shù)組代表腳本文件的路徑?! ?/p>
那么~/bundles/jqueryval指向的是哪個(gè)文件呢?
在ASP.NET MVC中提供了一個(gè)bundle的技術(shù),它可以用來合并和壓縮JavaScript和css文件,bundle的配置一般在App_Start目錄下的BundleConfig.cs文件下,從下圖的代碼中就可以看出,~/bundles/jqueryval代表了能夠被jquery.validate*匹配的所有文件:
然后向注冊路由一樣將其注冊到一個(gè)全局靜態(tài)Bundle列表中:
這樣在UI上就可以使用~/bundles/jqueryval來獲取到與驗(yàn)證相關(guān)的js文件,更多關(guān)于UI的內(nèi)容將在后續(xù)文章中介紹。
自定義ASP.NET MVC中的模型驗(yàn)證
上面介紹了ASP.NET MVC中的模型驗(yàn)證,其內(nèi)置了一些常用的驗(yàn)證方式,但是在實(shí)際開發(fā)中仍然會(huì)出現(xiàn)無法滿足需求的情況,所以在這些情況下就需要根據(jù)實(shí)際需求來自定義驗(yàn)證,包括后端驗(yàn)證與前端驗(yàn)證?! ?/p>
1、添加自定義驗(yàn)證特性:
上面代碼需要注意以下幾點(diǎn):
● 實(shí)現(xiàn)了ValidationAttribute類型并重寫了用于獲取錯(cuò)誤信息的FormatErrorMessage方法以及用于驗(yàn)證數(shù)據(jù)的IsValid方法。
● 實(shí)現(xiàn)了System.Web.Mvc命名空間下的IClientValidatable接口,該接口是ASP.NET MVC拓展的用于實(shí)現(xiàn)客戶端驗(yàn)證的接口,該接口用于創(chuàng)建并返回一個(gè)驗(yàn)證規(guī)則列表,該驗(yàn)證規(guī)則主要包含了錯(cuò)誤信息、驗(yàn)證類型、驗(yàn)證參數(shù)三個(gè)屬性,其中錯(cuò)誤信息在默認(rèn)的信息中添加了“來自客戶端驗(yàn)證”用于區(qū)分服務(wù)端驗(yàn)證。
注:由于客戶端驗(yàn)證僅僅是ASP.NET MVC中的特性,所以IClientValidatable接口存在與System.Web.Mvc程序集中。
2、拓展Jquery Validation插件,添加一個(gè)名為myblog.validate.extension.js的驗(yàn)證拓展文件,并對(duì)Jquery validation添加新的驗(yàn)證方法(注:方法第一個(gè)參數(shù)與GetClientValidationRules方法中設(shè)置的ValidationType屬性一致),最后通過jQuery.validator.unobtrusive.adapters添加MVC與Jquery Validation的關(guān)聯(lián):
注:添加關(guān)聯(lián)代碼時(shí)需要添加名稱與ValidationType屬性一致的messages及rules。
3、將拓展的js文件引入頁面中:
bundleConfig.cs:
頁面代碼:
4、將新添加的特性應(yīng)用到相應(yīng)的類型屬性上:
5、執(zhí)行結(jié)果:
小結(jié)
數(shù)據(jù)驗(yàn)證對(duì)于應(yīng)用程序來說是一個(gè)非常重要的功能,從本文的分析中可以看出,一個(gè)數(shù)據(jù)可能會(huì)在客戶端錄入時(shí)、服務(wù)器接收時(shí)以及業(yè)務(wù)邏輯處理時(shí)對(duì)其進(jìn)行驗(yàn)證,那么可能會(huì)有疑問這些代碼是否是重復(fù)的沒必要的,答案是否定的,首先對(duì)于服務(wù)器來說所有來自客戶端的數(shù)據(jù)都是不可信的,所以無論數(shù)據(jù)在瀏覽器中是否被驗(yàn)證過,都需要在服務(wù)端進(jìn)行驗(yàn)證,而對(duì)于業(yè)務(wù)邏輯來說,它是一個(gè)整體,它自己本身就規(guī)定了什么數(shù)據(jù)是合法的什么是非法的,所以其本身就必須包含驗(yàn)證邏輯,否則該業(yè)務(wù)邏輯的單元測試都無法通過,而最后對(duì)于服務(wù)端的Model驗(yàn)證來說,它做為請求的接收者,決定了是否執(zhí)行相應(yīng)的業(yè)務(wù)邏輯,它們即獨(dú)立又存在聯(lián)系。
另外文中還對(duì)涉及到的Unobtrusive Javascript進(jìn)行了簡要介紹,非侵入式JavaScript是一種思想,除了這里的數(shù)據(jù)驗(yàn)證外還可以將其用于其它地方。接下來的文章將對(duì)ASP.NET MVC如何將HTTP請求的數(shù)據(jù)綁定到Model進(jìn)一步說明。
以上這篇ASP.NET沒有魔法_ASP.NET MVC 模型驗(yàn)證方法就是小編分享給大家的全部內(nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
asp.net通過消息隊(duì)列處理高并發(fā)請求(以搶小米手機(jī)為例)
這篇文章主要介紹了asp.net通過消息隊(duì)列處理高并發(fā)請求(以搶小米手機(jī)為例),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-03-03一個(gè)伴隨ASP.NET從1.0到4.0的OutputCache Bug介紹
一個(gè)伴隨ASP.NET從1.0到4.0的OutputCache Bug介紹,學(xué)習(xí).net的朋友可以參考下。2011-11-11動(dòng)態(tài)改變ASP.net頁面標(biāo)題和動(dòng)態(tài)指定頁面樣式表的方法
動(dòng)態(tài)改變ASP.net頁面標(biāo)題和動(dòng)態(tài)指定頁面樣式表的方法...2007-04-04asp.net實(shí)現(xiàn)存儲(chǔ)和讀取數(shù)據(jù)庫圖片
這篇文章主要為大家詳細(xì)介紹了asp.net實(shí)現(xiàn)存儲(chǔ)和讀取數(shù)據(jù)庫圖片,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-11-11