demoshop

demo, trying to be the best_

撰寫網頁程式的時候經常的需要對於表單資料實行驗證的功能,在 ASP.NET MVC 2 的時代也有提供所謂的內建驗證,但因為前端是使用了 MicrosoftMvcValidation 來實作,因此很讓人不想學...而去改用其他的前端驗證,如 jQuery.Validate等好用的前端驗證,但驗證只做前端等於找死,因此又要去實作後端的部份 Code,前後改一下再加上自訂的驗證後等於自己寫了一套驗證模組,十分的辛苦,而且也不是普通使用者可以寫出來的(需要了解一些可愛的反射與屬性),但這痛苦的經驗不需要在 ASP.NET MVC 3 再來一次,因為官方提供了兩個介面(IClientValidatable、IValidatableObject)讓每位開發人員可以輕鬆簡單的擴充出自己需要的驗證規則,並且也很容易的寫成前端後端都支援的驗證。

demo廢言本篇主要介紹 IClientValidatable 的使用,IClientValidatable 這個介面可以讓開發人員簡單的實現前端與後端的驗證,原生提供了 Range、 RegularExpression、Required、StringLength、Compare、Remote 這幾個實務上經常使用的驗證規則,而這次 ASP.NET MVC 3 已經改使用 jQuery.Validate 來做前端的驗證引擎,並且利用所謂的 unobtrusive 設計模式來達到整合與抽離,讓 HTML 依然漂亮,如此大的改變就能了解到 ASP.NET MVC 3 的確是彌補了上一版的不足,以下就來介紹如何使用內建的這幾項驗證規則。


●先建立一個 ASP.NET MVC 3 原生的樣板,執行後前往註冊會員的頁面(預設在 /Account/Register )

什麼都不填的情況直接按下「Register」

有驗證耶

刻意關掉瀏覽器的 Javascript 讓前端驗證失效再按「Register」


神奇了,為什麼連後端驗證也有


●這樣版非常好,因為它已經自訂出一個 AccountModels 並且加上了驗證,開啟以後拉到最後方找到 RegisterModel 這個 Class

public class RegisterModel
{
    [Required]
    [Display(Name = "User name")]
    public string UserName { get; set; }

    [Required]
    [DataType(DataType.EmailAddress)]
    [Display(Name = "Email address")]
    public string Email { get; set; }

