Web API を始めてみよう

最近の Web アプリケーションの傾向は、サーバーサイドとクライアントサイドの実装がこれまで以上に疎結合になってきています。サーバーサイドでは API を公開し、クライアントサイドでは、JavaScript (jQuery) で非同期に API を経由してデータを JSON や XML で取得したり、Web アプリケーションだけでなく、WPF, Silverlight などを使ったアプリケーションやスマートフォン向けのアプリなどでの Web API の利用があたりまえになってきています。

サーバーサイドで公開され、HTTP 経由で呼び出しす API (Application Programming Interface) を一般的にも Web API と呼んでいますが、むかーしむかしは、XML Web サービスなどと呼ばれていたこともありました。

マイクロソフト開発プラットフォームでは、Web サービス (.asmx) や WCF (.svc) を使って Web API を実装することができますが、特に WCF に関しては非常に高機能な半面、若干複雑で分かりにくい印象を持っている方も多くいらっしゃるようです。

そこで、今日はこちらの “Getting Started: Building a simple Web API” をベースに、簡単な Web API の実装を紹介します。

※ 上記ページの翻訳をおこないつつ、一部実装例を変更して掲載します

0.用意する環境

1.ASP.NET MVC 3 プロジェクトの作成

「新しいプロジェクト」で「ASP.NET MVC 3 Web アプリケーション」を選び、プロジェクト名を入力します。今回は名前を “SuperHero” としてプロジェクトを作成しました。

Fig1

ソリューション エクスプローラーのプロジェクト名上で右クリックして、プロパティを選択します。そして、Web の設定ページを開き、サーバーの設定で「ポートを指定する」を選び、ポート番号として 9000 を入力します。

Fig2

2.WCF Web API 拡張パッケージの追加

WCF Web API 拡張パッケージを NuGet からプロジェクトにインストールします。「ツール」-「Library Package Manager」-「Manage NuGet Packages for Solution」を選択して表示されるダイアログで、左側のタブで「Online」-「All」を選んでから “WebApi” で検索すると関連したパッケージが表示されます。その中から “WebApi.All” を選んで Install ボタンを押すと関連パッケージが全てインストールされます。

Fig3

または、「ツール」-「Library Pacakge Manager」-「Package Manager Console」を開いてコマンドラインで下記を入力してもインストールできます。

Fig4

Fig5

ちなみに、「ツール」-「Library Package Manager」-「Package Visualizer」を開くと、NuGet を経由してインストールされているパッケージの依存関係が下図のように表示されますので、依存関係を確認するのにとても便利です。

Fig6

3.SuperHero API クラスの作成

ソリューション エクスプローラーのプロジェクト名上で右クリックして、「追加」-「新しいフォルダー」を選択し、APIs という名前のフォルダーを作ります。そして、作成した APIs フォルダ上で右クリックして、「追加」-「クラス」から SuperHeroApi.cs を作り、下記のコードを記述します。

 using System.ServiceModel;

namespace SuperHero.APIs
{
    [ServiceContract]
    public class SuperHeroApi
    {
    }
}

4.API のルーティングへの登録

Global.asax.cs ファイルを開き、下記の参照を追加します。

 using SuperHero.APIs;
using System.ServiceModel.Activation;
using Microsoft.ApplicationServer.Http;
using Microsoft.ApplicationServer.Http.Activation;

そして、RegisterRoutes メソッド内の、routes.MapRoute メソッド呼び出しの前に、下記の記述 (5, 6 行目) を追加します。

    1: public static void RegisterRoutes(RouteCollection routes)
    2: {
    3:     routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
    4:  
    5:     routes.Add(new ServiceRoute("api/heroes", new HttpServiceHostFactory(),
    6:                typeof(SuperHeroApi))); 
    7:  
    8:     routes.MapRoute(
    9:         ...
   10:     );
   11: }

この記述によって、 https://localhost:9000/api/heroes に SuperHeroApi がマップされます。

5.Hero クラスの作成と HTTP GET メソッドによる公開

続いて、API を通して提供するデータを表した POCO (Plain-old CLR Object) クラスを作ります。

