ASP.NET 2.0 ページ モデル

作成者: Microsoft

ASP.NET 1.x では、開発者はインライン コード モデルとコードビハインド コード モデルのいずれかを選択できました。 コードビハインドを実装するには、@Page ディレクティブの Src 属性または CodeBehind 属性を使います。 ASP.NET 2.0 でも、開発者は引き続きインライン コードとコードビハインドのいずれかを選択できますが、コードビハインド モデルには大きな改良が加えられています。

ASP.NET 1.x では、開発者はインライン コード モデルとコードビハインド コード モデルのいずれかを選択できました。 コードビハインドを実装するには、@Page ディレクティブの Src 属性または CodeBehind 属性を使います。 ASP.NET 2.0 でも、開発者は引き続きインライン コードとコードビハインドのいずれかを選択できますが、コードビハインド モデルには大きな改良が加えられています。

コードビハインド モデルの機能強化

ASP.NET 2.0 のコードビハインド モデルの変更を完全に理解するには、ASP.NET 1.x にあったモデルを簡単に復習することをお勧めします。

ASP.NET 1.x のコードビハインド モデル

ASP.NET 1.x のコードビハインド モデルは、ASPX ファイル (Web フォーム) とプログラミング コードを含むコードビハインド ファイルで構成されていました。 この 2 つのファイルは、ASPX ファイルの @Page ディレクティブを使って接続されていました。 ASPX ページ上の各コントロールには、分離コード ファイル内にインスタンス変数という形で対応する宣言がありました。 また、分離コード ファイルには、イベント バインディングのコードと、Visual Studio デザイナーに必要な生成コードも含まれていました。 このモデルはかなりうまく機能していましたが、ASPX ページ内のすべての ASP.NET 要素には分離コード ファイル内の対応するコードが必要であったため、コードとコンテンツが完全に分離されていませんでした。 たとえば、デザイナーが Visual Studio IDE の外部で ASPX ファイルに新しいサーバー コントロールを追加した場合、分離コード ファイルにそのコントロールの宣言が存在しないため、アプリケーションは中断します。

ASP.NET 2.0 のコードビハインド モデル

ASP.NET 2.0 では、このモデルが大幅に改良されています。 ASP.NET 2.0 のコードビハインドは、ASP.NET 2.0 で提供された新しい "部分クラス" を使用して実装されました。 ASP.NET 2.0 のコードビハインド クラスは、部分クラスとして定義されています (つまり、クラス定義の一部のみが含まれています)。 クラス定義の残りの部分は、実行時または Web サイトのプリコンパイル時に、ASPX ページを使って ASP.NET 2.0 によって動的に生成されます。 分離コード ファイルと ASPX ページ間のリンクは、引き続き @ Page ディレクティブを使って確立されます。 ただし、ASP.NET 2.0 では、CodeBehind 属性や Src 属性ではなく、CodeFile 属性が使われるようになりました。 Inherits 属性は、ページのクラス名を指定するためにも使われます。

一般的な @ Page ディレクティブは次のようになります。

<%@Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>

ASP.NET 2.0 分離コード ファイルの一般的なクラス定義は次のようになります。

public partial class _Default : System.Web.UI.Page

Note

現在、部分クラスをサポートしているマネージド言語は C# と Visual Basic だけです。 そのため、J# を使う開発者は、ASP.NET 2.0 のコードビハインド モデルを使用できません。

新しいモデルでは、開発者は自分で作成したコードのみを含むコード ファイルを作成できるようになるため、コードビハインド モデルは強化されます。 また、分離コード ファイルにはインスタンス変数の宣言がないため、コードとコンテンツは完全に分離されます。

Note

ASPX ページの部分クラスはイベント バインディングが実行される場所であるため、Visual Basic 開発者はコードビハインドで Handles キーワードを使ってイベントをバインドすることで、パフォーマンスがわずかに向上することを実感できます。 C# には同等のキーワードがありません。

新しい @ Page ディレクティブ属性

ASP.NET 2.0 では、@ Page ディレクティブに多くの新しい属性が追加されました。 次の属性が ASP.NET 2.0 で新しく追加されました。

非同期

Async 属性を使うと、ページが非同期で実行されるように構成できます。 非同期ページについては、このモジュールで後ほど説明します。

非同期タイムアウト

非同期ページのタイムアウトを指定しました。 既定値は 45 秒です。

CodeFile

CodeFile 属性は、Visual Studio 2002 と 2003 の CodeBehind 属性に代わるものです。

CodeFileBaseClass

