ScottGu's blog translated by Chica @ Wankuma

ASP.NET MVC ソース 更新 プレビュー

  

ASP.NETの新機能とリリースに対するプレビュー(ビルド可能なソースコード付き)を今後何度かご提供する予定ですが、その際に利用するための新しいASP.NET CodePlex プロジェクトをオープンしました。

先月はそこで初回のASP.NET MVC ソースコードを公開しました。この最初のソースにはVisual Studioのプロジェクトファイルが付いた、MIXで出荷したASP.NET MVC プレビュー2のリリースが含まれていますので、ご自分でパッチしてビルドすることが可能です。

数時間前に、そこのサイト上にASP.NET MVC ソースコードの更新版 を公開しました。この更新ソースは、ASP.NET MVC プレビューの正式リリースではありませんが、現状のソースツリーの状態をご確認頂くための暫定版になっています。 "ASP.NET MVC プレビュー3" のリリースは、残っているタスク(機能の追加や更新、VSツール統合の改良、VS expressバージョンのサポート、ドキュメントなど)が終了してから数週間後にはリリースを予定しております。もしきちんとドキュメントやサポートが整ったASP.NET MVCのインストールをご希望の場合はこの公式プレビューのリリースをお待ちになった方がよろしいかと思いますが、 早期の"プレビューのプレビュー"をご覧になってすぐにでも使用してフィードバックされたい場合は今回の更新版は興味深いかと思います。

今回の ASP.NET MVC ソース更新での改善

今週の更新( ここからダウンロードできます。)には ASP.NET MVCに対して多くの改善点が含まれています。その中のいくつかは以下の様なものです。:

  • ASP.NET MVC フレームワークのソースコードに加え、それをテストするために使用する単体テストのソースコードも投稿しています。これらのテストはMSTestとオープンソースの Moq モックフレームワークを使用して実装されています。その単体テストのVS 2008のプロジェクトファイルもありますので、ローカルのVS 2008 IDEで簡単にビルドして起動することができます。

  • Controllerクラスをテストするには非常に簡単です。モックオブジェクト(詳細は以下をご覧ください。)なしで、よくあるControllerのケースを単体テストすることができます。

  • URLルーティングシステム(詳細は以下)への機能追加と便利性の改善

ASP.NET MVC プロジェクトの新規作成

ローカルでMVCソースをダウンロード、コンパイルして独自のASP.NET MVC アセンブリをビルドすることができますし、またVSのテンプレートパッケージをダウンロードしてVisual Studioのプロジェクトテンプレートのあるプリビルドされたものを取得することで簡単にASP.NET MVC プロジェクトをビルドして最新のコードを使用することもできます。

ASP.NET MVC ソース更新の.VSI templateをインストールした後, 新規の"ASP.NET MVC アプリケーション"プロジェクトテンプレートが、"マイテンプレート"セクションの下の"新規プロジェクト" ダイアログに表示されます。 :

MVCプロジェクトテンプレートのこの新規"マイテンプレート" バージョンはASP.NET MVC プレビュー2リリースと共存します。(ダイアログのメインプロジェクトテンプレートセクションでご覧頂けます。)これにより同じマシン上でプロジェクトを安全に新規作成し、最新のソースバージョンと最新の公式プレビューバージョンの両方を使用することができます。

この更新されたASP.NET MVC プロジェクトテンプレートを使用して新規プロジェクトを作成すると、デフォルトでは以下の様なプロジェクトになります。 :

この新規プロジェクトソリューションには、"\Controllers"ディレクトリの下に1つのController ("HomeController")と、"\Views\Home"サブディレクトリの下に2つのView テンプレート("About" と "Index")が含まれています。 Viewテンプレートは両方とも共通のサイトのマスターページ("Site.master")に基づいており、スタイルは"\Content" ディレクトリの下の "Site.css" ファイルで定義されています。

アプリケーションを起動すると、ビルドインのWebサーバが自動で起動され、サイトの"Home" コンテンツ が確認できます。:

"About us"タブをクリックすると、"About" コンテンツが表示されます。:

プロジェクトの"HomeController" クラスは上記のURLを処理する仕組みになっており、以下のような2つのアクションメソッドを持っています。 :

