ASP.NET 4.5 の Web フォームの新機能

by Web Camps Team

新しいバージョンの ASP.NET Web Formsでは、データを操作するときのユーザー エクスペリエンスの向上に重点を置いた多くの機能強化が導入されています。

以前のバージョンのWeb Formsでは、データ バインディングを使用してオブジェクト メンバーの値を出力するときに、データ バインディング式 Bind() または Eval() を使用しました。 ASP.NET の新しいバージョンでは、新しい ItemType プロパティを使用して、コントロールがバインドされるデータの種類を宣言できます。 このプロパティを設定すると、厳密に型指定された変数を使用して、IntelliSense、メンバー ナビゲーション、コンパイル時チェックなど、Visual Studio 開発エクスペリエンスのすべての利点を受け取ります。

データ バインド コントロールを使用して、データの選択、更新、削除、挿入を行う独自のカスタム メソッドを指定できるようになりました。これにより、ページ コントロールとアプリケーション ロジック間の対話が簡略化されます。 さらに、モデル バインド機能が ASP.NET に追加されました。つまり、ページから直接メソッド型パラメーターにデータをマップできます。

最新バージョンのWeb Formsを使用して、ユーザー入力の検証も簡単にする必要があります。 System.ComponentModel.DataAnnotations 名前空間の検証属性を使用してモデル クラスに注釈を付け、すべてのサイト コントロールがその情報を使用してユーザー入力を検証することを要求できるようになりました。 Web Formsのクライアント側検証が jQuery と統合され、よりクリーンなクライアント側コードと目立たない JavaScript 機能が提供されるようになりました。

要求検証領域では、アプリケーションの特定の部分の要求検証を選択的にオフにしたり、無効な要求データを読み取ったりしやすくなるように改善されています。

HTML5 の新機能を利用するために、サーバー コントロールをWeb Formsするためのいくつかの機能強化が行われました。

  • TextBox コントロールの TextMode プロパティは、電子メール、datetime などの新しい HTML5 入力の種類をサポートするように更新されました。
  • FileUpload コントロールで、この HTML5 機能をサポートするブラウザーからの複数のファイルアップロードがサポートされるようになりました。
  • 検証コントロールで HTML5 入力要素の検証がサポートされるようになりました。
  • URL を表す属性を持つ新しい HTML5 要素で、runat="server" がサポートされるようになりました。 その結果、~ 演算子などの URL パスで ASP.NET 規則を使用して、アプリケーション ルートを表すことができます (たとえば、 <video runat="server" src="~/myVideo.wmv"></video>)。
  • UpdatePanel コントロールは、HTML5 入力フィールドの投稿をサポートするように修正されました。

公式の ASP.NET ポータルでは、「ASP.NET WebForms 4.5: ASP.NET 4.5 および Visual Studio 2012 の新機能」の新機能の例を確認できます。

すべてのサンプル コードとスニペットは、 Web Camps トレーニング キットに含まれています。

目標

このハンズオン ラボでは、次の方法を学習します。

  • 厳密に型指定されたデータ バインディング式を使用する
  • Web Formsで新しいモデル バインド機能を使用する
  • 分離コード メソッドへのページ データのマッピングに値プロバイダーを使用する
  • ユーザー入力の検証にデータ注釈を使用する
  • Web Formsで jQuery を使用して控えめなクライアント側検証を利用する
  • 詳細な要求検証を実装する
  • Web Formsで非同期ページ処理を実装する

前提条件

このラボを完了するには、次の項目が必要です。

セットアップ

コード スニペットのインストール

便宜上、このラボで管理するコードの多くは、Visual Studio コード スニペットとして使用できます。 コード スニペットをインストールするには、 .\Source\Setup\CodeSnippets.vsi ファイルを実行します。

Visual Studio Code スニペットに慣れていない場合に、その使用方法を学習する場合は、このドキュメントの付録「付録 C: コード スニペットの使用」を参照してください。

演習

このハンズオン ラボには、次の演習が含まれています。

  1. 演習 1: ASP.NET Web Formsでのモデル バインド
  2. 演習 2: データの検証
  3. 演習 3: ASP.NET Web Formsでの非同期ページ処理

Note

各演習には、演習を完了した後に取得する必要がある結果のソリューションを含む End フォルダーが含まれています。 このソリューションは、演習の作業に関する追加のヘルプが必要な場合は、ガイドとして使用できます。

このラボを完了するための推定時間: 60 分

演習 1: ASP.NET Web Formsでのモデル バインド

新しいバージョンの ASP.NET Web Formsでは、データを操作するときのエクスペリエンスの向上に重点を置いた多くの機能強化が導入されています。 この演習では、厳密に型指定されたデータ コントロールとモデル バインドについて学習します。

タスク 1 - Strongly-Typed Data-Bindingsの使用

このタスクでは、ASP.NET 4.5 で使用できる新しい厳密に型指定されたバインドを検出します。

  1. Source/Ex1-ModelBinding/Begin/ フォルダーにある Begin ソリューションを開きます。

    1. 続行する前に、不足している NuGet パッケージをいくつかダウンロードする必要があります。 これを行うには、[ プロジェクト ] メニューをクリックし、[ NuGet パッケージの管理] を選択します。

    2. [ NuGet パッケージの管理 ] ダイアログで、[ 復元 ] をクリックして、不足しているパッケージをダウンロードします。

    3. 最後に、[ソリューションのビルド] をクリックしてソリューションを ビルド | します

      Note

      NuGet を使用する利点の 1 つは、プロジェクト内のすべてのライブラリを出荷する必要がなく、プロジェクト サイズを小さくすることです。 NuGet Power Tools では、Packages.config ファイルでパッケージのバージョンを指定することで、プロジェクトを初めて実行するときに必要なすべてのライブラリをダウンロードできます。 このため、このラボから既存のソリューションを開いた後に、これらの手順を実行する必要があります。

  2. Customers.aspx ページを開きます。 メイン コントロールに番号なしのリストを配置し、各顧客を一覧表示するためのリピータ コントロールを内部に含めます。 次のコードに示すように、リピータ名を customersRepeater に設定します。

    以前のバージョンのWeb Formsでは、データ バインディングを使用してデータ バインディング先のオブジェクトのメンバーの値を出力する場合は、Eval メソッドの呼び出しと共にデータ バインディング式を使用し、メンバーの名前を文字列として渡していました。

    実行時に、Eval へのこれらの呼び出しでは、現在バインドされている オブジェクトに対するリフレクションを使用して、指定された名前のメンバーの値を読み取り、結果を HTML に表示します。 この方法を使用すると、任意の整形されていないデータに対してデータバインドを非常に簡単に行うことができます。

    残念ながら、メンバー名の IntelliSense、ナビゲーションのサポート (定義への移動など)、コンパイル時のチェックなど、Visual Studio の優れた開発時エクスペリエンス機能の多くが失われます。

    ...
    <asp:Content ID="Content3" ContentPlaceHolderID="MainContent" runat="server">
      <h3>Customers</h3>
      <ul>
        <asp:Repeater ID="customersRepeater" runat="server">
          <ItemTemplate>
                <li>
                    <%# Eval("FirstName") %>
                    <%# Eval("LastName") %>
                </li>
          </ItemTemplate>
        </asp:Repeater>
      </ul>
      <a href="CustomerDetails.aspx">Add a New Customer</a>
    </asp:Content>
    
  3. Customers.aspx.cs ファイルを開きます。

  4. 次の using ステートメントを追加します。

    using System.Linq;
    
  5. Page_Load メソッドで、リピータに顧客の一覧を設定するコードを追加します。

    (コード スニペット - Web Forms ラボ - Ex01 - 顧客データ ソースのバインド)

    protected void Page_Load(object sender, EventArgs e)
    {
        using (var db = new WebFormsLab.Model.ProductsContext())
        {
            this.customersRepeater.DataSource = db.Customers.ToList();
            this.customersRepeater.DataBind();
        }
    }
    

    このソリューションでは、EntityFramework を CodeFirst と共に使用して、データベースを作成してアクセスします。 次のコードでは、customersRepeater は、データベースからすべての顧客を返す具体化されたクエリにバインドされています。

  6. F5 キーを押してソリューションを実行し、[顧客] ページに移動して、リピータの動作を確認します。 ソリューションで CodeFirst を使用すると、アプリケーションの実行時にデータベースが作成され、ローカル SQL Express インスタンスに設定されます。

    リピータを使用して顧客を一覧表示する リピーターする

    リピータを使用して顧客を一覧表示する

    Note

    Visual Studio 2012 では、IIS Expressが既定の Web 開発サーバーです。

  7. ブラウザーを閉じて、Visual Studio に戻ります。

  8. 次に、 の実装を置き換えて、厳密に型指定されたバインドを使用します。 Customers.aspx ページを開き、リピータの新しい ItemType 属性を使用して、Customer 型をバインドの種類として設定します。

    <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
      <ul>
        <asp:Repeater ID="customersRepeater" 
                      ItemType="WebFormsLab.Model.Customer" 
                      runat="server">
          <ItemTemplate>
             ...
          </ItemTemplate>
        </asp:Repeater>
      </ul>
      <a href="CustomerDetails.aspx">Add a New Customer</a>
    </asp:Content>
    

    ItemType プロパティを使用すると、コントロールがバインドされるデータの種類を宣言でき、データ バインド コントロール内で厳密に型指定されたバインドを使用できます。

  9. ItemTemplate コンテンツを次のコードに置き換えます。

    <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
      ...
      <ul>
        <asp:Repeater ID="customersRepeater" ItemType="WebFormsLab.Model.Customer" runat="server">
          <ItemTemplate>
            <li>
              <a href="CustomerDetails.aspx?id=<%#: Item.Id %>">
                <%#: Item.FirstName %> <%#: Item.LastName %>
              </a>
            </li>
          </ItemTemplate>
        </asp:Repeater>
      </ul>
      <a href="CustomerDetails.aspx">Add a New Customer</a>
    </asp:Content>
    

    上記のアプローチの欠点の 1 つは、Eval() と Bind() の呼び出しが遅延バインディングであるということです。つまり、プロパティ名を表す文字列を渡します。 つまり、メンバー名の Intellisense、コード ナビゲーションのサポート (定義への移動など)、コンパイル時のチェックのサポートは得られません。

    ItemType プロパティを設定すると、データ バインディング式のスコープで 2 つの新しい型指定された変数が生成されます。 ItemBindItem。 これらの厳密に型指定された変数は、データ バインディング式で使用でき、Visual Studio 開発エクスペリエンスの利点を最大限に活用できます。

    式で使用される ": " は、セキュリティの問題 (クロスサイト スクリプティング攻撃など) を回避するために出力を自動的に HTML エンコードします。 この表記は、応答書き込みに .NET 4 以降で使用できますが、データ バインディング式でも使用できるようになりました。

    Note

    Item メンバーは、一方向バインディングに対して機能します。 双方向バインディングを実行する場合は、 BindItem メンバーを使用します。

    厳密に型指定されたバインドでの IntelliSense

    厳密に型指定されたバインドでの IntelliSense のサポート

  10. F5 キーを押してソリューションを実行し、[顧客] ページに移動して、変更が期待どおりに機能することを確認します。

    顧客の詳細の一覧表示 顧客

    顧客の詳細を一覧表示する

  11. ブラウザーを閉じて、Visual Studio に戻ります。

