Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

FluentValidation.Net doesn't produce client side unobtrusive validation when using .SetValidator()

I'm trying to get client side validation working for a page that uses editor templates.

A simplified example of my view model is e.g.:

[Validator(typeof(ValidationTestModelValidator))]
public class ValidationTestModel
{
    public string Name { get; set; }

    public string Age { get; set; }

    public ChildModel Child { get; set; }
}

The child model is e.g.:

public class ChildModel
{
    public string ChildName { get; set; }

    public string ChildAge { get; set; }
}

My validator is e.g.:

public class ValidationTestModelValidator : AbstractValidator<ValidationTestModel>
{
    public ValidationTestModelValidator()
    {
        RuleFor(m => m.Name)
            .NotEmpty()
            .WithMessage("Please enter the name");

        RuleFor(m => m.Age)
            .NotEmpty()
            .WithMessage("Please enter the age");

        RuleFor(m => m.Age)
            .Matches(@"\d*")
            .WithMessage("Must be a number");

        RuleFor(m => m.Child)
            .SetValidator(new ChildModelValidator());
    }
}

And the child model validator is e.g.:

public class ChildModelValidator : AbstractValidator<ChildModel>
{
    public ChildModelValidator()
    {
        RuleFor(m => m.ChildName)
            .NotEmpty()
            .WithMessage("Please enter the name");

        RuleFor(m => m.ChildAge)
            .NotEmpty()
            .WithMessage("Please enter the age");

        RuleFor(m => m.ChildAge)
            .Matches(@"\d*")
            .WithMessage("Must be a number");
    }
}

I have registered FluentValidation.Net with MVC3 by adding the following to Application_Start():

// Register FluentValidation.Net
FluentValidationModelValidatorProvider.Configure();

This generates unobtrusive client side validation perfectly for the two properties Name and Age, but nothing for the properties on the ChildModel.

Any ideas what I'm doing wrong here?

Update: It seems to work ok if I just annotate the ChildModel with the Validator attribute, however I want to apply the validation conditionally, hence the use of SetValidator().

like image 970
magritte Avatar asked Jan 31 '12 11:01

magritte


1 Answers

I tried to analyze the documentation http://fluentvalidation.codeplex.com/wikipage?title=mvc&referringTitle=Documentation. It states that the MVC integration works based on the attributes by default, because its validator factory uses the attribute to instantiate the appropriate validator. Apparently it does validate the ChildModel referenced by the property on the main model, but maybe this is just an automatic recursive traversal of the model structure to generate the client side validation code. So it might use the same mechanism to locate the appropriate validator for the ChildModel type. Could you test what happens if you remove the SetValidator rule (but leave the attribute for ChildModel), whether it would still generate the validators based on the attribute?

There is an explicit list of validators that are supported on the client side, but unfortunately SetValidator is not mentioned (or explained) there, which is a bad sign.

The doc also states that rules using a condition are not supported on the client side, so most probably you cannot workaround this with the use of SetValidator (as you stated in your update).

See also this discussion about client side conditional rules: http://fluentvalidation.codeplex.com/discussions/393596. The suggestion there was to implement the conditional rule in JS with jQuery Validation, however, this might be complicated if you have a complex validation that should be conditionally added.

How about letting it add the validators with the attribute, but somehow suppressing them afterwards? E.g. by removing the unobtrusive attributes from the elements afterwards?

like image 191
Tz_ Avatar answered Oct 11 '22 11:10

Tz_