ViewState の制御
Microsoft ASP.NET の Web フォーム ページは、複数のクライアントのラウンド トリップに渡って、そのページ自身の状態を保持することができます。コントロールにプロパティが設定されていると、ASP.NET はコントロールの状態の一部としてプロパティ値を保存します。アプリケーション側では、これによってページの有効期間が複数のクライアントの要求に渡って指定されます。このページ レベルの状態は、ページの ViewState と呼ばれます。
通常の Web フォームでは、ViewState はフォームの隠し変数としてサーバーによって送信されます。これはクライアントへの各応答の一部として行われます。また、ViewState は、ポストバックの一部としてサーバーに返されます。ただし、モバイル コントロールの使用時には、必要な帯域幅を減らすため、ASP.NET はページの ViewState をクライアントに送信しません。その代わり、ViewState はユーザーのセッションの一部としてサーバーに保存されます。ViewState がある場合、このページの ViewState を認識する隠しフィールドは、サーバーによってクライアントへの各応答の一部として送信され、クライアントによって次の要求の一部としてサーバーに返されます。
ViewState 履歴の管理
特定のページの ViewState はサーバー上に保存されるため、ブラウザの「戻る」機能を使用して履歴をさかのぼる場合に、現在の状態がブラウザの現在のページと同期されないことがあります。
たとえば、ユーザーがページ 1 に移動し、ボタンをクリックしてページ 2 に移動した後、[戻る] をクリックしてページ 1 に戻るとします。この場合、ブラウザの現在のページはページ 1 ですが、サーバーでの現在の状態はページ 2 です。
ASP.NET モバイル Web フォームは、この問題を軽減するため、ViewState 情報の履歴をユーザーのセッションの間保持します。クライアントに送信される各識別子は、この履歴内の位置に一致します。上の例で、ユーザーが再度ページ 1 からポストすると、モバイル Web フォームはページ 1 に保存されている識別子を使用して履歴と同期します。
この履歴のサイズは開発者が設定することが可能で、アプリケーションに合わせて調整する必要があります。既定のサイズは 6 ですが、以下の例に示すように、数値属性を Web.config ファイルのタグに追加することによって変更できます。
<configuration>
<system.web>
<mobileControls sessionStateHistorySize="10" />
</system.web>
</configuration>
有効期限が切れたセッションの処理
ViewState はユーザーのセッションの間保存されるため、セッションが有効な時間内にページがポストバックされないと ViewState の有効期限が切れることがあります。この有効期限は、モバイル Web フォームに固有のものです。使用できる ViewState のないページをユーザーがポストバックすると、ページの OnViewStateExpire メソッドが呼び出されます。このメソッドの既定の実装では、ViewState の有効期限が切れていることを示す例外がスローされます。ただし、有効期限後に ViewState を手動で復元する機能がアプリケーションにある場合、アプリケーションはこのメソッドをページ レベルでオーバーライドして、基本実装を呼び出さないように選択できます。
ViewState の有効化および無効化
セッションを使用して ViewState を管理する ASP.NET の長所は、応答のサイズが小さいことです。短所は、セッション状態を効率的に使用しないとパフォーマンスが低下することがあるという点です。開発者は、大量のデータと共にコントロールを使用するときに、カスタム ページングや ViewState の無効化などの方法を使用して、効率を向上できます。たとえば、ニュース記事を表示するサイトについて考えてみましょう。セッションの間、記事の内容をユーザーごとに保存する代わりに、このようなサイトでは各記事の 1 つのコピーだけをサーバーにキャッシュし、セッション状態の使用を最小限に抑えるような、データへの高度なアクセス方法を使用することができます。
コントロールとその子の ViewState を無効にするには、コントロールの EnableViewState プロパティを False に設定します。ページ全体の ViewState を無効にするには、属性 EnableViewState="false" をディレクティブ @Page に追加します。
ViewState が無効になっているときでも、一部のモバイル コントロールはクライアントのラウンド トリップ間の重要な状態情報を保存します。このような情報の例としては、ページの現在アクティブなフォームなどがあります。ViewState を無効にすると、ページは、ラウンド トリップ時にクライアントに送信される隠しフォーム変数として重要な情報を保存します。
Cookie およびクライアント状態の管理
既定では、ASP.NET のセッション管理機能はサーバーにセッションの Cookie をクライアントに書き出すように要求します。その後、クライアントはセッションの間に各要求の Cookie を送信し、サーバーはこの情報からセッション状態を調べます。しかし、多くのモバイル デバイスは Cookie をサポートしていません。ViewState を含め、セッション管理がこのようなデバイスで正常に機能するには、クッキーレス セッション管理を使用するようにアプリケーションを構成する必要があります。この機能を有効にすると、ASP.NET は自動的にセッション キーをアプリケーション URL に挿入します。
デバイスには、Cookie をサポートしていないものもあります。クライアントの状態を長期にわたって保持するため、アプリケーションは事前に入力された顧客番号を使用することができます。クライアントに Cookie 機能があるとは限らないので、アプリケーションはクライアントをブックマーク可能な代替ページに移動する必要があります。以下のサンプル コードは、このようなサイトの例を示しています。ユーザーがこの URL を参照すると、顧客 ID を入力するフォームが表示されます。このとき、アプリケーションはユーザーがブックマーク可能な代替 URL を表示します。
<%@ Page Inherits="System.Web.UI.MobileControls.MobilePage" Language="C#"
EnableViewState="false" %>
<script runat="server" language="c#">
protected void Page_Load(Object sender, EventArgs e)
{
String customerID = Request.QueryString["cid"];
if (customerID != null)
{
// A customer ID was found. Here, you would normally look
// up the customer's profile in a database.
// This code simulates such a lookup by converting the client ID
// back to a user.
int underscore = customerID.IndexOf('_');
if (underscore != -1)
{
// If visiting the first time, prompt the user to bookmark.
if (Session["FirstTime"] != null)
{
Session["FirstTime"] = null;
WelcomeLabel.Text = String.Format("Welcome to the site, {0}",
customerID.Substring(0, underscore));
ActiveForm = WelcomeForm;
}
else
{
ReturnLabel.Text = String.Format("Welcome back, {0}",
customerID.Substring(0, underscore));
ActiveForm = ReturnForm;
}
}
}
}
protected void LoginForm_OnSubmit(Object sender, EventArgs e)
{
// Generate a customer ID. Here, you would normally create
// a new customer profile.
String customerID = CustomerName.Text + "_" +
System.Guid.NewGuid().ToString();
String path = AbsoluteFilePath + "?cid=" +
Server.UrlEncode(customerID);
Session["FirstTime"] = true;
RedirectToMobilePage(path);
}
</script>
<mobile:Form runat="server">
<mobile:Label runat="server" StyleReference="title">
Welcome to the site. Please register to continue.
</mobile:Label>
<mobile:TextBox runat="server" id="CustomerName" />
<mobile:Command runat="server" OnClick="LoginForm_OnSubmit"
Text="Register" />
</mobile:Form>
<mobile:Form id="WelcomeForm" runat="server">
<mobile:Label runat="server" id="WelcomeLabel" />
Please bookmark this page for future access.
</mobile:Form>
<mobile:Form id="ReturnForm" runat="server">
<mobile:Label runat="server" id="ReturnLabel" />
</mobile:Form>
モバイル アプリケーションの ViewState の最適化
モバイル Web フォーム ページでは、以下の事項を考慮することが重要です。
- セッションの ViewState の保存は、高度に最適化されています。保存する ViewState がない場合は、セッションの間は何も格納されず、クライアントには識別子も送信されません。ただし、セッション管理を使用したくない、またはページのスループットを高くしたいと考えているアプリケーションの開発者は、ViewState の使用回数を減らすか、使用しない方法を検討してみてもかまいません。アプリケーションでは、多くの場合 (書式設定テキストのページのレンダリングなど) ViewState は不要であり、無効にするのが最適です。
- モバイル Web フォーム ページは、アプリケーションの ViewState 以外に、ページに関する他の種類の状態情報を格納する必要があります。この情報には、アクティブなフォームや、フォームの改ページ情報などがあります。このような情報は、サーバーに保存されるのではなく、常にクライアントに送信され、ほとんどの場合は最適化された方法で生成されます。たとえば、最初のフォームがアクティブになるか、フォームの最初のページが表示される場合は、既定の状態が存在するため、この情報は保存されません。このような状態情報は、プライベート ViewState と呼ばれます。すべてのコントロールは、LoadPrivateViewState および SavePrivateViewState メソッドをオーバーライドしてプライベート ViewState の読み取りまたは書き込みを行うことができます。
隠し変数の詳細、および隠し変数を使用して ViewState 情報を保存する方法については、「ASP.NET の状態管理」を参照してください。
メモ セキュリティ上のリスクを回避するため、セッション状態に重要な情報を含める場合は、HTTPS および SSL/TLS 認証を使用した、セキュリティで保護された接続を使用するようにしてください。
参照
セッション状態の管理 | ViewState のサポート | ASP.NET モバイル Web アプリケーションの作成 | アプリケーション開発者ガイド | モバイル Web アプリケーションの作成 | ASP.NET の状態管理 | LoadPrivateViewState | SavePrivateViewState