特集
» 2013年04月23日 12時30分 公開

特集:ASP.NET 4.5新機能概説(3):ASP.NET MVCの新機能 (4/6)

[花田善仁(監修:山田祥寛),WINGSプロジェクト]

ASP.NET Web APIを実現するフレームワーク

 郵便番号検索など、今ではさまざまなサービスがWeb APIとして公開されてきている。こうしたWeb APIは、スマートデバイス向けのネイティブ・アプリだけではなく、シングル・ページ・アプリのようなWebアプリからでも呼び出されている。

 ASP.NET MVC 4には、このWeb APIを実現する仕組みとして、またRESTfulサービスを実現するプラットフォームとして、「ASP.NET Web API」と呼ばれるフレームワークが追加された。

●ASP.NET Web APIの概要

 ASP.NET Web APIは以下のような機能が実装されている。

  • モダンなHTTPプログラミング・モデル
    − Web APIでは、強く型付けされたHTTPオブジェクト・モデルを使用して、HTTPリクエストとレスポンスを直接操作できる。また、Web APIを呼び出すあらゆる.NETアプリも、新しいHttpClientクラスを使うことで同様のプログラミング・モデルを使える
  • ルーティング
    − Web APIでは、ルート・パラメータや制約を含む、フルセットのルーティング機能をサポートする。さらに単純な規約によってアクションとHTTPメソッドとのマッピングを行えるようになった
  • コンテント・ネゴシエーション
    − Web APIでデータをやりとりするフォーマットにはいくつかの形式がある。この中から最適なフォーマットを選択するために、クライアントとサーバは、お互いに必要な情報を交換することで、いくつかの候補の中から最適なフォーマットを決定できるようになった。デフォルトでサポートされているフォーマットは「XML」「JSON」「URLエンコードされたフォーム」で、さらに開発者が独自フォーマットを追加することも可能となっている
  • モデル・バインディングと検証
    − モデル・バインダを使うと、HTTPリクエストのメッセージ・データからさまざまなデータを抽出し、Web APIのアクションで使用される.NETオブジェクトに変換できる。また、データに付加されたアノテーションを基に、アクション・パラメータの検証も行われる
  • フィルタ
    − Web APIでは、Authorize属性などのフィルタを使用できる。また独自フィルタの作成もサポートされている
  • クエリ・コンポジション
    − IQueryableオブジェクトを返すアクションに対してQueryableフィルタ属性を使用することで、ODataプロトコル(後述)のクエリ規約によるWeb APIへのクエリをサポートできる
  • テスタビリティの改善
    − Web APIは、スタティックなコンテキスト・オブジェクトでHTTPの設定を行うのではなく、HttpRequestMessageインスタンスとHttpResponseMessageインスタンスと動作するように実装されている。このことから単体テストなどを書きやすくなっている
  • コードベースな設定
    − Web APIの設定は、.configファイルに手を入れることなく、コードのみによって行われる
  • IoCコンテナのサポートの改善
    − Web APIはASP.NET MVCで実装されているService Locatorパターンをサポートし、依存性の解決を簡単に行えるようになった。このことによりIoC(Inversion of Control: 制御の反転)コンテナやDI(Dependency Injection: 依存性注入)フレームワークを簡単に組み込むことができる
    − 複雑なWebシステムでは、クライアントからさまざまなサービスを利用するが、サービスを利用するクラス1つ1つで依存関係のあるサービスを管理するのは非常にコストが高くなる。Service Locatorパターンを使用すると、このような依存するサービスの検索を1つのクラスに集約し、保守性を高められる
  • セルフ・ホスティング
    − Web APIはIISだけではなく独自プロセスでもホストできる。この場合でも、ルーティングなど、Web APIの全機能を使用可能
  • カスタム・ヘルプ・ページとテスト・ページの作成
    − 新しいIApiExplorerサービスを使うことで、Web APIのカスタム・ヘルプ・ページとテスト・ページを簡単に作成できる
  • モニタリングと診断
    − Web APIでは、軽量なトレースの仕組みを提供しており、これを使用すると、System.Diagnosticsなどのログ・フレームワークを簡単に統合できる
  • リンク生成
    − UrlHelperを使うことで、同じアプリ内の関連するリソースへのリンクを作成できる
  • Web API用プロジェクト・テンプレート
    − Web APIを簡単に作成するために、ASP.NET MVC 4プロジェクト・ウィザードに、新しくWeb API用のプロジェクト・テンプレートが追加された
  • スキャフォールディング
    − 「コントローラの追加」ダイアログを使うことで、Entity Frameworkを使用したWeb API用のコントローラを作成できるようになった