タスク 2 - Web Formsでのモデル バインドの概要

以前のバージョンの ASP.NET Web Formsでは、データの取得と更新の両方で双方向のデータ バインディングを実行する場合は、データ ソース オブジェクトを使用する必要があります。 オブジェクト データ ソース、SQL データ ソース、LINQ データ ソースなどです。 ただし、シナリオでデータを処理するためにカスタム コードが必要な場合は、オブジェクト データ ソースを使用する必要があり、これにはいくつかの欠点が生じていました。 たとえば、複合型を回避する必要があり、検証ロジックの実行時に例外を処理する必要があります。

新しいバージョンの ASP.NET Web Forms では、データ バインド コントロールはモデル バインドをサポートしています。 つまり、分離コード ファイルまたは別のクラスからロジックを呼び出すために、選択、更新、挿入、および削除の各メソッドをデータ バインド コントロールに直接指定できます。

これについては、GridView を使用して、新しい SelectMethod 属性を使用して製品カテゴリを一覧表示します。 この属性を使用すると、GridView データを取得するためのメソッドを指定できます。

  1. Products.aspx ページを開き、GridView を含めます。 厳密に型指定されたバインドを使用し、並べ替えとページングを有効にするには、次に示すように GridView を構成します。

    <asp:Content ID="Content3" ContentPlaceHolderID="MainContent" runat="server">
     <asp:GridView ID="categoriesGrid" runat="server"
        AutoGenerateColumns="false"
        ItemType="WebFormsLab.Model.Category" DataKeyNames="CategoryID">
        <Columns>
          <asp:BoundField DataField="CategoryId" HeaderText="ID" SortExpression="CategoryId" />
          <asp:BoundField DataField="CategoryName" HeaderText="Name" SortExpression="CategoryName" />
          <asp:BoundField DataField="Description" HeaderText="Description" />
          <asp:TemplateField HeaderText="# of Products">
            <ItemTemplate><%#: Item.Products.Count %></ItemTemplate>
          </asp:TemplateField>
        </Columns>
      </asp:GridView>
    </asp:Content>
    
  2. 新しい SelectMethod 属性を使用して、 GetCategories メソッドを呼び出してデータを選択するように GridView を構成します。

    <asp:GridView ID="categoriesGrid" runat="server"
        AutoGenerateColumns="false"
        ItemType="WebFormsLab.Model.Category" DataKeyNames="CategoryId"
        SelectMethod="GetCategories">
      <Columns>
        <asp:BoundField DataField="CategoryId" HeaderText="ID" SortExpression="CategoryId" />
        <asp:BoundField DataField="CategoryName" HeaderText="Name" SortExpression="CategoryName" />
        <asp:BoundField DataField="Description" HeaderText="Description" />
        <asp:TemplateField HeaderText="# of Products">
          <ItemTemplate><%#: Item.Products.Count %></ItemTemplate>
        </asp:TemplateField>
      </Columns>
    </asp:GridView>
    
  3. Products.aspx.cs 分離コード ファイルを開き、次の using ステートメントを追加します。

    (コード スニペット - Web Forms ラボ - Ex01 - 名前空間)

    using System.Collections.Generic;
    using System.Data.Entity;
    using System.Data.Entity.Infrastructure;
    using System.Linq;
    using WebFormsLab.Model;
    
  4. Products クラスにプライベート メンバーを追加し、ProductsContext の新しいインスタンスを割り当てます。 このプロパティには、データベースに接続できる Entity Framework データ コンテキストが格納されます。

    public partial class Products : System.Web.UI.Page
    {
        private ProductsContext db = new ProductsContext();
        ...
    
  5. LINQ を使用してカテゴリの一覧を取得する GetCategories メソッドを作成します。 クエリには Products プロパティが含まれるため、GridView は各カテゴリの製品の量を表示できます。 メソッドは、ページ ライフサイクルの後半で実行されるクエリを表す生の IQueryable オブジェクトを返します。

    (コード スニペット - Web Forms ラボ - Ex01 - GetCategories)

    public IQueryable<Category> GetCategories()
    {
      var query = this.db.Categories
        .Include(c => c.Products);
    
      return query;
    }
    

    Note

    以前のバージョンの ASP.NET Web Formsでは、独自のカスタム コードを記述し、必要なすべてのパラメーターを受け取るために必要な、オブジェクト データ ソース コンテキスト内で独自のリポジトリ ロジックを使用して並べ替えとページングを有効にしました。 これで、データ バインディング メソッドは IQueryable を返し、これはまだ実行されるクエリを表すので、適切な並べ替えパラメーターとページング パラメーターを追加するようにクエリを変更 ASP.NET。

  6. F5 キーを押してサイトのデバッグを開始し、[製品] ページに移動します。 GridView には、GetCategories メソッドによって返されるカテゴリが設定されていることがわかります。

    モデル バインドを使用した GridView の設定 モデル バインド

    モデル バインドを使用した GridView の設定

  7. ShiftF5 キー+押してデバッグを停止します。

タスク 3 - モデル バインドの値プロバイダー

モデル バインドを使用すると、データ バインド コントロールでデータを直接操作するカスタム メソッドを指定できるだけでなく、ページのデータをこれらのメソッドのパラメーターにマップすることもできます。 メソッド パラメーターでは、値プロバイダー属性を使用して値のデータ ソースを指定できます。 次に例を示します。

  • ページ上のコントロール
  • クエリ文字列値
  • データの表示
  • セッション状態
  • Cookie
  • 投稿されたフォーム データ
  • ビューの状態
  • カスタム値プロバイダーもサポートされています

MVC 4 ASP.NET 使用している場合は、モデル バインドのサポートが似ていることがわかります。 実際、これらの機能は ASP.NET MVC から取得され、Web Formsでも使用できるように System.Web アセンブリに移動されました。

このタスクでは、GridView を更新して、モデル バインドを使用してフィルター パラメーターを受け取り、各カテゴリの製品の量で結果をフィルター処理します。

  1. [Products.aspx] ページに戻るします。

  2. GridView の上部に LabelComboBox を追加して、次に示すように各カテゴリの製品数を選択します。

    <h3>Categories</h3>
    <asp:Label ID="Label1" runat="server" AssociatedControlID="minProductsCount">
         Show categories with at least this number of products:
    </asp:Label>
    <asp:DropDownList runat="server" ID="minProductsCount" AutoPostBack="true">
      <asp:ListItem Value="" Text="-" />
      <asp:ListItem Text="1" />
      <asp:ListItem Text="3" />
      <asp:ListItem Text="5" />
    </asp:DropDownList>
    <br/>
    
  3. GridView に EmptyDataTemplate を追加して、選択した製品数のカテゴリがない場合にメッセージを表示します。

    <asp:GridView ID="categoriesGrid" runat="server"
        AutoGenerateColumns="false"
        ItemType="WebFormsLab.Model.Category" DataKeyNames="CategoryId"
        SelectMethod="GetCategories">
      <Columns>
        <asp:BoundField DataField="CategoryId" HeaderText="ID" />
        <asp:BoundField DataField="CategoryName" HeaderText="Name" />
        <asp:BoundField DataField="Description" HeaderText="Description" />
        <asp:TemplateField HeaderText="# of Products">
          <ItemTemplate><%#: Item.Products.Count %></ItemTemplate>
        </asp:TemplateField>
      </Columns>
      <EmptyDataTemplate>
          No categories found with a product count of <%#: minProductsCount.SelectedValue %>
      </EmptyDataTemplate>
    </asp:GridView>
    
  4. Products.aspx.cs 分離コードを開き、次の using ステートメントを追加します。

    using System.Web.ModelBinding;
    
  5. 整数の minProductsCount 引数を受け取り、返された結果をフィルター処理するように GetCategories メソッドを変更します。 これを行うには、 メソッドを次のコードに置き換えます。

    (コード スニペット - Web Forms ラボ - Ex01 - GetCategories 2)

    public IQueryable<Category> GetCategories([Control]int? minProductsCount)
    {
        var query = this.db.Categories
        .Include(c => c.Products);
    
        if (minProductsCount.HasValue)
        {
            query = query.Where(c => c.Products.Count >= minProductsCount);
        }
    
        return query;
    }
    

    minProductsCount 引数の新しい [Control] 属性は、ページ内のコントロールを使用して値を設定する必要 ASP.NET 知らせます。 ASP.NET は、引数の名前 (minProductsCount) に一致するコントロールを検索し、必要なマッピングと変換を実行してパラメーターにコントロール値を入力します。

    または、 属性は、値を取得する場所からコントロールを指定できるオーバーロードされたコンストラクターを提供します。

    Note

    データ バインディング機能の目的の 1 つは、ページ操作のために記述する必要があるコードの量を減らすことです。 [コントロール] 値プロバイダーとは別に、メソッド パラメーターで他のモデル バインディング プロバイダーを使用できます。 その一部は、タスクの概要に記載されています。

  6. F5 キーを押してサイトのデバッグを開始し、[製品] ページに移動します。 ドロップダウン リストからいくつかの製品を選択し、GridView がどのように更新されているかを確認します。

    ドロップダウン リスト値を使用した GridView の

    ドロップダウン リスト値を使用した GridView のフィルター処理

  7. デバッグを停止します。

タスク 4 - フィルター処理にモデル バインドを使用する

このタスクでは、2 つ目の子 GridView を追加して、選択したカテゴリ内の製品を表示します。

  1. Products.aspx ページを開き、カテゴリ GridView を更新して[選択] ボタンを自動生成します。

    <asp:GridView ID="categoriesGrid" runat="server"
      AutoGenerateColumns="false"
      ItemType="WebFormsLab.Model.Category" DataKeyNames="CategoryId"
      SelectMethod="GetCategories"
      AutoGenerateSelectButton="true">
    
  2. 下部に productsGrid という名前の 2 つ目の GridView を追加します。 ItemTypeWebFormsLab.Model.Product に、DataKeyNames をProductId に、SelectMethodGetProducts に設定します。 AutoGenerateColumnsfalse に設定し、ProductId、ProductName、Description、UnitPrice の列を追加します。

    <h3>Products</h3>
    <asp:GridView ID="productsGrid" runat="server" 
        CellPadding="4"
        AutoGenerateColumns="false"
        ItemType="WebFormsLab.Model.Product"
        DataKeyNames="ProductId"
        SelectMethod="GetProducts">
        <Columns>
            <asp:BoundField DataField="ProductId" HeaderText="ID" />
            <asp:BoundField DataField="ProductName" HeaderText="Name" />
            <asp:BoundField DataField="Description" HeaderText="Description" HtmlEncode="false" />
            <asp:BoundField DataField="UnitPrice" HeaderText="Price" />
        </Columns>
        <EmptyDataTemplate>
            Select a category above to see its products
        </EmptyDataTemplate>
    </asp:GridView>
    
  3. Products.aspx.cs 分離コード ファイルを開きます。 GetProducts メソッドを実装して、カテゴリ GridView からカテゴリ ID を受け取り、製品をフィルター処理します。 モデル バインドでは、 categoriesGrid で選択した行を使用してパラメーター値が設定されます。 引数の名前とコントロール名が一致しないため、コントロール値プロバイダーでコントロールの名前を指定する必要があります。

    (コード スニペット - Web Forms ラボ - Ex01 - GetProducts)

    public IEnumerable<Product> GetProducts([Control("categoriesGrid")]int? categoryId)
    {
        return this.db.Products.Where(p => p.CategoryId == categoryId);
    }
    

    Note

    この方法により、これらのメソッドを簡単に単体テストできます。 Web Formsが実行されていない単体テスト コンテキストでは、[Control] 属性は特定のアクションを実行しません。

  4. Products.aspx ページを開き、製品 GridView を見つけます。 製品 GridView を更新して、選択した製品を編集するためのリンクを表示します。

    <h3>Products</h3>
    <asp:GridView ID="productsGrid" runat="server" 
      CellPadding="4"
      AutoGenerateColumns="false"
      ItemType="WebFormsLab.Model.Product"
      DataKeyNames="ProductId"
      SelectMethod="GetProducts">
      <Columns>
        <asp:TemplateField>
          <ItemTemplate>
            <a href="ProductDetails.aspx?productId=<%#: Item.ProductId %>">View</a>
          </ItemTemplate>
        </asp:TemplateField>
        <asp:BoundField DataField="ProductId" HeaderText="ID" />
        <asp:BoundField DataField="ProductName" HeaderText="Name" />
        <asp:BoundField DataField="Description" HeaderText="Description" HtmlEncode="false" />
        <asp:BoundField DataField="UnitPrice" HeaderText="Price" />
      </Columns>
      <EmptyDataTemplate>
        Select a category above to see its products
      </EmptyDataTemplate>
    </asp:GridView>
    
  5. ProductDetails.aspx ページの分離コードを開き、SelectProduct メソッドを次のコードに置き換えます。

    (コード スニペット - Web Forms ラボ - Ex01 - SelectProduct メソッド)

    public Product SelectProduct([QueryString]int? productId)
    {
        return this.db.Products.Find(productId);
    }
    

    Note

    [QueryString] 属性を使用して、クエリ文字列の productId パラメーターからメソッド パラメーターを入力します。

  6. F5 キーを押してサイトのデバッグを開始し、[製品] ページに移動します。 カテゴリ GridView から任意のカテゴリを選択し、製品 GridView が更新されていることを確認します。

    選択したカテゴリの製品を表示する 選択したカテゴリ

    選択したカテゴリの製品を表示する

  7. 製品の [表示 ] リンクをクリックして、ProductDetails.aspx ページを開きます。

    ページが、クエリ文字列から productId パラメーターを使用して SelectMethod を使用して製品を取得していることに注意してください。

    製品の詳細の表示 製品

    製品の詳細の表示

    Note

    HTML の説明を入力する機能は、次の演習で実装されます。

タスク 5 - 更新操作にモデル バインドを使用する

前のタスクでは、主にデータの選択にモデル バインドを使用しました。このタスクでは、更新操作でモデル バインドを使用する方法について説明します。

カテゴリ GridView を更新して、ユーザーがカテゴリを更新できるようにします。

  1. Products.aspx ページを開き、カテゴリ GridView を更新して [編集] ボタンを自動生成し、新しい UpdateMethod 属性を使用して、選択したアイテムを更新する UpdateCategory メソッドを指定します。

    <asp:GridView ID="categoriesGrid" runat="server"
        AutoGenerateColumns="false"
        ItemType="WebFormsLab.Model.Category" DataKeyNames="CategoryId"
        SelectMethod="GetCategories"
        AutoGenerateSelectButton="true"
        AutoGenerateEditButton="true"
        UpdateMethod="UpdateCategory">
    

    GridView の DataKeyNames 属性では、モデルバインド オブジェクトを一意に識別するメンバーを定義します。そのため、update メソッドが少なくとも受け取るパラメーターです。

  2. Products.aspx.cs 分離コード ファイルを開き、UpdateCategory メソッドを実装します。 メソッドは、現在のカテゴリを読み込むカテゴリ ID を受け取り、GridView から値を設定してから、カテゴリを更新する必要があります。

    (コード スニペット - Web Forms ラボ - Ex01 - UpdateCategory)

    public void UpdateCategory(int categoryId)
    {
        var category = this.db.Categories.Find(categoryId);
    
        this.TryUpdateModel(category);
    
        if (this.ModelState.IsValid)
        {
            this.db.SaveChanges();
        }
    }
    

    Page クラスの新しい TryUpdateModel メソッドは、ページ内のコントロールの値を使用してモデル オブジェクトを設定します。 この場合、編集中の現在の GridView 行の更新された値が category オブジェクトに置き換えられます。

    Note

    次の演習では、オブジェクトの編集時にユーザーが入力したデータを検証するための ModelState.IsValid の使用方法について説明します。

  3. サイトを実行し、[製品] ページに移動します。 カテゴリを編集します。 新しい名前を入力し、[ 更新 ] をクリックして変更を保持します。

    カテゴリの編集 カテゴリ

    カテゴリの編集

演習 2: データの検証

この演習では、ASP.NET 4.5 の新しいデータ検証機能について説明します。 Web Formsの新しい目立たない検証機能をチェックします。 ユーザー入力の検証には、アプリケーション モデル クラスのデータ注釈を使用します。最後に、ページ内の個々のコントロールに対する要求の検証を有効または無効にする方法について説明します。

タスク 1 - 目立たない検証

検証コントロールを含む複雑なデータを含むフォームでは、ページ内で生成される JavaScript コードが多すぎる傾向があり、コードの約 60% を表す可能性があります。 目立たない検証を有効にすると、HTML コードがよりクリーンで、より適切に見えます。

このセクションでは、ASP.NET で目立たない検証を有効にして、両方の構成によって生成された HTML コードを比較します。

  1. Visual Studio 2012 を開き、このラボのSource\Ex2-Validation\Begin フォルダーにある Begin ソリューションを開きます。 または、前の演習の既存のソリューションに引き続き取り組むことができます。

    1. 提供された Begin ソリューションを開いた場合は、続行する前に、不足している NuGet パッケージをダウンロードする必要があります。 これを行うには、ソリューション エクスプローラーで WebFormsLab プロジェクト [NuGet パッケージの管理] をクリックします。

    2. [ NuGet パッケージの管理 ] ダイアログで、[ 復元 ] をクリックして、不足しているパッケージをダウンロードします。

    3. 最後に、[ソリューションのビルド] をクリックしてソリューションを ビルド | します

      Note

      NuGet を使用する利点の 1 つは、プロジェクト内のすべてのライブラリを出荷する必要がなく、プロジェクト サイズが小さくなる点です。 NuGet Power Tools では、Packages.config ファイルでパッケージのバージョンを指定することで、プロジェクトを初めて実行するときに必要なすべてのライブラリをダウンロードできます。 このため、このラボから既存のソリューションを開いた後に、これらの手順を実行する必要があります。

  2. F5 キーを押して Web アプリケーションを起動します。 [顧客] ページに移動し、[ 新しい顧客の追加 ] リンクをクリックします。

  3. ブラウザー ページを右クリックし、[ ソースの表示 ] オプションを選択して、アプリケーションによって生成された HTML コードを開きます。

    ページ HTML コードの表示 ページ

    ページ HTML コードの表示

  4. ページのソース コードをスクロールし、ASP.NET がページ内に JavaScript コードとデータ検証コントロールを挿入して検証を実行し、エラー 一覧を表示していることに注意してください。

    CustomerDetails ページでの検証 JavaScript コード CustomerDetails ページ

    CustomerDetails ページの検証 JavaScript コード

  5. ブラウザーを閉じて、Visual Studio に戻ります。

  6. 次に、目立たない検証を有効にします。 Web.Config開き、AppSettings セクションで ValidationSettings:UnobtrusiveValidationMode キーを見つけますキー値を WebForms に設定します。

    <configuration>
      ...
      <appSettings>
        <add key="aspnet:uselegacysynchronizationcontext" value="false" />
        <add key="ValidationSettings:UnobtrusiveValidationMode" value="WebForms"/>
    

    Note

    また、一部のページに対してのみ非妨げな検証を有効にする場合に備えて、"Page_Load" イベントでこのプロパティを設定することもできます。

  7. CustomerDetails.aspx を開き、F5 キーを押して Web アプリケーションを起動します。

  8. F12 キーを押して IE 開発者ツールを開きます。 開発者ツールが開いたら、スクリプト タブを選択します。メニューから CustomerDetails.aspx を選択し、ページで jQuery を実行するために必要なスクリプトがローカル サイトからブラウザーに読み込まれたことに注意してください。

    ローカル IIS サーバーから jQuery JavaScript ファイルを直接読み込むローカル IIS サーバー

    ローカル IIS サーバーから jQuery JavaScript ファイルを直接読み込む

  9. ブラウザーを閉じて Visual Studio に戻ります。 Site.Master ファイルをもう一度開き、ScriptManager を見つけます。 値が Trueの EnableCdn プロパティを追加します。 これにより、jQuery はローカル サイトの URL ではなく、オンライン URL から読み込まれます。

  10. Visual Studio で CustomerDetails.aspx を開きます。 F5 キーを押してサイトを実行します。 インターネット エクスプローラーが開いたら、F12 キーを押して開発者ツールを開きます。 [ スクリプト ] タブを選択し、ドロップダウン リストを確認します。 jQuery JavaScript ファイルは、ローカル サイトからではなく、オンラインの jQuery CDN から読み込まれるので注意してください。

    CDN からの jQuery JavaScript ファイルの読み込み CDN

    CDN からの jQuery JavaScript ファイルの読み込み

  11. ブラウザーの [ソースの表示] オプションを使用して、HTML ページのソース コードをもう一度開きます。 目立たない検証 ASP.NET を有効にすると、挿入された JavaScript コードが data- *attributes に置き換えられました。

    目立たない検証コード 目立

    目立たない検証コード

    Note

    この例では、データ注釈を含む検証の概要を、いくつかの HTML 行と JavaScript 行のみに簡略化する方法を確認しました。 以前は、目立たない検証を行わないと、追加する検証コントロールが多いほど、JavaScript 検証コードが大きくなります。

タスク 2 - データ注釈を使用したモデルの検証

ASP.NET 4.5 では、Web Formsのデータ注釈の検証が導入されています。 各入力に対して検証コントロールを使用する代わりに、モデル クラスで制約を定義し、すべての Web アプリケーションで使用できるようになりました。 このセクションでは、新しい顧客フォームの検証/編集にデータ注釈を使用する方法について説明します。

  1. CustomerDetail.aspx ページを開きます。 EditItemTemplate セクションと InsertItemTemplate セクションの顧客の名と 2 番目の名前は、RequiredFieldValidator コントロールを使用して検証されます。 各検証コントロールは特定の条件に関連付けられているため、チェックする条件と同じ数の検証コントロールを含める必要があります。

  2. Customer モデル クラスを検証するためのデータ注釈を追加します。 Model フォルダーで Customer.cs クラスを開き、データ注釈属性を使用して各プロパティを装飾します。

    (コード スニペット - Web Forms ラボ - Ex02 - データ注釈)

    namespace WebFormsLab.Model
    {
      using System.Collections.Generic;
      using System.ComponentModel.DataAnnotations;
    
      public class Customer
      {
         [Key]
         public int Id { get; set; }
    
         [Required]
         public string FirstName { get; set; }
    
         [Required]
         public string LastName { get; set; }
    
         [Range(0, 130)]
         public int Age { get; set; }
    
         public Address Address { get; set; }
    
         [Phone]
         public string DaytimePhone { get; set; }
    
         [EmailAddress, StringLength(256)]
         public string EmailAddress { get; set; }
      }
    }
    

    Note

    .NET Framework 4.5 では、既存のデータ注釈コレクションが拡張されています。 使用できるデータ注釈の一部は、[CreditCard]、[Phone]、[EmailAddress]、[Range]、[Compare]、[Url]、[FileExtensions]、[必須]、[キー]、[RegularExpression] です。

    いくつかの使用例:

    [キー]: 属性が一意識別子であることを指定します

    [Range(0.4, 0.5, ErrorMessage="{Write an error message}"]: Double range

    [EmailAddress(ErrorMessage="Invalid Email"), MaxLength(56)):同じ行に 2 つの注釈があります。

    各属性内で独自のエラー メッセージを定義することもできます。

  3. CustomerDetails.aspx を開き、FormView コントロールの EditItemTemplate セクションと InsertItemTemplate セクションの姓フィールドと名フィールドの RequiredFieldValidator をすべて削除します。

    <EditItemTemplate>
      <fieldset>
         <p><asp:Label runat="server" AssociatedControlID="firstName">First Name: </asp:Label></p>
         <p><asp:TextBox runat="server" ID="firstName" Text='<%#: BindItem.FirstName %>' />
            &nbsp;<asp:RequiredFieldValidator runat="server" ControlToValidate="firstName" ErrorMessage="Please enter a value for First Name" ForeColor="Red" />
        </p>
    
         <p><asp:Label runat="server" AssociatedControlID="lastName">Last Name: </asp:Label></p>
         <p><asp:TextBox runat="server" ID="lastName" Text='<%#: BindItem.LastName %>' />
              &nbsp;<asp:RequiredFieldValidator runat="server" ControlToValidate="lastName" ErrorMessage="Please enter a value for Last Name" ForeColor="Red" />
        </p>
      ...
    <InsertItemTemplate>        
     <fieldset>
       <p><asp:Label runat="server" AssociatedControlID="firstName">First Name: </asp:Label></p>
       <p><asp:TextBox runat="server" ID="firstName" Text='<%#: BindItem.FirstName %>' />           
         &nbsp;<asp:RequiredFieldValidator runat="server" ControlToValidate="firstName" ErrorMessage="Please enter a value for First Name" ForeColor="Red" />
        </p>
    
       <p><asp:Label runat="server" AssociatedControlID="lastName">Last Name: </asp:Label></p>                
        <p><asp:TextBox runat="server" ID="lastName" Text='<%#: BindItem.LastName %>' />
         &nbsp;<asp:RequiredFieldValidator runat="server" ControlToValidate="lastName" ErrorMessage="Please enter a value for Last Name" ForeColor="Red" />
        </p>
      ...
    

    Note

    データ注釈を使用する利点の 1 つは、検証ロジックがアプリケーション ページで重複しないことです。 モデルで 1 回定義し、データを操作するすべてのアプリケーション ページで使用します。

  4. CustomerDetails.aspx 分離コードを開き、SaveCustomer メソッドを見つけます。 このメソッドは、新しい顧客を挿入するときに呼び出され、FormView コントロールの値から Customer パラメーターを受け取ります。 ページ コントロールとパラメーター オブジェクトの間のマッピングが発生すると、ASP.NET はすべてのデータ注釈属性に対してモデル検証を実行し、発生したエラーが ModelState ディクショナリに入力されます (存在する場合)。

    ModelState.IsValid は、検証の実行後にモデルのすべてのフィールドが有効な場合にのみ true を返します。

    public void SaveCustomer(Customer customer) 
    {
        if (this.ModelState.IsValid)
        { 
            using (var db = new ProductsContext())
            {
                ...
    
  5. CustomerDetails ページの末尾に ValidationSummary コントロールを追加して、モデル エラーの一覧を表示します。

    </fieldset>
        </InsertItemTemplate>
      </asp:FormView>
    
      <asp:ValidationSummary runat="server" ShowModelStateErrors="true" 
           ForeColor="Red" HeaderText="Please check the following errors:"/>
    </asp:Content>
    

    ShowModelStateErrors は ValidationSummary コントロールの新しいプロパティで、true に設定すると、ModelState ディクショナリからのエラーがコントロールに表示されます。 これらのエラーは、データ注釈の検証に起因します。

  6. F5 キーを押して Web アプリケーションを実行します。 フォームに誤った値を入力し、[ 保存 ] をクリックして検証を実行します。 下部にあるエラーの概要に注目してください。

    データ注釈を使用した

    データ注釈を使用した検証

タスク 3 - ModelState を使用したカスタム データベース エラーの処理

以前のバージョンのWeb Formsでは、長すぎる文字列や一意のキー違反などのデータベース エラーを処理するには、リポジトリ コードで例外をスローし、分離コードで例外を処理してエラーを表示する必要があります。 比較的単純な操作を行うには、大量のコードが必要です。

Web Forms 4.5 では、ModelState オブジェクトを使用して、モデルまたはデータベースのエラーを一貫した方法でページに表示できます。

このタスクでは、データベースの例外を適切に処理し、ModelState オブジェクトを使用して適切なメッセージをユーザーに表示するコードを追加します。

  1. アプリケーションの実行中に、重複した値を使用してカテゴリの名前を更新してみてください。

    重複する名前でカテゴリを更新する 重複したする

    重複した名前でカテゴリを更新する

    CategoryName 列の "unique" 制約が原因で例外がスローされていることに注意してください。

    重複したカテゴリ名の例外 重複

    重複したカテゴリ名の例外

  2. デバッグを停止します。 Products.aspx.cs 分離コード ファイルで、Db によってスローされた例外を処理するように UpdateCategory メソッドを更新します。SaveChanges() メソッドを呼び出し、ModelState オブジェクトにエラーを追加します。

    新しい TryUpdateModel メソッドは、ユーザーが提供するフォーム データを使用して、データベースから取得したカテゴリ オブジェクトを更新します。

    (コード スニペット - Web Forms ラボ - Ex02 - UpdateCategory ハンドル エラー)

    public void UpdateCategory(int categoryId)
    {
      var category = this.db.Categories.Find(categoryId);
    
      this.TryUpdateModel(category);
    
      if (this.ModelState.IsValid)
      {
        try
        {
          this.db.SaveChanges();
        }
        catch (DbUpdateException)
        {
          var message = string.Format("A category with the name {0} already exists.", category.CategoryName);
          this.ModelState.AddModelError("CategoryName", message);
        }
      }
    }
    

    Note

    理想的には、DbUpdateException の原因を特定し、根本原因が一意キー制約の違反である場合はチェックする必要があります。

  3. Products.aspx を開き、カテゴリ GridView の下に ValidationSummary コントロールを追加して、モデル エラーの一覧を表示します。

    <asp:GridView ID="categoriesGrid" runat="server"
      ...
    </asp:GridView>
    
    <asp:ValidationSummary ID="ValidationSummary1" runat="server" ShowModelStateErrors="true" />
    
    <h3>Products</h3>
    
  4. サイトを実行し、[製品] ページに移動します。 重複した値を使用して、カテゴリの名前を更新してみてください。

    例外が処理され、 ValidationSummary コントロールにエラー メッセージが表示されます。

    重複したカテゴリ エラー

    重複したカテゴリ エラー

タスク 4 - ASP.NET Web Forms 4.5 で検証を要求する

ASP.NET の要求検証機能は、クロスサイト スクリプティング (XSS) 攻撃に対する特定のレベルの既定の保護を提供します。 以前のバージョンの ASP.NET では、要求の検証は既定で有効になっており、ページ全体に対してのみ無効にできました。 新しいバージョンの ASP.NET Web Formsでは、1 つのコントロールに対する要求の検証を無効にしたり、遅延要求の検証を実行したり、検証されていない要求データにアクセスしたりできるようになりました (その場合は注意してください)。

  1. Ctrl キーを押しながら F5 キーを押して、デバッグなしでサイトを起動し、[製品] ページに移動します。 カテゴリを選択し、いずれかの製品の [編集] リンクをクリックします。

  2. HTML タグなど、危険な可能性のあるコンテンツを含む説明を入力します。 要求の検証が原因でスローされた例外に注意してください。

    危険な可能性のあるコンテンツを含む製品する

    危険な可能性のあるコンテンツを含む製品を編集する

    要求検証が原因でスローされた例外要求の検証

    要求の検証が原因でスローされた例外

  3. ページを閉じ、Visual Studio で Shift キーを押しながら F5 キーを押してデバッグを停止します。

  4. ProductDetails.aspx ページを開き、Description TextBox を見つけます。

  5. 新しい ValidateRequestMode プロパティを TextBox に追加し、その値を Disabled に設定します。

    新しい ValidateRequestMode 属性を使用すると、各コントロールで要求の検証を細かく無効にすることができます。 これは、HTML コードを受け取る可能性がある入力を使用し、ページの残りの部分で検証を機能させ続ける場合に便利です。

    <p>
      <asp:TextBox runat="server" ID="Description" TextMode="MultiLine" 
                Cols="60" Rows="8" Text='<%# BindItem.Description %>' 
        ValidateRequestMode="Disabled" />
    </p>
    
  6. F5 キーを押して Web アプリケーションを実行します。 もう一度製品の編集ページを開き、HTML タグを含む製品の説明を入力します。 これで、HTML コンテンツを説明に追加できるようになりました。

    製品の説明に対して要求の検証が無効になっている製品の

    製品の説明に対して無効になっている要求の検証

    Note

    運用アプリケーションでは、ユーザーが入力した HTML コードをサニタイズして、安全な HTML タグのみが入力されていることを確認する必要があります (たとえば、スクリプト> タグはありません<)。 これを行うには、 Microsoft Web Protection ライブラリを使用できます。

  7. 製品をもう一度編集します。 [名前] フィールドに「HTML コード」と入力し、[保存] をクリック します。 [要求の検証] は [説明] フィールドでのみ無効になっており、残りのフィールドは危険な可能性のあるコンテンツに対して引き続き検証されることに注意してください。

    残りのフィールドで要求の検証が有効になっている残りのフィールド

    残りのフィールドで要求の検証が有効になっている

    ASP.NET Web Forms 4.5 には、要求検証を遅延的に実行するための新しい要求検証モードが含まれています。 要求検証モードを 4.5 に設定すると、コードの一部が Request.Form["key"] にアクセスした場合、4.5 の要求検証 ASP.NET、フォーム コレクション内の特定の要素に対する要求の検証のみがトリガーされます。

    さらに、ASP.NET 4.5 には、Microsoft Anti-XSS ライブラリ v4.0 のコア エンコード ルーチンが含まれるようになりました。 Anti-XSS エンコード ルーチンは、新しい System.Web.Security.AntiXss 名前空間にある新しい AntiXssEncoder 型によって実装されます。 AntiXssEncoder を使用するように encoderType パラメーターを構成すると、ASP.NET 内のすべての出力エンコードで新しいエンコード ルーチンが自動的に使用されます。

  8. ASP.NET 4.5 要求の検証では、要求データへの検証されていないアクセスもサポートされます。 ASP.NET 4.5 では、Unvalidated という名前の HttpRequest オブジェクトに新しいコレクション プロパティが追加されます。 HttpRequest.Unvalidated に移動すると、Forms、QueryStrings、Cookie、URL など、すべての一般的な要求データにアクセスできます。

    Request.Unvalidated オブジェクト

    Request.Unvalidated オブジェクト

    Note

    HttpRequest.Unvalidated プロパティは注意して使用してください。 危険なテキストがラウンドトリップされず、疑いのない顧客にレンダリングされないように、生の要求データに対してカスタム検証を慎重に実行してください。

演習 3: ASP.NET Web Formsでの非同期ページ処理

この演習では、ASP.NET Web Formsの新しい非同期ページ処理機能について説明します。

タスク 1 - 画像をアップロードして表示するように製品の詳細ページを更新する

このタスクでは、製品の詳細ページを更新して、ユーザーが製品のイメージ URL を指定し、読み取り専用ビューに表示できるようにします。 指定したイメージのローカル コピーを同期的にダウンロードして作成します。 次のタスクでは、非同期的に動作するようにこの実装を更新します。

  1. Visual Studio 2012 を開き、このラボのフォルダーから Source\Ex3-Async\Begin にある Begin ソリューションを読み込みます。 または、前の演習の既存のソリューションに引き続き取り組むことができます。

    1. 提供された Begin ソリューションを開いた場合は、続行する前に、不足している NuGet パッケージをいくつかダウンロードする必要があります。 これを行うには、ソリューション エクスプローラーで WebFormsLab プロジェクトをクリックし、[NuGet パッケージの管理] を選択します。

    2. [ NuGet パッケージの管理 ] ダイアログで、[ 復元 ] をクリックして、不足しているパッケージをダウンロードします。

    3. 最後に、[ソリューションのビルド] をクリックしてソリューションを ビルド | します

      Note

      NuGet を使用する利点の 1 つは、プロジェクト内のすべてのライブラリを出荷する必要がなく、プロジェクト サイズを小さくすることです。 NuGet Power Tools では、Packages.config ファイルでパッケージのバージョンを指定することで、プロジェクトを初めて実行するときに必要なすべてのライブラリをダウンロードできます。 このため、このラボから既存のソリューションを開いた後に、これらの手順を実行する必要があります。

  2. ProductDetails.aspx ページ ソースを開き、FormView の ItemTemplate にフィールドを追加して製品イメージを表示します。

    <ItemTemplate>
         <fieldset>
              <p><b><asp:Label ID="Label2" runat="server" AssociatedControlID="itemProductName">Name:</asp:Label></b></p>
              <p><asp:Label runat="server" ID="itemProductName" Text='<%#: Item.ProductName %>' /></p>
              <p><b><asp:Label ID="Label3" runat="server" AssociatedControlID="itemDescription">Description (HTML):</asp:Label></b></p>
              <p><asp:Label runat="server" ID="itemDescription" Text='<%# Item.Description %>' /></p>
              <p><b><asp:Label ID="Label4" runat="server" AssociatedControlID="itemUnitPrice">Price:</asp:Label></b></p>
              <p><asp:Label runat="server" ID="itemUnitPrice" Text='<%#: Item.UnitPrice %>' /></p>
    
              <p><b><asp:Label ID="Label5" runat="server" AssociatedControlID="itemUnitPrice">Image:</asp:Label></b></p>
              <p>
                    <img src="<%# string.IsNullOrEmpty(Item.ImagePath) ? "/Images/noimage.jpg" : 
                    Item.ImagePath %>" alt="Image" />
              </p>
    
              <br />
              <p>
                    <asp:Button ID="Button1" runat="server" CommandName="Edit" Text="Edit" />&nbsp;
                    <asp:HyperLink NavigateUrl="~/Products.aspx" Text="Back" runat="server" />
              </p>
         </fieldset>
    </ItemTemplate>
    
  3. FormView の EditTemplate でイメージ URL を指定するフィールドを追加します。

    <fieldset>
         <p><asp:Label ID="Label2" runat="server" AssociatedControlID="ProductName">Name:</asp:Label></p>
         <p><asp:TextBox runat="server" ID="ProductName" Text='<%#: BindItem.ProductName %>' /></p>
         <p><asp:Label ID="Label3" runat="server" AssociatedControlID="Description">Description (HTML):</asp:Label></p>
         <p>
              <asp:TextBox runat="server" ID="Description" TextMode="MultiLine" Cols="60" Rows="8" Text='<%# BindItem.Description %>'
                    ValidateRequestMode="Disabled" />
         </p>
         <p><asp:Label ID="Label4" runat="server" AssociatedControlID="UnitPrice">Price:</asp:Label></p>
         <p><asp:TextBox runat="server" ID="UnitPrice" Text='<%#: BindItem.UnitPrice %>' /></p>
    
         <p><asp:Label ID="Label1" runat="server" AssociatedControlID="ImagePath">Image URL:</asp:Label></p>
         <p><asp:TextBox runat="server" ID="ImagePath" Text='<%#:  BindItem.ImagePath %>' /></p>
    
         <br />
         <p>
              <asp:Button runat="server" CommandName="Update" Text="Save" />
              <asp:Button runat="server" CommandName="Cancel" Text="Cancel" CausesValidation="false" />
         </p>
    </fieldset>
    
  4. ProductDetails.aspx.cs 分離コード ファイルを開き、次の名前空間ディレクティブを追加します。

    (コード スニペット - Web Forms ラボ - Ex03 - 名前空間)

    using System.IO;
    using System.Net;
    using System.Web;
    
  5. ローカルの Images フォルダーにリモート イメージを格納し、新しいイメージの場所の値を使用して製品エンティティを更新する UpdateProductImage メソッドを作成します。

    (コード スニペット - Web Forms ラボ - Ex03 - UpdateProductImage)

    private void UpdateProductImage(Product product)
    {
        string imageUrl = product.ImagePath;
    
        if (!string.IsNullOrEmpty(imageUrl) && !VirtualPathUtility.IsAbsolute(imageUrl))
        {
            product.ImagePath = string.Format(
                                     "/Images/{0}{1}", 
                                     product.ProductId, 
                                     Path.GetExtension(imageUrl));
    
            using (var wc = new WebClient())
            {
                wc.DownloadFile(imageUrl, Server.MapPath(product.ImagePath));
            }
        }
    }
    
  6. UpdateProductImage メソッドを呼び出すように UpdateProduct メソッドを更新します。

    (コード スニペット - Web Forms ラボ - Ex03 - UpdateProductImage 呼び出し)

    public void UpdateProduct(int productId)
    {
        var product = this.db.Products.Find(productId);
    
        this.TryUpdateModel(product);
    
        this.UpdateProductImage(product);
    
        if (this.ModelState.IsValid)
        {
            this.db.SaveChanges();
        }
    }
    
  7. アプリケーションを実行し、製品のイメージのアップロードを試みます。

    製品のイメージの設定 製品

    製品のイメージの設定

タスク 2 - 製品の詳細ページへの非同期処理の追加

このタスクでは、製品の詳細ページを更新して、非同期的に動作させます。 ASP.NET 4.5 非同期ページ処理を使用して、実行時間の長いタスク (イメージのダウンロード プロセス) を強化します。

Web アプリケーションの非同期メソッドを使用して、スレッド プールの使用方法 ASP.NET 最適化できます。 ASP.NET 要求に参加するためにスレッド プール内のスレッドの数が限られているため、すべてのスレッドがビジー状態になると、ASP.NET は新しい要求の拒否を開始し、アプリケーション エラー メッセージを送信し、サイトを使用できなくなります。

Web サイトでの時間のかかる操作は、割り当てられたスレッドを長時間占有するため、非同期プログラミングに適しています。 これには、実行時間の長い要求、データベースのクエリや外部 Web サーバーへのアクセスなど、オフライン操作を必要とするさまざまな要素やページがあるページが含まれます。 利点は、これらの操作に非同期メソッドを使用する場合、ページの処理中にスレッドが解放され、スレッド プールに返され、新しいページ要求に参加するために使用できることです。 つまり、ページはスレッド プールから 1 つのスレッドで処理を開始し、非同期処理の完了後に別のスレッドで処理を完了する可能性があります。

  1. ProductDetails.aspx ページを開きます。 Page 要素に Async 属性を追加し、true に設定します。 この属性は、IHttpAsyncHandler インターフェイスを実装するように ASP.NET に指示します。

    <%@ Page Title="" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true"
        CodeBehind="ProductDetails.aspx.cs" Inherits="WebFormsLab.ProductDetails"
        Async="true" %>
    
  2. ページの下部にラベルを追加して、ページを実行しているスレッドの詳細を表示します。

    <EmptyDataTemplate>Product not found</EmptyDataTemplate>
      </asp:FormView>
    
      <asp:Label ID="threadsMessageLabel" runat="server" />
    </asp:Content>
    
  3. ProductDetails.aspx.cs を開き、次の名前空間ディレクティブを追加します。

    (コード スニペット - Web Forms ラボ - Ex03 - 名前空間 2)

    using System.Web.UI;
    using System.Threading;
    
  4. UpdateProductImage メソッドを変更して、非同期タスクでイメージをダウンロードします。 WebClientDownloadFile メソッドを DownloadFileTaskAsync メソッドに置き換え、await キーワード (keyword)を含めます。

    (コード スニペット - Web Forms ラボ - Ex03 - UpdateProductImage Async)

    private void UpdateProductImage(Product product)
    {
        string imageUrl = product.ImagePath;
    
        if (!string.IsNullOrEmpty(imageUrl) && !VirtualPathUtility.IsAbsolute(imageUrl))
        {
            product.ImagePath = string.Format(
                "/Images/{0}{1}", 
                product.ProductId, 
                Path.GetExtension(imageUrl));
    
            this.RegisterAsyncTask(new PageAsyncTask(async (t) =>
            {
                using (var wc = new WebClient())
                {
                    await wc.DownloadFileTaskAsync(imageUrl, this.Server.MapPath(product.ImagePath));
                }
            }));
        }
    }
    

    RegisterAsyncTask は、別のスレッドで実行される新しいページ非同期タスクを登録します。 実行される Task (t) を含むラムダ式を受け取ります。 DownloadFileTaskAsync メソッドの await キーワード (keyword)は、DownloadFileTaskAsync メソッドの完了後に非同期的に呼び出されるコールバックにメソッドの残りの部分変換します。 ASP.NET は、すべての HTTP 要求の元の値を自動的に維持することで、 メソッドの実行を再開します。 .NET 4.5 の新しい非同期プログラミング モデルを使用すると、同期コードによく似た非同期コードを記述し、コンパイラがコールバック関数または継続コードの複雑さを処理できるようにします。

    Note

    RegisterAsyncTask と PageAsyncTask は、.NET 2.0 以降で既に使用できます。 await キーワード (keyword)は .NET 4.5 非同期プログラミング モデルの新機能であり、.NET WebClient オブジェクトの新しい TaskAsync メソッドと共に使用できます。

  5. コードを追加して、コードが開始され、実行が完了したスレッドを表示します。 これを行うには、次のコードを使用して UpdateProductImage メソッドを更新します。

    (コード スニペット - Web Forms ラボ - Ex03 - スレッドの表示)

    private void UpdateProductImage(Product product)
    {
      string imageUrl = product.ImagePath;
    
      if (!string.IsNullOrEmpty(imageUrl) && !VirtualPathUtility.IsAbsolute(imageUrl))
      {
        product.ImagePath = string.Format(
             "/Images/{0}{1}", 
             product.ProductId, 
             Path.GetExtension(imageUrl));
    
        this.RegisterAsyncTask(new PageAsyncTask(async (t) =>
        {
          var startThread = Thread.CurrentThread.ManagedThreadId;
    
          using (var wc = new WebClient())
          {
            await wc.DownloadFileTaskAsync(imageUrl, this.Server.MapPath(product.ImagePath));
          }
    
          var endThread = Thread.CurrentThread.ManagedThreadId;
    
          this.threadsMessageLabel.Text = string.Format("Started on thread: {0}<br /> Finished on thread: {1}", startThread, endThread);
        }));
      }
    }
    
  6. Web サイトの Web.configファイルを 開きます。 次の appSetting 変数を追加します。

    <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true"/>
    
  7. F5 キーを押してアプリケーションを実行し、製品のイメージをアップロードします。 コードが開始および終了したスレッド ID が異なる場合があることに注意してください。 これは、非同期タスクがスレッド プールとは別のスレッド ASP.NET 実行されるためです。 タスクが完了すると、ASP.NET タスクがキューに戻され、使用可能なスレッドが割り当てられます。

    イメージを非同期的にダウンロード

    イメージを非同期的にダウンロードする


まとめ

このハンズオン ラボでは、次の概念に対処し、デモを行いました。

  • 厳密に型指定されたデータ バインディング式を使用する
  • Web Formsで新しいモデル バインド機能を使用する
  • 分離コード メソッドへのページ データのマッピングに値プロバイダーを使用する
  • ユーザー入力の検証にデータ注釈を使用する
  • Web Formsで jQuery を使用して控えめなクライアント側検証を利用する
  • 詳細な要求検証を実装する
  • Web Formsで非同期ページ処理を実装する

付録 A: Visual Studio Express 2012 for Web のインストール

Microsoft Web Platform Installerを使用して、Microsoft Visual Studio Express 2012 for Web または別の "Express" バージョンをインストールできます。 次の手順では、Microsoft Web Platform Installerを使用して Visual Studio Express 2012 for Web をインストールするために必要な手順について説明します。

  1. [](https://go.microsoft.com/?linkid=9810169https://go.microsoft.com/?linkid=9810169) に移動します。 または、Web プラットフォーム インストーラーを既にインストールしている場合は、それを開き、製品 "Visual Studio Express 2012 for Web with Azure SDK" を検索できます。

  2. [ 今すぐインストール] をクリックします。 Web プラットフォーム インストーラーがない場合は、最初にダウンロードしてインストールするようにリダイレクトされます。

  3. Web プラットフォーム インストーラーが開いたら、[インストール] をクリックしてセットアップを開始します。

    インストール Visual Studio Express

    Visual Studio Expressのインストール

  4. すべての製品のライセンスと使用条件を読み、[ 同意 する] をクリックして続行します。

    ライセンス条項に同意する

    ライセンス条項に同意する

  5. ダウンロードとインストールのプロセスが完了するまで待ちます。

    Installation progress

    Installation progress

  6. インストールが完了したら、[完了] をクリック します

    インストールが完了しました

    インストールが完了しました

  7. [ 終了 ] をクリックして Web プラットフォーム インストーラーを閉じます。

  8. web 用Visual Studio Expressを開くには、[スタート] 画面に移動し、"VS Express" の書き込みを開始し、[VS Express for Web] タイルをクリックします。

    VS Express for Web タイル

    VS Express for Web タイル

付録 B: Web 配置を使用した ASP.NET MVC 4 アプリケーションの発行

この付録では、Azure Portal から新しい Web サイトを作成し、ラボに従って取得したアプリケーションを発行し、Azure によって提供される Web デプロイ発行機能を利用する方法について説明します。

タスク 1 - Azure Portal から新しい Web サイトを作成する

  1. Azure 管理ポータルに移動し、サブスクリプションに関連付けられている Microsoft 資格情報を使用してサインインします。

    Note

    Azure では、10 ASP.NET Web サイトを無料でホストし、トラフィックの増加に合わせてスケーリングできます。 こちらからサインアップできます。

    Windows Azure portalにログオンするします

    ポータルへのログオン

  2. コマンド バーの [ 新規 ] をクリックします。

    新しい Web サイトの作成 新

    新しい Web サイトの作成

  3. [コンピューティングWeb サイト] | をクリックします。 次に、[ クイック作成 ] オプションを選択します。 新しい Web サイトの使用可能な URL を指定し、[Web サイトの 作成] をクリックします。

    Note

    Azure は、制御および管理できるクラウドで実行されている Web アプリケーションのホストです。 [クイック作成] オプションを使用すると、完成した Web アプリケーションをポータルの外部から Azure にデプロイできます。 データベースを設定する手順は含まれません。

    クイック作成を使用した新しい Web サイトの作成 クイック作成

    クイック作成を使用した新しい Web サイトの作成

  4. 新しい Web サイト が作成されるまで待ちます。

  5. Web サイトが作成されたら、 URL 列の下にあるリンクをクリックします。 新しい Web サイトが動作していることを確認します。

    新しい Web サイトを参照する

    新しい Web サイトを参照する

    実行中の Web サイト

    実行中の Web サイト

  6. ポータルに戻るし、[名前] 列の下にある Web サイトの名前をクリックして、管理ページを表示します。

    Web サイト管理ページを

    Web サイト管理ページを開く

  7. [ ダッシュボード ] ページの [概要 ] セクションで、[ 発行プロファイルのダウンロード ] リンクをクリックします。

    Note

    発行プロファイルには、有効になっている各発行方法について、Web アプリケーションを Azure に発行するために必要なすべての情報が含まれています。 発行プロファイルには、発行メソッドが有効化される各エンドポイントに接続して認証するために必要な URL、ユーザーの資格情報、およびデータベース文字列が含まれています。 Microsoft WebMatrix 2Microsoft Visual Studio Express for Webおよび Microsoft Visual Studio 2012 では、Web アプリケーションを Azure に発行するためのこれらのプログラムの構成を自動化するための発行プロファイルの読み取りがサポートされています。

    Web サイト発行プロファイルのダウンロード Web

    Web サイト発行プロファイルのダウンロード

  8. 発行プロファイル ファイルを既知の場所にダウンロードします。 この演習では、このファイルを使用して Visual Studio から Azure に Web アプリケーションを発行する方法について説明します。

    発行プロファイル ファイルの保存 発行

    発行プロファイル ファイルの保存

タスク 2 - データベース サーバーの構成

アプリケーションでSQL Serverデータベースを使用する場合は、SQL Database サーバーを作成する必要があります。 SQL Serverを使用しない単純なアプリケーションをデプロイする場合は、このタスクをスキップできます。

  1. アプリケーション データベースを格納するためのSQL Database サーバーが必要です。 サブスクリプションから SQL Database サーバーを表示するには、Azure 管理ポータルの Sql Databases | Servers | Server のダッシュボードを参照してください。 サーバーを作成していない場合は、コマンド バーの [追加] ボタンを使用してサーバーを作成できます。 次のタスクで使用するように 、サーバー名と URL、管理者ログイン名、パスワードをメモしておきます。 データベースは後のステージで作成されるため、まだ作成しないでください。

    SQL Database サーバー ダッシュボード

    SQL Database サーバー ダッシュボード

  2. 次のタスクでは、Visual Studio からのデータベース接続をテストします。そのため、ローカル IP アドレスをサーバーの 許可 IP アドレスの一覧に含める必要があります。 これを行うには、[ 構成] をクリックし、[ 現在のクライアント IP アドレス ] から IP アドレスを選択し、[ 開始 IP アドレス ] テキスト ボックスと [終了 IP アドレス ] テキスト ボックスに貼り付けて、[ add-client-ip-address-ok-button ] ボタンをクリックします。

    クライアント IP アドレスの追加

    クライアント IP アドレスの追加

  3. クライアント IP アドレスが許可された IP アドレスの一覧に追加されたら、[保存] をクリックして変更を確認します。

    変更の確認

    変更の確認

タスク 3 - Web 配置を使用して ASP.NET MVC 4 アプリケーションを発行する

  1. ASP.NET MVC 4 ソリューションに戻るします。 ソリューション エクスプローラーで、Web サイト プロジェクトを右クリックし、[発行] を選択します

    アプリケーションの発行 アプリケーション

    Web サイトの発行

  2. 最初のタスクで保存した発行プロファイルをインポートします。

    発行プロファイルのインポート 発行

    発行プロファイルのインポート

  3. [ 接続の検証] をクリックします。 検証が完了したら、[ 次へ] をクリックします。

    Note

    [接続の検証] ボタンの横に緑色のチェックマークが表示されたら、検証が完了します。

    接続の検証

    接続の検証

  4. [ 設定] ページの [ データベース ] セクションで、データベース接続のテキスト ボックス ( DefaultConnection) の横にあるボタンをクリックします。

    Web 配置構成

    Web 配置の構成

  5. 次のようにデータベース接続を構成します。

    • [サーバー名] に、tcp: プレフィックスを使用してSQL Databaseサーバーの URL を入力します。

    • [ ユーザー名] に、サーバー管理者のログイン名を入力します。

    • [ パスワード] に、サーバー管理者のログイン パスワードを入力します。

    • 新しいデータベース名を入力します。

      宛先接続文字列の構成

      宛先接続文字列の構成

  6. 次に、 [OK] をクリックします データベースの作成を求められたら、[ はい] をクリックします。

    データベースの作成 データベース

    データベースを作成する

  7. Azure のSQL Databaseに接続するために使用する接続文字列は、[既定の接続] ボックスに表示されます。 続けて、 [次へ] をクリックします。

    SQL Databaseを指す接続文字列

    SQL Databaseを指す接続文字列

  8. [プレビュー] ページ 、[ 発行] をクリックします。

    Web アプリケーションの発行 Web アプリケーション

    Web アプリケーションの発行

  9. 発行プロセスが完了すると、既定のブラウザーで発行された Web サイトが開きます。

付録 C: コード スニペットの使用

コード スニペットを使用すると、必要なすべてのコードをすぐに入手できます。 ラボ ドキュメントでは、次の図に示すように、使用できるタイミングが正確に示されます。

Visual Studio コード スニペットを使用してプロジェクトにコードを挿入する する

Visual Studio コード スニペットを使用してプロジェクトにコードを挿入する

キーボードを使用してコード スニペットを追加するには (C# のみ)

  1. コードを挿入する場所にカーソルを置きます。
  2. スニペット名の入力を開始します (スペースやハイフンは使用しません)。
  3. IntelliSense には、一致するスニペットの名前が表示されます。
  4. 正しいスニペットを選択します (または、スニペット全体の名前が選択されるまで入力を続けます)。
  5. Tab キーを 2 回押して、カーソル位置にスニペットを挿入します。

スニペット名の入力を開始する スニペット名

スニペット名の入力を開始する

Tab キーを押して強調表示されたスニペットを選択する します

Tab キーを押して強調表示されたスニペットを選択する

Tab キーをもう一度押すと、スニペットがもう

Tab キーをもう一度押すと、スニペットが展開されます

マウスを使用してコード スニペットを追加するには (C#、Visual Basic、XML) 1. コード スニペットを挿入する場所を右クリックします。

  1. [ スニペットの挿入] の後に [ マイ コード スニペット] を選択します
  2. 関連するスニペットを一覧からクリックして選択します。

コード スニペットを挿入する場所を右クリックし、[スニペットの挿入] を選択しますします。

コード スニペットを挿入する場所を右クリックし、[スニペットの挿入] を選択します。

リストから関連するスニペットを選択します。そのスニペットをクリックします

リストから関連するスニペットをクリックして選択します