2007年12月13日木曜日

ASP.NETでMVCフレームワーク

まだ製品版ではないけど、リリース目前のVisualStudio 2008と.NET Framework 3.5で使えるASP.NET MVCフレームワーク。

ASP.NET 3.5 Extensions Preview : The Official Microsoft ASP.NET Site

これの日本語訳を読むと鳥肌立つよ。

ScottGuさんの最新の投稿 INDEX

ずいぶん前にどこかで誰かが「MVCで作ろうよ」っていうのを書いてたけど、フレームワークがあってこそだと思ってたから(わざわざすべてをハンドラ書いて処理するのが面倒だなと思うじゃない)、こういうふうに製品になるとかなり作り方が変わるよね。

次期EntLibでDependency Injectionのアプリケーションブロックが入るみたいだし、テストドリブンにもしやすそう。Sprint.NETやSeasar.NETがあるけど、なんとなく...、ねぇ。 .NET開発者のためのDI&AOP入門(前編) - @IT

今のところMVCToolkitも入れとかないと、便利なヘルパー機能は使えないけど、製品版には反映されることを期待。 URLルーティング、コントローラからビューへのViewData渡し、フォームの値をモデルに取り出す便利ヘルパー。LINQも使っていけば、全てが直観的で劇的に開発効率が上がる気がしてワクワクが止まらないっす。 ちなみにVS2008を入れて使ってみてないからよく分かんないんだけど、パート4でformのactionにcreateを指定しただけで、form要素の値がパラメータに渡されるのは要素のIDと変数名で見るから?摩訶不思議。 次にMVCToolkitで使えるHtmlHelperのSelectメソッドにID名とデータソースを渡すだけで、option要素のvalueにIDの値が入って、表示テキストに名前が適用されるのはなんでなんだ?例えばSupplierなんてSupplierIDが主キーだからまだvalue対象になるのはいいけど、テキスト表示にCompanyNameなのかContactNameなのかとか型を見ただけじゃわかんないよね~? ソース一式ダウンロードしてみたけど、Viewにはそんなこと何も書いてないし、一体全体どういうマッピングルールなんだろう。どこ見りゃわかるんだろう。 う~ん、気になる~。 はっ!!そうだ、MVCToolkitのソース見ればいいんじゃんね。 というわけで、ソースダウンロード。 http://asp.net/downloads/3.5-extensions/MVCToolkit.zip で、解凍して、それっぽいのを探すと、MVCToolkit/UIHelper/FormInputExtensionsってフォルダ発見。その中に SelectExtensions.csがあったから見てみたら、textFieldとvalueFieldを指定できるオーバーロードを発見。今回はそれを指定してないんだから、その時どうなってるのかなと思ってみていくと、とりあえずそのへんはお構いなしに、 MvcControlDataBinder.EvalDataSourceを呼び出してデータソースをDataTableに変換してる模様(同ソース90 行目)。

DataTable tbl = MvcControlDataBinder.EvalDataSource(dataSource, textField, valueField);

なわけで、EvalDataSourceを探すと、同フォルダのDataBinder.csに発見。 LINQで取得するエンティティだから多分IQueryable?Arrayってことはないよね...? Arrayなら最初の2つの項目を単にValueとTextってことにして突っ込んでるからテーブル構造を考えたら、それぞれ意味が通るようになるね。

} else if (dataSource is Array) { result.Columns.Add("Value"); result.Columns.Add("Text"); IEnumerable<object> arraySource = dataSource as IEnumerable<object>; en = arraySource.GetEnumerator(); while (en.MoveNext()) { DataRow dr = result.NewRow(); dr[0] = en.Current.ToString(); dr[1] = dr[0]; result.Rows.Add(dr); }

超単純。 IQueryableのときがどうなんだって話だよね~。
                            foreach (PropertyInfo p in props) {
                               dr[p.Name] = p.GetValue(en.Current, null);
                           } 

こうだから全項目をDataRowに突っ込んでるだけだよな~。 おかしいな~、と思ってSelectメソッドに戻ってみたら↓こうだった。

//loop the source foreach (DataRow dr in tbl.Rows) { string selectedFlag = string.Empty; string thisText = dr[1].ToString(); string thisValue=dr[0].ToString(); if (selectedValue != null) { if (HtmlExtensionUtility.AreEqual(selectedValue, dr[0])) selectedFlag = " selected=\"true\" "; } sbOptions.AppendFormat(optionFormat, helper.Encode(thisValue.ToString()), selectedFlag, helper.Encode(thisText)); }

DataRowの最初の項目をValue、2個目の項目をText。そのままかい! でも、なぞが解けてすっきり。 要するにHtml.Selectヘルパーメソッドに要素名とデータソースを渡した場合、エンティティの最初の項目がvalue属性に入って、2個目の項目を表示文字列にしたoption要素が生成されるってことですな。グッジョブ!

dotnetConf2015 Japan

https://github.com/takepara/MvcVpl ↑こちらにいろいろ置いときました。 参加してくださった方々の温かい対応に感謝感謝です。