[翻訳]ASP.NET WebAPIでの例外処理

6481 ワード

テキストリンク: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
  • を通過
  • グローバル
  • 指定したアクションにフィルタを適用します.
    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 Controlにフィルタを適用するには、GlobalConfiguration.Configuration.Filtersコレクションにフィルタインスタンスを追加します.このセット内の例外フィルタは、任意のWeb API ControllerのActionに適用されます.
    GlobalConfiguration.Configuration.Filters.Add(
        new ProductStore.NotImplExceptionFilterAttribute());

    「ASP.NET MVC 4 Webアプリケーション」プロジェクトテンプレートで作成したプロジェクトの場合、Web API構成コードをWebApiConfigクラスに配置します.このクラスはApp_にあります.スタートフォルダ:
    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);
        }
    }

    CreateErrorResponseはSystemです.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を用いた1つの利点は,他の任意の強いタイプのモデルと同じコンテンツネゴシエーションとシーケンス化プロセスを経験することである.

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

    転載先:https://www.cnblogs.com/songxingzheng/p/6478454.html