FluentValidation rule for null object
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://docs.fluentvalidation.net/en/latest/advanced.html?#prevalidate
EDIT 2022-07-19
As some commenters have pointed out, please check out answer https://stackoverflow.com/a/52784357/1943 for a newer implementation. I haven't personally vetted, but it's worth a try to give that a go first.
If you're using an older version, or you enjoy nostalgia, my original answer below is from 2013.
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);
}
}
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);
}
/// EXAMPLE FOR NETCORE-3.1
/// fluentvalidator-9.5.0
public class Organisation
{
public string Name { get; set; }
}
public class OrganisationValidator : AbstractValidator<Organisation>
{
public OrganisationValidator()
{
RuleFor(x => x.Name).NotNull().MaximumLength(50);
}
protected override bool PreValidate(ValidationContext<Organisation> context, ValidationResult result)
{
if (context.InstanceToValidate == null) {
result.Errors.Add(new ValidationFailure("", "org is null"));
return false;
}
return base.PreValidate(context, result);
}
}
[TestClass]
public class UnitTest1
{
[TestMethod]
public void ValidateWithNull()
{
var validator = new OrganisationValidator();
Organisation organisation = null;
var result = validator.Validate(organisation);
// result.Errors[0].ErrorMessage == "org is null";
}
}
I can't really test that right now, but you can either try to override Validate
, or include the rules in the When
block:
public CustomerValidator()
{
When(x => x != null, () => {
RuleFor(x => x.Surname).NotEmpty();
//etc.
});
}