Reputation: 11652
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");
}
Upvotes: 18
Views: 61112
Reputation: 923
Tested in VERSION >= 8.4.0
a new enum parameter is added to When
extension method
public enum ApplyConditionTo
{
//
// Summary: (default)
// Applies the condition to all validators declared so far in the chain.
AllValidators = 0,
//
// Summary:
// Applies the condition to the current validator only.
CurrentValidator = 1
}
by default (AllValidators): When
will ending by rules chain ends
(CurrentValidator): When
will be restricted to the first previous rule
Upvotes: 4
Reputation: 276
You just need to change the order of your calls. Try this:
RuleFor(x => x.DtPublishedTimeText)
.NotEmpty()
.WithMessage("Required Field")
.Must(BeAValidDate)
.WithMessage("Must be date")
.When(HasMaterialPublishedElseWhereText);
The When
applies to all previous rules. So in your code when you applied it straight after the NotEmpty
, it applied only to the NotEmpty
rule and not to the Must
rule.
Full demo on DotNetFiddle.
Upvotes: 16
Reputation: 4230
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);
}
Upvotes: 26