第264期 / October 5, 2019

分享到臉書!分享到維特!分享到噗浪!分享到Google+!分享到微博!轉寄友人友善列印

ASP.NET MVC資料驗證實作

作者/張良碩

[發表日期:2019/10/4]

作者簡歷

畢業於政治大學資訊管理研究所,任職於凌群電腦SDPM團隊研發替代役,負責SASP、Service與MyNote等內部系統的開發、維護與組態管理,曾參與CMMI 與ISO認證。主要專長為ASP.NET、Windows Communication Foundation(WCF)與SQL Server 應用。

前言

製作可供使用者輸入的網站應用時,一定會遇到資料驗證的需求,常見的例如:「此欄位為必填」、「此欄位長度不得超過XX」或是「Email格式不符」等等,過去我們會為了這些需求在前端(用戶端)與後端(伺服器端)撰寫大量的程式碼,如果只是必填的驗證或許還很簡單(如下圖)


《圖一》


一兩行就可以解決,但如果像是Email的驗證、值域、屬性比較或是日期驗證等其他需求,程式碼可能就會複雜許,以Email驗證為例,就會見到如天書般的正規表示式,如下:




好在ASP.NET MVC引入了System.ComponentModel.DataAnnotations命名空間,加上jquery.validate.js、jquery.validate.unobtrusive.js套件,讓前後端的資料驗證都能夠藉由Model的MetaData(中繼資料)加上特定HTML Tag來控制,同時也提供良好的擴展性以因應各式各樣的資料驗證需求,讓工程師在表單提交(Form Submit)的資料驗證上省下許多的工。

資料驗證實作-伺服器端篇

MVC3之後在web.config的下多了兩個預設的屬性,必須確認兩者皆設定為true。


《圖二》


在頁面使用的Model必須要引用System.ComponentModel.DataAnnotations


《圖三》


接著就可以在欄位上加上驗證屬性了,加上這些驗證屬性之後,Model就設定完成了,下列示範幾個最常用的驗證屬性:

一、[Required]:

資料欄位為必填,參數傳入的字串為自訂顯示訊息,以下圖為例,自訂訊息帶入指定語系檔,可以達到多語系的需求。


《圖四》


二、[Range]:

定義資料欄位的範圍,需要傳入最小值與最大值,範例為限制年齡範圍1~100歲之間


《圖五》


三、[StringLength]:

定義欄位字串長度的限制,輸入參數為最大長度值,範例為限制姓名長度不超過5。


《圖六》


四、[EmailAddress]:

驗證Email的格式。


《圖七》


五、[Remote]:

Remote無法在用戶端進行驗證,通常運用在安全層級較高的欄位,運作的方式為AJAX呼叫一個Controller的Action來進行驗證,根據Action回傳的Json來判斷是否驗證成功,範例為藉由姓名跟Email判定帳號是否重複。


《圖八》


Action:

接下來進行View的撰寫,會使用到Razor語法中的HtmlHelper,Razor可以在頁面上以@符號產生程式碼區塊以插入伺服器端的指令,而HtmlHelper是在View中最常見的一種,它能夠產生與Model繫結的HTML標籤,範例圖為View中的Razor指令與其產生的HTML,其中各個以 For結尾的方法,都是指涉到Model中RealName。


《圖九》



《圖十》


當資料傳送到繫結的欄位時(範例中的RealName)就會觸發資料驗證,如果沒有通過驗證就會傳回錯誤訊息,範例中的@Html.ValidationMessageFor(model => model.RealName, "", new { @class = "text-danger" }),會負責顯示錯誤訊息,如果沒有加上這個指令,雖然也會有驗證的功能,但頁面上不會顯示任何訊息。


《圖十一》


資料驗證實作-用戶端篇

我們已經完成了伺服器端的資料驗證,如果我們想在用戶端做資料驗證,就必須結合jquery.validate.js與jquery.validate.unobtrusive.js套件,jquery.validate.unobtrusive.js是Unobtrusive Javascript理念的一種實踐,結構與行為必須分離,換句話說只要任何Javascript指令被放到HTML標籤中就是不對的,所以在Unobtrusive Javascript的理念下,我們不會看到的設計,而結構與行為分離的理念也與MVC的關注點分離不謀而合。

