web-dev-qa-db-ja.com

HttpResponseMessageの代わりにIHttpActionResultを使うべきなのはなぜですか?

私はWebApiを使って開発しており、MicrosoftがIHttpActionResultを返す代わりに使用することをお勧めすると思われる新しいHttpResponseMessageインターフェースを導入したWebApi2に移行しました。私はこの新しいインターフェースの利点について混乱しています。 HttpResponseMessageを作成するための _わずかに_ 簡単な方法を主に提供するだけのようです。

これは「抽象化のための抽象化」であると私は主張します。私は何かが足りないのですか? 1行のコードを節約するだけでなく、この新しいインターフェースを使用することで得られる現実的な利点は何ですか?

昔の方法 (WebApi):

public HttpResponseMessage Delete(int id)
{
    var status = _Repository.DeleteCustomer(id);
    if (status)
    {
        return new HttpResponseMessage(HttpStatusCode.OK);
    }
    else
    {
        throw new HttpResponseException(HttpStatusCode.NotFound);
    }
}

ニューウェイ (WebApi2):

public IHttpActionResult Delete(int id)
{
    var status = _Repository.DeleteCustomer(id);
    if (status)
    {
        //return new HttpResponseMessage(HttpStatusCode.OK);
        return Ok();
    }
    else
    {
        //throw new HttpResponseException(HttpStatusCode.NotFound);
        return NotFound();
    }
}
298
Jason Roell

既存のコードでは、定型化された応答の1つに適合しないIHttpActionResultが作成されるため、HttpResponseMessageを使用しないことを決定することがあります。ただし、HttpResponseMessageの応答を使用してIHttpActionResultResponseMessageに適合させることはできます。これを理解するのにしばらく時間がかかったので、私はそれを投稿したいと思いました。

public IHttpActionResult SomeAction()
{
   IHttpActionResult response;
   //we want a 303 with the ability to set location
   HttpResponseMessage responseMsg = new HttpResponseMessage(HttpStatusCode.RedirectMethod);
   responseMsg.Headers.Location = new Uri("http://customLocation.blah");
   response = ResponseMessage(responseMsg);
   return response;
}

ResponseMessageは、コントローラが継承する必要がある基本クラスApiControllerのメソッドです。

280
AaronLS

HttpResponseMessageを引き続き使用できます。その機能はなくなりません。私はあなたと同じように感じ、追加の抽象化の必要はないとチームと広く議論しました。その存在を正当化しようとするいくつかの議論がありましたが、価値があると私を納得させるものはありませんでした。

つまり、 thisBrad Wilsonからのサンプルを見るまでです。連鎖可能な方法でIHttpActionResultクラスを構築すると、 "action-level"応答パイプラインを作成することができますHttpResponseMessageを生成します。カバーの下では、これがActionFiltersの実装方法ですが、アクションメソッドを読むとき、それらのActionFiltersの順序は明らかではありません。

ただし、アクションメソッドで明示的にチェーンできるIHttpActionResultを作成することにより、あらゆる種類の異なる動作を構成して応答を生成できます。

83
Darrel Miller

Microsoft ASP.Net Documentation で言及されているIHttpActionResultに対するHttpResponseMessageのいくつかの利点を以下に示します。

  • コントローラーの単体テストを簡素化します。
  • HTTP応答を作成するための共通ロジックを個別のクラスに移動します。
  • 応答の構築の低レベルの詳細を隠すことにより、コントローラーアクションの意図を明確にします。

しかし、ここに言及する価値のあるIHttpActionResultを使用する他の利点がいくつかあります。

  • 単一の責任原則を尊重する:アクションメソッドにHTTPリクエストを処理する責任を持たせ、HTTP応答メッセージの作成には関与させません。
  • System.Web.Http.Resultsで既に定義されている有用な実装OkNotFoundExceptionUnauthorizedBadRequestConflictRedirectInvalidModelState全リストへのリンク
  • デフォルトではAsyncおよびAwaitを使用します。
  • ExecuteAsyncメソッドを実装するだけで、独自のActionResultを簡単に作成できます。
  • ResponseMessageResult ResponseMessage(HttpResponseMessage response)を使用して、HttpResponseMessageをIHttpActionResultに変換できます。