CodeFileBaseClass 属性は、複数のページを 1 つの基底クラスから派生させる場合に使われます。 ASP.NET では部分クラスが実装されているため、この属性を指定しない場合、ASPX ページで宣言されたコントロールを参照する共有の共通フィールドを使う基底クラスは正しく機能しません。これは、ASP.NET のコンパイル エンジンにより、ページ内のコントロールに基づいて新しいメンバーが自動的に作成されるからです。 そのため、ASP.NET の複数のページに共通の基底クラスが必要な場合は、CodeFileBaseClass 属性で基底クラスを指定して定義し、その基底クラスから各ページのクラスを派生させる必要があります。 この属性を使う場合は、CodeFile 属性も必要です。

CompilationMode

この属性を使うと、ASPX ページの CompilationMode プロパティを設定できます。 CompilationMode プロパティは、値 AlwaysAutoNever を含む列挙型です。 既定値は Always です。 Auto 設定にすると、可能な場合、ASP.NET によってページが動的にコンパイルされません。 動的コンパイルからページを除外すると、パフォーマンスが向上します。 ただし、除外対象のページにコンパイルする必要があるコードが含まれている場合、ページの参照時にエラーがスローされます。

イベント検証を有効にする

この属性には、ポストバックとコールバックのイベントを検証するかどうかを指定します。 これを有効にすると、ポストバックまたはコールバック イベントの引数で、最初にレンダリングしたサーバー コントロールが発生元かどうかが確認されます。

テーマを有効にする

この属性には、ASP.NET テーマをページで使うかどうかを指定します。 既定値は false です。 ASP.NET テーマについては、モジュール 10 のページを参照してください。

LinePragmas

この属性には、コンパイル時に行 pragma を追加するかどうかを指定します。 行 pragma は、コードの特定のセクションをマークするためにデバッガーによって使われるオプションです。

MaintainScrollPositionOnPostback

この属性には、ポストバック間のスクロール位置を維持するために JavaScript をページに挿入するかどうかを指定します。 この属性は、既定では false です。

この属性が true の場合、ASP.NET により、ポストバックに次のような <script> ブロックが追加されます。

<script src="/website/WebResource.axd?d=jBAvpwrdOM_V_Xzeox989A2 &t=632653133849531250" type="text/javascript"> </script>

この script ブロックの src は WebResource.axd であることに注意してください。 このリソースは物理パスではありません。 このスクリプトが要求されると、ASP.NET によってスクリプトが動的に構築されます。

MasterPageFile

この属性は、現在のページのマスター ページ ファイルを指定します。 相対パスと絶対パスのどちらでも構いません。 マスター ページについては、モジュール 4 のページを参照してください。

スタイル シート テーマ

この属性を使うと、ASP.NET 2.0 テーマで定義されているユーザー インターフェイスの外観のプロパティをオーバーライドできます。 テーマについては、モジュール 10 のページを参照してください。

Theme の値

ページのテーマを指定します。 StyleSheetTheme 属性に値が指定されていない場合、Theme 属性はページ上のコントロールに適用されるすべてのスタイルをオーバーライドします。

Title の値

ページのタイトルを設定します。 ここで指定した値は、レンダリングされたページの <title> 要素に表示されます。

ViewStateEncryptionMode

ViewStateEncryptionMode 列挙型の値を設定します。 使用できる値は AlwaysAutoNever です。 既定値は Auto です。この属性が Auto の値に設定されている場合、コントロールが RegisterRequiresViewStateEncryption メソッドを呼び出して要求すると、viewstate は暗号化されます。

@ Page ディレクティブによるパブリック プロパティ値の設定

ASP.NET 2.0 の @ Page ディレクティブのもう 1 つの新しい機能は、基底クラスのパブリック プロパティの初期値を設定する機能です。 たとえば、基底クラスに SomeText というパブリック プロパティがあり、ページの読み込み時にそれを Hello に初期化するとします。 これは、次のように @ Page ディレクティブに値を設定するだけで実現できます。

<%@Page Language="C#" SomeText="Hello!" Inherits="PageBase" %>

@ Page ディレクティブの SomeText 属性を使用して、基底クラスの SomeText プロパティの初期値を Hello! に設定します。 以下の動画は、@ Page ディレクティブを使って基底クラスのパブリック プロパティの初期値を設定するチュートリアルです。

Screenshot of the Microsoft Visual Studio window with a red arrow indicating a Some Text attribute on one of the lines.

全画面表示で動画を開く

Page クラスの新しいパブリック プロパティ

次のパブリック プロパティは ASP.NET 2.0 で新しく追加されました。

AppRelativeTemplateSourceDirectory

ページまたはコントロールへのアプリケーション相対パスを返します。 たとえば、http://app/folder/page.aspx にあるページの場合、プロパティは ~/folder/を返します。

AppRelativeVirtualPath

ページまたはコントロールへの相対仮想ディレクトリ パスを返します。 たとえば、http://app/folder/page.aspx にあるページの場合、プロパティは ~/folder/page.aspx を返します。

AsyncTimeout

