ASP.NET MVC のモデルバインダは List や配列は添え字がシーケンシャルであれば、複合型でも問題なくバインド出来るのは知っていましたが、今日まで Dictionary のバインドに対応してることを知りませんでした…。これは恥ずかしい。
ASP.NET Wire Format for Model Binding to Arrays, Lists, Collections, Dictionaries - Scott Hanselman
Scott Hanselman 氏のブログに記述がありますが、日付は何と驚きの 2009 年ですよ!
という訳で、ASP.NET MVC では Dictionary のバインドは出来ますが、記法がかなり特殊になっています。現在主流の Expression を使った HTML ヘルパーはこの書き方に対応していないので、殆どの人は知らずに生きている気はしますね…。
ミニマムなサンプルコードを用意したので読んでもらった方が理解できる気がします。
public class HomeController : Controller { public ActionResult Index() { var model = new Dictionary<int, string> { { 1, "foo" }, { 10, "bar" }, { 100, "baz" } }; return View(model); } [HttpPost] public ActionResult Index(Dictionary<int, string> model) { return View(model); } }
アクションは Dictionary を作って受け取っているだけなので、違和感は全くないですね。
しかしながら、ビューはというと。
@model IDictionary<int, string> @using (Html.BeginForm()) { var i = 0; foreach (var item in Model) { <input type="hidden" name="[@i].Key" value="@item.Key" /> <input type="text" name="[@i].Value" value="@item.Value" /> i += 1; } <input type="submit" /> }
foreach を使っているのに添え字のためにカウンタ変数を用意していたり、Key と Value プロパティという存在しないものを触っていたりで、知らなければかけないコードになってます。
凄く見た目が気持ち悪いコードですが、動かすとちゃんとバインドされます。なんだか不思議な気分です。
普段使いするような書き方ではないと思いますが、どうしても非シーケンシャルなキーを持つデータをフォームで扱いたい場合には有効ですね。