ASP.NET WEB API モデルバインド その1 値の取得先
ASP.NET WEB API モデルバインドについてです。
モデルバインディングとは
モデルバインディングとは、ApiController のアクションメソッドの引数に定義した
パラメータの型(モデル)の値を、リクエストから生成し、メソッドに渡すことです。
ASP.NET MVC にもある概念です。
例:
public class ValuesController { // GET ~/api/values/?id=32 public string Get(int id) { // id には、QueryString "id" の値 32 が入っている。 } }
ASP.NET WEB API のモデルバインドでは、
このモデルである引数の値を、どこから取ってくるのか、
その1は、この取得先についてです。
デフォルトでは
先日、ASP.NET WEB API パイプラインのポスターが公開されました。
ASP.NET Web API HTTP Message Lifecycle
日本語版もでています。ASP.NET Web API HTTP メッセージ ライフサイクル 日本語版
このPDFの左下に、モデルバインドについての図があります。
この図は、WEB API のモデルバインドのデフォルトの挙動を説明しており、
値の取得先が一目で分かるようになっています。
- 型が ComplexType (自分で作成したクラスとか)だと、Body から値を生成します。
- 型が SimpleType (int, datetime, guid 等の Primitive 型)だと URI から値を生成します。
- 他、開発者が独自の処理で、値の取得先を変更することができます。(Header とか)
例
文字で見るよりコードで見たほうがわかりやすいです。
QueryString と Body から値を取得する例を挙げます。
例えばこんな HTTP リクエストを送ると… ↓
POST ~/api/values/?id=4 ContentType : application/json { Name : "Taro", Number : 1 }
Api Controller のアクションメソッドでは
このように値が取れます。 ↓
public void Post(int id, Person person) { //id : 4 //person.Name : "Taro" //person.Number : 1 //と値がバインドされる。 }
id は、ルーティングでプレースホルダーを使って定義することもできます。
属性で制御する
引数に属性をつけると、上記のデフォルトとは違って、
値の取得先を変更することができます。
例えばこんな HTTP リクエストでは… ↓
POST ~/api/values/?name=Taro&number=1
Api Controller のアクションメソッドでは
このようにすると値が取れます。 ↓
public void Post([FromUri]Person person) { //person.Name : "Taro" //person.Number : 1 //と値がバインドされる。 }
アクションメソッドの引数に、[FromUri] が
ついていることに注意です。
この属性を付けないと、例のように値がバインドされません。
※[FromBody]について
プリミティブ型に[FromBody]をつけて、Body から値を取得することはできますが、
かなり限定的になるのであまり使えません。
(json で { id : 4 } とかしてもバインドできません)
つまり
特に何もしなければ、int 型等のプリミティブ型の場合は、URI から、
自分で定義したクラスを指定すれば、Body から値が生成されます。
が、[FromBody] や [FromUri] などの属性を指定した場合は、
指定した場所から値が生成されます。
void Post(int id, Person person); // ↑ id は URI から、person は Body から void Post([FromBody]int id, [FromUri]Person person); // ↑ id は、Body から、person は URI から
WEB API のプロジェクトテンプレートのコードに、
[FromBody] が付いているのはこれが理由です。
この URL と Body の分け方、直感的だなと思うのですがどうでしょうか…。
ASP.NET MVC と比べて
もはや MVC と比べるのはナンセンスかもしれませんが…。
MVC のモデルバインドは、Key を指定すれば、ValueProvider さんが各所から値を用意してくれていました。
一方 WEB API のモデルバインドは、HTTP リクエストの値を直接指定するようになっています。
WEB API にも、MVC の ValueProvider や ModelBinder の仕組みはあり、
カスタマイズもできるのですが、やはり中身は、
HTTP リクエストの値をしっかり指定するような実装になります。
次はモデルを作っているところ
モデルの取得先を簡単に見てみましたが、先ほどのパイプラインのポスターの図には、
モデルを作る部分、MediaTypeFormatter・ModelBinder・ValueProvider も登場しています。
次はこの辺りを書ければいいなと思います。