以前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の場合と同様にコンソールアプリケーションでクライアントライブラリの使用方法を見ていきます。 […]