非同期ページ処理に使われるタイムアウトを取得または設定します (非同期ページについては、このモジュールで後ほど説明します)。

ClientQueryString

要求された URL のクエリ文字列部分を返す読み取り専用プロパティ。 この値は URL エンコードされています。 HttpServerUtility クラスの UrlDecode メソッドを使ってデコードできます。

ClientScript

このプロパティは ClientScriptManager オブジェクトを返します。これは、クライアント側スクリプトの ASP.NET 出力を管理するために使用できます (ClientScriptManager クラスについては、このモジュールで後ほど説明します)。

EnableEventValidation

このプロパティは、ポストバックとコールバックのイベントに対してイベント検証を有効にするかどうかを制御します。 有効にすると、ポストバックまたはコールバック イベントの引数で、最初にレンダリングしたサーバー コントロールが発生元かどうかが確認されます。

EnableTheming

このプロパティは、ASP.NET 2.0 テーマをページに適用するかどうかを指定するブール値を取得または設定します。

Form

このプロパティは、ASPX ページ上の HTML フォームを HtmlForm オブジェクトとして返します。

このプロパティは、ページ ヘッダーを含む HtmlHead オブジェクトへの参照を返します。 返された HtmlHead オブジェクトを使って、スタイル シート、Meta タグなどを取得および設定できます。

IdSeparator

この読み取り専用プロパティを使うと、ASP.NET がページ上のコントロールに対して一意の ID を構築するときに、コントロール識別子を区切るために使われる文字を取得できます。 コードから直接使用するためのものではありません。

IsAsync

このプロパティを使うと、非同期ページが可能になります。 非同期ページについては、このモジュールで後ほど説明します。

IsCallback

ページがコールバックの結果である場合、この読み取り専用プロパティは true を返します。 コールバックについては、このモジュールで後ほど説明します。

IsCrossPagePostBack

ページがクロスページ ポストバックの一部である場合、この読み取り専用プロパティは true を返します。 クロスページ ポストバックについては、このモジュールで後ほど説明します。

アイテム

ページ コンテキストに格納されているすべてのオブジェクトを含む IDictionary インスタンスへの参照を返します。 この IDictionary オブジェクトに項目を追加すると、コンテキストの有効期間中はそれらを使用できるようになります。

MaintainScrollPositionOnPostBack

このプロパティは、ポストバック後にブラウザー内のページのスクロール位置を維持する JavaScript を ASP.NET が発行するかどうかを制御します (このプロパティの詳細については、このモジュールの前半で説明しました)。

マスター

この読み取り専用プロパティは、マスター ページが適用されているページの MasterPage インスタンスへの参照を返します。

MasterPageFile

ページのマスター ページのファイル名を取得または設定します。 このプロパティは PreInit メソッドでのみ設定できます。

MaxPageStateFieldLength

このプロパティは、ページ状態の最大長をバイト単位で取得または設定します。 このプロパティが正の数に設定されている場合、ページのビュー状態は、指定されたバイト数を超えないように複数の非表示フィールドに分割されます。 プロパティが負の数の場合、ビュー状態はチャンクに分割されません。

PageAdapter

要求元のブラウザーのページを変更する PageAdapter オブジェクトへの参照を返します。

PreviousPage

Server.Transfer またはクロスページ ポストバックの場合は、前のページへの参照を返します。

SkinID

ページに適用する ASP.NET 2.0 スキンを指定します。

StyleSheetTheme

このプロパティは、ページに適用されるスタイル シートを取得または設定します。

TemplateControl

ページの包含コントロールへの参照を返します。

テーマ

ページに適用される ASP.NET 2.0 テーマの名前を取得または設定します。 この値は PreInit メソッドの前に設定する必要があります。

Title

このプロパティは、ページ ヘッダーから取得されるページのタイトルを取得または設定します。

ViewStateEncryptionMode

ページの ViewStateEncryptionMode を取得または設定します。 このプロパティの詳細については、このモジュールの前半を参照してください。

Page クラスの新しい保護されたプロパティ

ASP.NET 2.0 の Page クラスの新しい保護されたプロパティを次に示します。

アダプター

要求したデバイス上でページをレンダリングする ControlAdapter への参照を返します。

AsyncMode

このプロパティは、ページが非同期で処理されるかどうかを示します。 これは、コード内で直接ではなく、ランタイムで使うためのものです。

ClientIDSeparator

このプロパティは、コントロールの一意のクライアント ID を作成するときに区切り記号として使われる文字を返します。 これは、コード内で直接ではなく、ランタイムで使うためのものです。

PageStatePersister

このプロパティは、ページの PageStatePersister オブジェクトを返します。 このプロパティは、主に ASP.NET コントロールの開発者によって使用されます。

UniqueFilePathSuffix

