連載:〜ScottGu氏のブログより〜

ASP.NET MVC Preview 5とフォーム送信シナリオ

Scott Guthrie 著/Chica
2008/9/12
Page1 Page2 Page3 Page4

 本記事は、Microsoftの本社副社長であり、ASP.NETやSilverlightなどの開発チームを率いるScott Guthrie氏のブログを翻訳したものです。氏の許可を得て転載しています。

 先週の木曜日(2008年8月28日)、ASP.NET MVC 機能チームがASP.NET MVC フレームワークの“Preview 5”リリースを新しく公開しました*。このリリースはここからダウンロードできます。この“Preview 5”は.NET 3.5および最近リリースされた.NET 3.5 SP1の両方で動作します。また、Visual Studio 2008および(無料の)Visual Web Developer 2008 Express Edition SP1(現在ではクラス・ライブラリとWebアプリケーションの両方のプロジェクトが利用可能)でも使用できます。

 Preview 5には数多くの新機能と更新点が含まれています(これらは“Preview 4”の追加機能上に構築されています)。詳細については、ここにある“Preview 5”のリリース・ノートで変更および追加点がカバーされていますので、そちらをお読みください。このブログでは、今回のリリースで注目されている最大の機能の1つである、フォーム送信を行う場合のシナリオについてカバーしたいと思います。以下で構築するアプリケーションの完成版は、ここからダウンロードできます。

Web MVCパターンによる基本的なフォーム送信(Form Post)

 まず簡単なフォーム送信のシナリオである、製品データベースへ新製品を追加するケースを見てみましょう(図1)。


図1

 上記のページは、このアプリケーションでユーザーが“/Products/Create”に移動した場合に表示されます。このページのHTMLのフォーム・タグは以下のようになります(図2)。


図2

 上記のタグは標準のHTMLです。<form>要素の中に、<input type="text"/>テキストボックスが2つあり、フォームの下方にはHTMLの送信ボタンがあります。それを押すと、フォーム内でネストしている入力項目がサーバへ送信されます。このフォームはその“action”属性で指定されたURLへコンテンツを送信します。今回のケースでは“/Products/Save”です。

 以前のASP.NET“Preview 4”では、以下のような“Create”および“Save”の2つのアクション・メソッドを実装したProductsControllerクラスを使用して、このシナリオを実装していたかもしれません(図3)。


図3

 この“Create”アクション・メソッドには、初回の空のフォームを表示するHTMLビューを返す役割があります。“Save”アクション・メソッドは、その後、フォームがサーバへポストバックされたときに処理を行います。ASP.NET MVCフレームワークは、“ProductName”および“UnitPrice”のフォームから送信された値を、自動的にSaveメソッドのパラメータへ同じ名前でマッピングします。Saveアクションはその後LINQ to SQLを使用して新しいProductオブジェクトを作成し、エンドユーザーが送信した値をProductNameおよびUnitPriceの値に設定し、その新製品をデータベースへ保存しようとします。そのProductが保存に成功した場合、ユーザーは“/ProductsAdded”URLへリダイレクトされ、成功メッセージが表示されます。またエラーが発生した場合は、“Create”HTMLビューが再度表示されるので、ユーザーはそのエラー部分を修正し、リトライすることができます。

 そうすると、上記のProductsControllerとともに動作する以下のような“Create”HTMLビュー・テンプレートを実装して、適切なHTMLを生成することができます。Html.TextBoxヘルパー・メソッドを使用すると、<input type="text"/>要素が生成されます(そしてビューへ引き渡されたProductモデル・オブジェクトにある適切なプロパティから、それらの値を自動的にひも付けます)(図4)。


図4