ソリューション エクスプローラーのプロジェクト名上で右クリックして、「追加」-「新しいフォルダー」を選択し、Resources という名前のフォルダーを作ります。そして、作成した Resources フォルダ上で右クリックして、「追加」-「クラス」から Hero.cs を作り、下記のコードを記述します。

    1: namespace SuperHero.Resources
    2: {
    3:     public class Hero
    4:     {
    5:         public int HeroId { get; set; }
    6:         public string Name { get; set; }
    7:     }
    8: }

SuperHeroApi.cs に下記の参照を追加します。

 using System.ServiceModel.Web;
using SuperHero.Resources;

そして、下記の Get メソッドのコードを追加します。

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

WebGet 属性は、REST プログラミングモデルのもとで、HTTP GET で呼び出すことができるようにするものです。

6.スタートページの指定と実行

プロジェクトのプロパティページの Web の設定で、api/heroes を開始ページとします。

Fig7

そして、 F5 または Ctrl + F5 で実行すると、Heroes API の呼び出し結果として、下記のような XML データが取得できます。

Fig12

7.Heroes API のテストとテストクライアントの利用

WebApi 拡張パッケージでは、API アドレスに /test を付加することで、ブラウザベースの Web API テストクライアントを使用することができます。

まず、下記のコード (太字部分) を Global.asax.cs の RegisterRoutes メソッドに追加して、テストクライアントを有効にします。

    1: public static void RegisterRoutes(RouteCollection routes)
    2: {
    3:     routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
    4:  
    5:     var config = new HttpConfiguration() { EnableTestClient = true };
    6:  
    7:     routes.Add(new ServiceRoute("api/heroes", new HttpServiceHostFactory() {
    8:         Configuration = config }, typeof(SuperHeroApi))); 
    9:  
   10:     routes.MapRoute(
   11:         ...
   12:     );
   13: }

そして、F5 または Ctrl + F5 で実行してから、アドレスに /test を追加して呼び出すと、下記のようなテストクライアントが表示されます。

Fig8

HTTP メソッドに GET を指定して API URI を入力し、Send ボタンを押すと、API の呼び出し結果(レスポンス)を確認することができます。

image

Fig9

8.JSON 形式での API 呼び出し

続いて、JSON 形式でデータを取得してみます。

先ほどのテストクライアントで、Request ヘッダに application/json を指定して呼び出します。

image

すると、先ほどは XML 形式だったデータが JSON 形式で取得出来ていることが確認できます。

Fig10

実際に、jQuery などから API を呼び出す際もヘッダに application/json を指定することで JSON データを取得することができます。

9.OData クエリ サポートの有効化

最後に、OData クエリ ($top, $skip, $orderby, $filer) を使った呼び出しを試してみます。

SuperHeroApi.cs の Get メソッドを下記のように修正します (太字部分)。

    1: [WebGet(UriTemplate = "")]
    2: public IQueryable<Hero> Get()
    3: {
    4:     var heroes = new List<Hero>()
    5:     {
    6:         new Hero {HeroId = 1, Name = "スーパーマン"},
    7:         new Hero {HeroId = 2, Name = "バットマン"},
    8:         new Hero {HeroId = 3, Name = "ウェブマトリクスマン"},
    9:         new Hero {HeroId = 4, Name = "チャッカマン"},
   10:         new Hero {HeroId = 5, Name = "スライムマン"}
   11:     };
   12:  
   13:     return heroes.AsQueryable();
   14: }

これで、API URI に クエリ文字列 (例えば https://localhost:9000/api/heroes ?$top=3&$orderby=Name ) を付けて呼び出すと、”ウェブマトリクスマン” が最初のデータとして取得できるようになります。

Fig11

おわりに

NuGet を使って Web API パッケージ (WebApi.All) をインストールすると、ここで紹介したように WCF ベースの Web API の実装も比較的容易におこなえるようになります。今後、多様化するクライアントサイドのアプリケーション実装において、サーバーサイドでの API 公開は非常に重要になるでしょう。既に ASP.NET Web アプリケーションとして実装している状態でも、新たに Web API の実装を行う際には、ここでご紹介した方法もご検討してみてはいかがでしょうか。