'Validate multiple properties with one message
I'm trying to validate a class that has three required properties.
If one or more of them is null it should trigger a single validation message.
Is there a idiomatic way to describe this in fluent validator?
I'm looking at dependant rules but the bottom of the documentation's page advises against using them.
Furthermore I still want to validate all three properties. I just don't want duplicate messages.
I noticed RuleSets, but these seem to serve a different purpose.
Alternatively I could create a validator specifically for these three options but without message and then chain the new validator in the original one. Then I think I can give that one a single message.
But that's a lot of ceremony for a system that is built around being readable.
So looking for a readable way to express validation for three fields with a single message as result.
Solution 1:[1]
There are 3 main ways you can do this with FluentValidation: Conditions, dependent rules or a custom rule.
Conditions
You can use 3 separate rule declarations with When
conditions to ensure that you only ever get a single validation message.
RuleFor(x => x.Property1).NotNull()
.WithMessage("At least one is required");
RuleFor(x => x.Property2).NotNull()
.When(x => x.Property2 != null)
.WithMessage("At least one is required");
RuleFor(x => x.Property3).NotNull()
.When(x => x.Property1 != null && x.Property2 != null)
.WithMessage("At least one is required");
Dependent Rules
RuleFor(x => x.Property1).NotNull()
.WithMessage("At least one is required")
.DependentRules(() => {
RuleFor(x => x.Property2).NotNull()
.WithMessage("At least one is required")
.DependentRules(() => {
RuleFor(x => x.Property3).NotNull().WithMessage("At least one is required");
});
});
I don't particularly like this approach - I think it's hard to read (hence the warning in the documentation), but if you like this approach it'll work just fine.
Custom logic
RuleFor(x => x)
.Must(x => x.Property1 != null && x.Property2 != null && x.Property3 != null)
.WithMessage("At least one is required");
This approach is slightly different as it creates a model-level rule, so the error message will be associated with the entire model, rather than with a specific property.
Solution 2:[2]
Stop the validator when the first rule fails by setting the CascadeMode
property:
public class MyClassValidator : AbstractValidator<MyClass>
{
public DestinationDeviceValidator()
{
this.CascadeMode = CascadeMode.Stop;
this.RuleFor(x => x.Property1)
.NotNull();
this.RuleFor(x => x.Property2)
.NotNull();
this.RuleFor(x => x.Property3)
.NotNull();
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Dharman |
Solution 2 | Lukas |