天天看點

ASP.NET MVC自定義驗證邏輯1

1.自定義注解

假設要限制顧客輸入姓氏中單詞的數量,例如姓氏中單詞的數量不等超過10個,并且還要讓這種驗證(限定一個string類型的最大單詞數)重用。

所有的驗證注解(如Required和Range)特性最終都派生自基類ValidationAttribute,它是個抽象類,在命名空間

System.ComponentModel.DataAnnotations
           

中定義。同樣,自定義的驗證邏輯也必須派生自ValidationAttribute的類。

為了實作這個驗證邏輯,至少需要重寫基類中提供的IsValid方法中的其中一個版本。重寫IsValid方法時利用的ValidationContext參數,提供了很多可在IsValid傳回發内部使用的資訊,如模型類型、模型對象執行個體、用來驗證屬性的人性化顯示名稱以及其他有用資訊。

public class MaxWordsAttribute : ValidationAttribute
{
  protected override ValidationResult IsValid(object value, ValidationContext validationContext)
  {
    return ValidationResult.Success;
  }
}
           
IsValid方法中的第一個參數是要驗證的對象的值。如果這個對象值是有效的,就可以傳回一個成功的驗證結果,但在判斷它是由有效之前需要知道單詞數的上限。要獲得這一上限,可以通過向這個特性添加一個構造函數來要求顧客把最大單詞數作為一個參數傳遞給它:
public class MaxWordsAttribute : ValidationAttribute
{
  private readonly int _maxWords;
  public MaxWordsAttribute(int maxWords)
  {
     _maxWords = maxWords;
  }
  protected override ValidationResult IsValid(object value, ValidationContext validationContext)
  {
    return ValidationResult.Success;
  }
}
           
既然已經參數化了最大的單詞數,下面就可以實作驗證邏輯來捕獲錯誤了:
public class MaxWordsAttribute : ValidationAttribute
{
  private readonly int _maxWords;
  public MaxWordsAttribute(int maxWords)
  {
     _maxWords = maxWords;
  }
  protected override ValidationResult IsValid(object value, ValidationContext validationContext)
  {
    if(value != null)
    {
        var valueAsString = value.ToString();
        if(valueAsString.Split(' ').Length > _maxWords)
        {
           return new ValidationResult("Too many words!");
        }
        return ValidationResult.Success;
  }
}
           
上面代碼中的問題在于寫死的錯誤提示消息那行代碼。使用資料注解的開發人員希望可以使用ValidationAttribute的ErrorMessage屬性來自定義錯誤提示消息。同時還要與其他驗證特性一樣,提供一個預設的錯誤消息,并且還要利用驗證的屬性名稱來生成錯誤提示資訊:
public class MaxWordsAttribute : ValidationAttribute
{
  private readonly int _maxWords;
  public MaxWordsAttribute(int maxWords):base("{0}" has too many words)
  {
     _maxWords = maxWords;
  }
  protected override ValidationResult IsValid(object value, ValidationContext validationContext)
  {
    if(value != null)
    {
        var valueAsString = value.ToString();
        if(valueAsString.Split(' ').Length > _maxWords)
        {
           var errorMessage = FormatErrorMessage(
                  validationContext.DisplayName);
           return new ValidationResult(errorMessage);
        }
        return ValidationResult.Success;
  }
}
           
前面 的代碼做了兩處改動:
首先,向基類的構造函數傳遞一個預設的錯誤提示資訊。如果正在面向國際開發應用程式的話,就應該從一個資源檔案中提取這個預設的錯誤提示資訊。

注意:預設的錯誤提示資訊中包含了一個參數占位符{0}。這個占位符之是以存在,是因為第二處改動,即調用繼承的FormatErrorMessage方法會自動使用顯示的屬性名稱來格式化這個字元串。

FormatErrorMessage可以確定我們使用合适的錯誤提示消息字元串(即使這個字元串存儲在一個本地資源檔案中)。這條代碼語句需要傳遞name屬性的值,這個值可以通過validationContext參數的DisplayName屬性獲得。

使用:[MaxWords(10, ErrorMessage="There are too many words in {0}")]

繼續閱讀