HttpResponseMessageではなくIHttpActionResultを使用する必要があるのはなぜですか?


326

私はWebApiを使用して開発しており、WebApi2に移動しました。Microsoftは、を返すのではIHttpActionResultなく、使用することをお勧めする新しいインターフェイスを導入しましたHttpResponseMessage。この新しいインターフェイスの利点に戸惑っています。それは主にを作成するための少し簡単な方法を提供するだけのようHttpResponseMessageです。

これは「抽象化のための抽象化」であると私は主張します。何か不足していますか?コード行を保存する以外に、この新しいインターフェイスを使用することで得られる実際の利点は何ですか?

古い方法(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();
    }
}

面白いものを見つけました。これらの結果を他の誰かが検証できるかどうかはわかりません。しかし、いくつかの呼び出しでパフォーマンスが大幅に向上しました。*を使用した例でHttpResponseMessageは、9545 msで応答が返されました。*を使用するIHttpActionResultと、294 msで同じ応答が返されました。
Chris Lesage

@chrislesage 9545 msはほぼ10秒です。294msでも少し遅いです。あなたが100ms以上かかる何かがあるなら、何か他のものがそこで働いています。その物語には、eteに会う以上のものがあります。
AaronLS

回答:


305

IHttpActionResult既存のコードHttpResponseMessageが、定型応答の1つに適合しないを作成するため、使用しないことを決定する場合があります。ただし適応することができますHttpResponseMessageIHttpActionResultの返信定型文を使用してResponseMessage。これを理解するのに少し時間がかかったので、どちらか一方を選択する必要がないことを示して投稿しました。

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、あなたのコントローラから継承する必要があること。


1
ResponseMessageがResponseMessageResultになっていることを確認するのにしばらく時間がかかりました。おそらく最近名前が変更されたのでしょうか?PSまた、回答の新しいキーワードを見逃しており、提案に感謝します:)
Ilya Chernomordik

10
@IlyaChernomordik ResponseMessageResponseMessageResult2つの異なるものです。 ResponseMessage()は、コントローラーが継承する必要があるメソッドApiControllerあるため、単なるメソッド呼び出しです。したがって、newキーワードは必要ありません。おそらく継承していないApiControllerか、静的メソッド内にいます。 ResponseMessageResultの戻り型ですResponseMessage()
AaronLS 2015

3
@IlyaChernomordik私が書かれている可能性がありresponse = base.ResponseMessage(responseMsg)、それがより明確にそれが基本クラスApiControllerの方法であることを確認するために
AaronLS

おかげで、実際にApiControllerから継承されないサービスがありました。そのため、検索に時間がかかりました。
Ilya Chernomordik、2015

3
@pootzkoその通りです。私は、OPが「古い方法」対「新しい方法」としてフレームを作成することにより、2つのアプローチが相互に排他的であると彼らが信じていることを示唆しているように見えたという事実に対処しました。ダレルの答えはIHttpActionResultを返すことの利点のいくつかを説明するのに良い仕事をしていると思います、そして私の答えは古いHttpResponseMessageをIHttpActionResultに変換して両方の世界のベストを得ることができる方法を示しています。
AaronLS、2015年

84

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

私が見たまでつまり、このからサンプルをブラッド・ウィルソンIHttpActionResultチェーン可能な方法でクラスを構築すると、を生成するための「アクションレベル」の応答パイプラインを作成できるようになりますHttpResponseMessage。カバーの下で、これはActionFilters実装方法ですがActionFilters、アクションメソッドを読むとき、それらの順序は明白ではありません。これが、私がアクションフィルターのファンではない理由の1つです。

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


62

ここでは、Microsoft ASP.NetのドキュメントIHttpActionResult過剰にHttpResponseMessage言及されているいくつかの利点を示します

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

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

  • 単一の責任の原則の尊重:アクションメソッドにHTTP要求を処理する責任を持たせ、HTTP応答メッセージの作成に関与させません。
  • 便利な実装ですでにすなわちSystem.Web.Http.Resultsで定義されている:Ok NotFound Exception Unauthorized BadRequest Conflict Redirect InvalidModelState完全なリストへのリンク
  • デフォルトでは非同期と待機を使用します。
  • ExecuteAsyncメソッドを実装するだけで簡単に独自のActionResultを作成できます
  • HttpResponseMessageをIHttpActionResultResponseMessageResult ResponseMessage(HttpResponseMessage response)変換するために使用できます。


18

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

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

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

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

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

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

短い話-それはIHttpActionResult対ではありませんHttpResponseMessage。基本的には、応答を作成する方法です。自分で行うか、工場を通じて行います。


ファクトリの正当化で私が抱えていた問題は、ResponseFactory.CreateOkResponse()HttpResponseMessageを返すような静的メソッドを簡単に作成できることと、応答を作成するときに非同期のものを処理する必要がなかったことです。1人のチームメンバーは、ヘッダー値を生成するためにI / Oを実行する必要がある場合、非同期が有用である可能性があるという事実について言及しました。それがどれほど頻繁に起こるかはわかりません。
Darrel Miller

なぜファクトリメソッドパターンが必要なのかと同じだと思います。静的メソッドを使用してオブジェクトを作成しないのはなぜですか。確かに、それは実行可能です-すべてのオブジェクトの作成が適切なファクトリパターンに値するわけではありません。しかし、IMHOは、クラスのモデル化方法に依存します。複数の静的メソッドの形式でクラスに詰め込まれたさまざまなタイプの応答を作成するロジックが必要ですか、それともインターフェースに基づいてさまざまなクラスが必要ですか?繰り返しますが、良い点も悪い点もありません。それはすべて異なります。とにかく、私のポイントは、それは互いに重なっていないということであり、私は個人的に工場のものがより好きです:)
バドリ

6

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

IHttpActionResultのラップの一種であるWebAPIの2で導入されましたHttpResponseMessageExecuteAsync()を作成するメソッドが含まれていますHttpResponseMessage。コントローラの単体テストを簡素化します。

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


3

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はペイロードです。


2

IHttpActionResultover を使用する ことには、次の利点がありますHttpResponseMessage

  1. を使用するIHttpActionResultことで、ステータスコードではなく、送信されるデータのみに集中しています。したがって、ここではコードがより簡潔になり、保守が非常に簡単になります。
  2. 実装されたコントローラーメソッドの単体テストが容易になります。
  3. asyncおよびawaitをデフォルトで使用します。
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.