Tom Jones

FluentValidation exception after NotNull check

If you are validating a reference type which can be null, along with its properties, you may encounter a situation where the parent object being null causes FluentValidation to throw a NullReferenceException when validating the properties on that object.

Take the following rule in a custom Validator class:

1RuleFor(request => request.ZipFile)
2 .MustBeValidZipFile();

which uses the following extension method:

1public static IRuleBuilderOptions<T, IFormFile> MustBeValidZipFile<T>(
2 this IRuleBuilder<T, IFormFile> ruleBuilder)
3{
4 return ruleBuilder
5 .NotNull()
6 .WithMessage(ValidationMessages.FileIsNull)
7 .Must(file => file.FileName.Length < MaxFilenameSize)
8 .WithMessage(ValidationMessages.FilenameTooLong)
9 .Must(file => file.Length > 0)
10 .WithMessage(ValidationMessages.FileSizeMustNotBeZero)
11 .Must(file => file.FileName.ToLower().EndsWith(".zip"))
12 .WithMessage(ValidationMessages.ZipFilenameMustEndDotZip);
13}

Even though the IFormFile is null, subsequent checks on its properties will continue to be performed, therefore, attempting to check the FileName property on that object will result in a NullReferenceException.

This can be avoided by using the Cascade method to stop execution on the first error.

1RuleFor(request => request.ZipFile)
2 .Cascade(CascadeMode.Stop)
3 .MustBeValidZipFile();

This is covered in the FluentValidation documentation, but is tucked away under "other features" and not immediately obvious.