気になるところがあったんでしょうね。安易にRTMを出さず、品質上げるためにRC2リリースの決断に敬意を表します。2とはいえ、RC1との違いが単にインストーラだけなわけ無いですよね。リリースノートを確認しましょう。CodePlexにソース/Futuresも上がってるんですが、その下にDataAnnotationsを使ったModelBinderのサンプルが...。早く出してくれれば、自分でサンプル書かなくても良かったのに...。このDataAnnotationsModelBinderの実装を確認してみると、その内容がまた超かっこいいです。IDataErrorInfo使わずに、DefaultModelBinderを派生させて、OnPropertyValidatingのオーバーライドメソッド内でValidationAttribute属性の取得・実行とModelStateへのエラー投入を行ってる。入力検証の集約というより、DataAnnotationsはそれだけで検証を完結させておき、モデル自体の検証や、ビジネスルールの検証は切り離して行うという設計。IDataErrorInfoならErrorのオーバーライドでモデル検証も集約できるから、どっちが分かりやすいコード(このサンプルだとモデル検証は別途モデル層に実装しましょうということになる)になるかは、アプリケーション設計者の好みでどうぞ、ってことですかね。リリースノートに書かれてる変更点(それほど多くない)をさらっと確認してみると、以下のような感じです。3.5SP1必須です。サーバーインストールモードを用意しました。VS関係のインストールがないのでデブロイ環境へのインストールはこれを使いましょう。MVC_SERVER_INSTALL="YES"GACに入れるよ。AntiForgeryのCookie出力時にパスを指定できるようにしました。デプロイ環境(ルートからとかサブフォルダあるとか)に合わせてパスを調整できます。DefaultModelBinderが出力するエラーメッセージをローカライズできるようにしました。resxファイルを独自に定義して分かりやすいエラーメッセージを登録しておきましょう(InvalidPropertyValueとPropertyValueRequiredの2個だけ)。ValidationSummaryのオーバーロードが増えたよ。メッセージリストをul/liタグで展開する前にspanタグでのタイトル表示できるなり。jQuery1.3.1にしたよ。DropDownListの例外。web.configのauthenticationの値をLogOnに。Site.Masterとかで使ってるheadタグがrunat="server"をちゃんと動くように。checkboxとradiobuttonをModelStateからちゃんと復元。ルートのDefault.aspx(ルーティングでコントローラ+アクション指定してるとルートアクセスでデフォルトのコントローラ+アクションが実行されるけど、これにOutputCacheを指定しても効かない)でOutputCacheがちゃんと効くように。基本的にRC1のコードならそのまま動くっぽいですね。16:50System.Web.AbstractionsとSystem.Web.Routingの2つのアセンブリがSP1のものを利用するように変わったんですね。System.Web.Mvcだけ(Futuresを利用するならMicrosoft.Web.Mvcも)を配布すればよくなりました。MVCでの新しいサンプル。チュートリアルにそって順に良くなっていく。これはMVCerはみとくべき。Frameworkをモデルにして、アドレス帳サンプルを作成。この手順はオーソドックスな最初の作り方。これでMVCでの作成ってこれまでとどう違うのかが分かるはず。デザインギャラリーからデザインテンプレートを取得したり、自分でデザインしたものを1で作ったものに適用させて、見た目を綺麗にしましょう。ヘルパーなんかも書いたりしてデザインしやすくしておきましょう。フォームの入力検証を実装。シンプルな検証方法で、DataAnnotationsなどを使うわけではないです。どこで検証を実施すればいいのか、検証結果がどうViewに反映されるのかをしっかり押さえておきます。機能を疎結合にしましょう。モデル層はRepositoryに任せ、ロジック層はServiceに移動させる。それぞれインターフェイスと実装を分けて書きましょう。これまで書いたコードにたいするテストコードを書きましょう。モックを使うとテストコードを楽にかけるのでお気に入りのモックを使いましょう。ここではMoqを使います。MocksやTypeMockなんかもあるよ。テストの初期化時にインターフェースのインスタンスを生成し、コンストラクタインジェクション。Service層だけじゃなく、コントローラもテストコードを書きましょう。5でテストコードを書いたけど、ここからはテストドリブンな開発にしましょう。Group機能を追加する様子をテストを書くところから始めます。その後でテストをパスするコントローラコードを書き、繰り返して機能を実装していく。一通り出来たら、テストコードもあることだし、リファクタリングしてコードをService層に移動したり、Repository層に移動して、テストをパスしないコードが発生しないようにしましょう。最後にアプリケーションをAjax化して、使いやすさも向上させましょう。ページの部分更新をしたりするので、共通部分はコントロール化して、Ajaxでの更新時にPartialViewでページ全体じゃなく、必要な部分だけを返すようなコードにしましょう。MVCの開発スタイルの基本になると思います。身につけて、テストもはしょったりしないようにしましょう(自分で言っときながら耳が痛い...)。MVCに限った話ではないんですが、JavaScriptをページで使う場合、外部ファイル(scriptタグのsrc属性で指定する)にするか、インラインでページに直接書く(scriptタグ内にコードを書く)かどっちかになる。今時の作り方ならJavaScriptはページの最後で外部ファイルを取り込むのが、パフォーマンス的にもよろし、ということになってますね(ハイパフォーマンスWebサイト)。MVCでも、もちろん外部JSファイルを使ったアプリケーションを作るわけですが、ここで少し悩みが出てきました。処理コード(静的)としてのJavaScriptは簡単に外部に出せるから問題にはならないんですが、サーバーサイドで生成したデータを元に処理するコードの場合、そのデータをどうやって外部ファイルで使えばいいでしょうか。分かりにくい説明ですが、例えばサーバー上でデータベースから名前一覧を取得してViewDataに入れておいたとします(こればっかりは動的)。そのViewDataを外部JSファイルではもちろんそのまま参照できません。いうのもscriptタグで取り込んだ外部JSファイルとページそのもののリクエスト(MvcHandler)は別物だから、いくらコントローラのアクションでViewDataに値を入れたとしても外部JSファイルを取得したリクエスト(StaticFileHandler)では参照できないというのと、そもそもJSファイルが<%=~%>を解析して処理してくれないから。すればデータ(サーバーサイドで動的生成)をコード(JavaScriptを静的に取得)に簡単に渡せるんだろう。ページ専用のJavaScriptコードはどうしても、アクションで生成されるデータを使った動的コードにしたくなってしまう。それだと外部ファイルじゃなくViewにscriptタグを書いてしまうことになって、なんかスッキリしない。外部JSファイルを拡張子JSじゃなくASPXで作成し、JavaScript用のコントローラを作成(レスポンスのコンテンツタイプをapplication/x-javascriptに変更)し、動的にJSコードを生成するようにして(ViewファイルにJavaScriptコードを書く)、scriptタグでsrc指定。外部JSファイルにはコードだけを書き、Viewに出力されるHTMLにscriptタグを書いておいて適当な変数にデータ(JSON)で入れておいて、外部JSファイルからはこれを参照する。1の方法をとる場合、凄く分かりにくくなるのがコントローラが違うからViewとJavaScriptそれぞれでデータ取得のロジック(もちろんJavaScript用のコントローラではクライアントで必要なデータのみですが)を書かなきゃいけないからコードが散らばるうえに、VSで開発してるにも関わらずコードハイライトもインテリセンスも効かなくなる。以降charaを使った処理これだと2つのコントローラが必要になるし、ViewDataの生成と利用が離れすぎ。綺麗にコードとデータを分離するなら、2の方法が正解ですよね。その場合Viewページにscriptタグを書く必要がありますが、あくまで処理コードは外部に分離できる。以降charaを使った処理Viewアクション内でJavaScriptで利用するデータを生成しておき、外部スクリプトでのデータ参照はグローバル(この場合ならviewData)を見る。1の方法に固執しすぎてて、これを解決するためにカスタムのViewEngineを作ればいいんじゃないの?というおかしな路線に走ってしまって...。結局は2の方法にすることでViewEngine作る必要は無かったことに気がついたんだけど、その過程で今ネットで見つかるViewEngineの作り方が少し古いやり方な事に気がついたので、無駄にしないために、ココにメモとして残しておきます。MVCViewEngineを作るといっても、単にViewパスの検索場所を変更するためだけの目的もあれば、テンプレートエンジンを置き換えてしまう目的もあると思います。MVC)のようにWebFormViewEngineを派生させてViewLocationFormatsとMasterLocationFormatsをセットして、IViewは標準のWebFormViewを使えばいいですね。テンプレートエンジンを変えてしまいたい場合は、IViewEngineとIViewそれぞれを実装することになりますが、今回は少し楽をしてIViewEngineにはVirtualPathProviderViewEngineを使うことにします。何を作るかというと、拡張子jsの中に/$Key$/という形でテンプレートを入れとくと、ViewDataCollection内の同名Key値を埋め込むというテンプレート。これならJavaScriptのインテリセンスもコードハイライトも有効。IViewEngineの実装。JavaScriptView(viewPath);}}}IViewの実装。String.Empty;}}}置換部分の処理はまるっきりStephenさんのコードです...。拡張子jsのファイルはViewScriptsフォルダに入れておくようにしたものです。コントローラ名もフォマットに含めようと思ったんですが、そこはルーティングの登録を以下のようにしておくことでとりあえず必要無いな、と。ViewScriptsフォルダ内はコントローラ名フォルダ/スクリプト名.jsでファイルを入れておきます。);ViewEngineの登録も忘れずに。JavaScriptViewEngine());あとはViewScriptsControllerを書くだけ。View(path);}}}まずは動くコードを、という簡単なサンプルです。テスト用にViewScripts/Test.jsを作成。/$Test$/;alert(viewData);あとは、通常のViewでこれをインクルード。src="/ViewScripts/Test.js"></script>これで一応動くものが出来たわけですが、ここで2の方法でいいじゃん、と思い直してコードを破棄...。この方法だとViewScriptsControllerでいろんなViewDataを入れるためのコードが必要になって、面倒なことに。早い段階で気がつけば良かったけど、カスタムViewEngineを書いてみる勉強になったから良しとします。Engineじゃないかと思われます。作ってみたい方は是非そちらを参照してみてください。Intelligence結晶性知性。これを読んでいて、流動性知性はPCやネットで補完できる(外部記憶や計算能力)が、結晶性知性は「コンピュータによって模倣できない」と書かれてる。専門知や経験知からしか発達していかないインテリジェンスだから、それもそうだろうとは思うけど(画期的なAIっていうドラえもん級の夢のソフトウェアが出れば別)、外部知性というかたちでPCとネットで有効活用出来るとは思う。Wikiとかナレッジベースとかっていう形での実装ではなくて、もっとリアルタイムに近い形で。久しぶりにネガティブレガシーと出会いました。工業経済至上主義を未だ貫き(それはいい)、統計を完全否定し、ネットを不安視(あえて無視)することで現時点での自分の正当性を閉じた世界で証明しようとするその姿勢が面白かった。