013_模型驗證

来源:http://www.cnblogs.com/KeSaga/archive/2016/06/03/5555743.html
-Advertisement-
Play Games

模型驗證(Model Validation):是確保用戶接收的數據適合於綁定的模型,並且在不合適時,給用戶提供有用的信息,以幫助他們修正其問題的過程。 模型驗證過程一:檢查接收的數據——是保持域模型完整性的方式之一。 模型驗證過程二:幫助用戶修正問題。 示例項目介紹 項目模板:Basic 項目名稱: ...


模型驗證(Model Validation):是確保用戶接收的數據適合於綁定的模型,並且在不合適時,給用戶提供有用的信息,以幫助他們修正其問題的過程。

模型驗證過程一:檢查接收的數據——是保持域模型完整性的方式之一。

模型驗證過程二:幫助用戶修正問題。

示例項目介紹

項目模板:Basic

項目名稱:ModelValidation

一個新的模型類文件:Appointment.cs

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;

namespace ModelValidation.Models
{
    public class Appointment
    {

        public string ClinetName { get; set; }

        [DataType(DataType.Date)]
        public DateTime Date { get; set; }

        public bool TermsAccepted { get; set; }

    }
}

控制器:Home,用來提供處理Appointment模型類的動作方法

using ModelValidation.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace ModelValidation.Controllers
{
    public class HomeController : Controller
    {

        public ViewResult MakeBooking()
        {
            return View(new Appointment { Date = DateTime.Now });
        }

        [HttpPost]
        public ViewResult MakeBooking(Appointment appt)
        {
            // 在實際項目中,此處是存儲庫中存儲新的 Appointment 的語句
            return View("Completed", appt);
        }

    }
}

         本例不打算實現具體存儲等方面的功能,主要是為了能夠將註意力集中在模型綁定以及驗證過程方面。要清楚驗證模型的主要目的就為了防止在存儲庫中放置劣質或無意義的數據,並避免引起問題。

         下麵繼續創建兩個視圖MakeBooking.cshtml、Completed.cshtml:

         MakeBooking.cshtml,用來提供一個讓用戶創建新預約的表單:

@model ModelValidation.Models.Appointment

@{
    ViewBag.Title = "Make A Booking";
}

<h4>Book an Appointment</h4>

@using (Html.BeginForm())
{
    <p>Your name: @Html.EditorFor(m => m.ClinetName)</p>
    <p>Appointment Date: @Html.EditorFor(m => m.Date)</p>
    <p>@Html.EditorFor(m => m.TermsAccepted) I accept the terms $ conditions</p>
    <input type="submit" value="Make Booking" />
}

         用於提交表單後給用戶顯示預約細節的內容的Completed.cshtml視圖:

@model ModelValidation.Models.Appointment

@{
    ViewBag.Title = "Completed";
}

<h4>Your appointment is confirmed</h4>

<p>Your name is: @Html.DisplayFor(m => m.ClinetName)</p>
<p>The date of your appointment is: @Html.DisplayFor(m => m.Date)</p>

         導航地址到/Home/MakeBooking可以看到效果:

                         

         按照現在的情況,此刻程式會接收用戶遞交的任何數據,但為了保持程式和域模型的完整性,在接收用戶遞交的Appointment之前,需要確保三件事為“true”。

  • 用戶必須提供一個姓名
  • 用戶必須提供一個未來的日期(以yyyy/mm/dd格式)
  • 用戶必須選擇了覆選框,已接受條款和條件

   在這個示例中,模型驗證就是實施這些需求的過程。後面將採不同的技術來實現,以檢查用戶提供的數據,併在輸入無效數據時給予提示。

