2012-08-14 23 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

+1

@JoeはASP.NET MVC 2のためのもので、MVC 3には当てはまりません。 postは、OPがここで達成しようとしているバリデーターの依存プロパティー値を取り出す方法を示していません。 –

答えて

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

素晴らしいです、これはちょうど答えです**私は**を探しています!私の検証コンテキストを除いて、常にnullです。何か案は? –

+2

@GrimmTheOpiner私はこれが古いと知っていますが、探している人には 'public override bool RequiresValidationContext {get {return true; }} 'CustomAttribute' – Ryan

+0

@ Ryan Wow、なぜ私はこれをしたいのですか?私が覚えていても、私は今、さらに2つの仕事をしています! :-) –

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)); 
       } 
      } 
     } 

Attributeクラスを実装しますイベント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"; 

私は検証を省略することを決定したコードを簡単にするために。

関連する問題