ASP.NET MVC中API异常过滤器在异常情况下返回200响应代码

3
我为我的API编写了一个异常过滤器来处理API中引发的异常:
using System;
using System.Net;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class ApiExceptionFilter : ExceptionFilterAttribute {

    public override void OnException(ExceptionContext context) {

        // First, generate the status code based on the exception type
        HttpStatusCode status = context.Exception switch {
            UnauthorizedAccessException => HttpStatusCode.Unauthorized,
            ArgumentException => HttpStatusCode.BadRequest,
            MissingHeaderException => HttpStatusCode.BadRequest,
            NotFoundException => HttpStatusCode.NotFound,
            _ => HttpStatusCode.InternalServerError,
        };

        // Next, inject the status code and exception message into
        // a new error response and set the result with it
        context.Result = new JsonResult(new ErrorResponse {
            StatusCode = status,
            Message = context.Exception.Message
        });

        // Finally, call the base function
        base.OnException(context);
    }
}

这个函数按预期拦截异常,但我遇到的问题是它总是返回一个OK响应。如何确保响应包含异常消息并且响应代码是非200值?


顺便说一下,我喜欢这个实现。干得好。 - John Glenn
2个回答

5

不要返回JsonResult,因为它没有暴露可设置状态码的属性。取而代之,返回ExceptionResult并设置状态码,如下所示:

context.Result = new ExceptionResult(context.Exception, true)
{ StatusCode = status };

如果您仍然想要使用您的ErrorResponse对象,只需使用一个对象结果:
context.Result = new ObjectResult(new ErrorResponse {
    StatusCode = status,
    Message = context.Exception.Message
    })
    // set status code on result
    { StatusCode = status };

2
在.NET Core/.NET 6上,我们没有ExceptionResult,但是我们仍然可以实现这个目标。我们可以手动为此请求设置状态码。
    public override void OnException(ExceptionContext actionExecutedContext)
    {
        _logger.Error(actionExecutedContext.Exception);
        actionExecutedContext.ExceptionHandled = true;
        actionExecutedContext.HttpContext.Response.StatusCode = StatusCodes.Status500InternalServerError;
        actionExecutedContext.Result = new ObjectResult(new ErrorResponse()
        {
            StatusCode = (HttpStatusCode) StatusCodes.Status500InternalServerError,
            Message = actionExecutedContext.Exception.Message,
        });
        base.OnException(actionExecutedContext);
    }

据我所知,ErrorResponse是您自己的自定义模型。我使用了一个带有StatusCode(HttpStatusCode)和Message(string)的模型。 - Post Impatica

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接