Friday, March 8, 2013

Creating Custom Validation Attribute With Dependency To Other Property

In the last post, I went through the steps to make a custom validation attribute - if you missed it, check it out here: Creating Custom Validation Attribute. Now let's say we want to make our validator to look up on the value "37" from another property in our class (instead of hard-coding it). How do we do that? With the help of reflection, we can do that quite easily.

Here is our modified class:
  1. public class MyClass {
  2. // ... more code
  3. [MagicNumber("ThirtySeven", ErrorMessage = "Sum is not correct")]
  4. public int MyData { get; set; }
  5. // ... more code
  6. public int ThirtySeven {
  7. get { return 37; }
  8. }
  9. // ... more code
  10. }

In our new custom validator, we override a different IsValid method (the original one is commented out):
  1. [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)]
  2. sealed public class MagicNumberAttribute : ValidationAttribute {
  3. // constructor to accept the comparison property name
  4. public MagicNumberAttribute(string thirtySevenProperty) : base() {
  5. if (thirtySevenProperty == null) {
  6. throw new ArgumentNullException("thirtySevenProperty");
  7. }
  8. ThirtySevenProperty= thirtySevenProperty;
  9. }
  10.  
  11. // property to store the comparison field name
  12. public string ThirtySevenProperty{ get; private set; }
  13.  
  14. // public override bool IsValid(object value) {
  15. // var num = int.Parse(value.ToString());
  16. // return num == 37;
  17. // }
  18.  
  19. protected override ValidationResult IsValid(object value, ValidationContext validationContext) {
  20. // get property info of the "ThirtySevenProperty"
  21. PropertyInfo thirtySevenPropertyInfo = validationContext.ObjectType.GetProperty(ThirtySevenProperty);
  22.  
  23. // check if that property exists / valid
  24. if (thirtySevenPropertyInfo == null) {
  25. return new ValidationResult(String.Format(CultureInfo.CurrentCulture, "UNKNOWN PROPERTY", ThirtySevenProperty));
  26. }
  27.  
  28. // get the value of the property
  29. object thirtySevenPropertyValue = thirtySevenPropertyInfo.GetValue(validationContext.ObjectInstance, null);
  30.  
  31. // do comparison and return validation result with error if not equal
  32. if (!Equals(value, thirtySevenPropertyValue)) {
  33. return new ValidationResult(FormatErrorMessage(validationContext.DisplayName));
  34. }
  35.  
  36. // return null if everything is ok
  37. return null;
  38. }
  39. }

That's it!
Additional reading:

1 comment:

Tom said...

Nice post!