検索
連載

第3回 APIコントローラの実装方法連載:ASP.NET Web API 入門(3/3 ページ)

RESTfulなWeb APIを実装してみよう。ASP.NET Web API 2を使えば、実践的なHTTPサービスが容易に実装できる点に注目してほしい。

PC用表示 関連情報
Share
Tweet
LINE
Hatena
前のページへ |       

2-4 HTTPレスポンスの内容を指定する

画像:図6 HTTPレスポンスの内容の指定方法を表した概要図
図6 HTTPレスポンスの内容の指定方法を表した概要図

 HTTPレスポンスの内容は、アクション・メソッドの戻り値の型で表し、APIの処理を実行した後に戻り値のインスタンスを返すことで、HTTPレスポンスの内容を指定できる。

 またもう1つの方法として、特定の例外クラスをスローすることでもHTTPレスポンスの内容を指定できる。アクション・メソッド内でHttpResponseExceptionクラス(System.Web.Http名前空間)のインスタンスをスローすることで可能になる(後述するが、このときに構築されるHTTPレスポンスの中身は、必ずしもエラーを表すものではないことと、通常の.NET Frameworkの例外とは扱いが異なるので注意)。

 ASP.NET Web APIではこれら2つの方法を組み合わせることで、HTTPレスポンスの柔軟な操作が可能になる。HTTPレスポンスの指定方法と、実際に構築されるHTTPレスポンスの内容を下の表8、9にまとめた。

メソッドの戻り値の型 構築されるHTTPレスポンスの内容
Void ステータス・コード: 204 No Content
void, HttpResponseMessage以外の型(独自クラスやプリミティブ型など) ステータス・コード: 200 OK
Body:戻り値の値を書式で変換した値が格納される
HttpResponseMessage HttpResponseMessageクラスのプロパティで表される
表8 HTTPレスポンスの内容を、メソッドの戻り値の型で表す場合
・バージョン2では、「IHttpActionResult」クラスを戻り値に指定する方法が追加されている。
・非同期を利用する場合、戻り値の型にはTask<T>クラス(System.Threading.Tasks名前空間)も指定できる。この場合に構築されるHTTPレスポンスは、表のとおり、型パラメータ(Tに指定した型)に対応するものとなる。

メソッド内 構築されるHTTPレスポンスの内容
HttpResponseExceptionをスローする HttpResponseExceptionクラスのResponseプロパティ(HttpResponseMessage型)で表される
表9 HTTPレスポンスを、例外をスローすることで表す場合

 以降、サンプル・コードと共にそれぞれのHTTPレスポンスの指定方法と、どのようなときに利用できるかを解説していく。

○ 戻り値にvoidを指定する

 下のコードのように、アクション・メソッドの戻り値にvoidを指定すると、ステータス・コード「201 No Content」がクライアントへ返される。

public void Delete()
{
}

リスト8 アクション・メソッドの戻り値にvoidを指定したコード

 データの更新や削除などの処理を行うAPIにて、処理は成功したが、クライアントへ返すべき情報がない場合に、voidを指定するとよいだろう。

○ 戻り値にvoid/HttpResponseMessage以外の型を指定する

 この方法は、クライアントへ何らかのリソースを返したい場合に利用する。戻り値には、リソースを表す型を指定する。構築されるHTTPレスポンスは、ステータス・コードが「200 OK」、Bodyには戻り値を適切な書式(JSONやXMLなど)で変換された値が格納される**11

*11Bodyへ格納するときに行われる変換の書式は、HTTPリクエストの内容(デフォルトでは、ヘッダ「Accept」の値)によって選択される。


 リスト9と表10は、アクション・メソッドの戻り値に文字列型を指定した場合の例。リスト10と表11はPerson(独自クラス)データのコレクション型を指定した場合の例である。

public string GetName()
{
  return "taro";
}

リスト9 String型の戻り値を返す例

ステータス・コード 200 OK
Body(JSON形式の場合) "taro"
表10 戻り値の型にString型を指定した場合に返されるHTTPレスポンスの例

