特集:クライアントステート管理、3つの手法Visual Studio Magazine(6/9 ページ)

» 2004年12月28日 10時30分 公開
[Matthew Gibbs, Rob Howard,FTPOnline]

状態保存にビューステートを使う

 Webアプリケーションにおける通信は、一般的にHTTPというステートレスなプロトコルに基づいたものだ。

 ASP.NETのセッション状態機能は、SessionIDをクッキーに保存したりページのURLに埋め込んだりすることで実現されたHTTPのステートレスな世界からの抜け道だと言えよう。この共有されるセッションキー(SessionID)は、その後、リクエストを発生したブラウザにおいて、サーバに保存されたデータを関連づけるために用いられる。

 幾つかの場面では、セッション状態を要求することが必要無い時や望ましくないケースがある。共通テクニックは、次のように、フォームのフィールドにデータを隠して保存することだ。

<input type="hidden" value="some value here"/>

 クライアントサイドでがページをSUBMITし、HTTPのPOSTやGETリクエストがサーバに向けて発生した場合には、このデータはPOSTのボディデータやクエリ文字列の中に入り、ほかの入力フォームのデータと共に、サーバへ送信される。

 ASP.NETは、この隠し入力フィールドの概念を採用しており、ポストバック中のページ状態保持に利用している(「<form runat="server"/>」を使うすべてのASP.NETページは、同じページにフォームのコンテンツを送信する(訳注:これが「ポストバック」であり、「runat="server"」を付加させたformのaction属性は無視される)。この機能は、「ビューステート」として知られている。

 また、ビューステートでは、フォームに含まれる特別な「<input type="hidden" name="__VIEWSTATE"/>」という要素にデータが保存される。form要素の__VIEWSTATEのvalue属性に保存されるデータは、Base64エンコードされた文字列として構成される。これは、現在のページのViewStateに保存されるすべてのデータに加え、メッセージ認証コード(MAC:Message Autehntication Code)をシリアライズしたものだ。

 ページがサーバにポストバックされる場合、ASP.NETのページフレームワークは、__VIEWSTATE内のデータをデシリアライズし、自動的にViewStateのステートバッグに再格納する。そのためページが再度ポストバックされた時、ビューステートに加えておいたデータは、利用可能な状態になるのだ。

 ビューステートは、複雑なサーバコントロールを作る場合に役立つ。なぜならば、通常はフォーム要素として送信されないデータをビューステートに格納することができ、ページがポストバックされた際にそれを取り出すことができるためだ(追加リソース参照)。

 一方メッセージ認証コード(MAC:Message Autehntication Code)は、キーに依存する一方向ハッシュだ。MACは、ポストバック時に再計算した値と__VIEWSTATEに保存した値とを比較することで、ViewStateのデータが正しいかどうかを確認するために使われる。このMACが一致すれば、__VIEWSTATEのデータは正しい。もし一致しなければ、__VIEWSTATEのデータは無効であり、例外が発生することになる。

 ViewStateのデータは、Sessionデータを扱うのと同じ方法でアクセスが可能だ。つまり、値を設定したり取り出したりするのに、キーを用いる(訳注:「Session("キー") = 値」のようにSessionデータを扱うのと同様に、ViewStateの場合にも「ViewState("キー") = 値」の書式を使うという意味)。しかしSessionとは異なり、ViewStateのデータは、ポストバックを引き起こす「<form runat="server"/>」を利用するページでのみ利用可能だ。

 ViewStateに保存できるデータ型は、Int32、Boolean、String、Unit、Colorに制限されている。これら以外のデータ型は、著しいオーバーヘッドを招いてしまう。具体的には、文字列への変換がされるか、セッション状態で使うのと同じバイナリのシリアライザ(BinaryFormatter)が使われてシリアライズされることになる。

 ビューステートは、ページが持続する間(ここで示すページが持続する間とは、「最初のリクエスト」と「すべてのポストバック」の間)に必要となる少量のデータを取得するのに代償がかかるときに、非常に役立つ。その良き例が、ASP.NETフォーラムのソースコードにある。なお、ASP.NETフォーラムにある頻繁に利用されるコントロールのひとつが、データをページングする場合に使われるサーバコントロールだ。

 このサーバーコントロール(Paging.cs)は、SQL Serverに保存されたデータの複数レコードをページ単位で表示することを可能とする。ページングコントロール処理のひとつとして、利用可能なレコードの総数を追跡する機能が挙げられる。このレコード総数と、リクエストされたページに収まるレコード数を利用することで、コントロールは利用可能なページの総数を計算できるのだ。

 なお、利用可能なレコードの総数はリクエストごとに計算しない。代わりに、1回だけ取得してビューステートに保存する。このようにすることで、同じ情報をデータベースに問い合わせる複数のリクエストを抑え、サーバ負荷を軽減できるわけだ。

 次ページに挙げるコードは、Paging.csファイルにおけるテクニックの部分的な抜粋だ。全体のソースコードは、ASP.NETフォーラムサイトで参照できる。

© Copyright 2001-2005 Fawcette Technical Publications

注目のテーマ