このプロパティは、ブラウザーをキャッシュするためにファイル パスに追加される一意のサフィックスを返します。 既定値は __ufps= と 6 桁の数字です。

Page クラスの新しいパブリック メソッド

次のパブリック メソッドは、ASP.NET 2.0 の Page クラスに新しく追加されました。

AddOnPreRenderCompleteAsync

このメソッドを使って、非同期ページ実行用のイベント ハンドラー デリゲートを登録します。 非同期ページについては、このモジュールで後ほど説明します。

ApplyStyleSheetSkin

ページ スタイル シートのプロパティをページに適用します。

ExecuteRegisteredAsyncTasks

このメソッドは非同期タスクです。

GetValidators

指定された検証グループの検証コントロールのコレクションを返します。また、何も指定されていない場合は既定の検証グループを返します。

RegisterAsyncTask

このメソッドを使って、新しい非同期タスクを登録します。 非同期ページについては、このモジュールで後ほど説明します。

RegisterRequiresControlState

このメソッドを使って、ページ コントロールの状態を永続化する必要があることを ASP.NET に伝えます。

RegisterRequiresViewStateEncryption

このメソッドを使って、ページのビュー状態に暗号化が必要であることを ASP.NET に伝えます。

ResolveClientUrl

画像などのクライアント要求に使用できる相対 URL を返します。

SetFocus

このメソッドを使って、ページが最初に読み込まれるときに、指定したコントロールにフォーカスを設定します。

UnregisterRequiresControlState

コントロール状態の永続化が不要になったら、このメソッドを使って、渡されたコントロールの登録を解除します。

ページ ライフサイクルに対する変更

ASP.NET 2.0 のページ ライフサイクルは大幅に変わっていませんが、注意する必要がある新しいメソッドがいくつかあります。 ASP.NET 2.0 のページ ライフサイクルの概要を以下に示します。

PreInit (ASP.NET 2.0 の新機能)

PreInit イベントは、開発者がアクセスできるライフサイクルの最初のステージです。 このイベントが追加されたことで、ASP.NET 2.0 のテーマ、マスター ページ、ASP.NET 2.0 プロファイルのアクセス プロパティなどをプログラムで変更できるようになりました。ポストバック状態にある場合は、ライフサイクルのこの時点ではビュー状態がまだコントロールに適用されていないことを認識することが重要です。 そのため、開発者がこのステージでコントロールのプロパティを変更すると、ページ ライフサイクルの後半で上書きされる可能性があります。

Init

Init イベントは ASP.NET 1.x から変更されていません。 ここでは、ページ上のコントロールのプロパティを読み取ったり、初期化したりします。 このステージでは、マスター ページ、テーマなどが既にページに適用されています。

InitComplete (2.0 の新機能)

InitComplete イベントは、ページの初期化ステージの最後に呼び出されます。 ライフサイクルのこの時点で、ページ上のコントロールにアクセスはできますが、その状態はまだ設定されていません。

PreLoad (2.0 の新機能)

このイベントは、すべてのポストバック データが適用された後、Page_Load の直前に呼び出されます。

積載量

Load イベントは ASP.NET 1.x から変更されていません。

LoadComplete (2.0 の新機能)

LoadComplete イベントは、ページの読み込みステージの最後のイベントです。 このステージでは、すべてのポストバックとビュー状態のデータがページに適用されています。

PreRender

ページに動的に追加されるコントロールのビュー状態を適切に維持する場合、それらを追加するには PreRender イベントが最後の機会になります。

PreRenderComplete (2.0 の新機能)

PreRenderComplete ステージでは、すべてのコントロールがページに追加され、ページをレンダリングする準備が完了しています。 PreRenderComplete イベントは、ページのビュー状態が保存される前に発生する最後のイベントです。

SaveStateComplete (2.0 の新機能)

SaveStateComplete イベントは、すべてのページのビュー状態とコントロールの状態が保存された直後に呼び出されます。 これは、ページが実際にブラウザーにレンダリングされる前の最後のイベントです。

レンダー

Render メソッドは、ASP.NET 1.x 以降変更されていません。 ここで HtmlTextWriter が初期化され、ページがブラウザーにレンダリングされます。

ASP.NET 2.0 のクロスページ ポストバック

ASP.NET 1.x では、ポストバックは同じページにポストする必要がありました。 クロスページ ポストバックは許可されていませんでした。 ASP.NET 2.0 では、IButtonControl インターフェイスを介して別のページにポストバックする機能が追加されました。 新しい IButtonControl インターフェイスを実装するコントロール (サード パーティのカスタム コントロールに加え、Button、LinkButton、ImageButton) は、PostBackUrl 属性を使うことでこの新しい機能を利用できます。 次のコードは、2 ページ目にポストバックする Button コントロールを示しています。

