Asp.Net MVC 模型驗證詳解-實現客戶端、服務端雙重驗證


概要

         在asp.net webform開發中經常會對用戶提交輸入的信息進行校驗,一般為了安全起見大家都會在客戶端進行Javascript(利於交互)、服務端雙重校驗(安全)。書寫校驗代碼是一個繁瑣的過程。在Asp.Net MVC中就很好的解決了這一問題、利用模型的數據注解實現客戶端與服務端雙重校驗,使你的開發效率大大提高。

 

數據注解

         微軟提供了很多數據注解的類(通俗點就是特性標簽類),也為我們提供了自定義接口來滿足開發人員不同的需求。下面一一為大家說明。

         命名空間:System.ComponentModel.DataAnnotations;

       程序集:System.ComponentModel.DataAnnotations;

StringLength特性-限制長度

         這個特性看它命名規則就知道它是什么意思了,字符串長度對吧。是的你沒看錯,就是字符串長度。實例代碼:

[StringLength(20,ErrorMessage = "密碼不能超過20個字符")]
public string Password { get; set; }

我們只需要在模型屬性上加上這么個特性,那么校驗的時候這個字符串不能超過20個字符。ErrorMessage就是校驗不通過時的消息。

Required特性-不能為空

         這個特性表必須的、不能為空的。用於不為空校驗。默認為不允許為空。允許為空則添加AllowEmptyStrings = true

[Required(ErrorMessage = "密碼不能超過20個字符")]
public string Password { get; set; }

RegularExpression-規則校驗(正則校驗)

         正則表達式在校驗中是必不可少的一部分、微軟也為我們提供了這個類型,非常方便的使用。

[RegularExpression(@"^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$", ErrorMessage = "郵箱不正確")]
public string Email { get; set; }

Range-數值范圍

         當對一個數值進行校驗時、一般可能會用到取值范圍。比如年齡:

[Range(0,120,ErrorMessage = "年齡取值范圍0-120")]
public int Age { set; get; }

Compare-比較

         比較兩個值是否一致,一般用於二次輸入。Password是需要比較的值

[Compare("Password",ErrorMessage = "兩次輸入不一致")]
public string PasswordConfirm { get; set; }

Remote-遠程校驗

         這個在登錄的時候用的非常多。比如你的用戶名ID是否已經被注冊,這是需要從數據庫查詢之后才知道的。這個類有些特殊,它不在System.ComponentModel.DataAnnotations命名空間下,它是在System.Web.Mvc;命名空間下的。

 

[Remote("CheckUserName","Register",ErrorMessage = "用戶名已被注冊")]
public string UserName { get; set; }

 

Action:代表你要請求的方法

Controller:表示你要請求的控制器

這個特性有一個約定,就是你請求的這個路徑必須返回True或False,並且是以Json格式返回的。至於返回True或False的邏輯,看大家自己的需求了。

 

public ActionResult CheckUserName()
{
     return Json(false, JsonRequestBehavior.AllowGet);
}

 

Display-顯示名稱

         這個特性、個人認為不屬於校驗里面的一部分,它只是用戶前台展示時的一個顯示名稱。后面在為大家講解這個的實際應用

[Display(Name = "年齡")]
 public int Age { set; get; }

總結:

通過以上五種模型注解,一般能滿足生產中大部分校驗,如有特殊校驗,可以自定義特性來進行模型注解。了解了模型注解,也就是開始我們asp.net MVC校驗的第一步了。自定義數據注解我就不說了,看下這個就可以了:

 

http://www.cnblogs.com/zhangkai2237/archive/2012/12/12/2814825.html

數據綁定及驗證

首先要進行客戶端校驗有幾個比較重要的點:

1、  必須要用@Html.BeginForm()這種方式包含住輸入標簽。(自己試驗了下,是這樣的。如果有錯誤請好心提醒)

2、  必須要用強類型頁面。

3、  必須要引用Jquery庫、Jquery.Validate、Jquery.Validate.unobtrusive這三個文件

4、  web.config文件中這兩個值必須為True。默認為True

 

<appSettings>
    <add key="ClientValidationEnabled" value="true" />
    <add key="UnobtrusiveJavaScriptEnabled" value="true" />
</appSettings>

前台代碼:

