FluentValidation for When & must?

James123 picture James123 · Jun 3, 2014 · Viewed 33.1k times · Source

I am trying use FluentValidation validaton when dropdownlist value is yes and the field must be date. it is working when dropdownlist is yes checking for date. But also showing validation when I select No still it says Must be date.

It should not validate anymore if dropdownlist value otherthan the yes. How can we do that?

 RuleFor(x => x.DtPublishedTimeText)
            .NotEmpty()
            .When(HasMaterialPublishedElseWhereText)
            .WithMessage("Required Field")
            .Must(BeAValidDate)
            .WithMessage("Must be date");

private bool BeAValidDate(string val)
{
    DateTime date;
    return  DateTime.TryParse(val, out date);
}

private bool HasMaterialPublishedElseWhereText(MeetingAbstract model)
{
    return model.HasMaterialPublishedElseWhereText != null && 
             model.HasMaterialPublishedElseWhereText.Equals("yes");
}

Answer

Xenolightning picture Xenolightning · Jun 4, 2014

The issue you are having is the When predicate only applies to one rule. You need to have conditional validation on both the NotEmpty AND the Must.

There two ways to achieve this. Option 1 is tidier when there are only a couple of conditional rules, otherwise I'd use option 2.

RuleFor(x => x.DtPublishedTimeText)
    .NotEmpty()
        .When(HasMaterialPublishedElseWhereText)
        .WithMessage("Required Field")
    .Must(BeAValidDate)
        .When(HasMaterialPublishedElseWhereText)
        .WithMessage("Must be date");

Or

When(HasMaterialPublishedElseWhereText, () => {
    RuleFor(x => x.DtPublishedTimeText)
        .NotEmpty()
            .WithMessage("Required Field");
    RuleFor(x => x.DtPublishedTimeText)
        .Must(BeAValidDate)
            .WithMessage("Must be date");
});

Do note: I have no idea what HasMaterialPublishedElseWhereText is or what it looks like. I am assuming you can use it as a predicate


EDIT:

I'd also look at refactoring the HasMaterialPublishedElseWhereText method, the following is less error prone.

private bool HasMaterialPublishedElseWhereText(MeetingAbstract model)
{
    return String.Equals(model.HasMaterialPublishedElseWhereText, "yes", StringComparison.InvariantCultureIgnoreCase);
}