FluentValidation LogOnFailure覆盖 [英] FluentValidation LogOnFailure override

查看:222
本文介绍了FluentValidation LogOnFailure覆盖的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的验证器类我有几个规则。

我需要登录到数据库中的一些验证错误。

Inside my validator class I have couple of rules.
I need to log to database some validation errors.

下面是我的验证

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");

有关上述规则,我想只记录的特定错误消息。
我知道,我可以使用OnAnyFailure这样的:

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);
    }



但这种方式,我将无法登录任何有用,因为 OnAnyFailure 需要BindingModel为参数,所以我只得到用户的值没有错误信息输入。

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.

我试过创建扩展方法,将工作为 OnAnyFailure 而是因为我是新来的FluentValidation我无法编译,甚至我的代码。

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.

下面是我的代码:

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
}

基本上,我需要的是为 LogOnFailure ,将能够访问PropertyValidatorContext

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:

public class MyValidator
{
    public MyValidator()
    {
        // default behavior
        Validate();

        // works only when RuleSet specified explicitly as "Debug"
        RuleSet("Debug", ()=> {
            Validate();
            FailAndLogErrors();
        })

        private void Validate()
        {
            RuleFor(u => u.Age)
                //... set cascade mode, define rules with error messages
            RuleFor(u => u.LastName)
                //... set cascade mode, define rules with error messages
            RuleFor(u => u.BirthDate)
                //... set cascade mode, define rules with error messages
        }

        // force failing
        private void FailAndLogErrors()
        {
            RuleFor(m => m)
                .Must(m => false)
                .WithName("_fakeProperty_")
                .OnAnyFailure(m => LogIfFailed(this, m))
        }

        private void LogIfFailed(MyValidator validator, CreateAccountBindingModel obj))
        {
            var errors = validator.Validate(obj, "Debug").Errors;
            if (errors.Count > 1) // prevent displaying valid model
            {
                var fakeError = errors.First(e => e.PropertyName == "_fakeProperty_");
                errors.Remove(fakeError);
                WriteErrors(errors);
            }
        }

        private void WriteErrors(IList<ValidationFailure> errors)
        {
            foreach(var e in errors)
            {
                Debug.WriteLine(e);
            }
            Debug.WriteLine("");
        }
    }
}

这篇关于FluentValidation LogOnFailure覆盖的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