public class Person
{
  public int Id { get; set; }
  public string Name { get; set; }
}

public class PersonsController : ApiController
{
  public IEnumerable<Person> Get()
  {
    var list = new List<Person>()
      {
        new Person() { Id = 1, Name = "taro" },
        new Person() { Id = 2, Name = "hanako" }
      };
    return list;
  }
}

リスト10 Personデータのコレクションを返す例

ステータス・コード 200 OK
Body(JSON形式の場合) [{"Id":1,"Name":"taro"},{"Id":2,"Name":"hanako"}]
表11 戻り値の型にIEnumerable<Person>を指定した場合に返されるHTTPレスポンスの例

 都度、独自クラスを用意することが手間である場合は、JSON形式に限り、下のように匿名型を利用することもできる(XML形式に変換される場合、変換するコンポーネントが匿名型のシリアライズに対応していないため、エラーが発生するので注意)。

public object Get()
{
  string[] members = new string[] {"taro", "hanako"};
  return new { name = "groupA", members = members };
}

リスト11 object型を返す例

ステータス・コード 200 OK
Body(JSON形式の場合) {"name":"groupA","members":["taro","hanako"]}
表12 戻り値を匿名型で指定した場合に返されるHTTPレスポンスの例

 これらの方法は、例えばHTTPメソッド「GET」で何らかのリソースを返すAPIでよく利用される。任意の型を指定できるので、クライアントへ返したいリソースに合わせて、独自クラスや、String型、コレクション型など、さまざまな型を指定できることが利点だ。

○ 戻り値にHttpResponseMessageを指定する

 この方法は、返したいHTTPレスポンスの内容を詳細に制御したい場合に利用する。HttpResponseMessageクラスの生成は、コンストラクタより生成することが可能だが、ApiControllerクラスのRequestプロパティから、拡張メソッド*12を利用して生成するとよいだろう。

*12System.Net.Http名前空間で定義されているHttpRequestMessageExtensionsメソッド


 以下のリストは、それぞれ各種ステータス・コードを指定して、HttpResponseMessage型の戻り値を返している例だ。このとき、リソースを組み合わせて返したり(リスト13)、ヘッダ情報を付け加えて返したり(リスト14)できる。

public HttpResponseMessage Get()
{
  return Request.CreateResponse(HttpStatusCode.NotFound);
}

リスト12 ステータス・コード「404 Not Found」を返す例

public HttpResponseMessage Get()
{
  var person = new Person() { Name = "taro" };
  return Request.CreateResponse(HttpStatusCode.OK, person);
}

リスト13 ステータス・コード「200 OK」と、リソース(ここではPerson型のデータ)を返す例

public HttpResponseMessage Post()
{
  var customer = new Customer();
  HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Created, customer);
  response.Headers.Location = new Uri(Url.Link("DefaultApi", new { id = customer.Id }));
  return response;
}

リスト14 ヘッダ「Location」の値を指定して返す例

○ HttpResponseExceptionをスローする

 次は、戻り値の型ではなく、HttpResponseExceptionクラスのインスタンスをスローしてHTTPレスポンスの内容を指定する方法だ。

 この方法は、APIの処理の途中で、正常に処理が終了した場合のHTTPレスポンスとは別の内容を返したいときに利用できる。例えば、顧客APIコントローラ・クラスでも記述されている以下のコードが事例の1つである。

public Customer GetCustomer(int id)
{
  // Customersテーブルから、idが一致するデータを取得
  Customer customer = db.Customers.Find(id);
  if (customer == null)
  {
    // 一致するデータ存在しない場合は、ステータス・コード404を返す
    throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound)); // ……(1)
  }
  // Customerデータを返す
  return customer;
}

