Anyone who asks me will know that i love the simplicity and elegance of creating ASP.Net MVC’s custom data annotations when writing your own validation in ASP.Net MVC. One situation that can be a tricky one to dig yourself out of when coming to more advanced validation logic is writing custom validation attributes that can see/compare properties between itself and other model properties.

Anatomy of an ASP.Net MVC custom validation attribute

I’ve blogged before on how easy it is to write your own ASP.Net MVC Data Annotations for validation, when i wrote a post at the beginning of the year showing you how to write a data annotation to make sure checkboxes where ticked in the post Required CheckBox validation in ASP.Net MVC 2 onwards.

Basically writing your own validation attribute comes down to writing a class that inherits from ValidationAttribute and simple overloading the IsValid() method.

The above is so awesomely simple that it makes your fall in love with the MVC framework.

…But what about when you want to write a validator that uses other model properties to come to it’s conclusion of “IsValid”?…

Normally after facing the above question, you would freak out because your little IsValid() overridden method can’t see anything but the object/property that it is validating… Or can it?

ASP.Net MVC 3 onwards adds great functionality in the form of some overloads to the base validation class that supports some important reflection data that gets handed in a validation time. While working on a recent project at work with my colleague Mark Ellis we ran into this. Our head banging was the inspiration for this post.

A little story about Comparison

When wanting to find out more about the ability for validation attributes to talk to other model properties it would be good to take a look at an attribute that we know does this already every day; The CompareValidator.

The source code of the CompareValidator actually uses a different IsValid overload as shown below courtesy of Reflector (the free version… read into that as you will RedGate…)

This answers all the questions you where freaking out about, Why? because the magical context property that gets sent into the method is your model! This means that to access any of the other properties in your model you simply write something like this: