2012-08-14 86 views
40

我想創建一個自定義驗證屬性,我想在該屬性中將我的屬性值與我的模型類中的另一個屬性值進行比較。 比如我在我的模型類:如何創建自定義驗證屬性?

​​

我想創建一個自定義屬性使用這樣的:

[Custom("SourceCity", ErrorMessage = "the source and destination should not be equal")] 
public string DestinationCity { get; set; } 
//this wil lcompare SourceCity with DestinationCity 

我怎樣才能得到呢?

+1

http://haacked.com/archive/2009/11/19/aspnetmvc2-custom-validation.aspx – Joe 2012-08-14 20:05:40

+1

@Joe,這是ASP.NET MVC 2,不再適用於MVC 3.此博客文章沒有說明如何在驗證器中檢索依賴屬性值,這是OP在此嘗試實現的。 – 2012-08-14 20:14:52

回答

67

這裏是你如何可以獲取其他屬性值:

public class CustomAttribute : ValidationAttribute 
{ 
    private readonly string _other; 
    public CustomAttribute(string other) 
    { 
     _other = other; 
    } 

    protected override ValidationResult IsValid(object value, ValidationContext validationContext) 
    { 
     var property = validationContext.ObjectType.GetProperty(_other); 
     if (property == null) 
     { 
      return new ValidationResult(
       string.Format("Unknown property: {0}", _other) 
      ); 
     } 
     var otherValue = property.GetValue(validationContext.ObjectInstance, null); 

     // at this stage you have "value" and "otherValue" pointing 
     // to the value of the property on which this attribute 
     // is applied and the value of the other property respectively 
     // => you could do some checks 
     if (!object.Equals(value, otherValue)) 
     { 
      // here we are verifying whether the 2 values are equal 
      // but you could do any custom validation you like 
      return new ValidationResult(this.FormatErrorMessage(validationContext.DisplayName)); 
     } 
     return null; 
    } 
} 
+0

太棒了,這只是答案**我**尋找!除了我的驗證上下文始終爲空。有任何想法嗎? – 2013-11-07 10:18:42

+2

@GrimmTheOpiner我知道這是舊的,但對於任何正在嘗試添加'public override bool RequiresValidationContext {get {return true; }}'CustomAttribute' – Ryan 2017-06-29 02:53:55

+0

@Ryan哇,我爲什麼要這樣做?即使我記得,我現在還有兩份工作! :-) – 2017-06-29 12:21:51

4

請看看下面我舉的例子:

Model類工具INotifyPropertyChanged

public class ModelClass : INotifyPropertyChanged 
     { 
      private string destinationCity; 
      public string SourceCity { get; set; } 

      public ModelClass() 
      { 
       PropertyChanged += CustomAttribute.ThrowIfNotEquals; 
      } 

      [Custom("SourceCity", ErrorMessage = "the source and destination should not be equal")] 
      public string DestinationCity 
      { 
       get 
       { 
        return this.destinationCity; 
       } 

       set 
       { 
        if (value != this.destinationCity) 
        { 
         this.destinationCity = value; 
         NotifyPropertyChanged("DestinationCity"); 
        } 
       } 
      } 

      public event PropertyChangedEventHandler PropertyChanged; 

      protected virtual void NotifyPropertyChanged(string info) 
      { 
       if (PropertyChanged != null) 
       { 
        PropertyChanged(this, new PropertyChangedEventArgs(info)); 
       } 
      } 
     } 

屬性類也包含事件hendler。

internal sealed class CustomAttribute : Attribute 
    { 
     public CustomAttribute(string propertyName) 
     { 
      PropertyName = propertyName; 
     } 

     public string PropertyName { get; set; } 

     public string ErrorMessage { get; set; } 

     public static void ThrowIfNotEquals(object obj, PropertyChangedEventArgs eventArgs) 
     { 
      Type type = obj.GetType(); 
      var changedProperty = type.GetProperty(eventArgs.PropertyName); 
      var attribute = (CustomAttribute)changedProperty 
               .GetCustomAttributes(typeof(CustomAttribute), false) 
               .FirstOrDefault(); 

      var valueToCompare = type.GetProperty(attribute.PropertyName).GetValue(obj, null); 
      if (!valueToCompare.Equals(changedProperty.GetValue(obj, null))) 
       throw new Exception("the source and destination should not be equal"); 
     } 
    } 

使用

var test = new ModelClass(); 
    test.SourceCity = "1"; 
    // Everything is ok 
    test.DestinationCity = "1"; 
    // throws exception 
    test.DestinationCity ="2"; 

爲了簡化代碼,我決定省略驗證。

相關問題