2012-08-14 2 views
40

내 속성 값을 내 모델 클래스의 다른 속성 값과 비교하려는 사용자 지정 유효성 검사 특성을 만들려고합니다. 내 모델 클래스에있는 예를 들어 :사용자 정의 유효성 검사 속성을 만드는 방법은 무엇입니까?

...  
public string SourceCity { get; set; } 
public string DestinationCity { get; set; } 

내가 정의를 만들려면이처럼 사용하는 속성 :

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

어떻게 내가 거기받을 수 있나요?

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; 
    } 
} 
+1

http://haacked.com/archive/2009/11/19/aspnetmvc2-custom-validation.aspx – Joe

+1

@Joe, ASP.NET MVC 2 용이며 더 이상 MVC 3에 적용되지 않습니다. 또한이 블로그 게시물은 OP가 여기에서 달성하려고하는 바리케이터에서 종속 속성 값을 검색하는 방법을 설명하지 않습니다. –

답변

67

는 다른 속성 값을 얻을 수있는 방법 이벤트 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"; 

사용 나는 검증을 생략하기로 결정했다.

+0

위대한, 그냥 대답 ** ** 찾고 있어요! 내 유효성 확인 컨텍스트를 제외하고 항상 null입니다. 어떤 아이디어? –

+2

@GrimmTheOpiner 저는 이것이 오래된 것을 알고 있습니다 만, 누구든지보고있는 중에'public override bool RequiresValidationContext {get {return true; }}'CustomAttribute' – Ryan

+0

@ Ryan 와우, 왜 내가 이것을하고 싶었습니까? 내가 기억할 수 있다고해도, 나는 지금 두 가지 일을하고있다! :-) –

4

내 예를 들어 아래를보고하십시오 :

모델 클래스 구현 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)); 
       } 
      } 
     } 

속성 클래스 여기

2

이렇게하는 가장 좋은 방법은 IValidatableObject를 사용하는 것입니다. http://msdn.microsoft.com/en-us/data/gg193959.aspx

+0

IValidatableObject는 확실히 좋은 솔루션이지만 잠재적 인 재사용 가능성을 기반으로 ValidationAttribute는 훨씬 더 많은 것을 만들 것입니다 – WiiMaxx