    [Required]
    [StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
    [DataType(DataType.Password)]
    [Display(Name = "Password")]
    public string Password { get; set; }

    [DataType(DataType.Password)]
    [Display(Name = "Confirm password")]
    [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
    public string ConfirmPassword { get; set; }
}

注意事項有底色的就是關於驗證的 Attribute,因本篇主要是說明驗證因此與驗證無關的 Attribute 就不介紹了

就是因為有這些設定,因此註冊頁面才能支援前後端的驗證。


●上面看到的效果就是預設的 Required 驗證規則,很簡單就是必填的限制而已,不過既然預設支援那麼多,那不如就一個一個玩玩看吧。

public class RegisterModel
{
    [Required]//必填
    [StringLength(3,MinimumLength=2)]//最多三個字、最少兩個字
    [Display(Name = "User name")]
    public string UserName { get; set; }

    [Required]
    [DataType(DataType.EmailAddress)]
    [Display(Name = "Email")]
    [RegularExpression(@"\w+\@\w+",ErrorMessage="Email格式錯誤")]
    public string Email { get; set; }

    [Required]
    [StringLength(100, ErrorMessage = "{0} 欄位最少 {2} 個字,最多 {1} 個字", MinimumLength = 6)]
    [DataType(DataType.Password)]
    [Display(Name = "密碼")]
    public string Password { get; set; }

    [DataType(DataType.Password)]
    [Display(Name = "密碼確認")]
    [Compare("Password", ErrorMessage = "兩次密碼不一樣")]
    public string ConfirmPassword { get; set; }
}

注意事項將 RegisterModel 改成上方的規則後記得先編譯再前往註冊頁面試試看


●就可以看到新的驗證規則都生效了


demo廢言眼尖的朋友可能會發現, demo 少介紹一個 Remote ,沒錯!因為這個 Remote 比較特別因此抽出來說明,這個 Remote 的功能是讓前端去讀取後端的資料來驗證的,比如說剛剛的註冊會員功能,如果我們期待已經註冊過的 User Name 不能再被註冊,那上述介紹的任何一個驗證規則都無法勝任,因為驗證的邏輯牽扯到了資料庫中現有的資料,這種情況的時候就是使用 Remote 的時機,它可以利用 AJAX 的方式呼叫後端程式,由後端程式完成驗證後再傳回結果至前端,以下就是實作步驟。

 

●首先建立一個 ValidateController 並且在裡面寫上要給 Remote 呼叫的 Action

public class ValidateController : Controller
{
    public JsonResult CheckUserName(string userName)
    {
        bool isValidate = false;

        if (Url.IsLocalUrl(Request.Url.AbsoluteUri))
        {
            //利用 IsLocalUrl檢查是否為網站呼叫的
            //借此忽略一些不必要的流量

            if (userName != "demoshop")
            {
                //因連資料庫麻煩
                //所以假裝示範不可以註冊某一名字
                isValidate = true;
            }
        }
        // Remote 驗證是使用 Get 因此要開放
        return Json(isValidate, JsonRequestBehavior.AllowGet);
    }
}

●再來改變一下 RegisterModel 中的 UserName

[Required]//必填
[StringLength(10,MinimumLength=2)]//最多10個字、最少2個字
[Display(Name = "User name")]
[Remote("CheckUserName","Validate",ErrorMessage="遠端驗證失敗")]
public string UserName { get; set; }

注意事項此 Action 傳入的參數名稱必須要與你要驗證的屬性名稱一樣


●編譯過後回到註冊頁面,當我們輸入了「demoshop」時會顯示「遠端驗證失敗」的字樣


●開啟封包監控軟體(Firebug)查看第一次輸入「test」回傳的是「true」第二次輸入「demoshop」回傳的就是「false」了


●ASP.NET MVC 最令人喜歡的就是擴充性, Remote 驗證也提供了一些空間讓我們發揮,試想假設今天註冊的驗證需求改了, UserName 和 Email 都不能重複,難道我們要傻傻的寫兩次並且一直回後端問嗎?這不是一個網頁程式設計師該妥協的,所以程式又改成這樣

public JsonResult CheckUserName(string userName, string email)
{
    bool isValidate = false;

    if (Url.IsLocalUrl(Request.Url.AbsoluteUri))
    {
        if (userName != "demoshop" && email != "1234")
        {
            isValidate = true;
        }
    }
    return Json(isValidate, JsonRequestBehavior.AllowGet);
}

●RegisterModel 因為操作流程所以將 Remote 驗證移至 Email 欄位上

[Required]//必填
[StringLength(10, MinimumLength = 2)]//最多10個字、最少2個字
[Display(Name = "User name")]
public string UserName { get; set; }

[Required]
[DataType(DataType.EmailAddress)]
[Display(Name = "Email")]
[Remote("CheckUserName", "Validate", AdditionalFields = "UserName", ErrorMessage = "遠端驗證失敗")]
public string Email { get; set; }

注意事項千萬注意使用 AdditionalFields 的指定名稱大小寫一定要和欄位名稱一樣,像本範例你寫 AdditionalFields = "username" 是不會過的。


●編譯過後我們又回到註冊頁面

可以看到增加的欄位也利用 Querystring 傳到後端去了


●如果要傳遞的欄位不只一個,可以利用逗點來區隔,此範例就再加上 Password

[Remote("CheckUserName", "Validate", AdditionalFields = "UserName,Password",ErrorMessage = "遠端驗證失敗")]

(這樣也是有想到的所以說彈性還真好...

demo廢言第一篇好像就有點長了先前研究的時間不算,光是寫這篇就已經花了我六顆番茄,所以就先介紹到這吧,再來的文章重點在擴充與修改,本系列文目前已經規劃了九篇,還請各位有空多多回來觀看。

回應討論