ASP.NET Core 2.0校验:语法问题与校验问题的区分处理
区分ModelState错误类型,返回400或422状态码
当然可以区分!在ASP.NET Core 2.0中,我们可以通过ModelState里错误的特征来判断是JSON语法错误还是数据校验错误,从而返回对应的HTTP状态码。下面给你具体的实现方案:
一、在控制器内直接判断
你可以在CreateArticle方法里检查ModelState的错误细节:
[HttpPost] public async Task<IActionResult> CreateArticle([FromBody] CreateArticleInput input) { if (!ModelState.IsValid) { // 判断是否是JSON语法错误 bool isJsonSyntaxError = false; // 检查是否存在根路径($)的解析错误,这是JSON格式错误的典型标志 if (ModelState.ContainsKey("$")) { isJsonSyntaxError = true; } // 或者检查错误是否来自JSON解析异常(根据你使用的序列化器调整) else { // ASP.NET Core 2.0默认使用Newtonsoft.Json,用这个判断 isJsonSyntaxError = ModelState.Values .Any(v => v.Errors.Any(e => e.Exception is Newtonsoft.Json.JsonException)); // 如果后续切换到System.Text.Json,换成下面的判断 // isJsonSyntaxError = ModelState.Values // .Any(v => v.Errors.Any(e => e.Exception is System.Text.Json.JsonException)); } if (isJsonSyntaxError) { // 返回400 Bad Request,提示JSON格式错误 return BadRequest(new { Message = "Invalid JSON format in request body" }); } else { // 返回422 Unprocessable Entity,附带具体的校验错误 return UnprocessableEntity(ModelState); } } // 后续正常业务逻辑 return Ok(); }
二、全局过滤器(推荐)
如果你的项目里多个控制器都需要这个逻辑,写个全局过滤器更高效,不用重复代码:
1. 创建自定义过滤器
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Filters; using Newtonsoft.Json; // 对应ASP.NET Core 2.0默认的序列化器 public class ModelStateValidationFilter : ActionFilterAttribute { public override void OnActionExecuting(ActionExecutingContext context) { if (!context.ModelState.IsValid) { bool isJsonError = context.ModelState.ContainsKey("$") || context.ModelState.Values.Any(v => v.Errors.Any(e => e.Exception is JsonException)); if (isJsonError) { context.Result = new BadRequestObjectResult(new { Message = "Request body contains invalid JSON" }); } else { context.Result = new UnprocessableEntityObjectResult(context.ModelState); } } } }
2. 注册过滤器
在Startup.cs的ConfigureServices方法里添加:
public void ConfigureServices(IServiceCollection services) { services.AddMvc(options => { // 添加全局过滤器 options.Filters.Add<ModelStateValidationFilter>(); }); }
这样所有控制器的ModelState校验都会自动区分错误类型,返回对应的状态码,不用再在每个Action里写判断逻辑。
原理说明
- 当JSON格式错误时,ASP.NET Core的Body解析器会在ModelState中添加一个键为
$的错误,或者抛出JsonException(取决于序列化器),这是我们判断的核心依据。 - 而Required、StringLength这类校验错误,是模型绑定成功后,由数据注解验证产生的,不会有根路径的
$键,也不会有JSON解析异常。
这样处理完全符合HTTP状态码的语义:400表示请求本身格式错误(无法解析),422表示请求格式正确但内容不符合校验规则。
内容的提问来源于stack exchange,提问作者Victor
相关产品推荐
相关产品推荐