デフォルトの"Site.master" テンプレートは、ViewDataコレクションで"Title" の値を検索し、HTMLページの<title> 要素で描画します。デフォルトの"Index" Viewテンプレートは"Message" の値を検索しホームページの最初のメッセージに使用します。これらについてはお好みに応じてご変更頂ければと思います。

このASP.NET MVC でのControllerの変更

上記のコードをよく見ると、今回のASP.NET MVC ソース更新を使用してデフォルトで実装されているControllerクラスの変更点に気づかれると思います。

ASP.NET MVC プレビュー2リリースに伴い、上記のHomeControllerアクションメソッドは以下のように実装されています。 :

MVC の機能チームは今週の公開でいくつか試みを行っており、新しいものもいくつか試しています。 :

  1. 現在デフォルトでController上のアクションメソッドは"ActionResult" オブジェクト(voidではなく)を返すようになっています。このActionResult オブジェクトはアクション(描画するView、リダイレクト用URL、その他の実行アクションやルートなど)からの結果を示します。

  2. Controller ベースクラス上のRenderView()、RedirectToAction()、Redirect() ヘルパーメソッドは、現在型付けされたActionResult オブジェクト(アクションメソッドからさらに操作したり返したりすることが可能)を返します。

  3. 現在RenderView() ヘルパーメソッドは、描画するViewテンプレート名で明示的に引き渡さなくても呼ばれるようになっています。テンプレート名を省略した場合、RenderView() メソッドはデフォルトでアクションメソッド名を描画用のViewテンプレート名として使用します。"About()"アクションメソッド内にある引数なしの"RenderView()"を呼び出すと、"RenderView('About')"と明示的に書いたものと同じになります。

この新パターンを使用するのに、プレビュー2でビルドされた既存のControllerクラスを更新するのは非常に簡単です。(voidをActionResultに変更してRenderViewまたはRedirectToActionヘルパーメソッドの呼び出しの前にreturnステートメントを追加するだけです。)

アクションメソッドから返されるActionResultオブジェクト

では、何故Controllerのアクションメソッドを変更してActionResultオブジェクトをvoidの代わりに返すことになったのか? 数多くのWeb-MVC フレームワークはオブジェクトを返すアプローチを取っているのですが (DjangoやTapestryなど)、それはASP.NET MVC にもいくつか利点があることが分かったのです。 :

  1. Controllerに対してよりきれいでより簡単な単体テストが可能になります。アクションメソッドのリスポンス動作をテストするためにReponseオブジェクトやViewEngineオブジェクト上で仮メソッドを持つ必要がなくなりました。単体テスト内のアクションメソッドを呼び出してそこから返されたActionResultオブジェクトを使用して条件を入れていくだけです。(次のセクションを参照ください。)

  2. 条件に応じて2つの異なる結果が出る場合に、Controllerのロジックフローの方向をよりきれいにより明示的にすることができます。(例えば、条件AがTrueの場合はリダイレクトし、それ以外はViewテンプレートを描画する) これにより、大きなControllerアクションメソッドのコードが読みやすくなります。

  3. FilterActionAttributeがアクションメソッドを実行する前に結果を取得して、それを修正・変換するような場合に、いくつかの構成が可能になります。例えば、ProductCatalogコントローラ上の"Browse"アクションがRenderActionResultを返して製品の"List"ビューを描画したいことを示しているとします。 その時、Controllerクラス上に宣言的に設定されたFilterActionAttribute は、クライアントのMIMEタイプに応じてList-html.aspx またはList-xml.aspxのどちらかに描画される特定の"List" Viewテンプレートをカスタマイズすることができるようになります。複数のFilterActionAttributeはオプションで連結させることもできます。

  4. 今後機能を追加できる拡張性のあるメカニズムがあります。 新規のActionResult 型はActionResultベースクラスをサブクラスにして"ExecuteResult" メソッドをオーバーライドすることで簡単に作成することができます。"RenderFile()"ヘルパーメソッドは簡単に作成できます。開発者は新しい"FileActionResult"オブジェクトを返すアクションを書くだけです。

  5. 今後いくつかの非同期実行ケースが可能になります。アクションメソッドはAsyncActionResultオブジェクトを返すことができ、それはネットワーク操作上でワーカースレッドが譲渡されるのを待っているため、ASP.NETはそのネットワークコールが終了するまで次のリクエストの実行にそれを使用することができます。これにより、開発者はサーバ上でスレッドをブロックする必要なく、非常に効率的で拡張性のあるコードをサポートすることができます。

