Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Validating a property if another property has a value on MVC 3/jQuery Validator

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 only if the Prop1 is true.
public string Prop2 { get; set; }

Any idea? I need on client and server side. Thanks

like image 424
Cesar Avatar asked Mar 21 '11 18:03

Cesar


2 Answers

You could use MVC FoolProof Validation framework

It has useful feature like

[RequiredIf]
[RequiredIfNot]
[RequiredIfTrue]
[RequiredIfFalse]
[RequiredIfEmpty]
[RequiredIfNotEmpty]
[RequiredIfRegExMatch]
[RequiredIfNotRegExMatch]

[Is]
[EqualTo]
[NotEqualTo]
[GreaterThan]
[LessThan]
[GreaterThanOrEqualTo]
[LessThanOrEqualTo]

Hope this would help you!

like image 108
Murali Murugesan Avatar answered Sep 28 '22 06:09

Murali Murugesan


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<ValidationAttribute>())
        {
            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.

like image 27
Jim Schubert Avatar answered Sep 28 '22 08:09

Jim Schubert