在AspNet(Core)中验证后访问ValidationResult对象

时间:2018-05-15 18:23:35

标签: c# asp.net asp.net-web-api asp.net-core .net-core

假设我通过实现IValidatableObject interface:

为模型编写自定义验证
public class MyModel : IValidatableObject
{
    public string Name { get; set; }

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        if (Name == "Foo")
        {
            yield return new CustomValidationResult(42, nameof(Name));
        }
    }
}

public class CustomValidationResult : ValidationResult
{
    public CustomValidationResult(int bar, string memberName) : base("FooBar", new[] { memberName })
    {
        Bar = bar;
    }

    public int Bar { get; private set; }
}

现在我想访问控制器中的CustomValidationResult对象或动作过滤器。例如:

public class MyActionFilterAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext context)
    {
        if (!context.ModelState.IsValid) {
            // How to access the validation result?
            // Specifically, how to get the value '42' from here?
        }
    }
}

有没有办法实现这个目标?

1 个答案:

答案 0 :(得分:0)

不能。到您获得ModelStateDictionarycontext.ModelState)时,原来的ValidationResult对象已消失。但是核心数据仍然存在。它刚刚变了。 ValidationResult对象中的数据通过ModelStateDictionary添加到AddModelError(...)

在实践中,您将看到ValidationResult.MemberNames中的每个值都变成字典中的KeyValidationResult.ErrorMessage进入该ModelStateEntry.ErrorMessage集合中ModelStateEntry对象之一的Key

因此,换句话说,如果单个错误消息指示多个成员,则该错误消息将在字典中显示多次(每个“成员”一次)。并且当多个ValidationResult对象指定相同的MemberName时,单个Key的集合中将有多个错误。

回到您的示例:

public class MyActionFilterAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext context)
    {
        if (!context.ModelState.IsValid) 
        {
            string errorMsg = context.ModelState[nameof(MyModel.Name)].Errors[0]; // errorMsg will be "FooBar"
            // CustomValidationResult.Bar (42) is inaccessible from here because any original ValidationResult objects are gone.
        }
    }
}