検索
連載

ASP.NET Web APIの全体像をつかむ連載:ASP.NET Web API 入門(2/2 ページ)

RESTfulなHTTPサービスを構築するためのフレームワーク「ASP.NET Web API」を基礎から解説する連載スタート。まずは“Hello, World”のコードを説明し、挙動を確認する。

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

Hello, Worldコードを見てみよう

 ASP.NET Web APIの簡単なサンプル・コードを見てみよう。そのコードとは、Visual Studio 2012に搭載されているASP.NET Web APIプロジェクト・テンプレートから生成される初期のひな型コード(以降、プロジェクト・テンプレート・コード)だ。このテンプレートには、すでにいくつかのWeb APIが定義されている。

 HTTPサービスを提供するフレームワークなので、実際に処理を呼び出すにはHTTPリクエストを送信するクライアントが必要だ。「A Simple Test Client for ASP.NET Web API」というASP.NET Web API用のデバッグを行うためのパッケージも公開されているが、ここでは「Fiddler2」を使用する。IDEはVisual Studio Express 2012 for Web、言語はVisual C#を使用する。

プロジェクトの作成

 Visual Studio Express 2012 for Webを開き、(メニューバーから)[ファイル]−[新しいプロジェクト]を選択し、ASP.NET MVC 4のプロジェクト・テンプレートを選択してプロジェクト作成を進め(次の画面を参照)、その途中で表示されるダイアログで[Web API]を選択する。

「ASP.NET MVC 4 Web アプリケーション」のプロジェクト・テンプレートを選択して[OK]ボタンをクリック
「ASP.NET MVC 4 Web アプリケーション」のプロジェクト・テンプレートを選択して[OK]ボタンをクリック

次へ
その後に表示されるダイアログでは「Web API」プロジェクト・テンプレートを選択して[OK]ボタンをクリック
その後に表示されるダイアログでは「Web API」プロジェクト・テンプレートを選択して[OK]ボタンをクリック

 作成されるプロジェクトは、ASP.NET MVCとASP.NET Web APIを組み合わせたものである。

 作成直後に[F5]キーを押してデバッグを実行すると、次の画面のようにトップ・ページが表示される。これはASP.NET MVCにより生成されたページである。

プロジェクト・テンプレート・コードをそのまま実行した場合のトップ・ページ
プロジェクト・テンプレート・コードをそのまま実行した場合のトップ・ページ

 プロジェクト・テンプレート・コードには、ASP.NET MVCのコントローラやビュー、APIヘルプ・ページ関連のファイルが含まれているが、肝心のASP.NET Web APIのコードは2箇所だ。

 「ルーティングの設定」と「APIコントローラ」である。ルーティングの設定から見てみよう。なお、本記事ではコードの変更は行わない。

ルーティングの設定

 ルーティングの設定は、App_StartフォルダのWebApiConfig.csファイルに(次のように)記述されている。

using System.Web.Http;

namespace ApiTry
{
  public static class WebApiConfig
  {
    public static void Register(HttpConfiguration config)
    {
      config.Routes.MapHttpRoute(
        name: "DefaultApi",
        routeTemplate: "api/{controller}/{id}",
        defaults: new { id = RouteParameter.Optional }
      );

      // ……コメント省略
      //config.EnableQuerySupport();

      // ……コメント省略
      config.EnableSystemDiagnosticsTracing();
    }
  }
}

WebApiConfig.csファイルに記述されている「ルーティング設定」のコード
このファイルには、ルーティング設定やフォーマッタの設定など、ASP.NET Web APIの設定を記述する。

 このRegisterメソッドの初めに、MapHttpRouteメソッドで記述されているコードが、ルーティングの設定だ。この設定は必ず必要となる。

 MapHttpRouteメソッドの引数、routeTemplateに指定されている文字列(=URLテンプレート。この例では「api/{controller}/{id}」)に当てはまるリクエストを、APIコントローラのメソッドにマッピングする。このルーティングの設定は、URLの一部である「{controller}」の箇所に指定されたコントローラ名と同じAPIコントローラにマッピングされることを表す。例えば「api/values/1」というURLでHTTPのGETメソッドを呼び出した場合は、ValuesControllerクラス(=コントローラ)のGet(id)メソッドが呼び出され、引数として「1」が渡される。

 defaultsパラメータの引数のidプロパティに指定されている「RouteParameter.Optional」は、「id」が省略可能なパラメータであることを表している。つまり、URLの一部である「{id}」の値が設定されていてもいなくても、このルーティング設定が適用される。具体的には例えば「api/values」というURLでHTTPのGETメソッドを呼び出せば、ValuesControllerクラスのGetメソッド(引数なし)が呼び出されるということである。

 このルーティング設定に対応するURLと、マッピングされるAPIコントローラとパラメータの例を以下の表に記す。