明確地驗證模型

         最直接的驗證模型的方式是在動作方法中進行驗證。下麵是在MakeBooking動作方法的HttpPost版本中對Appointment類所定義的每一個屬性添加明確的檢查:

       

        [HttpPost]
        public ViewResult MakeBooking(Appointment appt)
        {
            if (string.IsNullOrEmpty(appt.ClinetName))
            {
                ModelState.AddModelError("ClinetName", "Please enter your name");
            }

            if (ModelState.IsValidField("Date") && DateTime.Now > appt.Date)
            {
                ModelState.AddModelError("Date", "Please enter a date in the future");
            }

            if (!appt.TermsAccepted)
            {
                ModelState.AddModelError("TermsAccepted", "You must accept the terms");
            }

            if (ModelState.IsValid)
            {
                // 在實際項目中,此處是存儲庫中存儲新的 Appointment 的語句
                return View("Completed", appt);
            }
            else
            {
                return View();
            }
            
        }

         上面對Appointment對象的各個屬性進行檢測時,使用的ModelState.IsValidField方法檢查的是綁定器是否能夠對一個屬性賦值。

         註意:如果無法從請求數據中解析到一個值,執行額外檢測或報告其他錯誤消息是沒有意義的。

         上面示例中在驗證了模型對象的所有屬性之後,讀取了ModelState.IsValid屬性,以考察是否有錯誤發送,如果在檢查期間調用Model.State.AddModelError方法,或創建Appointment對象時模型綁定器遇到了問題,該方法返回false。

            if (ModelState.IsValid)
            {
                // 在實際項目中,此處是存儲庫中存儲新的 Appointment 的語句
                return View("Completed", appt);
            }
            else
            {
                return View();
            }

         如果IsValid值為true,則會得到一個有效的Appointment對象,且會渲染Completed.cshtml視圖;如果是false,則說明出現了問題,此時將掉牙View方法渲染預設視圖。

向用戶顯示驗證錯誤

   通過調用View方法來處理驗證錯誤看上去可能有點怪,但是在MakeBooking.cshtml視圖中用來生成input元素的模板視圖輔助器,會檢查視圖模型的驗證錯誤。

   如果一個屬性報告了錯誤,那麼輔助器對相應的input元素添加一個CSS的class標簽屬性,其值為input-validation-error~/Content/site.css文件中包含了一個用於該樣式的預設定義,如:

.input-validation-error {

    border: 1px solid #f00;

   

}

         驗證錯誤的效果如圖:

 


設置覆選框樣式


 

         有些瀏覽器,包括Chrome和Firefox,會忽略運用於覆選框的樣式,這會導致不協調的視覺反饋。解決辦法是在~/Views/Shared/EditorTemplates/Boolean.cshtml中創建一個自定義模板,並將覆選框封裝在一個div元素中。以下是所使用的一個模板,但我們可以將其定製到自己的應用程式中:

@model bool?

@if (ViewData.ModelMetadata.IsNullableValueType)
{
    @Html.DropDownListFor(m => m, new SelectList(new[] { "Not Set", "True", "False" }, Model))
}
else
{
    ModelState state = ViewData.ModelState[ViewData.ModelMetadata.PropertyName];
    bool value = Model ?? false;

    if (state != null && state.Errors.Count > 0)
    {
        <div class="input-validation-error" style="float:left">
            @Html.CheckBox("", value)
        </div>
    }
    else
    {
        @Html.CheckBox("", value)
    }
}

         如果運用這個模板的屬性出現錯誤,該模板會將一個覆選框(CheckBox)封裝在一個運用了input-validation-error樣式的div元素中。

         只有當提交的數據能被模型綁定器解析,且能被驗證通過,才會顯示完成視圖,否則,將會提示驗證失敗的視圖。

         運用了上面覆選框樣式後的效果:

 

顯示驗證消息

         前面已經實現了高亮顯示錯誤欄位(通過對input元素的CSS樣式設置),但用戶仍不能清除的知道問題何在。對於這一問題,可以使用Html.ValidationSummary輔助器方法顯示已經註冊到該頁面的驗證錯誤的摘要,這也是一種方便而簡單的做法,如果沒有錯誤,該輔助器便不會產生任何HTML,用法如下(粗體部分):

@model ModelValidation.Models.Appointment

@{
    ViewBag.Title = "Make A Booking";
}

<h4>Book an Appointment</h4>