<asp:Button ID="SubmitReport" PostBackUrl="~/Default.aspx" runat="server" Text="Submit Report" />

ページがポストバックされると、ポストバックを開始するページには、2 ページ目の PreviousPage プロパティを介してアクセスできます。 この機能は、新しい WebForm_DoPostBackWithOptions クライアント側関数を介して実装されました。これを使うと、コントロールが別のページにポストバックされたときに、ASP.NET 2.0 によってページにレンダリングされます。 この JavaScript 関数は、クライアントにスクリプトを出力する新しい WebResource.axd ハンドラーに用意されているものです。

以下の動画は、クロスページ ポストバックのチュートリアルです。

Screenshot of a video walkthrough of a cross-page postback, showing an Internet Explorer browser page displaying a Submit Report option.

全画面表示で動画を開く

クロスページ ポストバックの詳細

ビュー状態

クロスページ ポストバック シナリオの最初のページからビュー状態がどうなるかについて、既に疑問に思ったことがあるかもしれません。 結局のところ、IPostBackDataHandler を実装していないコントロールは、ビュー状態を介してその状態を保持するため、クロスページ ポストバックの 2 ページ目でそのコントロールのプロパティにアクセスするには、そのページのビュー状態にアクセスできる必要があります。 ASP.NET 2.0 では、__PREVIOUSPAGE という 2 ページ目の新しい非表示のフィールドを使用して、このシナリオに対応します。 __PREVIOUSPAGE フォーム フィールドには最初のページのビュー状態が含まれているため、2 ページ目のすべてのコントロールのプロパティにアクセスできます。

FindControl の回避

クロスページ ポストバックの動画チュートリアルでは、FindControl メソッドを使用し、最初のページの TextBox コントロールへの参照を取得しました。 この方法はその目的にはうまく機能しますが、FindControl はコストが高く、追加のコードを書く必要があります。 幸いなことに、ASP.NET 2.0 には、この目的で使用できて多くのシナリオで機能する FindControl の代替手段が用意されています。 PreviousPageType ディレクティブを使用すると、TypeName または VirtualPath 属性を使用し、前のページへの厳密に型指定された参照を指定できます。 TypeName 属性を使用すると、前のページの型を指定できます。一方、VirtualPath 属性を使用すると、仮想パスを使用して前のページを参照できます。 PreviousPageType ディレクティブを設定したら、パブリック プロパティを使用してアクセスを許可するコントロールなどを公開する必要があります。

ラボ 1: クロスページ ポストバック

このラボでは、ASP.NET 2.0 の新しいクロスページ ポストバック機能を使用するアプリケーションを作成します。

  1. Visual Studio 2005 を開き、新しい ASP.NET Web サイトを作成します。

  2. page2.aspx という新しい Web フォームを追加します。

  3. Default.aspx をデザイン ビューで開き、Button コントロールと TextBox コントロールを追加します。

    1. Button コントロールに SubmitButton という ID を、TextBox コントロールに UserName という ID を与えます。
    2. Button の PostBackUrl プロパティを page2.aspx に設定します。
  4. ソース ビューで page2.aspx を開きます。

  5. 次のように @ PreviousPageType ディレクティブを追加します。

  6. 次のコードを page2.aspx のコードビハインドの Page_Load に追加します。

    Response.Write(PreviousPage.UserName.Text);
    
  7. [ビルド] メニューの [ビルド] をクリックしてプロジェクトをビルドします。

  8. 次のコードを Default.aspx のコードビハインドに追加します。

    public TextBox txtUserName {
        get { return this.UserName; }
    }
    
  9. page2.aspx の Page_Load を次のように変更します。

    Response.Write(PreviousPage.txtUserName.Text);
    
  10. プロジェクトをビルドします。

  11. プロジェクトを実行します。

  12. TextBox に名前を入力し、ボタンをクリックします。

  13. 結果はどうなりますか?

ASP.NET 2.0 の非同期ページ

ASP.NET で起こる競合の問題の多くは、外部呼び出し (Web サービスやデータベース呼び出しなど) の待機時間、ファイル IO 待機時間などが原因です。ASP.NET アプリケーションに対して要求が行われると、ASP.NET により、ワーカー スレッドの 1 つを使用してその要求が処理されます。 その要求は、要求が完了して応答が送信されるまで、そのスレッドを所有します。 ASP.NET 2.0 では、ページを非同期に実行する機能を追加することで、この種の問題がある待機時間の問題を解決しようとしています。 つまり、ワーカー スレッドは、要求を開始してから、追加の実行を別のスレッドに渡すことができるため、使用できるスレッド プールにすぐに戻ることができます。 ファイル IO、データベース呼び出しなどが完了すると、要求を完了するためにスレッド プールから新しいスレッドが取得されます。

ページを非同期で実行する最初の手順は、ページ ディレクティブの Async 属性を次のように設定することです。

