Setting the Cascade mode¶
You can set the cascade mode to customise how FluentValidation executes rules and validators when a particular rule in the validator class, or validator in the rule fails.
Rule-Level Cascade Modes¶
Imagine you have two validators defined as part of a single rule definition, a NotNull
validator and a NotEqual
validator:
public class PersonValidator : AbstractValidator<Person> {
public PersonValidator() {
RuleFor(x => x.Surname).NotNull().NotEqual("foo");
}
}
This will first check whether the Surname property is not null and then will check if it’s not equal to the string “foo”. If the first validator (NotNull
) fails, then by default, the call to NotEqual
will still be invoked. This can be changed for this specific rule only by specifying a cascade mode of Stop
(omitting the class and constructor definition from now on; assume that they are still present as above):
RuleFor(x => x.Surname).Cascade(CascadeMode.Stop).NotNull().NotEqual("foo");
Now, if the NotNull
validator fails then the NotEqual
validator will not be executed. This is particularly useful if you have a complex chain where each validator depends on the previous validator to succeed.
The two cascade modes are:
Continue
(the default) - always invokes all rules in a validator class, or all validators in a rule, depending on where it is used (see below).Stop
- stops executing a validator class as soon as a rule fails, or stops executing a rule as soon as a validator fails, depending on where it is used (see below).
If you have a validator class with multiple rules, and would like this Stop
behaviour to be set for all of your rules, you could do e.g.:
RuleFor(x => x.Forename).Cascade(CascadeMode.Stop).NotNull().NotEqual("foo");
RuleFor(x => x.MiddleNames).Cascade(CascadeMode.Stop).NotNull().NotEqual("foo");
RuleFor(x => x.Surname).Cascade(CascadeMode.Stop).NotNull().NotEqual("foo");
To avoid repeating Cascade(CascadeMode.Stop)
, you can set a default value for the rule-level cascade mode by setting the AbstractValidator.RuleLevelCascadeMode
property, resulting in
RuleLevelCascadeMode = CascadeMode.Stop;
RuleFor(x => x.Forename).NotNull().NotEqual("foo");
RuleFor(x => x.MiddleNames).NotNull().NotEqual("foo");
RuleFor(x => x.Surname).NotNull().NotEqual("foo");
With default global settings, this code will stop executing any rule whose NotNull
call fails, and not call NotEqual
, but it will then continue to the next rule, and always execute all three, regardless of failures. See “Validator Class-Level Cascade Modes” for how to control this behavior. This particular behaviour is useful if you want to create a list of all validation failures, as opposed to only returning the first one.
See “Global Default Cascade Modes” for setting the default value of this property.
Validator Class-Level Cascade Modes¶
As well as being set at the rule level, the cascade mode can also be set at validator class-level, using the property AbstractValidator.ClassLevelCascadeMode
. This controls the cascade behaviour in between rules within that validator, but does not affect the rule-level cascade behaviour described above.
For example, the code above will execute all three rules, even if any of them fail. To stop execution of the validator class completely if any rule fails, you can set AbstractValidator.ClassLevelCascadeMode
to Stop
. This will result in complete “fail fast” behavior, and return only return a maximum of one error.
See “Global Default Cascade Modes” for setting the default value of this property.
Global Default Cascade Modes¶
To set the default cascade modes at rule-level and/or validator class-level globally, set ValidatorOptions.Global.DefaultRuleLevelCascadeMode
and/or ValidatorOptions.Global.DefaultClassLevelCascadeMode
during your application’s startup routine. Both of these default to Continue
.
Warning
The RuleLevelCascadeMode, ClassLevelCascadeMode, and their global defaults are only available in FluentValidation 11 and newer.
Introduction of RuleLevelCascadeMode and ClassLevelCascadeMode (and removal of CascadeMode)¶
The AbstractValidator.RuleLevelCascadeMode
, AbstractValidator.ClassLevelCascadeMode
, and their global defaults were introduced in FluentValidation 11
In older versions, there was only one property controlling cascade modes: AbstractValidator.CascadeMode
. Changing this value would set the cascade mode at both validator class-level and rule-level. Therefore, for example, if you wanted to have the above-described functionality where you create a list of validation errors, by stopping on failure at rule-level to avoid crashes, but continuing at validator class-level, you would need to set AbstractValidator.CascadeMode
to Continue
, and then repeat Cascade(CascadeMode.Stop)
on every rule chain.
The new properties enable finer control of the cascade mode at the different levels, with less repetition.
Warning
The CascadeMode property was deprecated in FluentValidation 11 and removed in FluentValidation 12. The RuleLevelCascadeMode and ClassLevelCascadeMode properties should be used instead.
To convert to the new properties, see the upgrade guide.