この暫定版プレビューの目的の1つが、この新しいアプローチを、実在のアプリの構築に使用して習得して頂くことです。

また別のControllerベースクラスのサンプルも用意してますので、以前の"void"アクションリターンアプローチがお好みの場合にご利用頂ければと思います。この代替えのControllerベースクラスは意識的に今回のソース更新に含んでいません。なぜなら、"ActionResult"リターンアプローチをぜひお試し頂き、アプリ構築でのフィードバックをお願いしたいからです。

Controller アクションメソッドの単体テストの方法

上記で新しいActionResultアプローチにより単体テストのコントローラがより簡単(そして、通常のケースでモッキングの使用が不要)になったとお話ししました。では、このアクションの例を行ってみましょう。

以下のような単純なNumberControllerクラスを考えてください。 :

このControllerには"IsEvenNumber"アクションメソッドがあり、URL引数として数値を取ります。 IsEvenNumber アクションメソッドは最初に数値が負かどうかを確かめます。その場合、エラーページにリダイレクトされます。もし正数だった場合、数値が偶数か奇数かを判断し、適切なメッセージを表示するViewテンプレートに描画します。 :

新しいActionResultアプローチのおかげで、"IsEvenNumber"アクションメソッドに対して単体テストを書くのは非常に簡単になっています。

以下は負数だった場合に正しいHTTPリダイレクトを検証するための単体テストの例になります。 (例えば: /Number/IsEvenNumber/-1) :

上記でアクションメソッドをテストするためにモックオブジェクトが必要ないということがお分かり頂けると思います。代わりに単純にNumberControllerクラスのインスタンスを作成し、直接アクションメソッドを呼び出し(負数を引き渡し)、ローカルの"result" 変数に返す値を割り当てます。これに、"HttpRedirectResult"型に強く型付けされた"result"変数をキャストするために、C# の"as type" シンタックスを使用しています。

C# の"as" キーワードのいいところは、キャストが失敗した時(例えば、アクションメソッドがRenderViewResultを代わりに返した場合)に例外を投げるのではなくNullを値として割り当ててくれます。 つまり、気軽にテスト時にHttpリダイレクトが起こったことの検証で、結果がNullでないかどうかを検証するアサーションチェックを追加できます。その次に2つ目のアサーションチェックでその特定されたリダイレクトURLが正しいものかどうかの検証をすることができます。

ゼロ以外の数値が引き渡されたかどうかをテストするケースも簡単です。これを行うには2つのテスト、1つが偶数のテスト、1つが奇数のテストのメソッドを作成します。両方のテストでRenderViewResultが返され、そのViewに関連づいたViewDataの中で引き渡された"Message"が正しいかを検証するチェックを行います。 :

VS 2008でNumberControllerTestクラスを右クリックし、"テストの起動" メニューを選択します。 :

これは3つの単体テストをインメモリ(Webサーバは不要)で実行しNumberController.IsEvenNumber() アクションメソッドが正しい動作を行ったかどうかを報告します。 :

注:今週のソース公開ではController上のTempDataプロパティをテストするにはモッキングは必要になります。数週間後のASP.NET MVC プレビュー3ではこのテストにモッキングは不要になる予定です。

MapRoute ヘルパーメソッド

通常、ASP.NET MVC アプリケーションでのURLルーティングルールはGlobal.asaxクラスの"RegisterRoutes" メソッドで宣言します。

ASP.NET MVC プレビュー 1 と 2 では、ルートはRouteオブジェクトを直接インスタンス化して、MvcRouteHnadlerクラスにそれを接続した後、ルートルールを宣言するためにそこへ適切なプロパティを設定することで、ルートコレクションに追加されました。 :

上記コードはそのまま継続されますが、同じことを行うもっと単純なシンタックスを持つ新規の"MapRoute" ヘルパーメソッドも活用することができます。以下はASP.NET MVC プロジェクト(上記コードと入れ替えられます。)を新規作成した時にデフォルトで構成された協定のURLルートです。 :