由於我時間問題、我創建視圖的時候就直接創建了編輯視圖了。

 

   <script src="@Url.Content("~/Scripts/jquery-1.7.1.min.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
    
    @using (Html.BeginForm("Create","Register")) {
        @Html.ValidationSummary(true)
        <fieldset>
            <legend>RegisterViewModel</legend>
    
            <div class="editor-label">
                @Html.LabelFor(model => model.UserName)
            </div>
            <div class="editor-field">
                @Html.EditorFor(model => model.UserName)
                @Html.ValidationMessageFor(model => model.UserName)
            </div>
    
            <div class="editor-label">
                @Html.LabelFor(model => model.Password)
            </div>
            <div class="editor-field">
                @Html.EditorFor(model => model.Password)
                @Html.ValidationMessageFor(model => model.Password)
            </div>
    
            <div class="editor-label">
                @Html.LabelFor(model => model.PasswordConfirm)
            </div>
            <div class="editor-field">
                @Html.EditorFor(model => model.PasswordConfirm)
                @Html.ValidationMessageFor(model => model.PasswordConfirm)
            </div>
    
            <div class="editor-label">
                @Html.LabelFor(model => model.Phone)
            </div>
            <div class="editor-field">
                @Html.EditorFor(model => model.Phone)
                @Html.ValidationMessageFor(model => model.Phone)
            </div>
    
            <div class="editor-label">
                @Html.LabelFor(model => model.Email)
            </div>
            <div class="editor-field">
                @Html.EditorFor(model => model.Email)
                @Html.ValidationMessageFor(model => model.Email)
            </div>
    
            <p>
                <input type="submit" value="Save" />
            </p>
        </fieldset>
    }

補充前面一個內容、在屬性前加上Display特性,那么在前台@Html.LabelFor(model => model.Email)這種代碼就會優先使用Display里面定義的名稱,如果沒有定義,則顯示屬性的名稱(UserName)。

 

后台代碼:

 

public class RegisterController : Controller
    {
        //
        // GET: /Register/

        public ActionResult Index()
        {
            if (ModelState.IsValid)
            {
                //后台校驗。判斷所有數據是否建議通過、
            }
            return View();
        }
        
        public ActionResult CheckUserName()
        {
            return Json(false, JsonRequestBehavior.AllowGet);
        }

        [HttpPost]
        public ActionResult Create(RegisterViewModel model)
        {
            return View();
        }
    }

 

使用Entity Framework模型

 

在實際生產中我們用到的很有可能就是ORM框架,或者代碼生成器生成的代碼。為了避免每次重新生成后而將我們的數據注解給消失掉、微軟也提供了一種叫元數據共享的一種方式(我叫它”元數據”共享)

 

    /// <summary>
    /// 驗證類
    /// </summary>
    public class RegisterViewModel_Validate
    {
        [Display(Name = "用戶名")]
        [Required(ErrorMessage = "不能為空",AllowEmptyStrings = false)]
        [Remote("CheckUserName","Register",ErrorMessage = "用戶名已被注冊")]
        public string UserName { get; set; }

        [Display(Name = "密碼")]
        [Required(ErrorMessage = "密碼不能超過20個字符")]
        public string Password { get; set; }

        [Display(Name = "確認密碼")]
        [System.ComponentModel.DataAnnotations.Compare("Password",ErrorMessage = "兩次輸入不一致")]
        public string PasswordConfirm { get; set; }

        [Display(Name = "公司電話")]
        [Required(ErrorMessage = "公司電話不能為空")]
        [StringLength(20, ErrorMessage = "錯誤的公司電話")]
        [RegularExpression("^[0-9]+$", ErrorMessage = "公司電話不正確")]
        public string Phone { get; set; }


        [Required(ErrorMessage = "注冊人郵箱不能為空")]
        [RegularExpression(@"^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$", ErrorMessage = "郵箱不正確")]
        public string Email { get; set; }

        [Display(Name = "年齡")]
        [Range(0,120,ErrorMessage = "年齡取值范圍0-120")]
        public int Age { set; get; }
    }
    /// <summary>
    /// 自動生成的類
    /// </summary>
    [MetadataType(typeof(RegisterViewModel_Validate))]//該類共享RegisterViewModel_Validate元數據
    public partial class RegisterViewModel
    {

    }

 

我來了看起來方便就將兩個類放到了一個文件夾下面,在生產中你還是得分開他們,不然自動生產代碼還是會覆蓋我們寫的驗證代碼。

總結:

  想想應該算是比較完整的了。希望對一些還不太明白的朋友有所幫助,自己也重新加深了印象。從事MVC開發后,

感覺開發起來確實比較Web Form Happy多了,asp.net MVC這種開發方式我非常喜歡,而且可操作性、靈活性更強。

希望更多的朋友一起加入MVC的陣營吧。一起享受MVC 編碼的樂趣.....

 

  還有不明白的朋友可以私密我。歡迎討論

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM