FluentValidation rules chaining not stopping at first failure

I have a model:

public class DTO
{
    public int[] StatementItems { get; set; }
}

Which I want to validate that:

  1. StatementItems is not null
  2. StatementItems is not empty
  3. StatementItems does not contain any duplicate IDs

The validation rule chain I created is:

RuleFor(x => x.StatementItems).NotNull().NotEmpty().Must(x => x.Distinct().Count() == x.Count());

And I have a test as:

_validator.ShouldHaveValidationErrorFor(x => x.StatementItems, null as int[]);

When I run the test passing in a null value, I would expect it to fail on the first rule of the chain (NotNull()) and stop there. However, it complains that the lamda value used in the Must() is null.

Am I wrong in thinking that the Must() shouldn’t be run if the NotNull() fails? If so, how should this rule be written?

Thanks

Answer

Although @NPras’s answer did supply my with a solution, I didn’t like the fact that I’m duplicating the NotNull rule. After a bit more research on FluentValidation I have implemented it using DependentRules:

RuleFor(x => x.StatementItems).NotNull().NotEmpty()
            .DependentRules(d =>
                d.RuleFor(x => x.StatementItems).Must(x => x.Distinct().Count() == x.Count())
            );

So now the Must condition is only fired when the previous two rules are valid.

Leave a Reply

Your email address will not be published. Required fields are marked *