I\'ve been trying to work out how to create a FluentValidation rule that checks if the instance of an object it\'s validating is not null, prior to validating it\'s properti
As the above solutions didn't work for me (FluentValidation, Version=6.2.1.0 for Net45), I am posting what I did.
This is just a simple replacement/wrapper for ValidateAndThrow
extension method.
public static class ValidatorExtensions
{
public static void ValidateAndThrowNotNull<T>(this IValidator<T> validator, T instance)
{
if (instance == null)
{
var validationResult = new ValidationResult(new[] { new ValidationFailure("", "Instance cannot be null") });
throw new ValidationException(validationResult.Errors);
}
validator.ValidateAndThrow(instance);
}
}
You should be able to override the Validate
method in your CustomerValidator
class.
public class CustomerValidator: AbstractValidator<Customer>
{
// constructor...
public override ValidationResult Validate(Customer instance)
{
return instance == null
? new ValidationResult(new [] { new ValidationFailure("Customer", "Customer cannot be null") })
: base.Validate(instance);
}
}
I inherited from the fluent AbstractValidator and created a NullReferenceAbstractValidator class instead:
public class NullReferenceAbstractValidator<T> : AbstractValidator<T>
{
public override ValidationResult Validate(T instance)
{
return instance == null
? new ValidationResult(new[] { new ValidationFailure(instance.ToString(), "response cannot be null","Error") })
: base.Validate(instance);
}
}
and then inherited from that class with each validator that needed a null reference check:
public class UserValidator : NullReferenceAbstractValidator<User>
Use the Cascade mode.
Here is the example from the documentation.
RuleFor(x => x.Surname).Cascade(CascadeMode.StopOnFirstFailure).NotNull().NotEqual("foo");
Also from the documentation:
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.
For those using version >6.2.1 you need to override this signature instead, in order to achieve the same as @chrispr:
public override ValidationResult Validate(ValidationContext<T> context)
{
return (context.InstanceToValidate == null)
? new ValidationResult(new[] { new ValidationFailure("Property", "Error Message") })
: base.Validate(context);
}
This is an older post, but want to update the answers to include the following from the FluentValidation documentation:
Using PreValidate
If you need to run specific code every time a validator is invoked, you can do this by overriding the PreValidate method. This method takes a ValidationContext as well as a ValidationResult, which you can use to customise the validation process.
public class MyValidator : AbstractValidator<Person> {
public MyValidator() {
RuleFor(x => x.Name).NotNull();
}
protected override bool PreValidate(ValidationContext<Person> context, ValidationResult result) {
if (context.InstanceToValidate == null) {
result.Errors.Add(new ValidationFailure("", "Please ensure a model was supplied."));
return false;
}
return true;
}
}
https://fluentvalidation.net/start#using-prevalidate