<%@ Page Async="true" %>

この属性を使って、ページに IHttpAsyncHandler を実装するように ASP.NET に指示します。

次の手順では、PreRender の前にページのライフサイクルのある時点で AddOnPreRenderCompleteAsync メソッドを呼び出します (通常、このメソッドは Page_Load で呼び出されます)。AddOnPreRenderCompleteAsync メソッドは、BeginEventHandler と EndEventHandler という 2 つのパラメーターを受け取ります。 BeginEventHandler から IAsyncResult が返され、それがパラメーターとして EndEventHandler に渡されます。

以下の動画は、非同期ページ要求のチュートリアルです。

Screenshot of the video walkthrough of an asynchronous page request, showing the Microsoft Visual Code screen.

全画面表示で動画を開く

Note

EndEventHandler が完了するまで、非同期ページはブラウザーにレンダリングされません。 開発者の中には、非同期要求が非同期コールバックと似ていると考える方もいるでしょう。 そうではないことを認識することが重要です。 非同期要求の利点は、最初のワーカー スレッドをスレッド プールに返して新しい要求を処理できるため、IO バインドなどによる競合が軽減されることです。

ASP.NET 2.0 のスクリプト コールバック

Web 開発者は、コールバックに関連するちらつきを防ぐ方法を常に模索してきました。 ASP.NET 1.x でちらつきを回避するには SmartNavigation が最も一般的な方法でしたが、クライアントでの実装が複雑なため、一部の開発者にとっては SmartNavigation も問題の一因でした。 ASP.NET 2.0 では、スクリプト コールバックを使用してこの問題に対処しています。 スクリプト コールバックは XMLHttp を利用して、JavaScript 経由で Web サーバーに対して要求を行います。 XMLHttp 要求は、ブラウザーの DOM 経由で操作できる XML データを返します。 新しい WebResource.axd ハンドラーによって、XMLHttp コードはユーザーに表示されません。

ASP.NET 2.0 でスクリプト コールバックを構成するには、いくつかの手順が必要です。

手順 1: ICallbackEventHandler インターフェイスを実装する

ページがスクリプト コールバックに参加していることを ASP.NET で認識するには、ICallbackEventHandler インターフェイスを実装する必要があります。 次のように分離コード ファイルでこれを行うことができます。

public partial class _Default : System.Web.UI.Page, ICallbackEventHandler

次のように @ Implements ディレクティブを使用してこれを行うこともできます。

<%@ Implements Interface="System.Web.UI.ICallbackEventHandler" %>

インライン ASP.NET コードを使用する場合は、通常、@ Implements ディレクティブを使用します。

手順 2: GetCallbackEventReference を呼び出す

前述のように、XMLHttp 呼び出しは WebResource.axd ハンドラーにカプセル化されます。 ページがレンダリングされると、ASP.NET によって WebForm_DoCallback (WebResource.axd が提供するクライアント スクリプト) への呼び出しが追加されます。 WebForm_DoCallback 関数は、コールバックの __doPostBack 関数を置き換えます。 __doPostBack はプログラムによってページ上のフォームを送信することに注意してください。 コールバック シナリオでは、ポストバックを防ぐ必要があるため、__doPostBack では十分ではありません。

Note

クライアント スクリプト コールバック シナリオでも、__doPostBack はページにレンダリングされます。 ただし、コールバックには使用されません。

WebForm_DoCallback クライアント側関数の引数は、通常は Page_Load で呼び出されるサーバー側関数 GetCallbackEventReference を介して提供されます。 GetCallbackEventReference の一般的な呼び出しは次のようになります。

// Set up the JavaScript callback string cbRef = cm.GetCallbackEventReference(this, "document.getElementById('ddlCompany').value", "ShowCompanyName", "null", true);

Note

この場合、cm は ClientScriptManager のインスタンスです。 ClientScriptManager クラスについては、このモジュールで後ほど説明します。

GetCallbackEventReference にはオーバーロードされたバージョンがいくつかあります。 この場合、引数は次のとおりです。

this

GetCallbackEventReference が呼び出されるコントロールへの参照。 この場合は、ページそのものです。

document.getElementById('ddlCompany').value

クライアント側コードからサーバー側イベントに渡される文字列引数。 この場合、ddlCompany というドロップダウンの値を渡します。

ShowCompanyName

サーバー側コールバック イベントからの戻り値を (文字列として) 受け取るクライアント側関数の名前。 この関数は、サーバー側コールバックが成功した場合にのみ呼び出されます。 そのため、堅牢性を確保するために、一般には、エラーの発生時に実行するクライアント側関数の名前を指定する追加の文字列引数を受け取るオーバーロード バージョンの GetCallbackEventReference を使用することをお勧めします。

null