59
// this will return HttpResponseMessage as IHttpActionResult
return ResponseMessage(httpResponseMessage); 
30
Adam Tal

これは私の個人的な意見であり、Web APIチームの人々はおそらくそれをより明確に表現することができますが、これは私の2cです。

まず第一に、私はそれが相互の問題ではないと思います。アクションメソッドで何をしたいのかに応じて両方を使用することができますが、IHttpActionResultの本当の力を理解するためには、おそらくApiControllerOkなどの便利なNotFoundのヘルパーメソッドから外れる必要があります。

基本的に、私はIHttpActionResultHttpResponseMessageのファクトリとして実装するクラスだと思います。その考え方で、それは今や返されるべきオブジェクトとそれを生み出すファクトリーになります。一般的なプログラミングの意味では、特定の場合にはオブジェクトを自分で作成できます。特定の場合には、それを行うためのファクトリが必要です。こっちも一緒。

たくさんのレスポンスヘッダなど、複雑なロジックで構築する必要があるレスポンスを返したい場合は、それらすべてのロジックをIHttpActionResultを実装したアクション結果クラスに抽象化し、それを複数のアクションメソッドで使用してレスポンスを返すことができます。

戻り値の型としてIHttpActionResultを使用するもう1つの利点は、ASP.NET Web APIのアクションメソッドがMVCに似ていることです。メディアフォーマッタに巻き込まれることなく、あらゆるアクション結果を返すことができます。

もちろん、Darrelが指摘したように、アクションの結果を連鎖させて、APIパイプラインのメッセージハンドラ自体に似た強力なマイクロパイプラインを作成することができます。これはあなたのアクションメソッドの複雑さに応じて必要になります。

長い話を短くするとIHttpActionResultHttpResponseMessageではありません。基本的に、それはあなたが応答を作成したい方法です。それをあなた自身または工場を通して行いなさい。

16
Badri

Web APIは基本的に4つのタイプのオブジェクトを返します:voidHttpResponseMessageIHttpActionResult、その他の強い型です。 Web APIの最初のバージョンはHttpResponseMessageを返します。これはかなり単純なHTTP応答メッセージです。

IHttpActionResultはWebAPI 2によって導入されました。これはHttpResponseMessageの一種のラップです。 HttpResponseMessageを作成するExecuteAsync()メソッドが含まれています。それはあなたのコントローラのユニットテストを簡単にします。

その他の戻り型は、メディアフォーマッタを使用してレスポンスボディにWeb APIによってシリアル化された一種の強力な型指定クラスです。欠点は、404のようなエラーコードを直接返すことができないということでした。あなたがすることができるのはHttpResponseExceptionエラーを投げることだけです。

5
Peter.Wang

私はむしろIHttpActionResultのためにTaskExecuteAsyncインターフェース関数を実装したいと思います。何かのようなもの:

    public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
    {
        var response = _request.CreateResponse(HttpStatusCode.InternalServerError, _respContent);

        switch ((Int32)_respContent.Code)
        { 
            case 1:
            case 6:
            case 7:
                response = _request.CreateResponse(HttpStatusCode.InternalServerError, _respContent);
                break;
            case 2:
            case 3:
            case 4:
                response = _request.CreateResponse(HttpStatusCode.BadRequest, _respContent);
                break;
        } 

        return Task.FromResult(response);
    }

ここで、_requestはHttpRequest、_respContentはペイロードです。

3
appletwo

IHttpActionResultよりHttpResponseMessageを使用することには、次のような利点があります。

  1. IHttpActionResultを使用することによって、ステータスコードではなく送信されるデータのみに集中しています。そのため、ここではコードがきれいになり、保守が非常に簡単になります。
  2. 実装されたコントローラーメソッドの単体テストはより簡単になります。
  3. デフォルトでasyncawaitを使用します。
1
Debendra Dash