@using (Html.BeginForm())
{
    @Html.ValidationSummary()
    <p>Your name: @Html.EditorFor(m => m.ClinetName)</p>
    <p>Appointment Date: @Html.EditorFor(m => m.Date)</p>
    <p>@Html.EditorFor(m => m.TermsAccepted) I accept the terms $ conditions</p>
    <input type="submit" value="Make Booking" />
}

         效果如圖:

 

         對應的顯示這段錯誤消息的HTML如下:

<div class="validation-summary-errors" data-valmsg-summary="true">

<ul>

<li>Please enter your name</li>

<li>Please enter a date in the future</li>

<li>You must accept the terms</li>

</ul>

</div>

         ValidationSummary輔助器還有一些重載版本,有一些是允許開發時候設置顯示模型級錯誤的。一些常用的如下所列:

  • Html.ValidationSummary():生成所有驗證錯誤的摘要
  • Html.ValidationSummary(bool):如果bool參數為true,那麼只顯示模型級錯誤。如果是false則顯示所有錯誤
  • Html.ValidationSummary(string):在所有驗證錯誤摘要之前顯示一條消息(消息內容在string參數中)
  • Html.ValidationSummary(bool,string):在驗證錯誤消息前顯示一條消息。如果bool參數為true,則只顯示模型級錯誤

   當存在由於兩個或多個屬性值之間的相互作用而引發的錯誤時,可以使用模型級錯誤。這裡假設一個場景,作為我們的示例:假設姓名為“Joe”的客戶不能在星期一預約。辦法就是在MakeBooking動作方法中進行明確的驗證檢查,並報告模型級驗證錯誤:

       

        [HttpPost]
        public ViewResult MakeBooking(Appointment appt)
        {
            if (string.IsNullOrEmpty(appt.ClinetName))
            {
                ModelState.AddModelError("ClinetName", "Please enter your name");
            }

            if (ModelState.IsValidField("Date") && DateTime.Now > appt.Date)
            {
                ModelState.AddModelError("Date", "Please enter a date in the future");
            }

            if (!appt.TermsAccepted)
            {
                ModelState.AddModelError("TermsAccepted", "You must accept the terms");
            }

            if (ModelState.IsValidField("ClientName")
                && ModelState.IsValidField("Date")
                && appt.ClinetName == "Joe"
                && appt.Date.DayOfWeek == DayOfWeek.Monday)
            {
                ModelState.AddModelError("","Joe cannot book appointment on Mondays");
            }

            if (ModelState.IsValid)
            {
                // 在實際項目中,此處是存儲庫中存儲新的 Appointment 的語句
                return View("Completed", appt);
            }
            else
            {
                return View();
            }

        }

         示例的粗體部分的ModelState.AddModelError方法的第一個參數給出的是空字元串(""),這樣就可以註冊一條模型級錯誤。後面修改一下MakeBooking.cshtml視圖,使其只顯示模型機錯誤,這樣方便我們看到最終的效果:

@model ModelValidation.Models.Appointment

@{
    ViewBag.Title = "Make A Booking";
}

<h4>Book an Appointment</h4>

@using (Html.BeginForm())
{
    @Html.ValidationSummary(true)
    <p>Your name: @Html.EditorFor(m => m.ClinetName)</p>
    <p>Appointment Date: @Html.EditorFor(m => m.Date)</p>
    <p>@Html.EditorFor(m => m.TermsAccepted) I accept the terms $ conditions</p>
    <input type="submit" value="Make Booking" />
}

 

         這樣已修改,從上圖的效果中可以看出出現了兩個錯誤。一個是模型級的錯誤,就是紅色錯誤消息部分;第二個是是沒有勾選覆選框導致的,但是現在不會再顯示問題的描述消息了。

顯示屬性級驗證消息

         由於屬性級驗證消息是可以顯示在相應欄位的旁邊的,所以,就很容易把模型級錯誤和屬性級錯誤分開,將模型級錯誤作為整體的摘要顯示了,這樣也更合理一些。

要想單獨在相應的欄位旁邊顯示屬性級驗證消息,一般可以通過使用Html.ValidationMessageFor輔助器方法實現。

下麵是再次對MakeBooking.cshtml視圖的調整:

 

 

使用其他驗證技術

