きよくらの備忘録

「三日坊主と呼ばせない!日記」改め。主にソフトウェア開発関連の話題。

ASP.NET Web Forms 4.5の新フィーチャーを概観してみる

本エントリは、One ASP.NET Advent Calendar 2012の22日目の記事です。
クリスマスまであと少しですね。アドベントカレンダーもラストスパートです。

ASP.NET 4.5 Web Forms 4.5のフィーチャー一覧

12/3のエントリ『http://d.hatena.ne.jp/kiyokura/20121203/p1』でも触れましたが、ASP.NET 4.5ではWeb Formsにもいくつか機能強化が入っています。公式サイトにある記述を確認していただくと良いのですが、ざっくり箇条書きすると以下のように書いてあります。

  • Strongly Typed Data Controls
  • Model Binding
  • HTML Encoded Data-Binding Expressions
  • Unobtrusive Validation
  • HTML5 Updates


このうち、一つ目の『Strongly Typed Data Controls』は12/3のエントリ、『ASP.NET 4.5 Web Formの『強く型指定されたデータコントロール(Strong Typed Data Controls)』を試してみる - 三日坊主と呼ばせない!日記』で紹介しました。


二つ目の『Model Binding(モデルバインディング)』については、ちょっとボリュームがあって長くなりそう&実はまだちゃんと試していないので、改めて紹介したいと思います(^^;
ただ、このモデルバインディングについてはリリース前に赤シャツ男ことScott Guthrieがblogで詳細な解説を行っていて、日本語に翻訳された記事も参照できますので、興味がある方はそちらを確認してみてください。『Webフォームモデルバインディング パート1:データの選択 (ASP.NET vNextシリーズ)』、『Webフォームモデルバインディング パート2:データのフィルタリング (ASP.NET vNextシリーズ)』『Webフォームモデルバインディング パート3:更新と検証 (ASP.NET 4.5シリーズ)』の3回にわたって解説されています。ただし上記blogの掲載時点から正式リリースになるまでに一部プロパティー名などが変更になっているようですので、実際にコードを入力しながら確認する際はこちらの内容と合わせて確認してみてください。

また、合わせて、小野さんが One ASP.NET Advent Calender の20日のエントリーとして掲載されている最新の GridView ならページングもソーティングも楽々!の内容もとても参考になると思います。


では今回は、残りの3つについて、ざっくりご紹介したいと思います。

HTMLエンコードされたデータバインディング(HTML Encoded Data-Binding Expressions)

ASP.NET 4.5から、データバインディングのナゲットに自動的にHTMLエンコードを行って出力する記法が追加されました。以下のように、『<%#』の後に『:(コロン)』を追加する記法になります。

<asp:TemplateField HeaderText="Name">
    <ItemTemplate><%#: Item.Products.Name %></ItemTemplate>
</asp:TemplateField>

これはASP.NET 4で追加された、<%: %>コードナゲットのデータバインディング版、という理解で良いと思います。この機能追加のおかげで、今後はデータバインディングする際も手動でHttpUtility.HtmlEncodeを行う必要がなって便利になりますね。

控えめなバリデーション(Unobtrusive Validation)

…これ、実は最初は何を言ってるのかわかりませんでした(^^;
簡単にいうと、『検証コントロール(hogehogeValidator)を使った際に、HTML側に出力されるJavaScriptが控えめになる』という機能です。


百聞は一見に如かずということで、ちょっと試してみましょう。

ASP.NET 4.5のWeb Formのプロジェクトを作成し、適当に追加したaspxファイルに、以下のように適当にTextBoxとRequiredFieldValidator、Buttonを配置してみます。こんな感じですね。

<form id="form1" runat="server">
  <div>
    <asp:TextBox ID="TextBox1" runat="server" />
    <asp:RequiredFieldValidator ID="rfv1" runat="server" 
        ErrorMessage="入力必須です" ControlToValidate="TextBox1" />
    <asp:Button ID="Button1" runat="server" Text="確定" />
  </div>
</form>

これを実行してブラウザのHTMLビューを確認してみると、以下のように出力されます。

<div>
  <input name="TextBox1" type="text" id="TextBox1" />
  <span id="rfv1" 
    data-val-controltovalidate="TextBox1" 
    data-val-errormessage="入力必須です" 
    data-val="true" 
    data-val-evaluationfunction="RequiredFieldValidatorEvaluateIsValid" 
    data-val-initialvalue="" 
    style="visibility:hidden;">入力必須です</span>
  <input type="submit" name="Button1" value="確定" 
    onclick="javascript:WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions(&quot;Button1&quot;, &quot;&quot;, true, &quot;&quot;, &quot;&quot;, false, false))" id="Button1" />
</div>

以前をご存知の方は、「え?これだけ??」と思われるかもしれません。ちなみに以前*1はどのように出力されていたかというと、以下のようになっていました。

<div>
  <input name="TextBox1" type="text" id="TextBox1" />
  <span id="rfv1" style="visibility:hidden;">入力必須です</span>
  <input type="submit" name="Button1" value="確定" 
    onclick="javascript:WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions(&quot;Button1&quot;, &quot;&quot;, true, &quot;&quot;, &quot;&quot;, false, false))" id="Button1" />
</div>

(〜中略〜)

<script type="text/javascript">
//<![CDATA[
var Page_Validators =  new Array(document.getElementById("rfv1"));
//]]>
</script>

<script type="text/javascript">
//<![CDATA[
var rfv1 = document.all ? document.all["rfv1"] : document.getElementById("rfv1");
rfv1.controltovalidate = "TextBox1";
rfv1.errormessage = "入力必須です";
rfv1.evaluationfunction = "RequiredFieldValidatorEvaluateIsValid";
rfv1.initialvalue = "";
//]]>
</script>


<script type="text/javascript">
//<![CDATA[
var Page_ValidationActive = false;
if (typeof(ValidatorOnLoad) == "function") {
    ValidatorOnLoad();
}
function ValidatorOnSubmit() {
    if (Page_ValidationActive) {
        return ValidatorCommonOnSubmit();
    }
    else {
        return true;
    }
}
//]]>
</script>


比べるまでもなく、その名の通りずいぶん控えめ(Unobtrusive)になっています。Web From 4.5のid="rfv1"のspanを見てみると沢山のdata-*属性が定義されているのがわかります。Unobtrusive Validationの機能は、このdata-*属性を利用して必要な情報をHTMLタグ中に記述することで、出力されるHTMLをシンプルにしてくれる機能のようです。

ASP.NET 4.5 Web Formでは既定でUnobtrusive Validationが有効になっています。Unobtrusive Validationの有効・無効はいくつかの方法で行うことが可能で、必要であれば今まで通りの出力を行うことも可能になっています。以下の3つの方法で切り替えることができるように記載されていました。

1.Web.confgでValidationSettings:UnobtrusiveValidationModeを設定する(グローバル)

Web.confgのconfiguration/appSettingsにkey="ValidationSettings:UnobtrusiveValidationMode"のエントリを追加することで設定を切り替えることができます。例えば以下のような記述になります。

<configuration>
  <appSettings>
    <add key="ValidationSettings:UnobtrusiveValidationMode" value="WebForms"/>
  </appSettings>

valueは『WebForms』もしくは『None』で、WebFormsの場合は控えめな出力、Noneの場合は従来通りの出力になります。

2.System.Web.UI.ValidationSettings.UnobtrusiveValidationMode静的プロパティを設定する(グローバル)

ValidationSettings.UnobtrusiveValidationMode プロパティを設定する方法です。例えば、Global.asaxのApplication_Startで以下のようにやるべし、と書かれれていますね。

protected void Application_Start(object sender, EventArgs e)
{
  System.Web.UI.ValidationSettings.UnobtrusiveValidationMode = System.Web.UI.UnobtrusiveValidationMode.WebForms;
}
3.ページクラスのインスタンスのUnobtrusiveValidationModeプロパティで設定する(ページ単位)

ページ単位で変更したい場合は、今回ページクラスに新設されれたUnobtrusiveValidationModeプロパティの値を設定してやればOKのようです。aspx側のPageディレクティブなどでは設定できないようなので、ビハインド側から設定してやる必要があるようです。例えばこんな感じでコンストラクタやPage_Loadイベントハンドラ内でやってしまえば良いように思います。

public partial class SamplePage: System.Web.UI.Page
{
  public SamplePage()
  {
    this.UnobtrusiveValidationMode = System.Web.UI.UnobtrusiveValidationMode.WebForms;
  }
}

HTML5対応の更新(HTML5 Updates)

サーバコントロールで出力されるHTMLタグでいくつかHTML5対応の改善が行われているようです。

TextBoxのTextModeプロパティにHTML5で追加されたinput typeの追加対応

HTML5でinput typeにEmailや日付などいくつかのタイプが追加されていますが、TextBoxのTextModeプロパティーで対応が行われています。今までのSingleLine/MulltiLine/Passwordに加え、以下のタイプが追加されています。

  • Color
  • Date
  • DateTime
  • DateTimeLocal
  • Email
  • Month
  • Number
  • Range
  • Search
  • Phone
  • Time
  • Url
  • Week
FileUploadコントロールの複数ファイルアップロード対応

ブラウザが対応している場合、複数ファイルをアップロードできるようになりました。AllowMultipleプロパティをtrueにしてやることで、ブラウザが対応していれば複数ファイルのアップロードを行う事ができます。アップロードされたファイルはPostedFilesプロパティにIListで格納されています。

検証コントロールのHTML5 input要素の対応

検証コントロールがHTML5のinput要素に対応しました。たとえば、以下のようにValidatorでinput要素に対して検証を行うことができます

<input runat="server" id="inputDate" type="date" />
<asp:RangeValidator ID="RangeValidator1" runat="server" 
    ControlToValidate="inputDate" Type="Date" 
    MinimumValue="2010/1/1"
    MaximumValue="2012/12/31" 
    ErrorMessage="範囲外" />
URLを表す属性を持つHTML5の新要素でrunat="server"をサポート

VIDEO要素等、URLを表す属性(この場合はsrc属性)を持つ要素で、runat="server"をサポートしました。これで何が嬉しいかというと、URL中で『~』演算子を使ってパスを相対的に書くことができるようになる点が挙げられています。例えば、『

UpdatePanedlコントロールのHTML5 input要素のポストの修正

『The UpdatePanel control has been fixed to support posting HTML5 input fields.』と書かれていて、最初何のことを言っているのか良くわかりませんでしたが、どうやらConnectで挙げられてる『Partial postback (updatepanel) do not post new HTML5 input fields (type=number) 』が解決された…ということ…なのでしょうか?

ちょっと検証する時間が取れていませんので、これについてはまた検証してみたいと思います。

まとめ

こう見ると、やはりHTML5への対応というのが目立ちますね。input要素の新しいタイプなどはブラウザの対応にも左右されますが、モバイル開発などでは特に有効に利用できるシーンもあるように思います。ぜひ、一度確認してみていただければと思います。


さて、明日のOne ASP.NET Advent Calendar 2012 23日目は、@さんです。よろしくお願いしまーす!

*1:ASP.NET 4以前。このプロジェクトを設定の『対象のフレームワーク』を[.NET Framework 4]以前をに変更すると以前の出力を得ることができます