从Asp.Net MVC 6 API返回JSON错误

9

我正在尝试使用MVC 6构建Web API。但是,当我的一个控制器方法抛出错误时,响应的内容是一个非常漂亮格式的HTML页面,如果这是一个MVC应用程序,它将非常有信息价值。但由于这是一个API,我宁愿返回一些JSON。

注意:我的设置目前非常基础,只需设置:

    app.UseStaticFiles();
    app.UseIdentity();

    // Add MVC to the request pipeline.
    app.UseMvc();

我希望能够在整个系统中设置这个。在MVC 6的API中,有没有“正确/最佳”的方法来设置它?

谢谢...

1个回答

13

实现您的情况的一种方法是编写一个 ExceptionFilter,在其中捕获必要的细节并将 Result 设置为 JsonResult

// Here I am creating an attribute so that you can use it on specific controllers/actions if you want to.
public class CustomExceptionFilterAttribute : ExceptionFilterAttribute
{
    public override void OnException(ExceptionContext context)
    {
        var exception = context.Exception;
        context.Result = new JsonResult(/*Your POCO type having necessary details*/)
        {
            StatusCode = (int)HttpStatusCode.InternalServerError
        };
    }
}

您可以将此异常过滤器添加到所有控制器中以使其适用。 例如:

app.UseServices(services =>
{
    services.AddMvc();
    services.Configure<MvcOptions>(options =>
    {
        options.Filters.Add(new CustomExceptionFilterAttribute());
    });
.....
}

请注意,此解决方案并未涵盖所有情况......例如,在格式化程序写响应时抛出异常的情况。


所以我看到的其他方法是:#1:在基本控制器中覆盖OnActionExecuted。和#2:app.UseErrorHandler(“/ Home / Error”)转到控制器方法来处理错误。它们都可以工作,但似乎有点傻。这种方法似乎更好,但是这三种方法都无法处理例如由于错误的URL而导致的简单404。在任何这些方法启动之前就会被捕获。有没有一种拦截所有错误的方法? - swannee
谢谢提供信息。我不确定方法1,需要检查一下。方法2似乎是一个通用的解决方案,适用于在ErrorHandler中间件之后注册的任何中间件,并且当当前请求发生异常时,会重新路由到不同的URL进行处理。查看源代码,似乎这也无法处理格式化程序写入相关的异常。 - Kiran
1
关于您关于捕获404响应的问题。一般情况下,这些不被视为异常,但如果您也想捕获这些响应,则我可以考虑以下选项:1)在路由集合末尾注册一个捕获所有路由,当命中时确认之前的路由都不匹配;2)一个位于MVC之前的中间件,但问题是您无法区分MVC返回的404是由于URL不正确还是例如未找到给定ID的产品而导致的404。 - Kiran
1
这基本上是有效的,但会返回一个200状态码,这不是期望的。您能否使用CustomExceptionFilterAttribute返回500? - Hinrich
@Hinrich 您可以像这样指定JsonResult对象的StatusCode:var jsonResult = new JsonResult(exception); jsonResult.StatusCode = (int)HttpStatusCode.InternalServerError; - Nikolaj Dam Larsen

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