MapRoute() ヘルパーメソッドはオーバーロードされ2~4つの引数(ルート名、URLシンタックス、デフォルトのURL引数、URL引数の正規表現制約)を取ります。

システムで複数の名前付きルートを登録する度にMapRoute()を呼ぶことができます。例えば、デフォルトのルールに加え、以下の様に、"Products-Browse" 名前付きルーティングルールを追加することができます。 :

その後それに対してURLを生成したい場合、この"Products-Browse"ルールをControllerやViewで明示的に参照することができます。例えば、"Products-Browse" ルートへリンクさせて、それを以下の様にViewテンプレートでコードを使用して"Food" カテゴリ引数へ引き渡すということを、Html.RouteLinkビューヘルパーを使用して示します。 :

このビューヘルパーは、その後ルーティングシステムにアクセスして、適切なHTMLのハイパーリンクURLを以下の様に出力します。(注:ルートルールを使用したURLへのカテゴリ引数の自動引数代用方法) :

注:今週のソース公開では、生成された正しいルートURLを解決するためにHtml.RouteLink() ヘルパーへControllerやアクション引数(カテゴリ引数に加え)を引き渡す必要があります。ASP.NET MVC プレビュー 3 ではこれが不要になり、Html.RouteLink コールが利用できます。

その他のURLルートマッピング機能

今週のMVCソース公開では新規のURLルートマッピング機能が数多くサポートされており、現在、 "-", ".", ";" や、その他の文字をルートルールの一部に使用することができます。

例えば、"-" セパレータを使用して、以下の様なルールを使用して個別のURLから言語やロケール値をパースすることができます。 :

これは適切な"language"、 "locale"、"category" 引数を ProductsController.Browseアクションメソッドが発生した時に引き渡します。 :

URL ルートルール URLの例 アクションメソッドへの引数
{language}-{locale}/products/browse/{category} /en-us/products/browse/food language=en, locale=us, category=food
  /en-uk/products/browse/food language=en, locale=uk, category=food

または "." ファイル拡張子タイプをURLの最後に使用して、XML または HTML フォーマットのどちらの結果であるかを確認できます。 :

これは"category" と"format" 引数の両方を ProductsController.Browse アクションメソッドが発生した時に引き渡します。:

URL ルートルール URLの例 アクションメソッドへの引数
products/browse/{category}.{format} /products/browse/food.xml category=food, format=xml
  /products/browse/food.html category=food, format=html

ASP.NET MVC プレビュー 2ではルートルールにワイルドカードが導入されました。例えば、ルールでアクションメソッドへ残りのURIすべてを名前付きの引数として引き渡すようにすることができます。 :

これは、WikiController.DisplayPageアクションメソッドが発生した時に"contentUrl"引数を引き渡すことができます。:

URL ルートルール URLの例 アクションメソッドへの引数
Wiki/Pages/{*contentUrl} /Wiki/Pages/People/Scott contentUrl="People/Scott"
  /Wiki/Pages/Countries/UK contentUrl="Countries/UK"

これらのワイルドカードのルートは今週のプレビューでも引き続き動作し、ブログや、Wiki、CMS、その他コンテンツベースのシステムをビルドする時には非常に便利です。

新しいルーティングシステムをASP.NET MVCでも使用できますし、同じルーティングシステムを (ASP.NET Webフォームを使用している)ASP.NET Dynamic Dataでも現在使用することができます。

まとめ

上記により今週のASP.NET MVC のソース更新公開での機能の追加や変更が簡単にご紹介できれていればと思います。

すぐにご利用になりたい場合は、 ここからダウンロードして頂けます。また、ASP.NET MVC プレビュー 3 の公式公開も数週間後ですので、よろしければお待ちいただければと思います。これには、機能も追加されており(今週の公開でのフィードバックも含まれます。)、よりシームレスなインストーラや、VSとの統合、最新のドキュメントもご提供させて頂きます。

今週公開分のASP.NET MVC に対するご質問や問題点等については、www.asp.netASP.NET MVC フォーラム も是非ご確認頂ければと思います。

Hope this helps,

Scott

ScottGu's blog translated by Chica @ Wankuma 

※本翻訳に関しまして、Scottさんにはご了承頂いております。