在模型綁定器中執行驗證

         驗證也是預設模型綁定器的綁定過程的一部分。模型綁定器會為模型對象中的每一個屬性執行一些基本的驗證。

         下圖展示瞭如果為示例項目中模型對象的Date屬性遞交空或錯誤內容的驗證結果,這都是預設模型綁定器實現的:

 

 

         預設的模型綁定器類DefaultModelBinder提供了一些可以重寫的方法,以使得開發時可以方便的為一個綁定器添加驗證。通過重寫這些方法,便可以在創建自定義模型綁定器時,將自己的驗證邏輯放在綁定過程之中。

         建議:對於使用自定義驗證邏輯時,建議在模型類運用元數據的方式處理驗證,而不在模型綁定器中添加自定義驗證邏輯。

         DefaultModelBinder中對綁定過程添加驗證的方法:

方法

描述

預設實現

OnModelUpdated

在綁定器試圖對模型對象中的所有屬性進行賦值時調用

運用由模型元數據定義的驗證規則,並用ModelState註冊錯誤。

SetProperty

在綁定器對一個特定屬性運用一個值時調用

如果該屬性不能保存null值,並且沒有可以運用的值,那麼,將用ModelState註冊一條“The<name> field is   required (<name>欄位是必需的)”的錯誤消息(如上圖中顯示的“Date 欄位是必需的”)。如果有一個值,但不能進行解析,將註冊“The value <>   is not valid for <name>(值”<value>”對 <name> 無效)”的錯誤

用元數據指定驗證規則

         使用元數據指定規則的一個優點是,在整個項目中運用綁定過程的任何地方,都會強制執行驗證規則,而不只存在於個別動作方法之中。

         拿Appointment作為示例,看看是如何實現這種驗證方式的:

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;

namespace ModelValidation.Models
{
    public class Appointment
    {
        [Required]
        public string ClinetName { get; set; }

        [DataType(DataType.Date)]
        [Required(ErrorMessage = "Please enter a date")]
        public DateTime Date { get; set; }

        [Range(typeof(bool), "true", "true", ErrorMessage = "You must accept the terms")]
        public bool TermsAccepted { get; set; }

    }
}

         上面代碼中運用了兩個驗證註解屬性——Required和Range。下麵給出了內建驗證註解屬性的一些介紹:

  • Compare:

示例:[Compare("MyOtherProperty")]

描述:兩個屬性必須有同樣的值。當要求用戶對一個屬性提供兩次同樣的值時,這是有用的。如:一個郵件地址或一個口令

  • Range:

示例:[Range (10,20)]

描述:一個數字值(或實現IComparable的任何屬性類型),必須不超出指定的最小值和最大值。為了指定只有一端的邊界,可以用一個MinValue或MaxValue常數。如:[Range (int.MinValue,50)]

  • RegularExpression:

示例:[RegularExpression ("pattern")]

描述:一個字元串值,必須匹配指定的正則表達式模式。註意,該模式必須匹配用戶提供的所有值,而不只是其中的一個子串。預設它是大小寫敏感的,但可以通過運用(?!)修飾符,使大小寫不敏感。如:[RegularExpression ("(?!)mypattern")]

  • Required:

示例:[Required]

描述:必須是一個非空值,或一個不是只含空格的字元串。如果希望空格作為可接受值,可以用[Required(AllowEmptyStrings = true)]

  • StringLength:

示例:[StringLength (10)]

描述:一個字元串,必須不超過指定的最大長度。也可以指定一個最小長度:[StringLength (10,MinimumLength=2)]

         所有上述這些驗證註解屬性都可以給ErrorMessage屬性設置一個值,以指定一個自定義的錯誤消息,如:

[Required(ErrorMessage = "Please enter a date")]

         內建的驗證註解屬性是很基本的,且只能做屬性級驗證。即使這樣,仍需要一些技巧。可以考慮下麵這個例子:

[Range(typeof(bool), "true", "true", ErrorMessage = "You must accept the terms")]

         如果希望用戶選中了覆選框,以接受條款。此時不能使用Required註解屬性,因為用於布爾值的模板輔助器會產生一個隱藏的HTML元素,以確保即使覆選框未選中也會獲得一個值。為瞭解決這一問題,可以利用Range註解屬性的一個特性,它讓我們提供一個類型,並以字元串值指定上下限。通過把上下限均設置為true,可以為使用覆選框的布爾屬性的編輯器視圖創建一個等效的Required註解屬性。

