异常处理在 ASP.NET Web API

本文深入探讨了 ASP.NET WebAPI 中错误和异常处理的机制,包括 HttpResponseException、异常筛选器的使用及注册方式,以及如何通过 HttpError 对象返回错误信息。此外,还介绍了如何自定义异常处理逻辑,以及模型验证与 HttpError 的结合使用。

这篇文章描述错误和异常处理在 ASP.NET Web API。

HttpResponseException

如果 Web API 控制器引发未捕获的异常,会发生什么?默认情况下,大多数异常被转译为 HTTP 响应状态代码 500,内部服务器错误。

HttpResponseException型是一种特殊情况。此异常返回您在异常构造函数中指定的所有 HTTP 状态代码。例如,下面的方法返回 404,找不到,如果id参数无效。

public Product GetProduct(int id)
{
    Product item = repository.Get(id);
    if (item == null)
    {
        throw new HttpResponseException(HttpStatusCode.NotFound);
    }
    return item;
}

进行更多控制的响应,你也可以构造整个响应消息,包括它与HttpResponseException:

public Product GetProduct(int id)
{
    Product item = repository.Get(id);
    if (item == null)
    {
        var resp = new HttpResponseMessage(HttpStatusCode.NotFound)
        {
            Content = new StringContent(string.Format("No product with ID = {0}", id)),
            ReasonPhrase = "Product ID Not Found"
        }
        throw new HttpResponseException(resp);
    }
    return item;
}

异常筛选器

您可以自定义 Web API 如何处理异常通过编写的异常筛选器当控制器方法引发任何未处理的异常时执行异常筛选器就是HttpResponseException异常。HttpResponseException型是一种特殊的情况,因为它特别针对返回的 HTTP 响应。

异常筛选器实现System.Web.Http.Filters.IExceptionFilter接口。写异常筛选器的最简单方法是从System.Web.Http.Filters.ExceptionFilterAttribute类派生和重写OnException方法。

在 ASP.NET Web API 的异常筛选器是类似于那些在 ASP.NET MVC 中。然而,他们分别在一个单独的命名空间和函数声明。尤其是,在 MVC 中使用的HandleErrorAttribute类并不处理由 Web API 控制器引发的异常。

这里是一个过滤器,转换未实现的 HTTP 状态代码 501, NotImplementedException例外 ︰

namespace ProductStore.Filters
{
    using System;
    using System.Net;
    using System.Net.Http;
    using System.Web.Http.Filters;

    public class NotImplExceptionFilterAttribute : ExceptionFilterAttribute 
    {
        public override void OnException(HttpActionExecutedContext context)
        {
            if (context.Exception is NotImplementedException)
            {
                context.Response = new HttpResponseMessage(HttpStatusCode.NotImplemented);
            }
        }
    }
}

HttpActionExecutedContext对象的响应属性包含将发送到客户端的 HTTP 响应消息。

注册的异常筛选器

有几种方法来注册 Web API 异常筛选器 ︰

  • 由行动
  • 由控制器
  • 全球

若要将筛选器应用于具体的行动,添加筛选器作为属性行动 ︰

public class ProductsController : ApiController
{
    [NotImplExceptionFilter]
    public Contact GetContact(int id)
    {
        throw new NotImplementedException("This method is not implemented");
    }
}

若要将筛选器应用于所有控制器上的操作,添加筛选器作为属性控制器类 ︰

[NotImplExceptionFilter]
public class ProductsController : ApiController
{
    // ...
}

要将筛选器应用全球 Web API 的所有控制器,请将该筛选器的一个实例添加到GlobalConfiguration.Configuration.Filters集合。核发此集合中的筛选器适用于任何 Web API 控制器动作。

GlobalConfiguration.Configuration.Filters.Add(
    new ProductStore.NotImplExceptionFilterAttribute());

如果你使用"ASP.NET MVC 4 Web 应用程序"项目模板来创建您的项目,把里面的WebApiConfig类,位于 App_Start 文件夹中的 Web API 配置代码 ︰

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        config.Filters.Add(new ProductStore.NotImplExceptionFilterAttribute());

        // Other configuration code...
    }
}

HttpError

HttpError对象提供一致的方法来响应正文中返回错误的信息。下面的示例演示如何返回 HTTP 状态代码 404 (未找到) 与HttpError在响应正文中。

public HttpResponseMessage GetProduct(int id)
{
    Product item = repository.Get(id);
    if (item == null)
    {
        var message = string.Format("Product with id = {0} not found", id);
        return Request.CreateErrorResponse(HttpStatusCode.NotFound, message);
    }
    else
    {
        return Request.CreateResponse(HttpStatusCode.OK, item);
    }
}

CreateErrorResponse是在System.Net.Http.HttpRequestMessageExtensions类中定义的扩展方法。在内部, CreateErrorResponse创建一个HttpError实例,然后创建包含HttpErrorHttpResponseMessage.

在此示例中,如果该方法是成功的它返回的 HTTP 响应中的产品。但如果找不到要求的产品,HTTP 响应包含HttpError请求主体中。响应可能如下所示 ︰

HTTP/1.1 404 Not Found
Content-Type: application/json; charset=utf-8
Date: Thu, 09 Aug 2012 23:27:18 GMT
Content-Length: 51

{
  "Message": "Product with id = 12 not found"
}

HttpError被序列化为 JSON 在此示例中的通知。使用HttpError的优点之一是它穿过任何其他强类型的模型相同的内容协商和序列化进程。

HttpError 和模型验证

对于模型验证,可以将模型状态传递给CreateErrorResponse,要在响应中包含验证错误 ︰

public HttpResponseMessage PostProduct(Product item)
{
    if (!ModelState.IsValid)
    {
        return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
    }

    // Implementation not shown...
}

此示例可能会返回以下响应 ︰

HTTP/1.1 400 Bad Request
Content-Type: application/json; charset=utf-8
Content-Length: 320

{
  "Message": "The request is invalid.",
  "ModelState": {
    "item": [
      "Required property 'Name' not found in JSON. Path '', line 1, position 14."
    ],
    "item.Name": [
      "The Name field is required."
    ],
    "item.Price": [
      "The field Price must be between 0 and 999."
    ]
  }
}

关于模型验证的详细信息,请参见ASP.NET Web API 中的模型验证.

使用 HttpResponseException HttpError

前面的示例返回HttpResponseMessage消息从控制器的操作,但您也可以使用HttpResponseException返回HttpError这允许您返回一个强类型的模型中正常成功的情况,同时还返回HttpError ,如果有错误 ︰

public Product GetProduct(int id)
{
    Product item = repository.Get(id);
    if (item == null)
    {
        var message = string.Format("Product with id = {0} not found", id);
        throw new HttpResponseException(
            Request.CreateErrorResponse(HttpStatusCode.NotFound, message));
    }
    else
    {
        return item;
    }
}

这篇文章的初衷是在 2012 年 3 月 12 日

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值