状態管理のポイント
今回は紙面の都合上、業務アプリケーション開発で使用することの多い、ViewState、Sessionについて注意すべきことを説明します。そのほかの方法や、より詳細な情報については、以下のページを参照してください。
Session
Sessionは状態管理方法のうち最も使うものです。気軽に使用できる分乱用してしまいがちになりますが、使用する際には次のことに注意しましょう。
[1]あまりに巨大なデータは保存しない
現在処理を行っているすべてのセッションがサーバーにデータを保存するため、あまりに巨大なデータを保存するとすぐにサーバーのリソース(メモリなど)が枯渇してしまいます。
処理に必要な最低限のデータだけ保存するようにしましょう。
[2]不要になったらすぐにクリアする
SessionはViewStateのように使い捨てではなく、セッションが続いている間ずっと値を保持し続けます。つまり使わない状態を残したままにすると、その分サーバーのリソースが無駄になってしまいます。
不要になったらすぐにクリアするようにしましょう。クリアするにはキーを指定してnull(Visual BasicではNothing)を代入するか、Removeメソッドを使います。
Session["key"] = null;
Session.Remove("key");
[3]セッション状態モードのインプロセスは使用しない
Sessionのデータ保存場所(セッション状態モード)には大きく分けて次の3つがあり、設定ファイル(Web.config)で設定できます。
-
インプロセス(既定)
IISなどのWebサーバーのプロセスが持っているメモリ空間に保存する。 -
ステートサービス
セッション状態を保存するための専用サービスに保存する。 -
データベース
SQL ServerやOracleなどのデータベースに保存する。
基本的に上の方からパフォーマンス高→低、耐障害性低→高となっています。
これらはWeb.configのsessionState要素で切り替えることができますが、実運用環境では決して「インプロセス」にしてはいけません。
これは、IISのプロセスは一定の時間で自動的に再起動されるようになっており、その際メモリ内に保存したSessionのデータが破棄されてしまうためです。また、さまざまな条件によって発生するアプリケーションの再起動によっても、同様に破棄されます。
従って、最低でもステートサービスを使うようにし、あとは耐障害性やパフォーマンスの要件によって検討してください。
詳しくは以下のページを参照してください。
ViewState
ViewStateに設定されるデータは実際のところ、多くがサーバーコントロールによって自動的に設定されるものとなります。コードで状態を設定するケースは、個人的な感覚ではSessionに比べてあまり多くありません(その少ないケースの一つが、後で使用例として紹介する「ワンタイムトークン」です)。
自動的に設定される状態、明示的に設定する状態がありますが、基本はなるべく使わないようにし、データ量を抑えるというのが第一です。具体的には次のことに注意するようにしましょう。
[1]ViewStateが不要なコントロールでは無効にする
ViewStateにはサーバーコントロールによって、かなり大きなデータが自動で埋め込まれる場合があります。しかし、ViewStateによる状態保持が不要なケースも多く、コントロールごとにViewStateの有効、無効を制御することで、ViewStateのデータ量を減らせます。特に、ObjectDataSourceコントロールとデータバインドコントロールを組み合わせた場合、背後で自動的にSessionやデータベースなどから値を表示するようになるため、ViewStateは基本的に不要です。
ViewStateの有効、無効を設定するにはPageや各コントロールのEnableViewStateプロパティ、ViewStateModeプロパティを使います。これらのプロパティの違いはというと、EnableViewStateプロパティは親コントロールの値が子コントロールには引き継がれませんが、ViewStateModeプロパティは引き継がれます。
従って、Page.EnableViewStateプロパティをtrueにした上で、マスターページContentコントロールなどなるべく上位のコントロールのViewStateModeプロパティをDisabled、ViewStateを有効にしたいコントロールのViewStateModeプロパティをEnabledに設定する、といった方法を取ると良いでしょう。こうすることで、PageレベルのViewStateは有効、Pageに含まれるコントロール全体としては無効、必要なコントロールだけ有効、といった制御が可能になります。
なお、Page.ViewStateModeプロパティをDisabledにしてしまうと、サーバー側でViewStateに設定したPageレベルの状態すら保存されなくなってしまいますので注意しましょう。
もし興味があれば、サンプルアプリケーションのLocations.aspxにて、ContentコントロールのViewStateModeプロパティをDisabledからEnabledにして"__VIEWSTATE"項目のvalue属性の値がどう変化するか見てみてください。相当データ量に違いがあるはずです。
[2]あまり大きなデータを保存しない
大きなデータをViewStateに保存すると、その分ネットワークにも負荷がかかりますし、ブラウザでの表示も遅くなる恐れがあります。
従って、なるべく保存するデータ量を減らすため、基本的にViewStateではなくSessionを使うようにしましょう。ViewStateに設定する場合でも、ちょっとしたフラグや短い文字列程度の小さなデータにとどめておきましょう。
[3]機密性の高いデータを保存しない
ViewStateに格納する値はBase64エンコーディングされ、パッと見暗号化されたように見えます。しかしBase64エンコードは暗号化ではなく、簡単にデコードが可能です。そのため、機密性の高いデータを保存してしまうと、簡単に情報が漏れてしまいます。
従って、機密性の高いデータは原則としてViewStateではなくSessionに保存しましょう。どうしてもViewStateに保存したいという特殊な事情があるならば、System.Security.Cryptography名前空間に含まれる暗号化処理を行うクラス、例えばAesクラスやTripleDesクラスなどを使い、値を暗号化してから設定するようにしましょう。