Preview 5で改善されたフォーム送信

 上記のコードは以前の“Preview 4”リリースで動作し、そして“Preview 5”でも引き続き問題なく動作します。“Preview 5”リリースでは、いくつか新機能が追加されているので、このようなシナリオも、より機能的に処理できるようなります。

 これらの新機能には以下のものがあります。

  • シングル・アクションURLを発行し、それをHTTP Verbに応じてディスパッチする機能
  • リッチなパラメータ・オブジェクトがフォームの入力値から構築され、アクション・メソッドに引き渡されるようにするモデル・バインダ
  • フォームからの入力値を、アクション・メソッド内で既存のモデル・オブジェクトのインスタンスへマッピング可能にするヘルパー・メソッド
  • 入力およびエラーの検証処理の改善(例えば、自動的なエラー・フィールドのハイライト表示、フォームが再表示された際にエンドユーザーが入力した値が保存されている、など)

 このブログの残りで、これらの各シナリオを掘り下げたいと思います。

[AcceptVerbs]および[ActionName]属性

 上記のサンプルでは、2つのアクション・メソッド、“Create”および“Save”にわたる製品追加のシナリオを実装しました。このように実装を分割した理由は、コントローラのコードをよりクリーンにし、読みやすくするためです。

 このシナリオで2つのアクションを使用するマイナス点ですが、サイトには“/Products/Create”および“/Products/Save”の2つのURLを結果的に公開することになります。これは、入力がエラーで、HTMLフォームを再表示しなければならない場合に問題となります。そのエラーにより再表示されるフォームのURLが“/Products/Create”ではなく、“/Products/Save”になるからです(これはフォーム送信時のURLが“Save”だからです)。エンドユーザーがこの再表示ページをブラウザのお気に入りに追加した場合、あるいは、友達にそのURLをコピー&ペーストしてメールで送信した場合、間違ったURLが保存されているので、後でアクセスしたときにエラーが発生する可能性があります。また、公開している2つのURLは、もしあなたのサイトがクロールされ、機械的にaction属性が処理される場合、いくつかのサーチ・エンジンで問題を引き起こします。

 これらの問題点を回避する1つの方法としては、1つの“/Products/Create”URLだけを公開し、GETまたはPOSTリクエストに応じて異なるサーバ・ロジックを持つことです。ほかのWeb MVCフレームワークでよく使用されている方法は、単純にアクション・メソッドでif/else構文を作成して、処理を振り分けます(図5)。


図5

 上記の方法のマイナス点ですが、そのアクションの実装が一層読みにくくなり、テストも困難になることです。

 ASP.NET MVC “Preview 5”にはこのシナリオをよりうまく処理する方法があります。アクション・メソッドをオーバーロードして実装し、新しい[AcceptVerbs]属性を使用して、ディスパッチを処理するASP.NET MVCフィルタを使います。例えば、以下では2つのCreateアクション・メソッドを宣言しています。1つがGETで呼ばれるシナリオで、もう1つがPOSTで呼ばれるシナリオです(図6)。


図6

 この方法だと、多くの“if/else”構文をアクション・メソッドに記述しなくてよくなり、アクションのロジックをよりクリーンに構築できます。またこれらの2つの異なるシナリオをテストするために、Requestオブジェクトをモックする必要もなくなります。

 またオプションとして新しい[ActionName]属性を使用し、コントローラ・クラス上で実装しているメソッド名を、公開しているURLとは違うものにすることができます。例えば、2つのオーバーロードされたCreateメソッドをコントローラで持つのではなく、“Save”という名前のPOSTメソッドを持ちたい場合、[ActionName]属性にそのように設定することができます(図7)。


図7

 上記は、最初のフォーム送信のサンプルにあったものと同じコントローラ・メソッドのシグネチャ(CreateおよびSave)を持っています。違いは、1つのURL(/Products/Create)だけを公開して、自動的にHTTP Verbに応じて処理が変更されるところです(これによりブラウザのお気に入りやサーチ・エンジンで問題がなくなります)。

 

 INDEX
  〜ScottGu氏のブログより〜
  ASP.NET MVC Preview 5とフォーム送信シナリオ
  1.Web MVCパターンによる基本的なフォーム送信(Form Post)
    2.モデル・バインダ(Model Binder)/UpdateModelおよびTryUpdateModelメソッド
    3.エラー処理のシナリオ ―― フォームの再表示でエラー・メッセージを表示
    4.LINQ to SQL Entityへのビジネス・ルールの追加
 
インデックス・ページヘ  「〜ScottGu氏のブログより〜」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間