Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/google-apps-script/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# FluentValidation LogOnFailure覆盖_C#_Asp.net Web Api_Fluentvalidation - Fatal编程技术网

C# FluentValidation LogOnFailure覆盖

C# FluentValidation LogOnFailure覆盖,c#,asp.net-web-api,fluentvalidation,C#,Asp.net Web Api,Fluentvalidation,在我的validator类中,我有两条规则。 我需要将一些验证错误记录到数据库 以下是我的验证器: RuleFor(u => u.LastName) .Cascade(CascadeMode.StopOnFirstFailure) .NotEmpty().WithMessage("Last name is required") .Length(3, 20).WithMessage("Must have between 3 and 20 letters"); Rul

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

以下是我的验证器:

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");
对于以上规则,我只想记录特定的错误消息。 我知道我可以使用以下任何失败:

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

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

您可以再次验证模型以显示它:

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("");
        }
    }
}
公共类MyValidator
{
公共MyValidator()
{
//默认行为
验证();
//仅当规则集明确指定为“调试”时才起作用
规则集(“调试”,()=>{
验证();
FailAndLogErrors();
})
私有void Validate()
{
规则(u=>u.Age)
//…设置级联模式,定义带有错误消息的规则
规则(u=>u.LastName)
//…设置级联模式,定义带有错误消息的规则
规则(u=>u.生日)
//…设置级联模式,定义带有错误消息的规则
}
//强制失效
私有void FailAndLogErrors()
{
规则(m=>m)
.Must(m=>false)
.使用名称(“\u fakeProperty”)
.OnAnyFailure(m=>LogIfFailed(this,m))
}
私有void LogIfFailed(MyValidator验证器,CreateAccountBindingModel obj))
{
var errors=validator.Validate(obj,“Debug”).errors;
if(errors.Count>1)//阻止显示有效模型
{
var fakeError=errors.First(e=>e.PropertyName==“\u fakeProperty””;
错误。删除(fakeError);
写入错误(错误);
}
}
私有无效写入错误(IList错误)
{
foreach(错误中的变量e)
{
Debug.WriteLine(e);
}
Debug.WriteLine(“”);
}
}
}

创建覆盖将没有帮助,因为框架将使用单个参数(要验证的实例)调用
PropertyRule.OnFailure
。@AlekseyL。那么还有别的办法吗?方法的名称可以不同,不必重写。我想在发生错误时获取我的模型和属性验证上下文,就像我不知道有这样的扩展点一样,但你可以在
ActionFilter
检查模型状态并记录所有错误。如果你需要这个例子,请告诉我。@AlekseyL。我已经在FluentValidation repo(github.com/JeremySkinner/FluentValidation/issues/…)上发布了我当前的解决方案代码,我正在等待Jeremy的审核。我已经在我的项目中实现了这个解决方案,它工作得很好,但是我想在我发布它之前得到作者的评论。也许你可以看看它并分享你的想法?为什么不在特定的
必须
验证器中记录错误呢?谢谢,private void LogIfFailed(MyValidator validator,CreateAccountBindingModel obj)最后应该只有一个右括号
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("");
        }
    }
}