サーバーへのコールバックの前に開始されたクライアント側関数を表す文字列。 この場合、そのようなスクリプトはないので、引数は null です。

true

コールバックを非同期で実行するかどうかを指定するブール値。

クライアント上で WebForm_DoCallback を呼び出すと、これらの引数が渡されます。 そのため、このページがクライアント上でレンダリングされると、コードは次のようになります。

WebForm_DoCallback('__Page',document.getElementById('ddlCompany').value, ShowCompanyName,null,null,true)

クライアント上の関数のシグネチャが少し異なることに注目してください。 クライアント側関数は 5 つの文字列と 1 つのブール値を渡します。 その他の文字列 (上の例では null) には、サーバー側コールバックからのエラーを処理するクライアント側関数が含まれています。

手順 3: クライアント側コントロール イベントをフックする

上記の GetCallbackEventReference の戻り値が文字列変数に割り当てられていることに注目してください。 この文字列は、コールバックを開始するコントロールのクライアント側イベントをフックするために使用されます。 この例では、ページ上のドロップダウンによってコールバックが開始されるため、OnChange イベントをフックします。

クライアント側イベントをフックするには、単に次のようにクライアント側マークアップにハンドラーを追加します。

// Hook the JavaScript function to the onchange event of the dropdown ddlCompany.Attributes["onchange"] = String.Format("javascript:{0}", cbRef);

cbRef が GetCallbackEventReference の呼び出しからの戻り値であることを思い出してください。 これには、先ほど示した WebForm_DoCallback の呼び出しが含まれています。

手順 4: クライアント側スクリプトを登録する

GetCallbackEventReference の呼び出しでは、サーバー側コールバックが成功したときに、ShowCompanyName というクライアント側スクリプトを実行するように指定していたことを思い出してください。 このスクリプトは、ClientScriptManager インスタンスを使用してページに追加する必要があります (ClientScriptManager クラスについては、このモジュールで後ほど説明します)。次のように行います。

System.Text.StringBuilder clientScript = new System.Text.StringBuilder(""); ClientScriptManager cm = Page.ClientScript; // Create the client script clientScript.Append("function ShowCompanyName(companyName)"); clientScript.Append("{"); clientScript.Append("document.getElementById('CoClicked').innerHTML = \"You chose \" + companyName + \".\";"); clientScript.Append("}"); cm.RegisterClientScriptBlock(this.GetType(), "showCo", clientScript.ToString(), true);

手順 5: ICallbackEventHandler インターフェイスのメソッドを呼び出す

ICallbackEventHandler には、コードに実装する必要がある 2 つのメソッドが含まれています。 それは RaiseCallbackEventGetCallbackEvent です。

RaiseCallbackEvent は文字列を引数として受け取り、何も返しません。 文字列引数は、クライアント側呼び出しから WebForm_DoCallback に渡されます。 この場合、その値は ddlCompany というドロップダウンの value 属性です。 サーバー側コードは RaiseCallbackEvent メソッドに配置する必要があります。 たとえば、コールバックが外部リソースに対して WebRequest を行う場合、そのコードは RaiseCallbackEvent に配置する必要があります。

GetCallbackEvent は、クライアントに対するコールバックの戻り値を処理します。 これは引数を受け取らず、文字列を返します。 返される文字列は、クライアント側関数 (この場合は ShowCompanyName) に引数として渡されます。

上記の手順を完了すると、ASP.NET 2.0 でスクリプト コールバックを実行できるようになります。

Screenshot of the video walkthrough of performing the script callback in A S P dot NET 2 point 0. The Microsoft dropdown is highlighted.

全画面表示で動画を開く

ASP.NET のスクリプト コールバックは、XMLHttp の呼び出しをサポートするすべてのブラウザーでサポートされています。 これには、現在使用されている最新のブラウザーがすべて含まれます。 Internet Explorer は XMLHttp ActiveX オブジェクトを使用しますが、他の最新ブラウザー (次期 IE 7 を含む) は組み込みの XMLHttp オブジェクトを使用します。 ブラウザーがコールバックをサポートしているかどうかをプログラムで判断するには、Request.Browser.SupportCallback プロパティを使用します。 要求側クライアントがスクリプト コールバックをサポートしている場合、このプロパティは true を返します。

ASP.NET 2.0 でのクライアント スクリプトの操作

ASP.NET 2.0 のクライアント スクリプトは、ClientScriptManager クラスを使用して管理されます。 ClientScriptManager クラスは、型と名前を使用してクライアント スクリプトを追跡します。 これにより、同じスクリプトがプログラムによってページに複数回挿入されることを防ぎます。

Note

スクリプトがページに正常に登録された後、同じスクリプトを再度登録しようとしても、そのスクリプトは再度登録されません。 重複するスクリプトは追加されません。また、例外は発生しません。 不要な計算を避けるために、スクリプトが既に登録されているかどうかを判断するために使用できるメソッドがあるので、登録を複数回試行せずに済みます。

