標籤:引用 ice attr 架構 path ted ajax 準備 omv
前言
使用者輸入驗證的工作,不僅要在用戶端瀏覽器中執行,還要在服務端執行。主要原因是用戶端驗證會對輸入資料給出即時反饋,提高使用者體驗;伺服器端驗證,主要是因為不能完全信任使用者提供的資料。ASP.NET MVC架構提供了強大的驗證組件協助我們處理這些繁雜的問題。
資料驗證驗證註解的使用
驗證註解特性定義在命名空間System.ComponentModel.DataAnnotations中,它們提供了伺服器端驗證的功能,當在模型的屬性上使用時,架構也支援用戶端驗證。常用特性簡介:
- Required
當屬性值為null或者空時,將引發一個驗證錯誤,可以理解為若添加了Required特性,則此項為必填項。
- StringLength
限定字串長度。
- RegularExpression
使用Regex驗證輸入的字串是否符合格式要求。
- Range
用來指定輸入數值來的最小值和最大值。
- Compare
用來判斷兩個屬性是否擁有相同的值。例如,確保兩次輸入的密碼相同。
- Remote
利用伺服器端的回呼函數執行用戶端的邏輯驗證。
下面,通過一個簡單的樣本來講解這些特性的使用方法。
假設現在我們開發一套圖書管理系統,在Models檔案夾中建立Book類,用來儲存書籍的基本資料。
public class Book{ public int Id { get; set; } public string Name { get; set; } public string Author { get; set; } public int PagesNumber { get; set; } public string Publisher { get; set; } public string PublicationDate { get; set; } public string Content { get; set; } public decimal Price { get; set; } public decimal PriceConfirm { get; set; }}
添加BooksController,啟動項目,此時,ASP.NET MVC已經利用基架模板協助我們建立好了相應的controller和View,直接將瀏覽器定位到/Books/Create,可瀏覽如下用來添加書籍的頁面。
在添加書籍時,使用者希望對輸入的資料進行一些驗證,當輸入的資料無法通過相關驗證時,返回錯誤資訊。此時,驗證註解特性就派上了用場。
第一步,引入命名空間
using System.ComponentModel.DataAnnotations;using System.Web.Mvc;
向BooksController中添加CheckContent方法(為了使用remote特性做準備)
public JsonResult CheckContent(string content) { var result = db.Books.Where(m => m.Content == content).Count() == 0; return Json(result, JsonRequestBehavior.AllowGet); }
修改Book類,分別添加驗證註解:
public int Id { get; set; } [Required] //必填 public string Name { get; set; } [StringLength(50)] //作者姓名的長度不能超過50個字元 public string Author { get; set; } [Range(100, 10000)] //頁數保證在100~10000頁之間 public int PagesNumber { get; set; } public string Publisher { get; set; } [RegularExpression(@"^\d{4}(\-|\/|\.)\d{1,2}\1\d{1,2}$")] //日期格式 public string PublicationDate { get; set; } [Remote("CheckContent", "Books")] //內容介紹不能重複 public string Content { get; set; } public decimal Price { get; set; } [System.ComponentModel.DataAnnotations.Compare("Price")] //兩次輸入的價格必須一致 public decimal PriceConfirm { get; set; }
重新啟動項目,在Create頁面輸入不符合驗證邏輯的資料,效果如下:
重新輸入正確的資料,點擊Create,資料成功錄入後,我們再錄入另外一本書籍,Content內容與上一次添加的內容相同,得到錯誤資訊,此時Remote特性調用了CheckContent方法進行驗證。
★注意,Remote特性自動發送AJAX請求訪問後台代碼來實現驗證,它只有用戶端驗證,沒有服務端驗證。也就是說,當使用者瀏覽器關閉js,Remote檢查將不起作用,因此,Remote特性存在一定的安全隱患。同理,如果建立Controller時沒有勾選Reference script libraries選項,Remote特性也將不起任何作用。
自訂錯誤提示
每個驗證特性都允許傳入一個帶有自訂錯誤提示訊息的參數,例如以上樣本中RegularExpression特性返回的錯誤訊息,使用者可能無法理解Regex的含義,此時,我們就需要返回一些簡單易懂的錯誤訊息,向RegularExpression傳入ErrorMessage參數。
[RegularExpression(@"^\d{4}(\-|\/|\.)\d{1,2}\1\d{1,2}$",ErrorMessage ="請輸入有效日期格式,例如:2017-06-16")] //日期格式 public string PublicationDate { get; set; }
效果如下:
驗證註解的後台原理及控制器操作
預設情況下,ASP.NET MVC架構在模型繫結時執行驗證邏輯。模型繫結器一旦使用新值完成對模型屬性的更新,就會利用當前的模型中繼資料獲得模型的所有驗證器。ASP.NET MVC運行時提供了一個驗證器DataAnnotationsModelValidator來與資料註解一同工作。這個模型驗證器會找到所有的驗證特性並執行它們包含的驗證邏輯。模型繫結器捕獲所有失敗的驗證規則並把它們存放在模型狀態中。
控制器操作決定了在模型驗證失敗或成功時程式的執行流程。通常情況下,驗證成功,儲存使用者輸入資料,驗證失敗,重新渲染視圖,返回錯誤訊息。以下是系統自動建立的Create方法,首先判斷模型狀態ModelState是否存在錯誤,若不存在,則儲存書籍資訊,若存在敗,則重新渲染視圖。
[HttpPost] [ValidateAntiForgeryToken] public ActionResult Create([Bind(Include = "Id,Name,Author,PagesNumber,Publisher,PublicationDate,Content,Price,PriceConfirm")] Book book) { if (ModelState.IsValid) { db.Books.Add(book); db.SaveChanges(); return RedirectToAction("Index"); } return View(book); }
自訂驗證邏輯
上一節中介紹了這麼多驗證註解,我們不禁會問,使用者經常會提出很多奇葩的需求,我們能否自己定義一些驗證邏輯呢?答案是肯定的。本節,將介紹如何完成自訂邏輯驗證。
自訂註解
所有驗證註解特性最終都派生自基類ValidationAttribute,它是個抽象類別,因此,建立自訂註解特性時也必須派生自ValidationAttribute類。
假設使用者提出一個需求,由於某位作者遭到無情封殺,錄入書籍資訊時,作者一欄不能為指定的人名。
首先,添加CheckAuthorAttribute類派生自基類ValidationAttribute:
using System.ComponentModel.DataAnnotations;namespace MyFirstMvcProject.Infrastructure{ public class CheckAuthorAttribute : ValidationAttribute { }}
為了實現這個驗證,需要重寫基類的IsValid方法,ValidationContext參數提供了可在IsValid方法內部使用的資訊,如模型類型、模型對象執行個體、用來驗證屬性的顯示名稱等。IsValid方法的第一個參數是要驗證的對象的值,另外,我們通過建構函式擷取不能通過驗證的人名。
public class CheckAuthorAttribute : ValidationAttribute{ public string Author { get; set; } public CheckAuthorAttribute(string author) : base("{0} can not be this one. ") { this.Author = author; } protected override ValidationResult IsValid(object value, ValidationContext validationContext) { if (value != null) { if (value.ToString() == Author) { return new ValidationResult(FormatErrorMessage(validationContext.DisplayName)); } } return ValidationResult.Success; }}
上述代碼有兩點需要注意:
- 向基類建構函式傳遞一個預設值的錯誤提示資訊。
- FormatErrorMessage方法:基於出現比較錯誤的資料欄位對錯誤訊息應用格式設定。
修改Book類,在Author屬性上添加CheckAuthor特性。
[StringLength(50)] //作者姓名的長度不能超過50個字元 [CheckAuthor("Thomas", ErrorMessage = "Author can not be this one.")] public string Author { get; set; }
運行程式,輸入Author,點擊Create,效果如下:
到目前為止,我們已經成功建立自訂註解特性,但是細心的使用者又發現了,新添加的驗證只有在點擊了Create後才能觸發,其他的驗證都可以給出即時反饋。正如使用者所說,目前我們只添加了服務端驗證,下面將介紹如何為CheckAuthor特性添加用戶端驗證。
修改MaxWordsAttribute類,使其繼承IClientValidatable介面,實現GetClientValidationRules方法。
public class CheckAuthorAttribute : ValidationAttribute, IClientValidatable { public string Author { get; set; } public CheckAuthorAttribute(string author) : base("{0} can not be this one. ") { this.Author = author; } protected override ValidationResult IsValid(object value, ValidationContext validationContext) { if (value != null) { if (value.ToString() == Author) { return new ValidationResult(FormatErrorMessage(validationContext.DisplayName)); } } return ValidationResult.Success; } public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context) { var rule = new ModelClientValidationRule() { ValidationType = "checkauthor", ErrorMessage = FormatErrorMessage(metadata.GetDisplayName()) }; rule.ValidationParameters.Add("author", Author); yield return rule; }}
說明:
- IClientValidatable介面為ASP.NET MVC驗證架構提供一種用於在運行時發現驗證程式是否支援用戶端驗證的方法。GetClientValidationRules在類中實現,返回該類的用戶端驗證規則。
- ErrorMessage屬性用於存放錯誤提示訊息。
- ValidationParameters集合用於存放用戶端需要的參數,本例中即為Thomas.
- ValidationType屬性標識了用戶端需要的一段JavaScript代碼。
在Scripts檔案夾下添加JavaScript檔案,命名為customvalidators.js,鍵入如下代碼:
/// <reference path="jquery.validate.js" />/// <reference path="jquery.validate.unobtrusive.js" />$.validator.addMethod("checkauthor", function (value, element, author) { if (value) { if (value == author) { return false; } } return true;});$.validator.unobtrusive.adapters.addSingleVal("checkauthor", "author");
說明:
- AddSingleVal為需要從中繼資料中檢索唯一參數值的驗證規則建立適配器。第一個參數是適配器名稱,第二個參數是要從中繼資料中檢索的參數的名稱。
- 調用validator.AddMethod方法添加新的驗證器。
最後,在Views/Books/Create.cshtml中添加對customvalidators.js的引用:
@section Scripts { @Scripts.Render("~/bundles/jqueryval") <script src="~/Scripts/customValidators.js"></script>}
啟動程式,將Url定位到/Books/Create,在Author文字框中輸入Thomas,當焦點離開Author文字框後即可完成驗證。
ASP.NET MVC5(四):資料註解和驗證