ASP.NET Web API を使ってみよう: MVC 4 新機能シリーズ

ASP.NET MVC 4 Beta では、ASP.NET Web API という新しいフレームワークが追加されました。この ASP.NET Web API (以後 Web API と記します) は、ブラウザーやモバイルデバイスを含むさまざまなクライアントに対して RESTful なサービスを提供するのに適した HTTP サービス構築用のフレームワークです。まずは以下に ASP.NET MVC 4 Beta リリース ノートASP.NET Web API 項目の簡約を記載します。

  • 最新の HTTP プログラミングモデル
    Web API では、新しい強く型付けされた HTTP オブジェクトモデルを使って HTTP リクエストとレスポンスを直接操作できます。
  • ルーティングのフルサポート
    Web API は、ルートパラメーターや制約などの URL ルーティングの全機能をサポートします。加えて、規約によるアクションへのマッピングをサポートします。したがって、[HttpPost] などの属性をクラスやメソッドに付加する必要がありません。
  • Content negotiation
    クライアントとサーバーは、API から返されるデータの最適なフォーマットを決定して協調動作します。デフォルトでは、XML, JSON, Form URL encoded formats をサポートし、カスタムフォーマッタ―を追加して拡張も可能です。また、デフォルトの Content negotiation strategy を置き換えることさえ可能です。
  • モデルバインディングと検証
    モデルバインダーは HTTP リクエストのメッセージデータを Web API アクションで使われる .NET オブジェクトに簡単にバインドすることができます。
  • アクションフィルター
    Web API は [Authorize] 属性などのアクションフィルターをサポートします。また、カスタムアクションフィルターも作成して使用することができます。
  • Query composition
    Web API は、IQueryable<T> を返すことで簡単に OData の URL 規約によるクエリーをサポートできます。
  • Improved testability of HTTP details
    Web API アクションは HttpRequestMessage と HttpResponseMessage のインスタンスと共に動作します。また、これらのオブジェクトのジェネリック版を使うことで、HTTP タイプにカスタムタイプを追加することもできます。
  • Improved Inversion of Control (IoC) via DependencyResolver
    Web API は MVC の dependency resolver で用いられる Service locator pattern を使います。
  • Code-based configuration
    Web API の設定はコードでのみ行います。config ファイルは用いません。
  • Self-host
    Web API はルーティングやその他の Web API の機能を使いながら、IIS に加えて独自プロセスでもホストさせることができます。

 

ASP.NET Web API を使った HTTP サービスの作成

それではここで、ASP.NET Web API を使ってシンプルな HTTP サービスを作成してみます。

1. 新しい Web API プロジェクトの作成

Visual Studio 2010 のメニュー [新しいプロジェクト] で “ASP.NET MVC 4 Web Application” を選び、プロジェクト名を入力します。今回も こちらのブログ記事 "Web API を始めてみよう" に合わせて “SuperHero2” としてプロジェクトを作成しました。

NewProject

続いて表示される [New ASP.NET MVC 4 Project] ダイアログで、”Web API” を選択します。

SelectWebAPI

プロジェクトが作成されると、Web API 用のコントローラー ValuesController.cs がデフォルトで生成されます。この ValuesController では、GET, POST, PUT, DELETE に対応したアクションメソッドが用意されていると共に、ApiController クラスの派生クラスとなっていることが分かります。通常の ASP.NET MVC のコントローラーでは Controller クラスからの派生クラスとなりますので、まずはここが大きく異なるところになります (下記コード参照) 。

    1: namespace SuperHero2.Controllers
    2: {
    3:     public class ValuesController : ApiController
    4:     {
    5:         // GET /api/values
    6:         public IEnumerable<string> Get()
    7:         {
    8:             return new string[] { "value1", "value2" };
    9:         }
   10:  
   11:         // GET /api/values/5
   12:         public string Get(int id)
   13:         {
   14:             return "value";
   15:         }
   16:  
   17:         // POST /api/values
   18:         public void Post(string value)
   19:         {
   20:         }
   21:  
   22:         // PUT /api/values/5
   23:         public void Put(int id, string value)
   24:         {
   25:         }
   26:  
   27:         // DELETE /api/values/5
   28:         public void Delete(int id)
   29:         {
   30:         }
   31:     }
   32: }

2. モデルの追加

続いて、API を通して提供するデータを表した POCO (Plain-old CLR Object) クラスを作ります。このクラスのオブジェクトがモデルとして、Web API で JSON や XML などのフォーマットにシリアライズされクライアントサイドに提供されるデータとなります。

ソリューションエクスプローラーの Models フォルダー上で右クリックして、[追加] - [クラス] から Hero.cs を作り、下記のコードを記述します。

AddModel 

    1: namespace SuperHero2.Models
    2: {
    3:     public class Hero
    4:     {
    5:         public int Id { get; set; }
    6:         public string Name { get; set; }
    7:     }
    8: }

3. コントローラ Get アクションの実装

ここで、デフォルトで生成された ValuesController.cs の名前をモデル名に合わせて HeroesController.cs にリネームしておきます。「ファイルの名前を変更しようとしています。このプロジェクトのコード要素 ‘ValuesController’ への参照をすべて変更しますか?」のメッセージボックスが表示されたら [はい] をクリックします。ファイル名を変更するだけで、コード内のクラス名も HeroesController に変更されます。

