.NET TIPS

[ASP.NET]ビューステートに保存されるものは?

デジタルアドバンテージ
2003/06/20

 ASP.NETでは、ビューステート(ViewState)と呼ばれる機能により、Webページの状態は保存され自動的に復元される。ここではビューステートがどのように機能し、何の状態をどこに保存するのかを探ってみる。

ビューステートによる状態復元の仕組み

 まずは、ビューステートにより状態が復元される様子を実際に試してみよう。

 Visual Studio .NETで「ASP.NET Webページ」のプロジェクトを新規作成し、次の画面ようにLabelコントロールとButtonコントロール(ここではTextプロパティを「何もしない」に変更している)を配置する。

LabelコントロールとButtonコントロールを配置したWebフォーム(プロジェクト名は「ViewState1」とする)

 次にWebフォーム上をダブルクリックし、Page_Loadメソッドに次の画面のようにif文を1つ追加する。

ページのロード時に実行されるPage_Loadメソッド
ページが初めて実行されたときにのみ、Labelコントロールに文字列を設定するコードを追加する。

 ここで記述したコードは、ポストバック以外の場合、つまり最初にこのページを開いたときにのみ実行され、Labelコントロールのテキストを書き換える。[何もしない]ボタンは配置するだけで、そのボタン名どおり何の処理も記述しない。

 このWebアプリケーションを実行すると次のような画面になる。

「ViewState1」の初期画面
実行時にはLabelコントロールに文字列が設定される。イベント・ハンドラを記述していない[何もしない]ボタンを押してポストバックが発生した場合、この文字列はどうなるだろうか。

 さて、ここで[何もしない]ボタンをクリックすると、ラベルに表示されている文字列はどうなるだろうか。Form_Loadメソッドでは、ポストバック時には何の処理も行わない。ボタンに対するイベント・ハンドラも記述していない。つまりボタンをクリックしたときにサーバ側で実行されるコードは1行も記述していない。にもかかわらず、[何もしない]ボタンをクリックした場合には「ページがロードされました」メッセージは表示され続ける。これがビューステートによる状態の復元である。

 このようにページの状態を復元するためには、当然ながらどこかにデータを保存しておく必要がある。このビューステートのためのデータは、デフォルトではブラウザへ送信されるHTMLデータ内に保存されている。上のブラウザ画面でソースを表示した場合、<form>タグ部分は次のリストのようになっているはずだ。

<form name="Form1" method="post" action="WebForm1.aspx" id="Form1">

  <input type="hidden" name="__VIEWSTATE" value="dDwtMTMzOTc
  0NjEyO3Q8O2w8aTwxPjs+O2w8dDw7bDxpPDE+Oz47bDx0PHA8cDxsPFRle
  HQ7PjtsPOODmuODvOOCuOOBjOODreODvOODieOBleOCjOOBvuOBl+OBnzs
  +Pjs+Ozs+Oz4+Oz4+Oz7cShu2UDaZKKEIlWtpn7Qy4mCkQA==" />

  <span id="Label1" >
      ページがロードされました
  </span>

  <input type="submit" name="Button1"
         value="何もしない" id="Button1" />
</form>
「ViewState1」実行時のソース・コード内の<form>タグ部分
ビューステートのためのデータは隠しフィールドによりHTMLに埋め込まれている(読みやすいように一部の要素や属性を省略し、整形している)。

 「__VIEWSTATE」というname属性の付けられた隠しフィールド(type属性の値が「hidden」である<input>要素)がビューステートのためのデータである。ビューステートはこのようにエンコードされてクライアント側に送信される(エンコードされているだけで暗号化されているわけではない)。Webページ上に複数のコントロールがある場合でも、各コントロールのビューステートは、1つのエンコードされた文字列にまとめられ、隠しフィールドでページに埋め込まれる。

 「TIPS:[ASP.NET]ページのトレース情報を出力するには?」に従ってこのページのトレース情報を表示すれば、各コントロールのビューステート・データのサイズを確認することができる。この場合では、次の画面のようにLabelコントロール(IDは「Label1」)のビューステートのサイズが0でないことが分かる。そこには「ページがロードされました」というメッセージを表示するための情報が埋め込まれているためだ。

「ViewState1」実行時のトレース情報
Labelコントロール(IDは「Label1」)のビューステートのサイズが76bytesとなっているのが分かる。アンダースコア(‘_’)で始まるコントロールは、ASP.NETにより内部的に生成されたコントロールである。

 なお、隠しフィールドに保存されているビューステートは、次にポストバックが発生したときに状態を復元するためのものである。上記の例では、フォーム上の[何もしない]ボタンをクリックした場合に、ビューステートの値はサーバにポストされる。サーバ側ではこの値をデコードして、ブラウザに送信するHTML文を作成する際に、Labelコントロールに値を復元することができるわけだ。

ビューステートに保存されないもの

 別の「ASP.NET Webページ」プロジェクトを新規作成し、今度はTextBoxコントロールとButtonコントロールを配置してみよう。

TextBoxコントロールとButtonコントロールを配置したWebフォーム(プロジェクト名は「ViewState2」とする)

 今回はコードをまったく記述せず、すぐに実行してみる。まず次のような画面が表示される。

