.NET 5 API中如何为ValidationAttribute校验结果添加自定义响应码?
解决方案
问题根因
ASP.NET Core 中带有 [ApiController] 标记的控制器默认启用了自动模型校验逻辑,该逻辑优先级高于自定义 ActionFilter,校验失败时会直接返回 400 响应,不会进入你编写的过滤器逻辑,这就是你之前代码不生效的原因。
方案1:关闭默认自动校验,复用现有逻辑
只需要在 Startup.cs 的 ConfigureServices 方法中添加如下配置,关闭默认的模型校验过滤器即可让你的自定义过滤器正常触发:
services.Configure<ApiBehaviorOptions>(options => { // 关闭默认自动模型校验响应 options.SuppressModelStateInvalidFilter = true; });
配置完成后你之前写的 RequestModelValidationAttribute 就可以在校验成功、失败的场景下正常执行,不需要修改原有逻辑。
方案2:自定义带错误码的校验特性+替换全局校验响应工厂(更优雅的长期方案)
该方案不需要硬编码属性名对应错误码,可直接在业务模型的校验特性上配置对应错误码,可维护性更高:
步骤1:定义带错误码的自定义校验特性
/// <summary> /// 带业务错误码的自定义校验特性 /// </summary> public class BusinessValidationAttribute : ValidationAttribute { /// <summary> /// 业务错误码 /// </summary> public string ErrorCode { get; set; } protected override ValidationResult IsValid(object value, ValidationContext validationContext) { // 这里写入你原来的自定义校验逻辑 bool isValid = /* 你的校验规则 */; if (!isValid) { // 返回携带错误码和错误消息的校验结果 return new ValidationResult($"{ErrorCode}|{ErrorMessage}"); } return ValidationResult.Success; } }
步骤2:替换默认的模型校验失败响应工厂
services.Configure<ApiBehaviorOptions>(options => { options.InvalidModelStateResponseFactory = context => { var apiResponse = new ResponseModel<ResponseAPI> { ResponseMessage = "出现一个或多个校验错误。" }; // 取第一个校验失败的属性返回 var invalidModel = context.ModelState .FirstOrDefault(m => m.Value.ValidationState == ModelValidationState.Invalid); if (invalidModel.Value != null) { var errorMsg = invalidModel.Value.Errors.First().ErrorMessage; // 拆分错误码和错误消息 var msgParts = errorMsg.Split('|', 2); if (msgParts.Length == 2) { apiResponse.ResponseCode = msgParts[0]; apiResponse.Errors.Add(invalidModel.Key, new List<string> { msgParts[1] }); } else { // 系统默认校验错误走默认错误码 apiResponse.ResponseCode = "01"; apiResponse.Errors.Add(invalidModel.Key, new List<string> { errorMsg }); } } // 可根据需求修改HTTP状态码,比如返回200也可以 return new BadRequestObjectResult(apiResponse); }; });
步骤3:业务模型中使用
直接在需要校验的属性上配置对应错误码即可:
public class 你的请求类 { [BusinessValidation(ErrorCode = "01", ErrorMessage = "Property1不符合要求")] public string Property1 { get; set; } [BusinessValidation(ErrorCode = "02", ErrorMessage = "Property2不符合要求")] public string Property2 { get; set; } [BusinessValidation(ErrorCode = "03", ErrorMessage = "Property3不符合要求")] public string Property3 { get; set; } }
内容的提问来源于stack exchange,提问作者Vivek Nuna
相关产品推荐
相关产品推荐