URL マッピングされるAPIコントローラ・クラス パラメータidの値
http://localhost:XXXX/api/values ValuesController 無し
http://localhost:XXXX/api/values/3 ValuesController 3
http://localhost:XXXX/api/books BooksController 無し
http://localhost:XXXX/api/room/2 RoomController 2
プロジェクト・テンプレート・コードのルーティング設定におけるURLの例と、それにマッピングされるAPIコントローラの一覧

 HttpConfigurationクラス(System.Web.Http名前空間)に対してルーティング設定を行っているが、そのほかの設定もこのRegisterメソッド内で行える。上記のコード例にもあるEnableQuerySupportメソッドやEnableSystemDiagnosticsTracingメソッドはその一例だ(ここでは詳説を省く)。

 基本的にASP.NET Web APIの設定を行うときは、このHttpConfigurationクラスに対して処理を書くことになるだろう。

 このRegisterメソッドは、(次のコード例のように)Global.asax.csファイルのApplication_Startメソッドにより実行される((1))。なおRegisterメソッドは、アプリケーション起動時に必ず実行されなければならない。

namespace ApiTry
{
  public class WebApiApplication : System.Web.HttpApplication
  {
    protected void Application_Start()
    {
      AreaRegistration.RegisterAllAreas();

      WebApiConfig.Register(GlobalConfiguration.Configuration);  //(1)
      FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
      RouteConfig.RegisterRoutes(RouteTable.Routes);
      BundleConfig.RegisterBundles(BundleTable.Bundles);
    }
  }
}

Global.asax.csファイルのApplication_Startメソッドにより実行されるRegisterメソッド
(1)のところで、Application_Startメソッドで、WebApiConfigクラスのRegisterメソッドが実行されている。それ以外は、全てASP.NET MVCの設定コードだ。

 以上が、プロジェクト・テンプレート・コードにおける、ルーティングの設定だ。パラメータの正規表現や、HTTPメソッドの制約なども追加できるが、詳細は次回以降の記事で解説する。

 次は、APIコントローラのコードを見てみよう。

APIコントローラ

 ControllersフォルダにValuesControllerクラスのファイルが追加されているので開いてみよう(同フォルダにあるHomeControllerクラスのファイルは、ASP.NET MVCのコントローラ・クラスのためのものである)。

 先ほども説明したように、このValuesControllerクラスが、ASP.NET Web APIにおける「APIコントローラ」と呼ばれるものである。APIコントローラは、一般的にはApiControllerクラス(System.Web.Http名前空間)を継承し、サフィックスとして「Controller」を付ける(厳密に言うと、APIコントローラはApiControllerクラスを継承しなくても、IHttpControllerインターフェイス(System.Web.Http.Controllers名前空間)を実装していればよい)。クラス内には、エンドポイントとなるメソッドがいくつか定義されている。

 ValuesControllerクラスのコードは以下のとおりだ。

using System.Collections.Generic;
using System.Web.Http;

namespace ApiTry.Controllers
{
  public class ValuesController : ApiController
  {
    // GET api/values
    public IEnumerable<string> Get()
    {
      return new string[] { "value1", "value2" };
    }

    // GET api/values/5
    public string Get(int id)
    {
      return "value";
    }

    // POST api/values
    public void Post([FromBody]string value)
    {
    }

    // PUT api/values/5
    public void Put(int id, [FromBody]string value)
    {
    }

    // DELETE api/values/5
    public void Delete(int id)
    {
    }
  }
}