Rename2

    1: namespace SuperHero2.Controllers
    2: {
    3:     public class HeroesController : ApiController
    4:     {
    5:         ...
    6:     }
    7: }

続いて、HeroesController.cs に下記の参照を追加します。

    1: using SuperHero2.Models;

そして、1 つ目の Get アクション メソッドを下記に書き換えます。

    1: // GET /api/values
    2: public IEnumerable<Hero> Get()
    3: {
    4:     var heroes = new List<Hero>
    5:     {
    6:         new Hero {Id = 1, Name = "スーパーマン"},
    7:         new Hero {Id = 2, Name = "バットマン"},
    8:         new Hero {Id = 3, Name = "ウェブマトリクスマン"},
    9:         new Hero {Id = 4, Name = "チャッカマン"},
   10:         new Hero {Id = 5, Name = "スライムマン"}
   11:     };
   12:  
   13:     return heroes;
   14: }

ここでは、実装サンプルをシンプルにするために、Get アクション メソッド内にデータをハードコーディングしていますが、実際はここで何かしらのデータ アクセスをおこなってモデルデータを取得することになるでしょう。

4. 実行

ひとまずは、これで Hero モデルのリストデータを取得する Web API が実装できましたので、実行してデータが取得できるか確認してみます。F5 または Ctrl + F5 で実行すると、Web API プロジェクトテンプレートで作成された ASP.NET MVC の Index ページが表示されます。

startPage

こちらのブログ記事で紹介した WCF Web API 拡張パッケージで提供されていたようなテスト用クライアントは、現状 ASP.NET Web API では使用できませんので、ここでは IE9 の F12 開発者ツール のネットワークキャプチャ機能を使って Web API からのレスポンスデータを確認します。(Fiddler などの HTTP キャプチャツールを使用してもかまいません)

IE9 で F12 キーを押して F12 開発者ツールを開き、[ネットワーク] タブを開きます。そして、[キャプチャの開始] ボタンを押して、HTTP のキャプチャを開始します。この状態で、IE9 のアドレスバーに https://localhost:XXXX/api/heroes と入力して、リクエストとレスポンスをキャプチャします(XXXX にはスタートページのポート番号を入力します)。

F12_capture1

キャプチャ データをダブルクリックするか、選択してから [詳細ビューに移動] をクリックすると、リクエスト ヘッダーやレスポンス ヘッダーなどを確認することができます。ここで [応答本文] を見ると JSON 形式で Hero データが取得出来ていることが確認できます。

F12_capture2

5. jQuery による JSON データの取得と表示

最後に、Index.cshtml で、api/heroes から JSON 形式でヒーロー データを取得し、ページ上に表示してみます。Index.cshtml ページを開き、<div id=”body”> 内部の要素を全て削除してから、下記のスクリプトやマークアップを記述します。

    1: <!DOCTYPE html>
    2: <html lang="en">
    3: <head>
    4:     <meta charset="utf-8" />
    5:     <title>ASP.NET Web API</title>
    6:     <link href="@Url.Content("~/Content/Site.css")" 
    7:         rel="stylesheet" type="text/css" />
    8:     <script src="@Url.Content("~/Scripts/jquery-1.6.2.min.js")" 
    9:         type="text/javascript"></script>
   10:     <meta name="viewport" content="width=device-width" />
   11:  
   12:     <style type="text/css">
   13:         #heroes
   14:         {
   15:             font-family: Meiryo;
   16:             font-size: 1.2em;
   17:         }
   18:     </style>
   19:  
   20:     <script type="text/javascript">
   21:         $(function () {
   22:             // Send an AJAX request
   23:             $.getJSON("api/heroes/",
   24:                 function (data) {
   25:                     // On success, 'data' contains a list of products.
   26:                     $.each(data, function (key, val) {
   27:                         // Format the text to display.
   28:                         var str = val.Id + ': ' + val.Name;
   29:                         // Add a list item for the product.
   30:                         $('<li/>', { html: str }).appendTo($('#heroes'));
   31:                     });
   32:                 });
   33:         });
   34:     </script>
   35:  
   36: </head>
   37: <body>
   38:     <header>
   39:         <div class="content-wrapper">
   40:             <div class="float-left">
   41:                 <p class="site-title">
   42:                     <a href="/">ASP.NET Web API</a></p>
   43:             </div>
   44:         </div>
   45:     </header>
   46:     <div id="body">
   47:         <ul id="heroes"></ul>
   48:     </div>
   49: </body>
   50: </html>

jQuery は、もともとプロジェクトに追加されているバージョン 1.6.2 をそのまま使用していますが、NuGet を通して最新版にアップデートしても構いません。Web API の呼び出しには、jQuery の getJSON メソッドを利用して非同期にデータを取得し、<ul id=”heroes”> の子要素として追加しています。

実行結果は下記の通りです。Web API として用意した api/heroes から取得した JSON データが Index.cshtml ページに表示されていることが確認できます。

image

おわりに

ASP.NET MVC 4 Beta で追加された新しいフレームワーク ASP.NET Web API の概要をご紹介しました。より詳しい情報は下記の ASP.NET オフィシャルページ (英語) をご参照いただければと思います。また随時、こちらのブログなどでも機能紹介していきたいと思います。

Getting Started with ASP.NET Web API

(赤シャツ男こと ScottGu’s Blog でも ASP.NET Web API シリーズ が始まりました!)