zoukankan      html  css  js  c++  java
  • [翻译] ASP.NET WebAPI 中的异常处理

    原文链接:https://docs.microsoft.com/en-us/aspnet/web-api/overview/error-handling/exception-handling


    本文介绍了在 ASP.NET Web API 中的错误和异常处理

    • HttpResponseException
    • Exception Filters
    • Registering Exception Filters
    • HttpError

    HttpResponseMessage

    如果一个 Web API 控制器抛出一个未处理的异常会发生什么?默认情况,大多数异常会被转换为 HTTP 响应,状态码为500(服务器内部错误)。

    HttpResponseMessage 类型是一种特殊情况。该异常返回异常构造函数中指定的任何 HTTP 状态码。例如,以下方法中如果 id 无效,则返回 404(找不到指定的资源)。

    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 响应。

    ASP.NET Web API 中的异常过滤器和 ASP.NET MVC 中的异常过滤器很相似。但是,但是,它们分别声明在单独的命名空间和函数中。特别地,MVC中使用的HandleErrorAttribute 类不处理 Web API 控制器抛出的异常。

    这里有一个过滤器,将**NotImplementedException **异常转换为 HTTP 状态码 501 ---- 未被实现:

    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 ** 对象的 **Response **属性包含将被发送给客户端的响应消息。

    注册异常过滤器

    有集中方法注册 Web API 异常过滤器:

    • 通过 Action
    • 通过 Controller
    • 全局

    为指定的 Action 应用过滤器:

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

    为 Controller 的所有 Action应用过滤器:

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

    为全局所有的 Web API Controller 应用过滤器,要在 GlobalConfiguration.Configuration.Filters 集合中添加一个过滤器实例。 在这个集合中的异常过滤器应用到任何 Web API Controller 的 Action:

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

    如果你是用 "ASP.NET MVC 4 Web Application" 项目模版创建的项目,把 Web API 配置代码放在 WebApiConfig 类中,该类位于 App_Start 文件夹里:

    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            config.Filters.Add(new ProductStore.NotImplExceptionFilterAttribute());
    
            // Other configuration code...
        }
    }
    

    HttpError

    HttpError 对象提供了一种在响应正文中返回错误信息的一致方法。以下示例显示如何在响应正文中返回HttpError的HTTP状态代码404(找不到)。

    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);
        }
    }
    

    CreateErrorResponseSystem.Net.Http.HttpRequestMessageExtensions 类的一个扩展方法,在内部 CreateErrorResponse 构建一个 HttpError 实例,然后创建一个包含 HttpError 的 **HttpResponseMessage **。

    在下面例子中,如果方法成功将在 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 and Model Validation

    对模型验证来说,你可以把模型状态传给 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."
        ]
      }
    }
    

    更多关于模型绑定的信息,请参见Model Validation in ASP.NET Web API

    和 HttpResponseException 一起使用 HttpError

    前面的示例,从控制器的 Action 返回一个 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;
        }
    }
    
  • 相关阅读:
    hdu 1873 看病要排队
    母函数详解
    【RDMA】无损网络和PFC(基于优先级的流量控制)
    图解Linux网络包接收过程
    结对编程 <==> 断背山?
    CMPP和SMPP协议比较
    Berkerly DB、SQL Server的性能比较
    使用Berkeley DB遇到问题了
    重新学习C语言
    超长短信的处理办法
  • 原文地址:https://www.cnblogs.com/songxingzheng/p/6478454.html
Copyright © 2011-2022 走看看