UpdatePanelの更新履歴を管理するHistory機能
AJAXのデメリットの一つに「部分更新されたページの状態を保持できない」というものがあります。GridViewコントロールなどのようにデータとしてバックエンドに反映できるものなら問題はありません。しかし、ラベルの値などを部分更新を利用して更新した場合だとどうでしょう?「ユーザーとしては、前のラベルの値が見たかったので、ブラウザの戻るボタンを押しますが、ページの挙動は思い通りに行かず、前のページに戻ってしまう。このような問題は現実的に起こり得ます。
今回追加されたHistory機能は、部分更新を行う際に履歴ポイント(戻るボタン/進むボタンをクリックできるポイント)を作成し、特定の値を退避させることができます。戻るボタンか進むボタンをクリックした際に、対応したイベント上で退避させた値を取得し、反映させることができるようになります(図6)。
今回紹介するHistory機能は、ASP.NET 3.5 SP1上でしか利用できません。つまり、一般的なWebテクノロジでこのHistory機能は利用できません。しかし、現在RCとなっているIE 8では、AJAXの履歴管理機能というのが提供予定です。これはASP.NET 3.5 SP1に限定されない履歴管理機能です。挙動はASP.NET 3.5 SP1のHistory機能と、ほぼ同じですが、クライアントサイドスクリプトで設定が可能なので、どのWebテクノロジでも履歴管理機能が利用できるようになります。
ただし、現時点でこの履歴管理機能を実装しているブラウザはIE 8のみとなっています。サーバーサイド技術はユーザーにとって無関係な部分ですが、ブラウザを限定させてしまうという意味ではユーザーにとって不自由を感じさせてしまうかもしれません。
履歴ポイントは、URLの末尾にクエリ文字列内のデータとして#マークの後ろに記述されます。URLは文字数制限があるため、ページすべての情報を格納することは非常に難しいです。状態を保持するための情報は最小単位で格納することが重要です。
前置きが長くなりましたが、実際にScriptManagerコントロールの設定を見てみましょう。
<asp:ScriptManager ID="ScriptManager1" runat="server" EnableHistory="True" />
EnableHistory
プロパティがTrueになっていることが確認できます。ScriptManagerコントロール側のHistory機能設定はこれだけです。後は、サーバーサイドで履歴ポイントへのデータの格納と取り出しを設定します。なお、上記タグ内には記述されていませんが、既定でEnableSecureHistoryState
プロパティがTrueに設定されています。EnableSecureHistoryState
プロパティがFalseに設定されていると、URLの末尾に格納される値がそのまま表示され、決してセキュアとは言えません。例えばFalseを設定するシナリオとして、インターネット上に公開するのではなく、イントラネット内で利用される社内業務Webアプリケーションが挙げられます。社内業務Webアプリケーションの場合、情報を確認できるメリットも出てきます。
既定の設定であるTrueの場合はViewStateと同じ設定を使用して格納されるデータがハッシュされます。これでセキュアに履歴ポイントを利用できるようになります。それでも、この履歴ポイント上で機密情報を格納することは決して推奨できません。格納するデータは第3者に露出してしまうことを前提に、要否を検討するようにしてください。
EnableSecureHistoryStateがTrueの場合と、Falseの場合は同様の値でも以下の図7のように表示が変わります。EnableSecureHistoryStateの唯一の難点はハッシュしない時に比べてハッシュした場合の文字数が多くなってしまう点です。まさに最小単位で格納することが重要になる機能だということがご確認できるかと思います。
続いて、サーバサイドのポイントを解説します。サーバーサイドで行うべき作業は大きく2つにわかれます。
- 履歴ポイントの作成(データの退避)
- 戻る/進むボタンを押した時の挙動(データの復元)
それぞれ以下のコードになります。
'1.履歴ポイントの作成(データの退避) Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click Dim text As String text = TextBox1.Text.ToString() Label1.Text = text ListBox1.Items.Add(text) ' クリックの時点のTextBoxのテキストを追加 ' 現在の状態を元に復元 ScriptManager1.AddHistoryPoint("key", text, "Hello," + text) End Sub ' 2.戻る/進むボタンを押した時の挙動(データの復元) Protected Sub ScriptManager1_Navigate(ByVal sender As Object, ByVal e As System.Web.UI.HistoryEventArgs) Handles ScriptManager1.Navigate If e.State("key") <> Nothing Then Label1.Text = e.State("key").ToString() TextBox1.Text = e.State("key").ToString() ListBox1.Items.Add("Navigateイベント呼び出し") Else Label1.Text = "" TextBox1.Text = "" End If End Sub
1.では、AddHistoryPoint
メソッド利用して、履歴ポイントを作成しています。AddHistoryPoint
メソッドはDictionary
クラス同様に扱います。第一パラメータに値を格納するキーを設定し(サンプルではText)、第二パラメータに格納する値を設定することで利用できます(サンプルではTextBoxコントロールの値)。第三パラメータを設定した場合、ブラウザのタイトルに記述した情報を表示させることができます(サンプルではHello,XXXとタイトル表示)。履歴ポイントの作成は以上です。
2.では、ScriptManagerコントロールのNavigateイベントを設定しています。Navigateイベントは戻る/進むボタンをクリックしたときに呼び出されるイベントです。このNavigateイベント内に履歴ポイントに格納したデータを取り出すコードを記述します。System.Web.UI.HistoryEventArgs
のState
プロパティは、パラメータに履歴ポイントで格納したキー(今回は、key)を設定することで、格納した値を取得できます。後は、反映させたいコントロールにデータを設定するだけです。サンプルではLabelコントロールとTextBoxコントロールに値を設定しています。
以上で設定は完了です。実行結果は次のようになります(図8~9)。