【问题标题】:How to avoid InvalidModelStateResponseFactory to interfere with an error response already generated in FluentValidation如何避免 InvalidModelStateResponseFactory 干扰 FluentValidation 中已生成的错误响应
【发布时间】:2021-01-13 09:25:22
【问题描述】:

我正在使用 FluentValidation 开发一个 .NET Core 3.0 MVC 项目,用于验证来自 React 前端的输入。我不能依赖输入在前端得到验证。

我正在使用 InvalidModelStateResponseFactory 来捕获转换错误,例如"zz" 为整数,并使用 FluentValidation 验证数字是否有效,例如

我的问题是,当 FluentValidation 捕获错误时,InvalidModelStateResponseFactory 会在之后捕获它,即使没有转换错误。并且来自 FluentValidation 的错误消息丢失了。

FluentValidation 可以验证 int 是否过大。例如:

public class XCommand
{
    public int myInt {get;set;}
}

验证器:

public class XCommandValidator : AbstractValidator<XCommand>
{
    RuleFor(x => x.myInt).InclusiveBetween(0, 99).WithMessage("only below 100");
}

如果验证器失败 {myInt : 100},我可以捕获异常并返回一个很好的错误响应。

如果前端发送 {myInt : "zz"} 我收到 MVC 生成的错误(不涉及 InvalidModelStateResponseFactory):

{"errors":{"myInt":["无法将字符串转换为整数:zz。路径 'myInt',第 1 行,位置 1。"]},"type":"https:// /tools.ietf.org/html/rfc7231#section-6.5.1","title":"出现一个或多个验证错误。","status":400,"traceId":"|ae6d5a28-4822b30b8c0ae039。"}

当我遇到转换错误时,我想控制我发送到前端的错误响应的格式。为了捕捉转换错误,我在 Startup.cs 中设置了一个 InvalidModelStateResponseFactory:

services.Configure<ApiBehaviorOptions>(options =>
{
   options.InvalidModelStateResponseFactory = contex =>
   {
      // create a nice error response
   };
}); 

我的问题是,如果我没有转换错误,但值无效,例如{myInt : 100} 它在 FluentValidator 中失败。 InvalidModelStateResponseFactory 被激活,InvalidModelStateResponseFactory 中产生的错误响应被发送到前端。 FluentValidation 中生成的消息丢失。

如何避免 InvalidModelStateResponseFactory 干扰 FluentValidation 中已生成的错误响应?

【问题讨论】:

    标签: asp.net-mvc fluentvalidation


    【解决方案1】:

    解决方案是创建一个自定义验证过滤器,它可以捕获来自 MVC“本机”和 FluentValidator 的所有验证错误。

    public class CustomValidationFilter : IActionFilter
    {
        public void OnActionExecuted(ActionExecutedContext context) { }
        public void OnActionExecuting(ActionExecutingContext context)
        {
            if (!context.ModelState.IsValid)
            {               
                SortedList<string, List<string>> err = new SortedList<string, List<string>>();
                foreach (var modelStateKey in context.ModelState.Keys)
                {
                    var modelStateVal = context.ModelState[modelStateKey];
                    if (modelStateVal.ValidationState == Microsoft.AspNetCore.Mvc.ModelBinding.ModelValidationState.Invalid)
                    {                     
                        err.Add(modelStateKey, modelStateVal.Errors.Select(e => e.ErrorMessage).ToList());                       
                    }
                }
    
                var responseObj = new
                {
                    Errors = err
                };
    
                context.Result = new JsonResult(responseObj)
                {
                    StatusCode = 400
                };
            }
        }
    }
    

    在 StartUp.ConfigureServices 中必须添加:

    services.Configure<ApiBehaviorOptions>(options =>
    {
        options.SuppressModelStateInvalidFilter = true;
    });
    

    【讨论】:

      猜你喜欢
      • 2013-10-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-05-15
      • 1970-01-01
      • 2011-12-02
      • 2014-04-06
      • 1970-01-01
      相关资源
      最近更新 更多