註意:DataType註解屬性不能用於驗證用戶輸入——只能對使用模板輔助器進行渲染的值提供提示。因此,不要指望用DataType(DataType.EmailAddress)這樣的註解屬性來強制一個特定的格式。

 

  1.創建自定義的屬性驗證註解屬性

使用Range註解屬性類固然能夠變相的實現Required註解屬性的功能,但這還是顯得有些笨拙。好在,可以創建自定義的屬性驗證註解屬性,而這隻需要從ValidationAttribute類進行派生即可。

為了演示其工作機制,需要向項目中添加一個Infrastructure文件夾,併在其中創建一個MustBeTrueAttribute類:

using System.ComponentModel.DataAnnotations;

namespace ModelValidation.Infrastructure
{
    public class MustBeTrueAttribute : ValidationAttribute
    {
        public override bool IsValid(object value)
        {
            return value is bool && (bool)value;
        }
    }
}

         在這個示例中,驗證邏輯很簡單。如果這是一個具有true值的bool型,那麼這個值就是有效的。下麵看看如何使用這個自定義的註解屬性,以實現前面的Range註解屬性的驗證效果:

using ModelValidation.Infrastructure;
using System;
using System.ComponentModel.DataAnnotations;

namespace ModelValidation.Models
{
    public class Appointment
    {
        [Required]
        public string ClinetName { get; set; }

        [DataType(DataType.Date)]
        [Required(ErrorMessage = "Please enter a date")]
        public DateTime Date { get; set; }

        [MustBeTrueAttribute(ErrorMessage = "You must accept the terms")]
        public bool TermsAccepted { get; set; }

    }
}

         這樣看起來會更簡便,下圖是最終效果:

 

         還有一種方式是,通過內建的驗證註解屬性來派生新類,這等於提供了擴展內建驗證註解屬性行為的能力。下麵是Infrastructure中的示例類FutureDateAttribute:

using System;
using System.ComponentModel.DataAnnotations;

namespace ModelValidation.Infrastructure
{
    public class FutureDateAttribute : RequiredAttribute
    {
        public override bool IsValid(object value)
        {
            return base.IsValid(value) && ((DateTime)value) > DateTime.Now;
        }
    }
}

         在代碼中,由於使用的基類的IsValid方法,所以重寫方法包含了所有基本驗證步驟,下麵是對其應用:

using ModelValidation.Infrastructure;
using System;
using System.ComponentModel.DataAnnotations;

namespace ModelValidation.Models
{
    public class Appointment
    {
        [Required]
        public string ClinetName { get; set; }

        [DataType(DataType.Date)]
        [FutureDateAttribute(ErrorMessage = "Please enter a date in the future")]
        public DateTime Date { get; set; }

        [MustBeTrueAttribute(ErrorMessage = "You must accept the terms")]
        public bool TermsAccepted { get; set; }

    }
}

 

  2.創建模型驗證註解屬性

   現在來看看自定義的模型驗證註解屬性,為了演示,在Infrastructure文件夾中創建NoJoeOnMondaysAttribute.cs類:

using System;
using System.ComponentModel.DataAnnotations;
using ModelValidation.Models;

namespace ModelValidation.Infrastructure
{
    public class NoJoeOnMondaysAttribute : ValidationAttribute
    {
        public NoJoeOnMondaysAttribute()
        {
            ErrorMessage = "Joe cannot book appointment on Mondays";
        }

        public override bool IsValid(object value)
        {
            Appointment app = value as Appointment;
            if (app == null
                || string.IsNullOrEmpty(app.ClinetName)
                || app.Date == null)
            {
                // 還沒有正確的類型的模型要驗證,或者還沒有所需要的 ClientName 和 Date 屬性的值
                return true;
            }
            else
            {
                return !(app.ClinetName == "Joe" && app.Date.DayOfWeek == DayOfWeek.Monday);
            }
        }

    }
}

         與單個屬性的情況相比,在模型類上使用的驗證註解屬性時,模型綁定器傳遞給IsValid方法的object參數將是模型對象,比如Appointment。