●ODataアクセスをサポートする機能[2012.2 Update]

 2012.2 Updateでは上記に加えて、Web APIに関連して、いくつかの機能が追加されている。ここではASP.NET Web API ODataについて紹介する。

 OData(Open Data)プロトコル(以降、単に「OData」)は、CRUD(create、read、update、delete)操作を通じてデータセットへの問い合わせと操作を行うための統一的な手法を提供する、Web用のデータ・アクセス・プロトコルだ。また、ODataはXML形式のAtomPubとJSONの両フォーマットをサポートし、扱うデータに関するメタデータを公開する方法を定義する。このメタデータを利用してクライアントは型情報やデータセットの関係について知ることができるようになる。ODataについての仕様などは、http://www.odata.orgを参照されたい。

 Web APIでは、データセットに対してODataに関する操作やエンドポイントの作成などを簡単に行える仕組みが用意されている。

 ここでは、ODataを使用したWeb APIの例を紹介する。具体的なコードは、ODataSampleプロジェクトを参照のこと(ダウンロードはこちらから)。

 このサンプルでは、Personオブジェクトを取得するだけのWeb APIを定義する。まずPersonクラスをModelsフォルダ以下に作成する。Modelsフォルダ上で右クリックし、(表示されるコンテキスト・メニューから)[追加]−[クラス]を選択する(次の画面を参照)。

Modelsフォルダにクラスを追加 Modelsフォルダにクラスを追加

 クライアントからエンティティを指定して検索できるようにするにはエンティティのキーとなるプロパティが必要になる。今回のサンプルでは、次のコードに示すように、IDプロパティをエンティティのキーとして使用する。またこのIDプロパティは、バックエンドのデータベースでは主キーとして利用されることになる。

public class Person
{
  public int ID { get; set; }
  public string FirstName { get; set; }
  public string LastName { get; set; }
}

リスト2 作成したPersonクラス(Person.csファイル)

 次にODataを扱うためのコントローラを実装する。先ほどと同様にControllersフォルダ上で右クリックして今度は[追加]−[コントローラー]を選択する。

 これにより次の画面のようなダイアログが表示される。このダイアログでは、コントローラ名として「PeopleController」を指定している。またEntity Frameworkを使用しないので、スキャフォールディングのオプションにあるテンプレート設定項目には空のAPIコントローラを指定した。

追加するコントローラの設定 追加するコントローラの設定

 次に、ApiControllerクラスを継承している部分を「EntitySetController<Person, int>」クラスを継承するように変更する。ここで指定したEntitySetController<TEntity, TKey>クラスは、ODataのエンティティを公開するために必要な処理を実装しているコントローラで、ODataControllerクラスを継承しており、さらにODataControllerクラスはApiControllerクラスを継承している。

 今回はサンプルということで、Personオブジェクトを静的(static/Shared)なリストで保持し、一覧取得と指定されたキーに対応するPersonオブジェクトを返すメソッドを追加する。

 EntitySetControllerクラスには、これらのメソッドがあらかじめ定義されているので、次の2つのメソッドをオーバーライドして実装する。

  • public override IQueryable<Person> Get()
  • protected override Person GetEntityByKey(int key)

 実装例は以下のようになる。

