You need to enable JavaScript to run this app. 如何重抛FluentValidation异常并解决其报错后ErrorHandlingMiddleware不执行的问题?
优惠活动
大模型
产品
解决方案
定价
更多

如何重抛FluentValidation异常并解决其报错后ErrorHandlingMiddleware不执行的问题?

问题根因

当前FluentValidation未触发ErrorHandlingMiddleware的核心原因:

  • 配置的fv.RunDefaultMvcValidationAfterFluentValidationExecutes = false仅会关闭MVC原生数据注解的校验逻辑,FluentValidation完成校验后,依然会把错误信息写入ModelState,由MVC内置的API行为逻辑直接生成400响应,全程不会抛出可被管道中间件捕获的ValidationException,错误根本不会传递到错误处理中间件层。
  • 部分场景下还存在中间件注册顺序错误:如果ErrorHandlingMiddleware注册在MVC端点映射的下游,就算有异常抛出,也无法被中间件捕获。
实现方案

1. 调整服务配置,将ModelState校验错误转为抛出异常

在现有AddMvc的配置链上追加ConfigureApiBehaviorOptions配置,把原本被MVC内置捕获的模型校验错误(含FluentValidation写入的错误)直接组装成ValidationException向上抛出,让异常沿管道传递到错误处理中间件:

services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Latest)
    .AddJsonOptions(options =>
    {
        options.JsonSerializerOptions.IgnoreNullValues = true;
    })
    .AddFluentValidation(fv =>
    {
        fv.RegisterValidatorsFromAssemblyContaining<LoginValidator>();
        fv.RunDefaultMvcValidationAfterFluentValidationExecutes = false;
    })
    .ConfigureApiBehaviorOptions(options =>
    {
        // 替换默认的400响应生成逻辑
        options.InvalidModelStateResponseFactory = context =>
        {
            // 提取ModelState中存储的所有FluentValidation校验错误
            var validationFailures = context.ModelState
                .Where(entry => entry.Value.Errors.Any())
                .SelectMany(entry => entry.Value.Errors
                    .Select(err => new ValidationFailure(entry.Key, err.ErrorMessage)))
                .ToList();
            // 直接抛出FluentValidation的ValidationException,异常将沿管道向上传递
            throw new ValidationException(validationFailures);
        };
    });

注意:此处抛出的ValidationException必须使用FluentValidation命名空间下的类型,和你HandleMessage方法中switch匹配的异常类型保持完全一致,否则会命中全局异常的默认分支。

2. 核对请求管道的中间件注册顺序

ASP.NET Core管道的执行规则为:从上到下注册的组件依次处理请求,从下到上处理抛出的异常。必须保证ErrorHandlingMiddleware注册在MVC端点映射的上游(也就是代码顺序上写在UseEndpoints之前),才能捕获到MVC层抛出的异常。正确的注册顺序参考:

// 错误处理中间件放在最上游,最先注册
app.UseMiddleware<ErrorHandlingMiddleware>();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
// MVC端点映射在下游,异常从这里向上传递
app.UseEndpoints(endpoints =>
{
    endpoints.MapControllers();
});

3. 触发链路验证

完成上述配置后,当FluentValidation检测到校验规则不通过时的完整链路为:

  • 模型绑定阶段把校验错误写入ModelState
  • 自定义的InvalidModelStateResponseFactory捕获这些错误,抛出ValidationException
  • 异常沿管道向上传递,被ErrorHandlingMiddleware捕获,命中预定义的ValidationException分支,生成统一格式的错误响应
补充说明
  • 现有FluentValidation的注册逻辑本身无问题,不需要额外调整
  • FluentValidation官方集成模式下的校验错误默认是作为模型校验结果返回,不是未处理异常,不要依赖默认行为触发异常
  • 场景中如果存在手动调用校验器的逻辑,校验失败后可以直接抛出ValidationException,同样能被中间件捕获,不需要额外适配逻辑

内容的提问来源于stack exchange,提问作者user8753842

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.11.04 00:24:07