代码之家  ›  专栏  ›  技术社区  ›  Z.Chen

ASP.NET核心中间件无法捕获NewtonSoft异常

  •  1
  • Z.Chen  · 技术社区  · 6 年前

    我使用中间件捕获请求异常并像这样写响应

    public async Task Invoke(HttpContext context /* other dependencies */)
    {
        try
        {
    
            await next(context);
        }
        catch (Exception ex)
        {
            logger.LogError(ex.Message);
            await HandleExceptionAsync(context, ex); //write response
        }
    }
        private static Task HandleExceptionAsync(HttpContext context, Exception exception)
        {
            FanjiaApiResultMessage resultMessage = new FanjiaApiResultMessage()
            {
                ResultCode = -1,
                Data = null,
                Msg = exception.Message
            };
            string result = JsonConvert.SerializeObject(resultMessage);
            context.Response.ContentType = "application/json;charset=utf-8";
            if (exception is QunarException)
            {
                context.Response.StatusCode = (int)(exception as QunarException).httpStatusCode;
            }
            else
                context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
            return context.Response.WriteAsync(result);
        }
    

    这样的请求模型参数

    public class FlightModel {
       [JsonProperty("depCity", Required = Required.Always)]
       public string DepCity { get; set; }
    }
    
    public IActionResult Test(FlightModel model){
      return Content("test");
    }
    

    当我发布没有深度的飞行模型时,我会得到例外

    {
        "errors": {
            "": [
                "Required property 'depCity' not found in JSON. Path '', line 6, position 1."
            ]
        },
        "title": "One or more validation errors occurred.",
        "status": 400,
        "traceId": "8000000a-0003-ff00-b63f-84710c7967bb"
    }
    

    显然,中间件不会捕获异常。

    为什么中间件不被捕获?

    1 回复  |  直到 6 年前
        1
  •  2
  •   Simon C Zameer Khan    6 年前

    aspnet核心模型验证失败不会引发异常。它以默认格式为自己的响应提供状态代码400(错误请求)。

    有几种方法可以覆盖这一点,包括自定义属性: https://www.jerriepelser.com/blog/validation-response-aspnet-core-webapi/

    看起来是这样的:

    public class ValidateModelAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext context)
        {
            if (!context.ModelState.IsValid)
            {
                context.Result = new ValidationFailedResult(context.ModelState);
            }
        }
    }
    

    然后按如下方式添加:

    [Route("api/values")]
    [ValidateModel]
    public class ValuesController : Controller
    {
    ...
    }
    

    或者您可以通过重写 InvalidModelStateResponseFactory 就像这个问题: How do I customize ASP.Net Core model binding errors?

    下面是一个例子:

    services.Configure<ApiBehaviorOptions>(o =>
    {
        o.InvalidModelStateResponseFactory = actionContext =>
            new MyCustomBadRequestObjectResult(actionContext.ModelState);
    });