アクションの引数には自動的に同名のルーティング、クエリ、フォームパラメータがバインドされますが、プリミティブ型以外にもクラスなどの複合型を指定してもバインドを行うことが出来ます。これらはモデルバインダという機能によって実現されていて、標準で文字列や数値、アップロードされたファイルなど様々な型に対応しています。
[HttpPost] public ActionResult Upload(HttpPostedFileBase uploadFile) { // uploadFile には <input type="file" name="uploadFile" /> タグでポストされたファイルがバインドされる return View(); }
ポストされたデータのバインディング以外にも、モデルバインダはモデルの作成時に定義したデータアノテーション属性を認識して、自動的にモデルの検証を行ってくれます。検証時にエラーが見つかった場合には ModelState.IsValid プロパティの値が false になるので簡単に判別することが出来ますし、この後に作成するビューでは自動的にエラーの表示に対応したコードを生成してくれるので、何もコードを書く必要なく面倒なエラーチェックを実装することが出来ます。
モデルバインダ自体は ASP.NET MVC では以下のような Create アクションや Edit アクションなどで標準的に使われています。
// // POST: /Video/Create [HttpPost] public ActionResult Create(Video video) { try { // モデルバインドに成功したか確認 if (!ModelState.IsValid) { return View(); } // モデルバインダが作成した video エンティティを追加する _videoRepository.Add(video); // 変更をデータベースへ反映させる _videoRepository.Save(); return RedirectToAction("Index"); } catch { return View(); } }
この例ではフォームからポストされたデータは Video 型が持っている同名のプロパティにそれぞれ自動的にバインドされ、video パラメータとして利用することが出来ます。Video 型で受け取ることが出来るので、データベースへの登録が非常に簡単になりますね。
引数以外でもコントローラクラスに用意されている UpdateModel, TryUpdateModel メソッドを使って、明示的にバインドを行うことも出来、一般的には以下のコードのように、編集機能などでデータベースから取得したエンティティに対して、ポストされたデータへの更新を行う際に使います。
// // POST: /Video/Edit/5 [HttpPost] public ActionResult Edit(int id, FormCollection collection) { try { // id 引数を使ってデータベースから該当のエンティティを取得 var video = _videoRepository.Find(id); // フォームからポストされたデータで video の値を書き換える UpdateModel(video); // エンティティの変更をデータベースへ反映させる _videoRepository.Save(); return RedirectToAction("Index"); } catch { return View(); } }
モデルバインダは非常に優秀なので、殆どのシナリオでは自動的に認識して型変換を行ってくれます。例えば以下のように配列を指定した場合でも見事にバインドしてくれます、素敵ですよね。
public ActionResult Array(string[] values) { // input タグの name 属性やクエリパラメータのキー名が values となっている値が全てが配列として格納される return View(); }
ASP.NET MVC を理解する上での非常に重要な要素ですので、今回は具体的なコードを複数出して単独の記事として扱ってみました。次回からは各アクションを実装していくのですが、当たり前のように利用しますので検証周りも合わせて理解しておくことが重要です。お疲れ様でした。