對於上述代碼,該驗證註解屬性會進行檢查,以確保已經有了一個Appointment對象,且如果有,則也就有了可以使用的ClientName和Date屬性的值。如果是這樣,就可以確保Joe不能試圖預約星期一。下麵給出了在Appointment類上的使用情況:

using ModelValidation.Infrastructure;
using System;
using System.ComponentModel.DataAnnotations;

namespace ModelValidation.Models
{
    [NoJoeOnMondays]
    public class Appointment
    {
        [Required]
        public string ClinetName { get; set; }

        [DataType(DataType.Date)]
        [FutureDateAttribute(ErrorMessage = "Please enter a date in the future")]
        public DateTime Date { get; set; }

        [MustBeTrueAttribute(ErrorMessage = "You must accept the terms")]
        public bool TermsAccepted { get; set; }

    }
}

         此時,在動作方法中執行著兩個同一種類的驗證,而且都使用驗證註解屬性,這也意味著,對同一驗證問題,用戶會看到兩個類似的錯誤消息。為瞭解決這一問題,已經從Home控制器的MakeBooking動作方法中刪除了明確的驗證檢查,效果是讓驗證註解屬性全權負責執行自定義的驗證檢查:

using ModelValidation.Models;
using System;
using System.Web.Mvc;

namespace ModelValidation.Controllers
{
    public class HomeController : Controller
    {

        public ViewResult MakeBooking()
        {
            return View(new Appointment { Date = DateTime.Now });
        }

        [HttpPost]
        public ViewResult MakeBooking(Appointment appt)
        {
            if (ModelState.IsValid)
            {
                // 在實際項目中,此處是存儲庫中存儲新的 Appointment 的語句
                return View("Completed", appt);
            }
            else
            {
                return View();
            }

        }

    }
}

         需要瞭解當檢查到屬性級問題時,模型級驗證註解屬性不會生效。此時,啟動程式,並輸入姓名Joe和日期2016/5/30,並取消覆選框的選中狀態,當遞交表單時,會看到只有關於覆選框的警告。然後選中覆選框,然後再次遞交,只有這時才會看到模型級錯誤:

 

定義自驗證模型

         通過繼承IValidatableObject介面,便可以將驗證邏輯在模型中實現,者便可得到自驗證模型:

using ModelValidation.Infrastructure;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;

namespace ModelValidation.Models
{
    public class Appointment : IValidatableObject
    {
        public string ClinetName { get; set; }

        [DataType(DataType.Date)]
        public DateTime Date { get; set; }

        public bool TermsAccepted { get; set; }

        public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
        {
            List<ValidationResult> errors = new List<ValidationResult>();

            if (string.IsNullOrEmpty(ClinetName))
            {
                errors.Add(new ValidationResult("Please enter your name"));
            }

            if (DateTime.Now > Date)
            {
                errors.Add(new ValidationResult("Please enter a date in the future"));
            }

            if (errors.Count == 0 && ClinetName == "Joe")
            {
                errors.Add(new ValidationResult("Joe cannot book appointment on Mondays"));
            }

            if (!TermsAccepted)
            {
                errors.Add(new ValidationResult("You must accept the terms"));
            }

            return errors;

        }
    }
}

   IValidatableObject介面定義的Validate方法以ValidationContext為參數,這個參數不是MVC專用的,且也不常用。Validate方法的返回結果是ValidationResult對象的一個枚舉,其中每一個都表示一個驗證錯誤。

         如果模型類實現了IValidatableObject介面,那麼在模型綁定器對每一個模型屬性賦值之後,便會調用該Validate方法。這樣做的好處是,它結合了將驗證邏輯放入動作方法的靈活性,但又具有任何時候都會運用模型綁定過程創建模型類型實例的一致性。另一個好處是,可以在一個地方將模型級和屬性級驗證結合在一起,這意味著所有錯誤都顯示在一起。很多人不習慣這麼做,但這也是十分適合MVC的設計模式的,且這樣擁有了靈活性和一致性。

 

