Search code examples
asp.net-mvc-3validationclient-side-validation

What is the simple way to do conditional validation on client-side?


I googled for the answer and I found many questions and blog post in the topics. Many seems very complicated way and some are incomplete.

I have a Customer object with 2 property of type Address. 1 is BillingAddress and the other is ShippingAddress. In the form, I am using an EditorTemplate for the Address type. User have an option to choose whether ShippingAddress is same as BillingAddress.

public class Customer
{
    public virtual string CustomerName { get; set; }
    public virtual string Title { get; set; }
    public virtual Address BillingAddress { get; set; }
    public virtual Address ShippingAddress { get; set; }
    public virtual bool ShippingSameAsBilling { get; set; }
    // Cont..
}

public class Address
{
    public virtual string AddressLine { get; set; }
    [Required]
    public virtual string City { get; set; }
    // Cont..
}

Note: I have a checkbox in my view for public virtual bool ShippingSameAsBilling { get; set; }

My problem is, I need validation on Address property which is a type of Address class having required fields. Everything works fine if the user does not choose "Shipping address is same as Billing Address". If he/she choose them to be same and fill only BillingAddress, then the ShippingAddress EditorTemplate shows error on required fields.

I can remove [Required] attribute from Address class and validate manually in server side after form is posted. It would work well in this scenario for me. Also I need to know how the client side validation can be bind into existing mvc validation manually? Or please suggest me a better way to achieve this goal.


Solution

  • I would suggest you to try out fluentValidation its also on NUGET as a package.

    You are way more in control of your validation and it is in my opinion a cleaner way then using attributes. short example:

    [Validator(typeof(CustomerValidator))]
    public class Customer{
        public virtual string CustomerName { get; set; }
        public virtual string Title { get; set; }
        public virtual Address BillingAddress { get; set; }
        public virtual Address ShippingAddress { get; set; }
        public virtual bool ShippingSameAsBilling { get; set; }
        // Cont..
    }
    
    public class CustomerValidator : AbstractValidator<Customer> {
        public CustomerValidator() {        
            RuleFor(x => x.CustomerName ).Length(0, 10);
            RuleFor(x => x.Email).EmailAddress();
            RuleFor(x => x.ShippingAddress).NotEmpty()
                    .When(customer => !customer.ShippingSameAsBilling );
        }
    }
    


    (note that you have to specify a validator for your Address class as well and add the attribute)

    Look trough the documentation how to disable the validation for the shipping address as i'm not sure that NotEmpty() is correct, you might want to look at the .Must() or SetValidator() maybe.

    And finally add the FluentValidationModelValidatorProvider.Configure(); to your application_start