MVC Framework RC 版での機能追加点(その②)
※ほんとうはタイトルを "ASP.NET MVC Framework RC 版での機能追加点(その②)" としたかったのですが、'The "Name" of a post and/or article must be unique. Your post was not saved or updated. ' などという原因不明のエラーが返るためにこんなタイトルに...。
――― ・ ――― ・ ――― ・ ――― ・ ――― ・ ――― ・ ――― ・ ――― ・ ―――
先回の ASP.NET MVC Framework RC 版の変更点で書き忘れましたが、インストールについて大きな変更、というか、正しく動くようになった点があります。
それはインストール時のアイテムテンプレートの追加です。
β 版では、日本語向けにアイテムテンプレートが正しくインストールされず、1033 のフォルダの内容を、1041(日本語の LCID)という名前のフォルダを作成してコピーするという手順が必要でしたが、RC 版では当然ながらこの作業は必要なく、インストーラーの処理のみで MVC Framework を使用した開発を開始することができます。
今回も ASP.NET MVC Framework の新機能について書きますが、新機能どうしにあまり関係がないのと、機能的こまかいということもありますのでメモ程度ということで。。
既定のマスターページの<head> セクションの変更
既定のマスターページの<head> セクションに空のプレースホルダを儲けられました。
これは、<head> 内のタイトル、スタイルシート、スクリプトの制御を各々のコンテンツページからしやすいようにするためです。
( ようするに、ページタイトルの変更などが今までより簡単に行うことができるようになるということです。 )
( 既定のマスターページの <head> セクション )
<head runat="server"> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> <asp:ContentPlaceHolder ID="head" runat="server"> <title></title> </asp:ContentPlaceHolder> <link href="../../Content/Site.css" rel="stylesheet" type="text/css" /> </head> |
BeginRouteForm メソッドの追加
HtmlHelper への新しいBeginRouteForm 拡張メソッドが追加されました。このメソッドは既存の BeginForm メソッドとほとんど同じですが、ポストする URL を生成するときにルート名を指定することができます。
(BeginRouteForm メソッドの記述例)
<% using (Html.BeginRouteForm("Default")) { %> ・ ・ ・ <% } %> |
DropDownList および ListBox メソッドの変更
DropDownList と ListBox のヘルパーメソッドが、ユーザーから報告のあったユーザビリティに関するさまざまな問題を改善するために変更されました。
以前のバージョンでは、これらのメソッドの引数として指定できるのは、SelectList と MultiSelectList だけでした。
RC 版では LINQを使用して IEnumerable<T> オブジェクトを IENumerable<ListItem> オブジェクトに変換し、リストアイテムとして使用することができます。
具体的には、以下のようにも
( コントローラー側 アクションメソッド内 )
Models.pubsDataContext pubsdatacontext = new Models.pubsDataContext();var peopleList = from person in pubsdatacontext.employee select new SelectListItem { Text = (person.fname + " " + person.lname ), Value = person.pub_id, Selected = (person.pub_id == "") };ViewData["ListIems"] = peopleList; |
( ビュー側 )
<%=Html.ListBox("listBox", (IEnumerable<SelectListItem>)ViewData["ListIems"])%> |
以下のようにも記述することができます。
( ビュー側 )
<% using (MvcApp.Models.pubsDataContext pubsdatacontext = new MvcApp.Models.pubsDataContext()) { IEnumerable<SelectListItem> employeeList = from person in pubsdatacontext.employee select new SelectListItem { Text = (person.fname + " " + person.lname), Value = person.pub_id, Selected = (person.pub_id == "") }; Response.Write(Html.ListBox("listBox", employeeList)); } %> |
CSRF 攻撃の防止の用ヘルパー の追加
CSRF 攻撃 ( XSRF攻撃とも言う ) の防止策として CSRF ヘルパーが追加されました。
CSRF ヘルパーはフォーム内 <hidden> フィールドのトークン情報と、cookie 内のトークン情報を使用して、データの Post 元の正当性について確認するのを補助します。
たとえば以下のように Html.AntiForgeryToken アシスタントを使用すると、フォーム内の <hidden> フィールドに一意なトークン情報が出力され、コントローラ側の偽装フィルタの検証処理に使用されます。
( ビュー側 )
<% using(Html.Form()) { %> <!-- フォーム要素 --> <%= Html.AntiForgeryToken() %> <% } %> |
( コントロール側 Post を受け取るアクションメソッド )
[ValidateAntiForgeryToken][AcceptVerbs(HttpVerbs.Post)]public ActionResult Edit(Product product){ //Post された情報を処理するコード} |
この設定を行うことにより、以下の情報がフォームの <hidden> フィールドと cookie に設定されます。
( < hidden > フィールドへの出力例)
<input name="__RequestVerificationToken" type="hidden" value="zdurK7QikUnxJ+6wo2RAJyocuIbHAkCXq6bJk5gnC2cQYnCrEN6/cTgFDxMyw2+b" /> |
( cookie へのトークンの設定例)
キー | __RequestVerificationToken |
値 | pBd3/+aoAbE3VePc7gJF4yQyzL5RfxyEfdFgm50NxLMTrSIAwqDjsjMLkASeD0af |
ちなみに偽装したフォームで情報を送信すると、以下のようなエラーが返ります。
( 偽装したフォームからの Post によるエラー )
'/' アプリケーションでサーバー エラーが発生しました。 viewstate MAC の検証フィールドです。このアプリケーションが Web Farm またはクラスタによってホストされている場合、 <machineKey> 構成が同一の validationKey および検証アルゴリズムを指定していることを確認してください。 AutoGenerate をクラスタで使用することはできません。 説明 : 現在の Web 要求を実行中に、ハンドルされていない例外が発生しました。エラーに関する詳細および例外の発生場所については、スタック トレースを参照してください。 |
ただし、既にお気づきの人もあると思うのですが、"あれをこうしてああすれば"、この防止策もバイパスすることが可能なので、CSRF 攻撃の対策を徹底的に行いたい場合は、合わせてリファラの検証処理も追加することを個人的にはお勧めします。
Action メソッドからバイナリコンテンツを返すため File ヘルパーの追加
レスポンスにバイナリコンテンツの追加を行うために、File ヘルパーメソッドが追加されました。
File ヘルパーを使用すると以下のように簡単にファイルを扱うことができます。
( コントローラー側コード: ブラウザに画像を出力 )
public ActionResult downLoad(){ return File(@"C:\store\image\flower.jpg", "image/JPEG");} |
File ヘルパーメソッドは、ファイルの出力のみでなく複数の動作を持っており、どのオーバーロードが呼ばれるかによって、以下の FileResult 派生型のひとつを返します。
( File ヘルパーメソッドの返り値)
型 | 機能 |
FilePathResult | パスで指定されたファイルをレスポンスに書き込み |
FileStreamResult | レスポンスにストリームを書き込み |
FileContentResult | バイト配列をレスポンスに書き込み |
X-Requested-With HTTP ヘッダーが認識可能に
IsMvcAjaxRequest メソッドが IsAjaxRequest メソッドに改名し、さらに X-Requested-With HTTP ヘッダーを認識する更新されました。
HTTP-X-Requested-With ヘッダーは、Prototype.js、jQuery、Dojo などのメジャーな JavaScript ライブラリによって使用されるヘッダーであり、一般的にリクエストが Ajax によるものであるかどうかを判定するのに使用されます。
この変更に合わせ、 ASP.NET AJAX ヘルパーもリクエストでのこのヘッダーを送るよう更新されましたが、ファイアウォールの、不明なヘッダーを削除する機能による問題の発生を回避するため、フォームの本文でも引き続き送信を行います。
その他の新機能について
私のブログで紹介しきれなかった ASP.NET MVC Framework RC 版での変更点は以下のとおりです。
- ログオン、登録、パスワード変更ページのための FieldSet-based HTML レイアウト
- LogOn.aspx、Register.aspx、および ChangePassword.aspx のページ内のマークアップは、 <TABLE> 要素を使用するのではなく <FIELDSET> 要素を使用するよう変更
- Visual Studio による MVC ファイルのリファクタリング
- コントローラー、アクションの名前を変更すると関連するフォルダ、ビューの名前などを自動で変更
- ControllerContext クラスは RequestContext クラスを継承しない
- ControllerContext クラスは RequestContext をカプセル化し、それから派生する代わりにプロパティを使用してそれを公開
- ControllerContext とそれを継承したタイプの多くのプロパティは、virtual の代わりに sealed
- Form ヘルパーか "." (ドット) を含んだ ID 属性の指定が可能に
- アクションメソッドで [Bind(Prefix="")] の指定が不要に
- 意図しないプレフィックスの使用防止のために空文字を指定しなくてもよい
- モデルバインダー API の変更
- DefaultModelBinder クラスに スキーマの検証とカスタムパインデング用の拡張ポイントが追加
- IDataErrorInfoのためのモデルバインダーサポートが追加
- Descriptor Type の追加
- HtmlHelper<T> クラスの追加
- JavaScriptResult アクションリザルトと JavaScript コントローラーメソッドの追加
- Beta からの Bug フィックス
正式リリース前の過渡期に関する情報なので、リリース後はあまり意味が無くなってしまう情報かも知れませんが、興味のある方は ASP.NET MVC Framework RC 版がインストールする Reademe.htm からドキュメントを入手してください。
Reademe.htm にアクセスするには、Windowos の [スタート] ボタン - [すべてのプログラム] - [ ASP.NET MVC RC] を選択し、フォルダをオープンさせてください。
ではまた。
Comments
- Anonymous
February 18, 2009
毎度参考にさせてもらっています。日本語のMVC情報が少ないので投稿して頂けると多くの方の参考になるかと思います。 今後も楽しみにしています。 >※ほんとうはタイトルを "ASP.NET MVC Framework RC 版での機能追加点(その②)" としたかったのですが、'The "Name" of a post and/or article must be unique. Your post was not saved or updated. ' などという原因不明のエラーが返るためにこんなタイトルに...。 これですが、もしかしたらタイトルがURLに直結する(半角英数字をURLに変換)仕組みになっているようなので、多少半角文字(記号はダメっぽいですね)を追加すると通ったかもしれません。 私も以前同じ所で躓いていたのでご参考になれば幸いです。