私は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();
}
}
既存のコードでは、定型化された応答の1つに適合しないIHttpActionResult
が作成されるため、HttpResponseMessage
を使用しないことを決定することがあります。ただし、HttpResponseMessage
の応答を使用してIHttpActionResult
を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
のメソッドです。
HttpResponseMessage
を引き続き使用できます。その機能はなくなりません。私はあなたと同じように感じ、追加の抽象化の必要はないとチームと広く議論しました。その存在を正当化しようとするいくつかの議論がありましたが、価値があると私を納得させるものはありませんでした。
つまり、 thisBrad Wilsonからのサンプルを見るまでです。連鎖可能な方法でIHttpActionResult
クラスを構築すると、 "action-level"応答パイプラインを作成することができますHttpResponseMessage
を生成します。カバーの下では、これがActionFilters
の実装方法ですが、アクションメソッドを読むとき、それらのActionFilters
の順序は明らかではありません。
ただし、アクションメソッドで明示的にチェーンできるIHttpActionResult
を作成することにより、あらゆる種類の異なる動作を構成して応答を生成できます。
Microsoft ASP.Net Documentation で言及されているIHttpActionResult
に対するHttpResponseMessage
のいくつかの利点を以下に示します。
- コントローラーの単体テストを簡素化します。
- HTTP応答を作成するための共通ロジックを個別のクラスに移動します。
- 応答の構築の低レベルの詳細を隠すことにより、コントローラーアクションの意図を明確にします。
しかし、ここに言及する価値のあるIHttpActionResult
を使用する他の利点がいくつかあります。
Ok
NotFound
Exception
Unauthorized
BadRequest
Conflict
Redirect
InvalidModelState
( 全リストへのリンク )ExecuteAsync
メソッドを実装するだけで、独自のActionResultを簡単に作成できます。ResponseMessageResult ResponseMessage(HttpResponseMessage response)
を使用して、HttpResponseMessageをIHttpActionResultに変換できます。// this will return HttpResponseMessage as IHttpActionResult
return ResponseMessage(httpResponseMessage);
これは私の個人的な意見であり、Web APIチームの人々はおそらくそれをより明確に表現することができますが、これは私の2cです。
まず第一に、私はそれが相互の問題ではないと思います。アクションメソッドで何をしたいのかに応じて両方を使用することができますが、IHttpActionResult
の本当の力を理解するためには、おそらくApiController
、Ok
などの便利なNotFound
のヘルパーメソッドから外れる必要があります。
基本的に、私はIHttpActionResult
をHttpResponseMessage
のファクトリとして実装するクラスだと思います。その考え方で、それは今や返されるべきオブジェクトとそれを生み出すファクトリーになります。一般的なプログラミングの意味では、特定の場合にはオブジェクトを自分で作成できます。特定の場合には、それを行うためのファクトリが必要です。こっちも一緒。
たくさんのレスポンスヘッダなど、複雑なロジックで構築する必要があるレスポンスを返したい場合は、それらすべてのロジックをIHttpActionResult
を実装したアクション結果クラスに抽象化し、それを複数のアクションメソッドで使用してレスポンスを返すことができます。
戻り値の型としてIHttpActionResult
を使用するもう1つの利点は、ASP.NET Web APIのアクションメソッドがMVCに似ていることです。メディアフォーマッタに巻き込まれることなく、あらゆるアクション結果を返すことができます。
もちろん、Darrelが指摘したように、アクションの結果を連鎖させて、APIパイプラインのメッセージハンドラ自体に似た強力なマイクロパイプラインを作成することができます。これはあなたのアクションメソッドの複雑さに応じて必要になります。
長い話を短くするとIHttpActionResult
対HttpResponseMessage
ではありません。基本的に、それはあなたが応答を作成したい方法です。それをあなた自身または工場を通して行いなさい。
Web APIは基本的に4つのタイプのオブジェクトを返します:void
、HttpResponseMessage
、IHttpActionResult
、その他の強い型です。 Web APIの最初のバージョンはHttpResponseMessage
を返します。これはかなり単純なHTTP応答メッセージです。
IHttpActionResult
はWebAPI 2によって導入されました。これはHttpResponseMessage
の一種のラップです。 HttpResponseMessage
を作成するExecuteAsync()
メソッドが含まれています。それはあなたのコントローラのユニットテストを簡単にします。
その他の戻り型は、メディアフォーマッタを使用してレスポンスボディにWeb APIによってシリアル化された一種の強力な型指定クラスです。欠点は、404のようなエラーコードを直接返すことができないということでした。あなたがすることができるのはHttpResponseException
エラーを投げることだけです。
私はむしろ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はペイロードです。
IHttpActionResult
よりHttpResponseMessage
を使用することには、次のような利点があります。
IHttpActionResult
を使用することによって、ステータスコードではなく送信されるデータのみに集中しています。そのため、ここではコードがきれいになり、保守が非常に簡単になります。async
とawait
を使用します。