執行客戶端驗證

         之前講的驗證技術都是伺服器端驗證。很多情況下需要得到即時的反饋,這就需要客戶端驗證了。客戶端驗證通常是使用JavaScript實現的,由於這種驗證是在客戶端進行的,也就是說在數據傳遞到服務端之前,這樣就給用戶提供了即時反饋並修正錯誤的機會。

         MVC框架支持漸進式客戶端驗證(Unobtrusive Client-Side Validation。漸進式指的是在生成的HTML元素上添加驗證標簽屬性來表示驗證規則。這些標簽屬性由包含在MVC框架中的JavaScript庫進行解釋,框架又轉而依靠對jQUery驗證庫所作的配置,並完成實際的驗證工作。

提示:客戶端驗證致力於驗證個別屬性。並且如果使用MVC內建的支持,則很難建立模型級的客戶端驗證。

         客戶端驗證機制可參見下圖:

               

         

啟用和禁用客戶端驗證

         客戶端驗證是由Web.config文件中的兩個設置來控制的。如:

 

         為了是客戶端驗證生效,紅框中的這兩個屬性必須設置為true。預設創建MVC項目時這些會自動創建,並被設置為true。

提示:也可以配置基於個別視圖的客戶端驗證,只需要在視圖的一個razor代碼塊中設置HtmlHelper.ClientValidationEnabled和HtmlHelper.UnobtrusiveJabaScriptEnabled即可。

         在上面配置正確後,還需要確保在發送給瀏覽器的HTML中引用了以下這三個JavaScript庫才行:

  • /Scripts/jquery-1.8.2.min.js:jQuery主庫
  • /Scripts/jquery.validate.min.js:jQuery驗證
  • /Scripts/jquery.validate.unobtrusive.min.js:jQuery漸進式驗證

給一個視圖添加這些JavaScript文件最簡單的方式是使用新的腳本捆綁包特性(其工作原理在相關專項中再做介紹)。這是MVC4中新增特性。下麵是一個示例,我們修改的是項目的佈局視圖:_Layout.cshtml:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width" />
    <title>@ViewBag.Title</title>
    @Styles.Render("~/Content/css")
    @Scripts.Render("~/bundles/modernizr")
</head>
<body>
    @RenderBody()

    @Scripts.Render("~/bundles/jquery")
    @Scripts.Render("~/bundles/jqueryval")
    @RenderSection("scripts", required: false)
</body>
</html>

 

使用客戶端驗證

         下麵刪除了Appointment模型類中IValidatableObject介面的實現,因為它對客戶端驗證無效,另外,還做了其他修改,以使其支持客戶端驗證:

using ModelValidation.Infrastructure;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;

namespace ModelValidation.Models
{
    public class Appointment
    {
        [Required]
        [StringLength(10, MinimumLength = 3)]
        public string ClinetName { get; set; }

        [DataType(DataType.Date)]
        public DateTime Date { get; set; }

        public bool TermsAccepted { get; set; }

    }
}

         下圖是在”Your name”文本框中輸入X後,使用Tab鍵或點擊其他輸入元素後即可顯示出來的效果:

 

         驗證結果之所以即時生效,實際上是因為執行驗證的JavaScript代碼會阻止遞交表單,直到不再出現為止(如果用戶繼續輸入正確的內容,錯誤消息將會即時消失)。

理解客戶端驗證機制

         使用MVC框架客戶端驗證特性的優點之一是不必編寫JavaScript,而是用HTML標簽屬性來表示驗證規則。下麵對比一下啟用和禁用客戶端驗證時所得到的HTML,下例是以ClientName屬性,通過Html.EditorFor輔助器所渲染的結果:

禁用:

<input name="ClinetName" class="text-box single-line" id="ClinetName" type="text" value="">

啟用:

<input name="ClinetName" class="text-box single-line" id="ClinetName" type="text" value="" data-val-required="ClinetName 欄位是必需的。" data-val-length-min="3" data-val-length-max="10" data-val-length="欄位 ClinetName 必須是一個字元串,其最小長度為 3,最大長度為 10。" data-val="true">

         上面啟用時被標黃色背景的為與客戶端驗證相關的項。

MVC的客戶端驗證支持不會生成任何JavaScript腳本或JSON數據來指導驗證過程,這就像框架的其他部分,依靠的是約定:添加的標簽屬性以data-val為首碼,jQuery驗證庫通過檢查這個標簽屬性,會識別出這是一個需要驗證的欄位。

各個驗證規則是以一個data-val-<name>標簽屬性的形式指定的,其中name是所運用的規則。如:運用於模型類的Required註解屬性,生成的是data-val-required標簽屬性。有些規則需要額外的標簽屬性,如長度規則:data-val-length-min和data-val-length-max標簽屬性,用例指定最小和最大字元串長度。

MVC客戶端驗證的一個很好的特點就是,不管是客戶端還是伺服器端驗證,用以指定驗證規則的屬性是相同的。也就是說,從不支持JavaScript的瀏覽器而來的數據會得到通用的驗證——將轉由伺服器端進行驗證,而無需做額外的任何工作。漸進式也就是指的這一點:當jQuery驗證庫不能正常發揮作用時,這些標簽屬性在客戶端將是一些正常的HTML標記(但不起作用),此時客戶端驗證失效,而驗證則會在伺服器端進行。


MVC客戶端驗證與jQuery驗證


 

MVC客戶端驗證:建立在jQuery驗證庫之上,藉助於驗證標簽屬性來使用jQuery驗證庫。無需編寫腳本。

jQuery驗證:通過Jav

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 介紹 comm命令可以對兩個已排序好的文本的內容進行交集和差集的對比,記住必須是已排序過的文件;可以使用sort命令對沒有排序的文件進行排序,comm命令在對比結果中會產生三列分別是:在A中不在B中的內容,在B中不在A中的內容,AB的交集的內容。 事例 [root@localhost test]# ...
  • 作為一個菜鳥,對於SSL證書,我瞭解不多,只知道用了它網站更安全,所以這次使用SSL證書途中遇到各方面的各種問題,到今天為止終於全部解決。 一、證書格式 前兩天在那什麼雲上面買了個SSL證書,是WoSign的,證書簽發後下載下來有兩個文件,.pem和.key,查詢得知IIS需要.pfx格式的證書文件 ...
  • 以上文章由本文作者根據網路上其它的例子學習整合再加上自己的思想凝聚而成,如有侵犯請聯繫本人,速刪 ...
  • 經常,會有一些人搞不清楚.NET和c#和ASP.NET這三者之間的關係,她們都是什麼呢?他們之間有什麼關係呢?今天我簡單給大家總結一下吧。 首先:什麼是.NET? .NET是微軟公司下的一個開發平臺,.NET核心就是.NET Framwork(.NET框架)是.NET程式開發和運行的環境,在這個平臺 ...
  • 捆綁包(Bundle): 能夠組織和優化CSS以及JavaScript文件,是由視圖和佈局引發瀏覽器向伺服器請求的文件。 顯示模式(Display Mode): 針對不同的設備採用不同的視圖。 理解預設腳本庫 在創建除Empty以外的任一MVC項目時,Visual Studio都會在Scripts文 ...
  • //設備在地圖上進行標註 function GetGateInfo(vSID, vMap) { var icon = "../Content/easyui/themes/icons/gate.png"; var myIcon = new BMap.Icon(icon, new BMap.Size(3 ...
  • 一、編輯器簡介 寫這個控制項之前總想找一找開源的,可以偷下懶省點事。可是各種地方都搜遍了也沒有找到。 於是,那就做第一個吃螃蟹的人吧! 控制項主要有三個功能:塗鴉、裁剪、合成。 塗鴉:主要是用到了InkToolbar和InkCanvas。 裁剪:這個用到的比較複雜,源碼會公佈出來。 合成:將塗鴉圖層按比 ...
  • 1.設置WinForm窗體屬性showinTask=false 2.加notifyicon控制項notifyIcon1,為控制項notifyIcon1的屬性Icon添加一個icon圖標。 3.添加窗體最小化事件(首先需要添加事件引用): 4.添加點擊圖標事件(首先需要添加事件引用): private v ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...