ValuesControllerクラス

 それぞれのメソッドの上に、対応するURLとHTTPリクエストのメソッドの例がすでにコメントとして記述されている。

 だが、先ほどのルーティング設定では、コントローラの指定は行ったが、メソッドの指定は行わなかった。なぜこのようにURLにマッピングされているか?

 答えは、メソッドの選択は、HTTPリクエストのメソッド(GETやPOSTなど)により行われるからである。

 HTTPリクエストのメソッドがGETの場合は「Get」で始まるメソッドが、POSTである場合は「Post」で始まるメソッドが、というふうに、HTTPリクエスト・メソッドと、APIコントローラのメソッドの名前が対応している場合にマッピングされる。例として、このValuesControllerクラスのGetメソッドの名前を、「GetValues」に変更したとしてもマッピングは変わらず動作する。

 また、ValuesControllerクラスには、引数の違うGetメソッドが2つ定義されている。

 これは、HTTPリクエストのURLで、先ほどのルーティングで設定したURLテンプレート「api/{controller}/{id}」の{id}に当たる部分が定義されているかいないかの違いによる。

 上記のコードの「[FromBody]」は、引数の値がHTTPリクエストのBodyの値であることを表す。

 以上のように細かいルールや設定が存在するが、取りあえず今回は「エンドポイントを定義するにはAPIコントローラを用意し、メソッドを定義する」とだけ覚えておいてほしい。

実行してみよう

 コードの確認は以上だ。[F5]キーでデバッグを開始した後、Fiddler2を起動し、各APIを呼び出してみよう。

HTTP GETメソッド: ValuesControllerクラスのGetメソッド(引数なし)にマッピング

 まずは、以下のようなHTTPリクエストを送信する。

   
HTTPメソッド GET
URL http://localhost:XXXX/api/values/
最初に試すHTTPリクエスト(引数なしのGetメソッドにマッピング)
「XXXX」の部分は実行環境ごとに異なるので、各自で適切な数字を指定する必要がある。

  このHTTPリクエストは、ValuesControllerクラスの引数無しのGetメソッドにマッピングされる。

 なお、URLの「localhost」の後ろの「XXXX」という値は、起動されたブラウザのURL欄にある値と同じものに置き換えて指定する。

 Fiddler2でHTTPリクエストを作成するには、次の画面で示すように、まず[Composer]タブをクリックする((1))。

Fiddler2でHTTPリクエストを作成
Fiddler2でHTTPリクエストを作成

  HTTPメソッドの欄には「GET」((2))を、URLには「http://localhost:xxxx/api/values」((3))を入力する。入力した後、[Execute]ボタン((4))をクリックする。これにより、HTTPリクエストが送信される。

 送信されたHTTPリクエストは、次の画面に示す左の欄((5))に一覧として表示される。今、送信したリクエスト内容に当たる最後の行を選択し、[Inspectors]タブ((6))をクリックしよう。

Fiddler2でHTTPレスポンスを確認
Fiddler2でHTTPレスポンスを確認

 すると、右側の上部にはHTTPリクエストについて、下部ではHTTPレスポンスについての情報が表示される。下部の[Raw]タブ((7))をクリックし、HTTPレスポンスの中身を確認してみよう。

 最後の行に「["value1","value2"]」と表示されているはずだ((8))。これは、ValuesControllerクラスの引数無しのGetメソッドの戻り値である。IEnumerable<string>型の値が、JSON型のデータに変換されてHTTPレスポンスに格納されていることを表している。

HTTP GETメソッド: ValuesControllerクラスのGetメソッド(引数あり)にマッピング

 試しに、もう一方の引数ありのGetメソッドを、以下のようなHTTPリクエストで呼び出してみよう。

   
HTTPメソッド GET
URL http://localhost:XXXX/api/values/5
2回目のHTTPリクエスト(引数ありのGetメソッドにマッピング)

 2回目のHTTPリクエストは、URLの末尾に「5」とidを指定する。このHTTPリクエストは、ValuesControllerクラスの引数ありのGetメソッドにマッピングされる。

 先と同じ方法で、HTTPレスポンスのBodyの値を確認してみると、「"value"」と表示されるはずだ。さらに、引数ありのGetメソッドにブレークポイントを設定してみてほしい。すると次の画面のように、引数のidに、URLで指定した「5」が代入されていることが確認できるはずだ。

ValueControllerクラスの引数ありのGetメソッドに設定されたブレークポイントで実行が停止したところ
ValueControllerクラスの引数ありのGetメソッドに設定されたブレークポイントで実行が停止したところ
最初の中括弧にブレークポイントを設定し、APIを呼び出した後、引数のidにカーソルを当てている。

HTTP POSTメソッド: ValuesControllerクラスのGetメソッド(引数なし)にマッピング

 次は、Postメソッドを呼び出してみよう。Getメソッドのときとは違い、HTTPリクエストのBodyに値を設定する必要がある。

 HTTPリクエストは以下のとおりだ。

   
HTTPメソッド POST
URL http://localhost:XXXX/api/values/
HTTPヘッダ Content-Type : application/x-www-form-urlencoded
Body =hello
3回目のHTTPリクエスト(引数なしのPostメソッドにマッピング)

 3回目のHTTPリクエストは、HTTPヘッダとBodyの値を設定する。このリクエストは、ValuesControllerクラスのPostメソッドにマッピングされる。

 HTTPメソッドとURLについては、先ほどと同じなのでFiddler2での指定方法の説明は省略する。HTTPヘッダとBodyの設定方法は、以下のとおりだ。

Fiddler2で、POSTメソッドのHTTPリクエストを作成する
Fiddler2で、POSTメソッドのHTTPリクエストを作成する

 HTTPメソッド欄で「POST」を選択すると((9))、下部に[Request Body]入力欄が表示される((10))。この欄に「=hello」と入力する。

 また、HTTPヘッダ((11))に、「Content-Type : application/x-www-form-urlencoded」を入力する。

 最後に[Execute]をクリックして、HTTPリクエストを送信してみよう。

 また、そのときにPostメソッドにブレークポイントを設定し、引数のvalueに「hello」という文字列が代入されていることを確認してほしい(次の画面はその例)。

ValueControllerクラスのPOSTメソッドに設定されたブレークポイントで実行が停止したところ
ValueControllerクラスのPOSTメソッドに設定されたブレークポイントで実行が停止したところ
最初の中括弧にブレークポイントを設定し、APIを呼び出した後、引数のvalueにカーソルを当てている。

 次は、Getメソッドのときと同じように、HTTPレスポンスの内容を確認してみよう。

POSTメソッドでHTTPリクエストを送信したときのHTTPレスポンスのBodyを確認する
POSTメソッドでHTTPリクエストを送信したときのHTTPレスポンスのBodyを確認する

 Bodyの値は格納されておらず、先頭に「204 No Content」((12))と表示されているはずだ。これは、HTTPステータス・コードの1つで、処理には成功したが、返す値はないことを表している。

 ValuesControllerクラスのPostメソッドのように、戻り値がvoidの場合は、ステータス・コード「204 No Content」が返される。

 以上、GetメソッドとPostメソッドに対応するAPIを、Fiddler2を使って呼び出した。

HTTP PUTメソッドと、HTTP DELETEメソッド

 PutメソッドとDeleteメソッドにおいても、同じように呼び出せるので、試してみてほしい。それぞれに対応するHTTPリクエストの例を、以下に記載しておく。

   
HTTPメソッド PUT
URL http://localhost:XXXX/api/values/3
HTTPヘッダ Content-Type : application/x-www-form-urlencoded
Body =newValue
HTTPリクエスト(Putメソッドにマッピング)

   
HTTPメソッド DELETE
URL http://localhost:XXXX/api/values/4
HTTPリクエスト(Deleteメソッドにマッピング)

 HTTPメソッドがDELETEの場合は、HTTPリクエストのBodyに値を設定する必要はない。

 お気づきかと思うが、ValuesControllerクラスのGet/Post/Put/Deleteのメソッドは、それぞれデータの取得/追加/更新/削除を想定したAPIのメソッドである。

 パラメータidを用いてURLでリソースを表し、HTTPメソッドによってその操作を指示する、これはRESTfulなHTTPサービスの特徴の1つである。


 本稿では、ASP.NET Web APIがRESTfulなHTTPサービスを構築するためのフレームワークであることを説明した。

 最後のHello, Worldのコードは、String型という単純な値のやりとりを行うAPIの例だが、実際は、データのオブジェクトを使い、APIコントローラでは、取得・追加・更新・削除などの処理を行う。また、条件によっては返すHTTPレスポンスの制御が必要になってくる。

 次回は、そのデータの操作について、RESTfulなAPIを実装する方法も含めて解説を行う予定だ。

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

連載:ASP.NET Web API 入門

Copyright© Digital Advantage Corp. All Rights Reserved.

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