c# - FluentValidation LogOnFailure 覆盖

标签 c# asp.net-web-api fluentvalidation

在我的验证器类中,我有几条规则。
我需要将一些验证错误记录到数据库中。

这是我的验证器:

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:

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 作为参数,所以我只会获取用户输入的值而不会出现错误消息。

我尝试创建可用作 OnAnyFailure 的扩展方法,但因为我是 FluentValidation 的新手,所以我什至无法编译我的代码。

下面是我的代码:

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

这样我就可以调用:

private void LogOnFailure(CreateAccountBindingModel obj), PropertyValidatorContext context)
{
    //log logic
}

基本上我需要的是为能够访问 PropertyValidatorContext 的 LogOnFailure 创建覆盖。

最佳答案

您可以第二次验证您的模型以显示它:

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

关于c# - FluentValidation LogOnFailure 覆盖,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38436630/

相关文章:

c# - Fluentvalidation WithMessage 和单例实例

asp.net-mvc - 流利验证可确保列表中至少包含一项属性值为somevalue的项目

c# - 将右侧 UITableViewCell 中的标签与自动布局对齐

c# - 重构 PropertyChangedEventHandler

c# - 在每个方法中初始化一个新的套接字是一件好事吗?

c# - 如何查询基于双列为 "close to"某个值的数据集?

asp.net - 使用 ASP.NET Web API 2.0 和 Ionic Cordova 应用程序启用社交登录

serialization - .NET WebAPI 序列化 k_BackingField 肮脏

asp.net - POST 参数未使用 VBA 传递到 Web API

c# - 在 FluentValidation 中为规则集设置消息失败