using ODataSample.Models; // Personクラス
        ……省略……
using System.Web.Http.OData; // EntitySetControllerクラス

namespace ODataSample.Controllers
{
  public class PeopleController : EntitySetController<Person, int>
  {
    static List<Person> people = new List<Person>
    {
      new Person() { ID=1, FirstName="一郎", LastName="田中" },
      new Person() { ID=2, FirstName="二郎", LastName="鈴木" },
      new Person() { ID=3, FirstName="三郎", LastName="山田" },
      new Person() { ID=4, FirstName="四郎", LastName="池田" },
      new Person() { ID=5, FirstName="五郎", LastName="佐藤" },
    };

    public override IQueryable<Person> Get()
    {
      return people.AsQueryable();
    }

    protected override Person GetEntityByKey(int key)
    {
      return people.FirstOrDefault(p => p.ID == key);
    }
  }
}

リスト3 完成したPeopleControllerクラスの実装例(PeopleController.csファイル)

 最後にWeb APIとして外部からアクセスできるようにするために、ルーティングの登録を行う。登録処理を行うコードは、「App_Start\WebApiConfig.cs」ファイルのRegisterメソッドに以下の内容で追加する。

// ODataのエンドポイント用にEDMを作成
ODataModelBuilder modelBuilder = new ODataConventionModelBuilder();
modelBuilder.EntitySet<Person>("People");
Microsoft.Data.Edm.IEdmModel model = modelBuilder.GetEdmModel();

// ルーティング登録
config.Routes.MapODataRoute("ODataRoute", "odata", model);

リスト4 ODataアクセスAPIへのルーティング登録(WebApiConfig.csファイル)

 エンティティ・データ・モデル(EDM)はデータの抽象モデルで、メタデータの作成などに使用される。上記の例では、Personクラスのエンティティ・セットを「People」という名前で登録している。MapODataRouteメソッドでは、ODataのモデルとURIとの対応関係を登録している。

 この例では、Personオブジェクトの一覧情報にアクセスするためのURIは以下のようになる。

http://ホスト名/odata/People

OData経由でオブジェクトにアクセスするためのURL

 ブラウザから上記URIを指定してPersonオブジェクトの一覧情報を取得すると、以下のようなJSON形式データが返ってくる。

{
  "odata.metadata":"http://localhost:60203/odata/$metadata#People","value":[
    {
      "ID":1,"FirstName":"¥u4e00¥u90ce","LastName":"¥u7530¥u4e2d"
    },{
      "ID":2,"FirstName":"¥u4e8c¥u90ce","LastName":"¥u9234¥u6728"
    },{
      "ID":3,"FirstName":"¥u4e09¥u90ce","LastName":"¥u5c71¥u7530"
    },{
      "ID":4,"FirstName":"¥u56db¥u90ce","LastName":"¥u6c60¥u7530"
    },{
      "ID":5,"FirstName":"¥u4e94¥u90ce","LastName":"¥u4f50¥u85e4"
    }
  ]
}

リスト5 「http://ホスト名/odata/People」で取得されるPersonオブジェクトの一覧データ

 次に、「ID=1」のデータを取得するには、次のようにクエリ・パラメータとして「key=1」を追加してブラウザでアクセスする。

http://ホスト名/odata/People?key=1

OData経由で「ID=1」のPersonオブジェクトにアクセスするためのURL

 得られる結果は以下のようになる。

{
  "odata.metadata":"http://localhost:60203/odata/$metadata#People/@Element",
    "ID":1,"FirstName":"¥u4e00¥u90ce","LastName":"¥u7530¥u4e2d"
}

リスト6 「http://ホスト名/odata/People?key=1」で取得されるPersonデータ

Copyright© Digital Advantage Corp. All Rights Reserved.

編集部からのお知らせ

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。