ClientScriptManager のメソッドは、現在の ASP.NET 開発者であれば誰でもよく知っているはずです。

RegisterClientScriptBlock

このメソッドを使用して、レンダリングされたページの上部にスクリプトを追加します。 これは、クライアントで明示的に呼び出される関数を追加する場合に便利です。

このメソッドには 2 つのオーバーロードされたバージョンがあります。 4 つの引数のうち 3 つは共通しています。 これらは次のとおりです。

type (string)

type 引数には、スクリプトの型を特定します。 通常は、type にはページの型 (this.GetType()) を使用することをお勧めします。

key (string)

key 引数は、スクリプトのユーザー定義キーです。 これは、スクリプトごとに一意である必要があります。 既に追加されているスクリプトと同じキーと型のスクリプトを追加しようとしても、追加されません。

script (string)

script 引数は、追加する実際のスクリプトを含む文字列です。 StringBuilder を使用してスクリプトを作成し、次に StringBuilder に対して ToString() メソッドを使用して script 引数を割り当てることをお勧めします。

3 つの引数のみを受け取るオーバーロードされた RegisterClientScriptBlock を使用する場合は、script 要素 (<script> と </script>) をスクリプトに含める必要があります。

4 つ目の引数を受け取る RegisterClientScriptBlock のオーバーロードを使用することもできます。 4 つ目の引数は、ASP.NET が script 要素を追加するかどうかを指定するブール値です。 この引数が true の場合、スクリプトには script 要素を明示的に含めないでください。

スクリプトが既に登録されているかどうかを判断するには、IsClientScriptBlockRegistered メソッドを使用します。 こうすることで、既に登録されているスクリプトの再登録を試行せずに済みます。

RegisterClientScriptInclude (2.0 の新機能)

RegisterClientScriptInclude タグは、外部スクリプト ファイルにリンクするスクリプト ブロックを作成します。 これには 2 つのオーバーロードがあります。 1 つは、キーと URL を受け取るものです。 2 つ目は、型を指定する 3 つ目の引数を追加するものです。

たとえば、次のコードを使って、アプリケーションの script フォルダーのルートにある jsfunctions.js にリンクするスクリプト ブロックを生成します。

ClientScriptManager cm = Page.ClientScript; if(!cm.IsClientScriptIncludeRegistered("jsfunc")) { cm.RegisterClientScriptInclude(this.GetType(), "jsfunc", "/scripts/jsfunctions.js"); }

このコードにより、レンダリングされるページに次のコードが生成されます。

<script src="/scripts/jsfunctions.js" type="text/javascript"></script>

Note

スクリプト ブロックはページの下部にレンダリングされます。

スクリプトが既に登録されているかどうかを判断するには、IsClientScriptIncludeRegistered メソッドを使用します。 こうすることで、スクリプトの再登録を試行せずに済みます。

RegisterStartupScript

RegisterStartupScript メソッドは、RegisterClientScriptBlock メソッドと同じ引数を受け取ります。 RegisterStartupScript を使用して登録されたスクリプトは、ページの読み込み後、OnLoad クライアント側イベントの前に実行されます。 1.X の場合、RegisterStartupScript を使用して登録されたスクリプトは終了の </form> タグの直前に配置され、RegisterClientScriptBlock を使用して登録されたスクリプトは開始の <form> タグの直後に配置されました。 ASP.NET 2.0 では、両方とも終了の </form> タグの直前に配置されます。

Note

RegisterStartupScript を使用して関数を登録した場合、その関数はクライアント側コードで明示的に呼び出すまで実行されません。

IsStartupScriptRegistered メソッドを使用してスクリプトが既に登録されているかどうかを確認し、スクリプトの再登録を試行しないようにします。

その他の ClientScriptManager メソッド

ClientScriptManager クラスの他の便利なメソッドを次に示します。

GetCallbackEventReference このモジュールで前述したスクリプト コールバックを参照してください。
GetPostBackClientHyperlink クライアント側イベントからポストバックするために使用できる JavaScript 参照 (javascript:<call>) を取得します。
GetPostBackEventReference クライアントからのポストバックを開始するために使用できる文字列を取得します。
GetWebResourceUrl アセンブリに埋め込まれているリソースの URL を返します。 RegisterClientScriptResource と組み合わせて使用する必要があります。
RegisterClientScriptResource Web リソースをページに登録します。 これらはアセンブリに埋め込まれ、新しい WebResource.axd ハンドラーによって処理されるリソースです。
RegisterHiddenField 非表示のフォーム フィールドをページに登録します。
RegisterOnSubmitStatement HTML フォームの送信時に実行されるクライアント側コードを登録します。