微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

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

我正在使用 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 中生成错误响应?

解决方法

解决方案是创建一个自定义验证过滤器,并捕获来自 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;
});

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。