Inside my validator class I have couple of rules.
I need to log to database some validation errors.
Here are my validators:
RuleFor(u => u.LastName)
.Cascade(CascadeMode.StopOnFirstFailure)
.NotEmpty().WithMessage("Last name is required")
.Length(3, 20).WithMessage("Must have between 3 and 20 letters");
RuleFor(u => u.BirthDate)
.Cascade(CascadeMode.StopOnFirstFailure)
.NotNull().WithMessage("Birth date is required")
.Must(c => c > new DateTime(1920, 01, 01)).WithMessage("Too old");
RuleFor(u => u.Age)
.Cascade(CascadeMode.StopOnFirstFailure)
.NotNull().WithMessage("This is required")
.GreaterThan(18).WithMessage("Must be at least 18")
.Must((model, age, context) =>
{
DateTime today = DateTime.Today;
int ageToCompare = today.Year - model.BirthDate.Year;
return ageToCompare == age;
}).WithMessage("Invalid age");
For above rules I'd like to log only specific error messages. I'm aware that I can use OnAnyFailure like this:
RuleFor(u => u.Age)
.Cascade(CascadeMode.StopOnFirstFailure)
.NotNull().WithMessage("This is required")
.GreaterThan(18).WithMessage("Must be at least 18").OnAnyFailure(LogOnFailure)
.Must((model, age, context) =>
{
DateTime today = DateTime.Today;
int ageToCompare = today.Year - model.BirthDate.Year;
return ageToCompare == age;
}).WithMessage("Invalid age").OnAnyFailure(LogOnFailure)
private void LogOnFailure(CreateAccountBindingModel obj))
{
Debug.WriteLine(obj);
}
but this way I won't be able to log anything useful, because OnAnyFailure
takes BindingModel as parameter, so I'll only get values user entered without error messages.
I've tried to create extension method that would work as OnAnyFailure
but because I'm new to FluentValidation I wasn't able to even compile my code.
Below is my code:
public static class IRuleBuilderOptionsExtensions
{
public static IRuleBuilderOptions<T, TProperty> OnAnyFailure<T, TProperty>(this IRuleBuilderOptions<T, TProperty> rule, Action<T, PropertyValidatorContext> onFailure)
{
return rule;
//return rule.Configure(config => {
// config.OnFailure = onFailure.CoerceToNonGeneric();
//});
}
}
This way I could be able to call:
private void LogOnFailure(CreateAccountBindingModel obj), PropertyValidatorContext context)
{
//log logic
}
Basically what I need is to create override for LogOnFailure
that will be able to access PropertyValidatorContext.
You can validate your model second time to display it: