以前WCF Web APIについて書きましたが、その後紆余曲折あり、まず、WCFのプロダクトでは無くなり、それに従いWCFとしてホストされることは出来なくなり、ASP.NET MVCによるホスト機能に特化され、名前もASP.NET Web APIとなり、実質的にASP.NET MVC 4の1機能になっています。
また、新たに公開されたVisual Studio 2012ではASP.NET 4 Webアプリケーションテンプレートでサポートされています。
※以下記事の元になった記事は日本マイクソフト井上さんの記事(Web APIをはじめてみよう)が元になっています
そこで、以前の記事でWCF Web APIで書かれた内容をASP.NET Web APIで書き直したいと思います。
準備
ASP.NET 4 Webアプリケーションテンプレートを使って新しいプロジェクトを作成します。下の図と異なりますが、ソリューション名はSuperHero2とします。
新しいASP.NET MVC 4プロジェクトダイアログでWeb APIを選択します。
OKをクリックすると、基本のものに加えてWeb API関連のコンポーネントへの参照やファイルが追加されたASP.NET MVC 4のプロジェクトが作成されます。
Modelの追加
APIを通して提供するモデルとなるクラスを追加します。Modelsのフォルダの下にHeroクラスを追加します。EFを使ってSQL Serverにデータ保存するようにしています。
using System.Data; using System.Data.Entity; using System.Data.Entity.Infrastructure; using System.Data.SqlClient; using System.ComponentModel.DataAnnotations; namespace SuperHero2.Models { public class Hero { [Key] public int Id { get; set; } public string Name { get; set; } } public class HeroContext : DbContext { public DbSet Heroes { get; set; } } }
APIの実装
RESTのAPIの実装を追加します。GET, POST, DELETE, PUTを追加します。
まず、Controllersの下にデフォルトで生成された ValuesController.cs の名前をモデル名に合わせて HeroesController.cs に変更します。
HeroesController.csにModelへの参照を追加します。
using SuperHero2.Models;
まずはGetです。
/// /// ヒーローのリストを取得する。 /// /// /// ODataのインターフェイスをサポートするように戻り値をIQueryable(T)型に変更した。 /// /// ヒーローのリスト(JSON). public IQueryable Get() { List heroes; using (var context = new HeroContext()) { heroes = context.Heroes.ToList(); } //ListをIQueryableに変換する。 return heroes.AsQueryable(); }
エンティティモデルをリスト化して返しています。
次はPOST。
前回は複数のヒーローをリストで一気に塚で着るようにしていましたが、今回は名前を渡すと一人のヒーローを追加するようにしました。
/// /// ヒーローを追加する /// ///追加するヒーローの名前 /// /// Fiddler2などでのテストの仕方 /// httpヘッダに追加 /// Accept: text/html /// Content-Type: text/json; charset=utf-8 /// ボディに追加するヒーローの名前をutf-8でダブルクォート(")で囲う。 /// 例:"仮面ライダー1号" /// /// 追加に成功した場合201を返して、追加したヒーローを返す。 public HttpResponseMessage Post([FromBody]string heroName) { Hero _hero; using (var context = new HeroContext()) { _hero = new Hero(); _hero.Name = heroName; context.Heroes.Add(_hero); context.SaveChanges(); //201でレスポンスメッセージを作成する。 return Request.CreateResponse(HttpStatusCode.Created, _hero); } }
Web APIのメソッド引数に[FormUrl]属性がついた場合か、何も指定が無い場合には、Urlより引数パースしようとします。[FromBody]属性がついた場合にはHTTPメッセージのボディのデータより引数のデータをパースしようとします。
引数でな与えられた名前で、EFを使ってヒーローのレコードを追加し、成功した場合には201を返すように処理しています。
次はDELETE。
Idを引数にとって、そのIdのヒーローを削除します。
/// /// 引数で与えられたヒーローを削除する。 /// /// /// 引数idで与えられたヒーローが存在しない場合には404エラーが発生する。 /// /// public void Delete(int id) { Hero _hero; using (var context = new HeroContext()) { _hero = context.Heroes.Find(id); if (_hero != null) { context.Heroes.Remove(_hero); context.SaveChanges(); } else { //idのヒーローが見つからない場合には404を返す。 throw new HttpResponseException(HttpStatusCode.NotFound); } } }
次はPUT。
URL引数のidで与えられたIdのヒーローに対して、ボディに書かれている新しい名前でヒーローの名前委を変更します。
/// /// ヒーローの名前を変更する /// ///名前を変更したいヒーローのid ///変更する名前 /// /// Fiddler2などでのテストの仕方 /// URL /// http://(hostname):(port)/api/heroes?id=(変更するid) /// httpヘッダに追加 /// Accept: text/html /// Content-Type: text/json; charset=utf-8 /// ボディに追加するヒーローの名前をutf-8でダブルクォート(")で囲う。 /// 例:"仮面ライダー1号" /// /// /// 変更に成功した場合には200を返して、変更結果を返す。 /// public HttpResponseMessage Put(int id, [FromBody]string name) { using (var context = new HeroContext()) { var _hero = context.Heroes.Find(id); if (_hero != null) { _hero.Name = name; context.SaveChanges(); return Request.CreateResponse(HttpStatusCode.OK, _hero); } else { //idのヒーローが見つからない場合には404を返す。 throw new HttpResponseException(HttpStatusCode.NotFound); } } }
基礎的な内容は以上のようになります。
以前のWCF Web APIとの大きな違いはコントローラの各APIメソッドに対して属性が無くなり、それよりもメソッド名でRESTのどの命令に対応したメソッドかわかるようにしており、属性という設定が廃されてASP.NET MVCの「設定より規約」が徹底されています。
WCF Web APIのときにはWCFなので、サービスのテストページが自動的に作成されていましたが、ASP.NET Web APIとなって、現在その機能は実装されていませんので、Fiddllerなどでテストされる場合のhttpヘッダの設定等については、コード中のXMLコメントに書いています。またヘルプページの自動作成機能も無くなっています。ただ、ASP.NETのロードマップには両方とも含まれているので、いずれこれらの機能も追加されるかもしれません。
今回GitHubでソースコードを公開していますので、全体コードを確認されたい方や、ご興味をもたれた方は下をご確認下さい。
コメント
[…] ASP.NET MVC クライアント編サーバー編に続き、クライアント側についてもWCF Web APIの場合と同様にコンソールアプリケーションでクライアントライブラリの使用方法を見ていきます。 […]