在頁面引用jquery.validate.js與jquery.validate.unobtrusive.js套件之後,只要input標籤data-val=“true”表示啟用客戶端驗證,data-val-rulename=”驗證失敗訊息"則為<input>加上各式的規則,例如: data-val-required="此欄是必填 "。


《圖十二》


如果不使用Razor語法產生HTML,直接在<input>標籤內加上data-val*的屬性,例如:

<input type="text" id="myEmail" name="myEmail" value="myEmail@syscom.com.tw"
data-val="true" data-val-email=”Email格式不符"/>
<span data-valmsg-for="myEmail"></span>

也能有驗證的功能,但因為沒有指涉到Model的欄位,所以就只能作用於用戶端。

資料驗證實作-客製驗證篇

MVC已經提供了很多驗證的規則,但不可能涵蓋了所有的需求,除了伺服器端限定可以呼叫自訂規則的CustomValidation之外,我們還可以選擇自行撰寫驗證類別,更棒的是在伺服器與用戶端都可以執行驗證。

現在要製作一個驗證類別CompareExtensions,可以比對兩個欄位的日期或數字,第一步要先繼承ValidationAttribute與IClientValidatable:


《圖十三》


ValidationAttribute類別執行伺服器端的驗證,IClientValidatable介面則是為了用戶端的驗證。

第二步是覆寫IsValid方法,在這裡實作驗證的規則,覆寫FormatErrorMessage來自訂錯誤訊息。


《圖十四》


第三步是實作IClientValidatable介面的GetClientValidationRules方法,需要注意的是ValidationType與ValidationParameters的參數名稱都必須是小寫的英數字字元:


《圖十五》


第四步在Model中加上自訂的屬性:


《圖十六》


第五步是擴充jquery.validate.js,因為在js套件內建的規則並沒有我們自訂的規則,所以用戶端的驗證不會運作。

在我們自己新增的js檔案裡面先引用jquery.validate.js與jquery.validate.unobtrusive.js,接下來把我們的驗證加入到jquery.validate.js與jquery.validate.unobtrusive.js中,adapters(jquery.validate.unobtrusive.js)第一個參數用於識別HTML中的規則名稱,第二個是驗證屬性值的HTML名稱,第三個function是對額外參數的處理,options.rules[...]會變成addMethod function(value, element, params)中的params傳入,而addMethod(jquery.validate.js)就是驗證規則,基本上就是把伺服器端的規則搬過來用Javascript再寫一遍。


《圖十七》


最後打開網頁,套用自訂規則欄位的HTML產生了data-val開頭的屬性,也能正確運作自訂的驗證規則。


《圖十八》


結語

資料驗證在資料正確性或資訊安全領域都是不可或缺的一環,而大部分的應用也會預防單一驗證機制失效而設置伺服器端與用戶端的驗證,而ASP.NET MVC DataAnnotations將前後端的驗證整合,雖然此套驗證機制是透過表單提交來觸發,但也可以透過指令改寫等其他方式來改變觸發條件,不管是非同步呼叫(AJAX)、或是一個按鈕觸發都可以達成,開發人員能夠比以往高上許多的效率為網頁應用提供一套容易維護又穩定的資料驗證機制。

參考資料
  • 蔡文龍(2016)。Visual C# 2015程式設計經典。台北:碁峰資訊股份有限公司。


  • demo、小朱、陳傳興、王育民與陳仕傑(2016)。ASP.NET MVC5 網站開發美學(9刷)。台北:碁峰資訊股份有限公司。


  • Bear Bibeault、Yehuda Katz、Aurelio De Rosa(2016)。jQuery 實戰手冊第三版。台北:碁峰資訊股份有限公司。


  • https://blog.darkthread.net/blog/unobtrusive-jquery-validation/