FluentValidation .NotEmpty()校验器无法返回预期自定义错误消息
你收到的带traceId、errors字段的400响应,不是FluentValidation返回的,也不是你控制器里写的自定义错误返回逻辑生成的——这是ASP.NET Core自带的[ApiController]自动模型校验拦截的结果。
你的Name属性是不可空string类型,框架模型绑定阶段如果检测到请求没传该参数,会直接判定ModelState无效,在请求进入你的控制器代码之前就自动返回默认格式的400响应,你配置在FluentValidation里的NotEmpty自定义错误消息根本没有执行机会。
其他校验规则(长度、枚举范围、自定义Must校验)能正常返回自定义消息,是因为这些场景下参数值已经成功绑定到模型,模型校验通过,请求能正常进入控制器,走到你手动调用FluentValidation校验的逻辑。
二选一即可:
方案1:全局关闭框架自动模型校验拦截
在Program.cs的服务注册代码里添加如下配置,禁用框架自动返回400的逻辑,让所有请求都进入控制器执行你自己的校验流程:
builder.Services.AddControllers() .ConfigureApiBehaviorOptions(options => { options.SuppressModelStateInvalidFilter = true; });
注意:该配置是全局生效的,关闭后你需要自行处理所有接口的参数校验,避免漏过绑定阶段的错误。
方案2:修改属性类型绕过隐式必填校验
如果你的项目启用了可空引用类型,把Name属性改成可空字符串类型,框架就不会自动给它加隐式的必填校验:
public class UserByNameRequest { public string? Name { get; set; } public bool? ExactMatch { get; set; } public SortEnum? Sort { get; set; } }
修改后空值场景下请求会正常进入控制器,FluentValidation的NotEmpty规则会触发,返回你配置的自定义错误消息。这种方案不需要修改全局配置,影响范围更小。
你现在写错误消息用string.Format在校验器构造阶段就固定了文本,可以换成FluentValidation内置的占位符,后续修改属性名时不需要同步改错误消息:
RuleFor(userRequest => userRequest.Name) .NotEmpty() .WithMessage("Informed parameter {PropertyName} is invalid.") .Length(3, 64) .WithMessage("Informed parameter {PropertyName} is invalid.");
内容的提问来源于stack exchange,提问作者Pedro Perondini