「ViewState2」の初期画面
テキスト・ボックスに文字列を入力し、[何もしない]ボタンを押してポストバックが発生した場合、入力した文字列はどうなるだろうか。

 ここでテキスト・ボックスに文字を入力し、[何もしない]ボタンをクリックするとどうなるだろうか。ポストバックが発生しページは書き換わるが、大方の予想どおりテキスト・ボックスには入力された文字列が復元される。

 ただし、この復元処理もビューステートによるものと誤解されがちだが、テキスト・ボックスに入力された文字列はビューステートには保存されない。なぜなら、わざわざ隠しフィールドに埋め込んで送信しなくとも、テキスト・ボックスに入力された値はフォームのサブミットによりサーバへ送信されるからだ。トレース情報を見ても、TextBoxコントロール「TextBox1」のビューステートのサイズは0byteであることを確認することができる。

「ViewState2」実行時のトレース情報
文字列を入力したTextBoxコントロール(IDは「TextBox1」)のビューステートのサイズが0byteであることから、ビューステートには状態が保存されていないことが分かる。

 このように、フォーム・データのポストによりその値がサーバへ送信される入力系コントロール(TextBoxコントロール、CheckBoxコントロール、ListBoxコントロールなど)で入力された値については、自動的に復元されるが、そのデータはビューステートには保存されない。逆にいうと、それ以外のコントロールの値や状態は、デフォルトではすべてビューステートにより保存されるということだ。

ビューステートに保存されるもの

 TextBoxコントロールに入力された値はビューステートには保存されないが、TextBoxコントロールのプロパティの状態はビューステートで保存され、復元される。最後にこれを確認しておこう。

 まず新しいプロジェクトを作成し、次の図のようにButtonコントロールと3つのTextBoxコントロールを配置する。3番目のTextBoxコントロールには、配置時にプロパティ・ウィンドウでBackColorプロパティに値を設定し、背景色を付けておく。

3つのTextBoxコントロールとButtonコントロールを配置したWebフォーム(プロジェクト名は「ViewState3」とする)
3番目のTextBoxコントロールには、配置時にプロパティ・ウィンドウでBackColorプロパティに値を設定して背景色を赤にしている。

 また、[プロパティ設定]ボタンをダブルクリックし、そのイベント・ハンドラ内に次のコードを追加する。

TextBox1.BackColor = Color.Blue;
TextBox2.Width = 300;

 アプリケーションを実行すると、次のような画面が開く。

「ViewState3」の初期画面

 [プロパティ設定]ボタンをクリックすると、そのボタンのイベント・ハンドラに記述したコードにより、1番目、2番目のTextBoxコントロールは次の図のように変化する。

「ViewState3」で[プロパティ設定]ボタンを押した後の画面
ボタンのイベント・ハンドラに記述したコードにより、1番目のTextBoxコントロールの背景色は青になり、2番目のTextBoxコントロールの幅が大きくなる。

 さて、トレース情報を見てみよう。

「ViewState3」実行時のトレース情報
最初の2つのTextBoxコントロールについては、その状態がビューステートに保存されているが、3番目のTextBoxコントロールはビューステートを使用していない。

 最初の2つのTextBoxコントロールについては、そのバイト数からプロパティの変更情報がビューステートに保存されたことが分かる。

 ただし、3番目のTextBoxコントロールについてはビューステートのサイズは0byteである。これは、デザイン時に設定したプロパティについてはビューステートに保存されないことを示している。デザイン時に設定したプロパティの値は、生成されるコードに静的に埋め込まれる。そしてそのコードは、ページがアクセスされインスタンスが生成されるときに毎回実行される。このためデザイン時に設定されたプロパティ値もビューステートには保存されない。ボタンに設定した文字列もそうである。

 以上、ビューステートについて見てきた。通常“Windows”アプリケーションでは、実行時にセットしたプロパティや入力した値は、それを明示的に変更あるいは消去するまで消滅することはない。ASP.NETのビューステートは、それをWebアプリケーションでも実現してしまう非常に強力な機能であるといえるだろう。ビューステートに関する処理はプログラマーが意識しなくても自動的に機能する。しかし、そのデータをページに埋め込んでいるという点で、使い方を誤ると時としてネットワークに大きな負荷をかけてしまうこともあり得る。これについては別稿でまとめる予定だ。End of Article

カテゴリ:Webフォーム 処理対象:ビューステート
関連TIPS:[ASP.NET]ページのトレース情報を出力するには?
 
この記事と関連性の高い別の.NET TIPS
[ASP.NET]DataGridコントロールでビューステートを使用せずにページ表示するには?
[ASP.NET]ポストとポストバックの違いは?
[ASP.NET]DataGridコントロールの列にボタンを表示するには?
[ASP.NET]DataGridコントロールでページ表示するには?
ASP.NETでボタンのクリック時に確認メッセージを表示するには?
このリストは、(株)デジタルアドバンテージが開発した
自動関連記事探索システム Jigsaw(ジグソー) により自動抽出したものです。
generated by

「.NET TIPS」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間