how can I use a Required Validation in a property Prop2 only if the Prop1 is true?
Ex:
public bool Prop1 { get; set; }
[Required] // I need this validation
There are two parts to this. First, you have to write a required attribute that's only required if the other property meets your criteria.
You'd have to do something like:
public class RequiredComparerAttribute : RequiredAttribute
{
public OtherProperty { get; set; }
public override bool IsValid(object value)
{
// TODO: use reflection to validate other property as PropertyInfo
// or validate it's value after it is decided to be valid
foreach (ValidationAttribute va in property
.GetCustomAttributes(typeof(ValidationAttribute), true)
.OfType())
{
if (!va.IsValid(value))
{
return false; // not required
}
}
return true; // required
}
}
Then, in Application_Start in the Global.asax, you'll have to register the validator, which you can just reuse the RequiredAttribute's validator:
DataAnnotationsModelValidatorProvider
.RegisterAdapter(typeof(RequiredComparerAttribute),
typeof(RequiredAttributeAdapter));
If you want to add your own validator, you'll have to write a custom validator. Phil Haack has an example on his blog: http://haacked.com/archive/2009/11/19/aspnetmvc2-custom-validation.aspx
Edit: Take a look at CompareAttribute in .NET Reflector for a sense of how to get the value of the OtherProperty. CompareAttribute also implements IClientValidatable
to provide those validation rules needed on the client side.
I don't think CompareAttribute will work for you because you have to validate that a value is required based on content of another property, not compare the equality of two properties.
Edit2: What does the Validation provider do?
It adds rules to the form and provides messages for those rules. You can see exactly how the RequiredAttributeAdapter
does this by downloading the MVC 3 source. To understand what it does on the client side, you can open the MVC 3 page in Google Chrome, hit CTRL+SHIFT+J to bring up a developer tools window and enter:
$('form:first').data().unobtrusiveValidation.options
The rules object inside options specifies how to validate each item and the message object specifies the error message that will be displayed for each validation error.
Edit3: Full example
Since answering this question, I've written a blog post with a full example of creating a custom attribute on the client (unobtrusive validation) and server. The blog post is here. This example is for a 'contains' attribute, but it should be pretty easy to modify to become a required comparison.