リスト15 APIの処理の途中で正常に終了しなかった場合に、HttpResponseExceptionオブジェクトを返すコード例
  (1)HttpResponseExceptionクラスのインスタンスをスローしている。

 このリスト15に記述されているAPIの主な処理は、URLで指定されたIdと同じIdを持つ顧客データを返すことだ。だが、該当する顧客データが存在しない場合は、ステータス・コード「404 Not Found」を返すという処理も行う。

 この場合、これまで解説した戻り値の型を指定する方法では、下のリスト16のように、戻り値の型にHttpResponseMessageを指定して、HTTPレスポンスの内容を指定するであろう。

public HttpResponseMessage /* ……(1) */ GetCustomer(int id)
{
  // ……省略……
  if (customer == null)
  {
    // 一致するデータ存在しない場合は、ステータスコード404を返す
    return Request.CreateResponse(HttpStatusCode.NotFound); // ……(2)
  }
  // Customerデータを返す
  return Request.CreateResponse(HttpStatusCode.OK, customer); // ……(2)
}

リスト16 戻り値の型にHttpResponseMessageを指定した場合のコード例(非推奨)
同じ振る舞いが定義されたAPIのコードであるリスト15とは違い、アクション・メソッドの戻り値の型にHttpResponseMessageクラスを指定し((1))、顧客データの存在の有無に関わらずHttpResponseMessageクラスのインスタンスを返している((2))。

 もちろんこの方法でも正常に動作するが、この場合はコード15ように、HttpResponseExceptionオブジェクトをスローする方法を推奨する。なぜなら、戻り値の型にHttpResponseMessageクラスではなく、顧客データを表すCustomerクラスを指定することにより、処理が成功した場合は顧客データを返すことを表現し、データが存在しないといったように処理が成功しない場合は、成功時とは違うHTTPレスポンスを返す、ということを表現できるからだ。

 このように戻り値の型でAPIの本来の目的を表現することは、人間の目だけではなくプログラムの目にとっても有効である。ヘルプ・ページの自動生成*13など、APIの定義をプログラムから読み取ることは少なくない。ぜひとも、このHttpResponseExceptionオブジェクトのスローを活用してほしい。

*13ASP.NET Web APIのヘルプ・ページについては、「ASP.NET MVCの新機能」を参考のこと。


 説明が長くなってしまったが、HttpResponseExceptionオブジェクトをスローする利点を把握したところで、サンプル・コードと共に実装方法を確認しよう。

 HttpResponseExceptionクラスは、以下のリストに示すように、コンストラクタからインスタンスを生成する。このときも、リソースを組み合わせて返したり(リスト17、リスト18)できる。

public string Get()
{
  throw new HttpResponseException(HttpStatusCode.NotFound);
}

リスト17 ステータス・コード「404 Not Found」を返す例

public string Get()
{
  var person = new Person() { Name = " Taro" };
  HttpResponseMessage reponse = Request.CreateResponse(HttpStatusCode.OK, person);
  throw new HttpResponseException(reponse);
}

リスト18 ステータス・コード「200 OK」と、リソース(ここではPerson型のデータ)を返す例

補足: HttpResponseExceptionクラスとそのほかのExceptionクラスについて

 アクション・メソッド内にて、HttpResponseExceptionクラス以外の例外クラスがスローされた場合は、ASP.NET Web APIフレームワークによって、ステータス・コード「500 Internal Server Error」のHTTPレスポンスが返される。これは、例外処理を行う場合に利用する仕組みだ。同じ例外クラスでも、HttpResponseExceptionクラスとそのほかの例外クラスでは、挙動と目的が違うので注意してほしい。


 APIコントローラの実装についての解説は以上になる。ASP.NET Web APIにおける最低限必要になる実装の詳細な紹介は、あと残すところ「ルーティングの設定」のみだ。


 本稿では、ASP.NET Web APIの最低限必要となる実装の内の1つである「APIコントローラの実装」についての解説を行った。次回からは、「ルーティングの設定」と、ASP.NET Web APIの特徴を生かした実装について解説を行う予定だ。

「連載:ASP.NET Web API 入門」のインデックス

連載:ASP.NET Web API 入門

Copyright© Digital Advantage Corp. All Rights Reserved.

前のページへ |       
ページトップに戻る