Session オブジェクト  

完全な機能を持つ Web アプリケーションを作成するための最も大きな課題の 1 つは、サーバーからの要求時に毎回ユーザーについて確認することなく、ユーザーがサイト内を移動中に、ユーザー固有の情報を追跡できるようにすることです。維持する必要がある他の情報には、ユーザーの識別情報、該当する場合はユーザーのセキュリティ情報、およびより高度なアプリケーションでは、ユーザーが行った選択に応じて Web サイトの外観をカスタマイズできるようにするユーザー設定があります。ユーザー固有の情報を維持する上での主要な問題には、現在標準となっている HTTP 1.0 プロトコルの制限があります。

HTTP 1.0 には、ユーザーの識別情報とユーザー固有のデータを維持できるようにする、永続的な接続のメカニズムが用意されていますが、その有用性には制限があります。HTTP 1.0 では、技術的な詳細を必要とすることなく、クライアントブラウザが Keep-Alive メッセージをプロキシサーバーに送信できます。基本的に、このメッセージは、要求元のクライアントとオープンな接続を維持するようにプロキシサーバーに伝えます。ただし、この接続要求は、多くの場合プロキシサーバーによって認識されません。プロキシサーバーでのこの問題は、プロキシサーバーと要求された Web サーバー間の接続がハングするという問題につながります。簡単に説明すると、Web サーバーとの接続を維持するとエラーになりやすく、クライアントブラウザによってこれまでに最も一般的に使用されているプロトコルである、HTTP 1.0 を使用した接続の維持は信頼性に欠けます。

Microsoft Internet Information Server (および他の Web サーバー) によるこの問題のソリューションは、HTTP Persistent Client State Mechanism、つまり Cookie を使用してユーザーを識別するという方法です。IIS は、組み込み型の Session オブジェクトを使用してこのメカニズムを扱います。

Session オブジェクトは現在のユーザーの Web サーバーでのセッションを表します。これはユーザー固有であり、そのプロパティとメソッドにより、そのユーザーの接続中は、そのユーザーに固有の情報をサーバー上で操作できます。この長さは、Web アプリケーション内でクライアントがページを最初に要求したときから、ユーザーが Web サーバーに最後の要求を行ってから 20 分までと定義されます。20 分は、変更できる初期設定値です。本章で後述する「Timeout」の項を参照してください。

ユーザーセッションは次の 3 つの方法の 1 つで開始されます。

    既にサーバーに接続されていないユーザーが、Session_OnStart イベントのコードを持つ GLOBAL.ASA ファイルが含まれたアプリケーションにある Active Server Pages を要求する

    ユーザーが、任意のセッションスコープ変数に情報を保存するスクリプトの Active Server Pages を要求する

    GLOBAL.ASA ファイルが、SCOPE パラメータを Session に設定した <OBJECT> タグを使用するオブジェクトを初期化するアプリケーションで Active Server Pages を要求する

ユーザーセッションは Web サイト上の指定したアプリケーションに固有です。他のアプリケーションを指定する仮想ディレクトリの下にある仮想ディレクトリに 1 つのアプリケーションがある場合は、一度に複数のアプリケーションに対してセッション情報を維持することができます。

Web サーバーは、固有の SessionID 値を使用して各ユーザーを識別します。この SessionID 変数は、Web サーバーでのユーザーセッションの開始時に各ユーザーに割り当てられ、Web サーバーのメモリに保存されます。セッション ID は、SessionID を含む Cookie をユーザーのコンピュータに書き込むことで、クライアントに保存されます。この Cookie は、ユーザーが要求を行うたびにサーバーに送信されます。ユーザーを識別するため、サーバーは Cookie を取得し、メモリに保持されている SessionID と一致させます。

SessionID 変数に加えて、個別のユーザーに固有の他の情報を保存できます。任意の セッションレベル変数は Active Server Pages スクリプトのどこでも初期化または変更できます。セッションレベル変数が特定の値に初期化されるようにするには、GLOBAL.ASA ファイルの Session_OnStart イベントプロシージャでコードをスクリプト化できます。このイベントプロシージャは、ユーザーのセッションが開始したときに発生します。GLOBAL.ASA ファイル (第 11 章を参照) は、各 ASP アプリケーション固有のコードを記述できる特殊ファイルです。このファイルのコードは、ユーザーセッションが開始したときに処理されます。

既に説明したように、Session オブジェクトは、個別のユーザーに関する情報を維持する点において非常に重要です。Session オブジェクトを使用すると、Web サイトから情報を要求する、英語以外のクライアントに固有の特殊な問題に対応することもできます。

コメントおよびトラブルシューティング  
 
 

Session オブジェクトを使用するときに注意する必要がある最も重要なものの 1 つは、そのスコープです。セッションレベルスコープで保存する情報は、アプリケーションのユーザーセッションの時間中はスコープ内にあります。これは重要なポイントです。たとえば、コードで、Web サイトの Search アプリケーションのコンテキストに定義されたセッションレベル変数を扱うとします。このアプリケーションの仮想ディレクトリ /search は、次の物理ディレクトリを反映しています。

D:\www\apps\search

現在のスクリプト SearchStart.ASP は、このディレクトリにあります。セッションレベル変数 strSearchPref をこのスクリプトで初期化したとします。次に、仮想ディレクトリ /contrib が次の物理ディレクトリを表す、他のアプリケーションにある別のアプリケーションスクリプトContribMain.ASP にユーザーが移動します。

D:\www\apps\contrib

このユーザーが、Search アプリケーションが含まれた仮想ディレクトリのスクリプトに 20 分以内 (または設定されている任意のセッション時間) に戻ると、strSearchPref セッションレベル変数値がリセットされます。これは複雑な Web アプリケーションでは重大なエラーの発生原因となります。 ユーザーセッションのセッションレベル変数は、アプリケーションから離れていた時間が同じ Web サイトのアプリケーションに使用された場合でも、セッション終了時に有効期限が切れます。

この問題を避ける 1 つの方法は、アプリケーションをネストすることです。たとえば、次のパスのように、/contrib 仮想ディレクトリを検索ディレクトリの下に配置します。

D:\www\apps\search\contrib

この設定を使用すると、Contribution アプリケーションの仮想パス /contrib は、Search アプリケーションのコンテキスト内に残ります。

ユーザーセッションが終了するまでのデフォルト時間を変更できると説明しましたが、この変更はなぜ必要なのでしょうか。それには 2 つの可能な理由があります。最初は、ユーザーのセッション情報を 20 分以上保存したい場合です。たとえば、ユーザーがサイトを 20 分以上離れた後に戻ることがわかっている場合があります。2 番目の可能性は、ユーザーのセッション情報をより早く終了したい場合です。たとえば、ユーザーはサイトに長時間接続しないことがわかっているので、メモリ内のセッション保存情報によるサーバーのメモリ消費への影響を最小限にしたい場合があります。この情報を初期設定とは異なるように設定する方法については、本章で後述する「Timeout」の項を参照してください。

このすべてのセッションレベル情報の保存は、クライアントに送信され、さらにサーバーに戻される Cookie の使用に基づいています。ユーザーが Cookie を無効にしているか、Cookie の使用をサポートしていない古いブラウザを使用している場合はどうでしょうか。Windows NT 認証または基本認証を使用している場合、 Request オブジェクトの ServerVariables コレクションの LOGON_USER 要素からユーザーを識別できます。この情報からは、サーバー上のデータベースまたはテキストファイルから、ユーザー固有のデータを取得できます。Windows NT 認証または基本認証を使用していない場合は、ユーザーを識別できる可能性は低くなります。過去には、ユーザーの IP アドレスを識別子として使用できましたが、DHCP およびファイアウォールを使用した動的に生成される IP アドレスの場合、ユーザーを識別するために IP アドレスは役に立たないと考える必要があります。

CodePage  
Session.CodePage (= intCodePageValue)
 

Web サーバーが 現在のスクリプトの動的コンテンツを表示するために使用するコードページを指定または取得します。コードページは、特定のロケールで使用されるすべての英数字および句読記号を含む文字セットです。

 
パラメータ
intCodePageValue

サーバーにインストールされた特定の文字セットに対応する符号なし整数です。CodePage プロパティを設定すると、その文字セットを使用するコンテンツが表示されます。次の表に、このパラメータで使用可能な有効な値の一部のみを示します。

CodePage の値

言語

932

日本語の漢字

950

中国語

1252

米国英語 (およびほとんどの欧州言語)

 
<%

' In the following code, assume that the original code 
' page setting is 1252 for American English. The 
' example demonstrates the use of the CodePage property 
' of the Session object to temporarily set the character
' set to Chinese so the text sent to the browser uses the
' Chinese character set:
Dim uintOrigCodePage
Dim uintChineseCodePage

uintChineseCodePage = 950
uintOrigCodePage = Session.CodePage

Session.CodePage = uintChineseCodePage
%>
' +-----------------------------------------------------------+
' | This text is sent to the client browser using the         |
' | Chinese character set.                                    |
' +-----------------------------------------------------------+
<%

' Remember to reset your CodePage property if you don't want 
' the rest of of the text created and placed into the HTML 
' stream to be displayed using the new character set.
Session.CodePage = uintOrigCodePage

%>
 
メモ

デフォルトでは、Active Server Pages は CODEPAGE ディレクティブを使用してスクリプトページに設定する、どのような文字セットでも使用します。第 11 章を参照してください。CodePage プロパティを設定すると、ブラウザに送信されたテキストのみに対して、この設定が上書きされます。スクリプトのテキストは、CODEPAGE ディレクティブを使用して宣言されたのと同じ文字セットを使用して、ASP とスクリプト間、またはスクリプトと ActiveX コンポーネンツ間で通信されます。

 
LCID  
Session.LCID (= intLCID)
 

ロケールは、特定の情報をフォーマットするユーザー設定を表します。たとえば、一部のロケールでは、「月/日/年」形式で日付がフォーマットされます。これは米国の標準ロケールです。各ロケールは、そのロケールに固有の LCID またはロケール ID で識別されます。このコードは、オペレーティングシステムで定義されます。

スクリプトのコンテンツのロケール識別子を設定するには、Session オブジェクトの LCID プロパティを使用します。LCID プロパティは、動的なコンテンツを Web ブラウザに表示するために使用される、有効なロケール識別子を表します。

 
パラメータ
intLCID

有効な 32 ビットロケール識別子。

 
<%

' The following code demonstrates the use of the LCID property 
' to temporarily set the locale identifier to Standard French.

Dim intOrigLCID
Dim intFrenchLCID

intFrenchLCID = 1036
intOrigLCID = Session.LCID

Session.LCID = intFrenchLCID
%>
' +-----------------------------------------------------------+
' | This text sent to the client browser will be formatted    |
' | according to the rules set by the locale identifier for   |
' | Standard French. For example, dates would be formatted    |
' | using the Day/Month/Year format, instead of the U.S.      |
' | standard Month/Day/Year.                                  |
' +-----------------------------------------------------------+
<%

' The next line resets the LCID property:
Session.LCID = intOrigLCID

%>
 
メモ

LCID プロパティは構文が CodePage プロパティと似ており、時刻と日付のフォーマットルールを設定できます。また、文字列をアルファベット順にするためのルールも設定します。

ASP の LCID ディレクティブを使用する場合、スクリプトの環境のロケール識別子をサーバーで設定することになります。Session.LCID プロパティはデフォルトでこの値を使用します。別のフォーマットルールを使用して文字列または日時情報をクライアントに送信する場合は、Session オブジェクトの LCID プロパティを設定する必要があります。ただし、その場合、スクリプトに対して内部的に文字列および日時の値がフォーマットされる方法には影響はありません。

 
SessionID  
Session.SessionID
 

現在の各ユーザーセッションを個別に識別する読み取り専用の値。この値は Long 型で、クライアントコンピュータに Cookie として保存されます。ユーザーセッション中に、ユーザーのブラウザはこの Cookie をユーザーを識別する方法として Web ブラウザに送信します。

 
パラメータ

なし

 
<%

' The following code retrieves the current SessionID for
' a given user:

Dim lngUserSessionId

lngUserSessionId = Session.SessionID

%>
 
メモ

SessionID プロパティは、ユーザーが Web サーバーからページを最初に要求したときに生成されます。Web サーバーは、複雑なアルゴリズムを使用して SessionID プロパティの値を作成し、この値をユーザーのコンピュータに Cookie として保存します。その後、ユーザーが Web サーバーからページを要求するたびに、この Cookie が HTTP 要求ヘッダでサーバーに送信されます。次に、サーバーは SessionID に従ってユーザーを識別できます。Cookie は、クライアントがブラウザを再起動するか、Webmaster が Web サーバーを再起動するときのみ、再初期化されます。

SessionID Cookie はクライアントブラウザで保持され、2 台のいずれかのコンピュータ (クライアントまたは Web サーバー) が再起動されるまで、Web サーバーに送信され、認識されます。この時間は、Session オブジェクトの Timeout プロパティとは無関係です。たとえば、ユーザーのセッションが終了するか、Session オブジェクトの Abandon メソッドを使用して中止されたとします。次に、ユーザーはブラウザを再起動することなくサイトを再訪問します。最後のセッション後に Web サーバーが再起動されていないと想定し、Web サーバーはユーザー用に新しいセッションを開始しますが、同じ SessionID を使用します。この SessionID は再び HTTP 要求の一部として Web サーバーに送信されます。

この最後の点が重要です。クライアントブラウザと Web サーバーアプリケーションの両方が再起動されていない場合のみ、SessionID がユーザーを個別に識別すると想定できます。たとえば、この値を主キーとして使用しないでください。この値はブラウザまたはサーバーが停止され、再起動されるたびにリセットされます。

Cookie をサポートしないか、Cookie を無効にしているブラウザでは、HTTP 要求ヘッダの一部として SessionID を送信しません。この場合は、他の方法を使用してユーザーを識別する必要があります。また、EnableSessionState プリプロセッサディレクティブを使用して、Web アプリケーションが Cookie を使用しないようにすることもできます。詳細については、第 11 章を参照してください。

Cookie を使用せずに情報を維持するには、各要求からの情報を QueryString に追加するか、ページの非表示のフォーム要素からの識別情報をポストします。

 
Timeout  
Session.Timeout (=intMinutes)
 

Web サーバーがページを要求または更新することなく、ユーザーのセッション情報を維持する分単位の時間。この値はデフォルトで 20 分に設定されます。

 
パラメータ
intMinutes

Web サーバーがセッション情報を維持する分数です。

 
<%

' The following code resets the Timeout property of the
' Session object from its default of 20 minutes to 5 
' minutes.

Session.Timeout = 5

%>
 
メモ

Timeout プロパティは使用が単純です。このプロパティの値はどれだけでも高い値に設定できますが、Timeout プロパティの値は、各ユーザーセッションが必要とする Web サーバーのメモリ消費に直接影響します。

サイトへのユーザーの訪問時間が短い場合は、この設定を例のように低く設定するように検討します。ただし、1 つのページでクライアントサイドスクリプトの電卓を表示する場合など、各ページへの訪問時間が長い場合は、この値を増やすことを検討します。

Session オブジェクトのほとんどのプロパティとは異なり、このプロパティは現在のセッションだけではなく、すべてのユーザーセッションに影響します。Session オブジェクトの Timeout プロパティの値を 120 分に設定する場合、 ユーザーのセッション情報は、最後の要求またはページの最後の更新後 120 分まで、Web サーバーのメモリに残ります。

 
Contents コレクション  
Session.Contents.Item("Pi") = 3.14
 

スクリプトを通じたセッションレベルスコープによって (つまり、<OBJECT> タグを使用しないで) 追加されたすべての変数とオブジェクトを含みます。

Session オブジェクトの Contents コレクションには、他の ASP コレクションのように、次のプロパティがあります。

Item

Contents コレクションの特定のメンバーの値を取得します。文字列キーまたはインデックス番号を使用するメンバーを指定します。文字列キーの値は、この項で後述する Key プロパティを通じ、インデックスを使って取得します。たとえば、Contents コレクションの要素を値 Pi で初期化する場合、次のようなコード行を使用します。

Session.Contents.Item("Pi") = 3.14

前のコード行では、コレクションに含まれる目的の要素は、キー値 "Pi" を使用して指定します。このように初期化すると、次のコード行を使用して、Contents コレクションのこの要素の値を取得できます。

dblMyVar = Session.Contents.Item("Pi")

すぐに明らかになることですが、これが Contents コレクションに追加される最初の要素であるとします。

次のコード行が示すように、キーではなく、コレクションに含まれるインデックスを使用しても、Contents コレクションに含まれる要素の値を取得できます。

dblMyVar = Session.Contents.Item(1)

Contents コレクションに含まれる最初の要素を表すには、0 ではなく 1 を使用します。これは小さなポイントですが、このコード行で 0 を使用すると、変数 dblMyVar は未定義の値で初期化されます。残念ながら、これによりエラーは発生しません。結果として、変数が不適切に初期化されるだけです。

dblMyVar = Session.Contents.Item(0) ' WRONG.

Item は Contents コレクションのデフォルトのプロパティであり、Contents コレクションは Application オブジェクトのデフォルトのコレクションです。つまり、次の 3 行のコードは、アプリケーションでまったく同じ方法で解釈されます。

Session.Contents.Item("Pi") = 3.14
Session.Contents("Pi") = 3.14
Session("Pi") = 3.14

同様に、次の 3 つのコード行もまた同等であると想定できます。

Session.Contents.Item(1) = 3.14159
Session.Contents(1) = 3.14159
Session(1) = 3.14159

ただし、これは Contents コレクションに含まれる最初の要素がキーを使用して定義されている場合だけです。ASP に添付されたマニュアルには記載されていませんが、前述の最初の 2 つのコード行のいずれかを使用するには、キーを使用してその要素をあらかじめ定義しておく必要があります。たとえば、Contents コレクションに 2 番目の要素を追加するとします。次のいずれかのコード行を使用して、この要素を初期化することはできません。

Session.Contents.Item(2) = 3.14159     ' WRONG.
Session.Contents(2) = 3.14159          ' WRONG.

残念ながら、この例外にも例外があります。次のコードを使用すると、2 番目の変数を初期化できます。

Session(2) = 3.14159

これらの矛盾を考えた場合、Contents コレクションに含まれる特定の要素の値を参照する際に常に一番安全な方法は、インデックスではなくキーを使用することであることがすぐにわかります。

また、メンバーのインデックスは変更される可能性があるため、Contents コレクションの特定のメンバーを参照するときもキーを使用することが重要です。たとえば、アプリケーションに次のコードがあるとします。

Session("strFirstName") = "Arthur"
Session("strMiddleName") = "Keyton"
Session("strLastName") = "Weissinger"

これらの変数が Contents コレクションに追加された最初の 3 つの変数であるとすると、後でそのインデックスを使用してそれぞれを参照できます。

strFirst = Session(1) 
strMiddle = Session(2)
strLast = Session(3)

ただし、コレクションから変数を完全に削除する Remove メソッド (本章で後述します) を使用する場合は、strMiddleName 変数を削除すると、インデックス番号が変更されます。

Session.Contents.Remove("strMiddleName")

strFirst = Session(1)       ' Initializes to "Arthur" 
strMiddle = Session(2)      ' Initializes to "Weissinger"
strLast = Session(3)        ' Initializes to Undefined.
Key

Contents コレクションの特定の要素の名前を表します。各要素の値は Item プロパティで表されるということを思い出してください。同様に、各要素の名前は、Key プロパティによって表されます。

特定のキーの名前が不明な場合は、順序参照を使用して取得できます。たとえば、コレクションに含まれる 3 番目の要素のキー名を取得してから、その要素の値を取得するとします。この場合は、次のコードを使用できます。

strKeyName = Session.Contents.Key(3)
strKeyValue = Session.Contents.Item(strKeyName)
Count

コレクションに含まれる現在の要素の数を返します。

他の ASP コレクションと同じように、Item プロパティを使用することにより、Contents コレクションの任意のフィールドの値を取得できます。ただし、本マニュアルの他の部分と同じように、以下の例では構文が短縮されているので、Item プロパティの使用を明示的に示しているわけではありません。次に例を示します。

strSecurityCode = Session("UserSecurityCode")

このコードは、次のコードの短縮形式です。

strSecurityCode = Session.Contents.Item("UserSecurityCode")

コレクションの Item プロパティ、Key プロパティ、および Count プロパティの詳細については、第 4 章の 4.2 項を参照してください。

ASP 3.0 までは、Contents コレクションに保存された項目は、ユーザーセッションが終了するまでメモリに残りました。一方、ASP 3.0 では、コレクションのメンバーを削除できる 2 つのメソッドが追加されました。

Remove  
Session.Contents.Remove(Key | Index)
 

Contents コレクションから特定のメンバーを削除します。IIS 5.0 で追加された Remove メソッドを使用すると、すべての変数を削除することなく、メモリ上で Session の Contents コレクションから特定の変数を削除できます。

Remove メソッドは、メモリの管理とクリーンアップに優れるため、Contents コレクションへの重要な追加です。これにより、ユーザーセッションを中断しないで、コレクションの要素の一部をメモリから削除できます。Contents コレクションの Item プロパティで説明したように、Remove メソッドを呼び出すときはインデックスではなく文字列キーを使用することが非常に重要です。要素のインデックスはアプリケーションの継続期間中に変わることがあり、Remove メソッドを呼び出すと、予期しない結果となる可能性があります。

 
パラメータ
Key

削除する Contents コレクションの特定のメンバーの名前を指定する文字列変数です。

Index

削除する Contents コレクションの特定のメンバーのインデックスを指定する整数変数です。

 

次のスクリプトは、Contents コレクションの 2 つのメンバーを削除します。

<%
' This script assumes you have been "carrying around" various form
' variables for an online membership request form. The user has filled
' out the form, she has a username and is now a member. Now you would    
' like to remove her form data which you stored in Session variables 
' because it was convenient and the form's security had to be relatively
' high.
strFirstName = Session("strFirstName")
strLastName  = Session("strLastName")

.
.
.
Session.Contents.Remove("strFirstName")
Session.Contents.Remove("strLastName")
.
.
.
%>
 
RemoveAll  
Session.Contents.RemoveAll
 

Contents コレクションのすべてのメンバーを削除します。IIS 5.0 に加えて、RemoveAll メソッドはセッションを破棄することなく、すべてのセッションスコープ変数をメモリから削除できます。

Remove メソッドと同様、RemoveAll メソッドは Contents コレクションへの重要な追加機能であり、より効果的なメモリ管理とクリーンアップを可能にします。このメソッドを使用すると、セッションそのものを破棄することなく、すべてのセッションスコープ変数を削除できます。

 
パラメータ

なし

 

次のスクリプトは、Contents コレクションのすべてのメンバーを削除します。

<%
' This script assumes you have been "carrying around" various form 
' variables for an online membership request form. The user has 
' filled out the form, she has a username
' and is now a member. Now you would like to remove her form data which 
' you stored in Session variables because it was convenient and the
' form's security had to be relatively high.
' strFirstName = Session("strFirstName")
' strLastName  = Session("strLastName")

.
.
.
Session.Contents.RemoveAll
.
.
.
%>

次のスクリプトは、ユーザーが訪れる 2 つの ASP スクリプトのうち最初のスクリプトです。最初のスクリプトは、ユーザーのブラウザを 2 番目のスクリプトにリダイレクトします。最初のスクリプトでは、ユーザーのセッションレベル変数 (SessionVar1SessionVar2、および SessionVar3) が作成されます。

<HTML>
<HEAD><TITLE>Session Contents Example Page1</TITLE></HEAD>
<BODY>
<%
Dim strVar1
Dim strVar2
Dim strVar3

strVar1 = "Session Variable 1"
strVar2 = "Session Variable 2"
strVar3 = "Session Variable 3"

' Each of the next three varieties of syntax
' are equivalent.
Session.Content.Item("SessionVar1") = strVar1
Session.Content("SessionVar2") = strVar2
Session("SessionVar3") = strVar3

Response.Redirect SessionPage2.asp
%>
</BODY>
</HTML>

2 番目のスクリプトでは、Session オブジェクトの Contents コレクションの現在の要素を調べます。

<HTML>
<HEAD><TITLE>Session Contents Example Page2</TITLE></HEAD>
<BODY>
<%
Dim intContentsCount
Dim strAppStatus
Dim strKey
Dim intCounter
Dim objMyComponent
Dim arystrNames( )


intContentsCount = Session.Contents.Count
strAppStatus = "Open"
%>
There are <%= intContentsCount %> items in the 
Session's Contents collection. <BR>
<%
For Each strKey in Session.Contents
%>
   The next item in Session's Contents collection<BR>
   has <%= strKey %> as its key and
   <%= Session.Contents(strKey) %>
   as its value.<BR>
<%
Next

' Set the AppStatus item in the Contents collection. 
' If this Session variable has been created before this,
' this line resets its value. If it has not been 
' created, this line creates it.
strAppStatus = "Page2...InProcess..."
Session("AppStatus") = strAppStatus

%>
The first three elements of the Session's Contents 
collection are as follows: <BR>
<%
' Retrieve the first three elements of the Contents 
' collection.
For intCounter = 1 to 3
%>
   <%= Session.Contents(intCounter) %> <BR>
<%
Next
%>
A second trip through the first three items.
<%
' This could just as accurately have been written 
' like this:
For intCounter = 1 to 3
%>
   <%= Session.Contents.Item(intCounter) %> <BR>
<%
Next

' Add an object to the Contents collection, then use that
' object's PrintDoc method through the Contents collection.
' (NOTE: For more on the Server object, see Chapter 9.)

'************************************************************
' If you try this script on your own, it will raise an error
' because of the lack of the Server component.
'************************************************************
Set objMyComponent = Server.CreateObject("MyComp.clsSpecial")
Session ("objRef") = objMyComponent 

' Call the object's method through the Contents collection.
Session ("objRef").PrintDoc
%>
</BODY>
</HTML>
 
メモ

Session オブジェクトの Contents コレクションにオブジェクト変数を追加すると、Contents 構文を通じてそのオブジェクトのメソッドとプロパティにアクセスできます。たとえば、次のコードは MyServerComp オブジェクトのインスタンスを作成し、その LastUpdated プロパティを参照します。

Dim datLastUpdated
Set Session.Contents(objSessionMyObj)  =  _ 
   Server.CreateObject("MyCompanyDLL.MyServerComp")
datLastUpdated = Session.Contents(objSessionMyObj).LastUpdated

配列を Contents コレクションに追加するときは、配列全体を追加します。配列の要素を変更するときは、配列のコピーを取得し、要素を変更して、配列全体をもう一度 Contents コレクションに追加します。次の例に、このポイントを示します。

<% Response.Buffer = True%>
<HTML>
<HEAD><TITLE>Session Array Example</TITLE></HEAD>
<BODY>
<%
' Create an array variable and add it to the 
' Contents collection.
ReDim arystrNames(3)

arystrNames(0) = "Chris"
arystrNames(1) = "Julie"
arystrNames(2) = "Vlad"
arystrNames(3) = "Kelly"

Session.Contents("arystrUserNames") = arystrNames
%>
The second name in the User Names array is <BR>
<%= Session("arystrUserNames")(1) %>
<%

' Change an element of the array being held in the 
' Contents collection. Use a different (new) array 
' to temporarily hold the contents. Creating a new 
' array is the safest way to work with Session 
' arrays because most of the time you cannot be 
' guaranteed how many elements are contained 
' in a Session array created in another script.
arystrNames2 = Session("arystrUserNames")
arystrNames2(1) = "Mark"

Session("arystrUserNames") = arystrNames2
' The second name is now Mark.
%>
<BR><BR>Now, the second name in the User Names array is <BR>
<%= Session("arystrUserNames")(1) %><BR>
<BR><BR><BR><BR><BR>
NOTE: The first element of the Contents collection is still
1, not 0 -- even though the first element of the array in element 1 
("arystrUserNames") is 0:<BR><BR>
<%= Session.Contents(1)(0)%> <BR>
</BODY></HTML>

GLOBAL.ASA ファイルに作成したオブジェクトは、そのオブジェクトのプロパティまたはメソッドを最初に呼び出すまで、サーバー上では実際にインスタンス化されません。

ObjectContext オブジェクトを使用してトランザクションでオブジェクトを使用する場合は、そのオブジェクトにアプリケーションスコープまたはセッションスコープを与えないでください。トランザクションで使用されたオブジェクトは、トランザクションの最後に破棄され、それ以降にプロパティを参照するかそのメソッドを呼び出すとエラーが発生します。

Session オブジェクトの Contents (および StaticObjects) コレクションは、Application オブジェクトの Contents コレクションに非常に似ています。

Contents コレクションは Session オブジェクトのデフォルトのコレクションですが、Application オブジェクトの Contents コレクションとは異なる 1 つの動作があります。Session オブジェクトから直接項目を取得することはできません。Contents コレクション (Session オブジェクトのデフォルトコレクション) および Item メソッド (コレクションの初期設定値) への暗黙的な参照は正しく解決できないためです。

次のコードがあるとします。

<HTML>
<HEAD><TITLE>Strange Behaviour</TITLE></HEAD>
<BODY>
<%
Session.Contents.Item("Item1") = "SessionVar1"
Session.Contents.Item("Item2") = "SessionVar2"
Session.Contents.Item("Item3") = "SessionVar3"
%>
. . . [additional code]

Contents コレクションは Session オブジェクトのデフォルトのコレクションであるため、次のコード行を使用して Item2 を参照できます。

strNewVar = Session("Item2")

しかし、Application オブジェクトの Contents コレクションとは異なり、次のコード行を使用して同じ要素を参照することはできません。このコード行は、取得しようとする変数に応じて無視されるか、エラーを発生させます。

strNewVar = Session(2)

ただし、次の例外があります。

strNewVar = Session.Contents.Item(2)

または

strNewVar = Session.Contents(2)

は正しく動作します。

この動作について記述したマニュアルは見つかりませんでしたが、IIS および Personal Web Server での動作は一貫していることが確認されています。

 
StaticObjects コレクション  
strFirstObjName = _
   Session.StaticObjects.Key(1)
 

<OBJECT> タグの使用を通じてアプリケーションに追加される、セッションレベルスコープを持つすべてのオブジェクトを含みます。StaticObjects コレクションを使用して、コレクションの特定のオブジェクトのプロパティを取得します。StaticObjects コレクションを使用して、コレクションの指定されたオブジェクトの特定のメソッドを使用することもできます。

Session オブジェクトの StaticObjects コレクションには、他の ASP コレクションのように、次のプロパティがあります。

Item

コレクションの特定の要素の値を表します。アイテムを指定するには、インデックス番号またはキーを使用します。

Key

コレクションの特定の要素の名前を表します。次に例を示します。

strFirstObjName = _
   Session.StaticObjects.Key(1)

Session オブジェクトの StaticObjects コレクションの最初の要素の名前を取得します。

Key プロパティの値を使用して、要素の値を名前で取得します。たとえば、最初の要素の名前が objMyObject であるとします。

strKey = Session.StaticObjects.Key(1)
Session.StaticObjects.Item(strKey).Printer = "Epson 540"

上のコードは、Session オブジェクトの StaticObjects コレクションの objMyObject 要素の Printer プロパティの値を設定します。

Count

コレクションに含まれる現在の要素の数を返します。

他の ASP コレクションと同じように、Item プロパティを使用することにより、StaticObjects コレクションの任意のフィールドの値を取得できます。ただし、本マニュアルの他の部分と同じように、以下の例では構文が短縮されているので、Item プロパティの使用を明示的に示しているわけではありません。次に例を示します。

strPrinterName = Session.StaticObjects("objMyObj").Printer

このコードは、次のコードの短縮形式です。

strPrinterName = Session.StaticObjects.Item("objMyObj").Printer

コレクションの Item、Key、および Count プロパティの詳細については、第 4 章の 4.2 項を参照してください。

' < FROM GLOBAL.ASA >
' This code resides in the GLOBAL.ASA file at the
' root of the current application. The following
' <OBJECT> tag is only processed once for the current
' application.
' See Chapter 11 for more details on the GLOBAL.ASA file.

<OBJECT RUNAT=Server 
SCOPE=Session
ID=AppInfo1 
PROGID="MSWC.MyInfo">
</OBJECT>

<OBJECT RUNAT=Server 
SCOPE=Session
ID=AppInfo2 
PROGID="MSWC.MyInfo">
</OBJECT>

' <>


<%
' The following code initializes the AppInfo1 component.
' This initialization code can reside anywhere.
AppInfo1.PersonalName = "Gertrude Stein"
AppInfo1.PersonalAddress = "233 Main Street"

AppInfo2.PersonalName = "David Davidson"
AppInfo2.PersonalAddress = "19A West Avenue"

' The following code uses the StaticObjects collection
' of the Session object to retrieve the value
' of the PersonalName property of both AppInfo1 and AppInfo2. 
For Each objInfo In Session.StaticObjects
%>
   The personal name is <BR>
   <%= Session.StaticObjects(objInfo).PersonalName%>
<%
Next
%>

There are <%= Session.StaticObjects.Count %> items
in the Session's StaticObjects collection.
 
メモ

Session オブジェクトの StaticObjects コレクションを使用すると、<OBJECT> タグの使用を通じてセッションスコープでインスタンス化された任意のオブジェクトにアクセスできます。Server.CreateObject を使用してインスタンス化されたオブジェクトは、このコレクションを通じてアクセスできません。

Microsoft による IIS 5.0 マニュアルの StaticObjects の例では、このコレクションに対してループを実行すると、各オブジェクトのプロパティを参照できることが述べられています。これは誤解を招く可能性があります。それは、マニュアルではコレクションはオブジェクトそのものを表すのではなく、実際はオブジェクトのすべてのプロパティを表すとなっているからです。StaticObjects コレクションのオブジェクトのプロパティまたはメソッドにアクセスする場合、次のように、Key の前後のかっこの外側にドット演算子を使用し、それに続いてプロパティまたはメソッド名を使用する必要があります。

<%= Session.StaticObjects(objInfo).PersonalName%>

このコードが動作するのは、Session.StaticObjects(objInfo)objInfo オブジェクトへの参照を返すためです。

GLOBAL.ASA ファイルで作成されたオブジェクトは、そのオブジェクトのプロパティまたはメソッドが最初に呼び出されるまで、サーバーで実際にはインスタンス化されません。したがって、StaticObjects コレクションを使用してこれらのオブジェクトのプロパティまたはメソッドにアクセスできるのは、アプリケーションに含まれる他の一部のコードによりサーバー上でオブジェクトがインスタンス化された後になります。

ObjectContext オブジェクトを使用したトランザクションでオブジェクトを使用する場合は、そのオブジェクトにアプリケーションスコープまたはセッションスコープを与えないでください。トランザクションで使用されるオブジェクトはトランザクションの最後に破棄され、それ以降にそのプロパティを参照するかメソッドを呼び出すとエラーが発生します。

 
Abandon  
Session.Abandon
 

指定されたユーザーセッションに関する情報を維持するために、Web サーバーによって使用されているメモリを解放します。ただし、他のユーザーのセッション情報には影響しません。Abandon メソッドを明示的に呼び出さない場合、Web サーバーはセッションがタイムアウトするまですべてのセッション情報を維持します。

 
パラメータ

なし

 

次のスクリプトを使用すると、セッション変数をクリアするページにブラウザをリダイレクトするリンクをユーザーがクリックできます。

<HTML>
<HEAD><TITLE>Session Abandon Example Page1</TITLE></HEAD>
<BODY>
Click <A HREF = "/SessionAbandonPage2.asp">here</A> to reset your user preferences.
</BODY>
</HTML>

次のスクリプトは、実際にはセッション変数をクリアします。

<HTML>
<HEAD><TITLE>Session Abandon Example Page2</TITLE></HEAD>
<BODY>
<%

' The following code abandons the current user session.
' Note that the actual information stored for the current
' user session is not released by the server until the
' end of the current Active Server Pages.

Session.Abandon

%>
Your user preferences have now been reset.
</BODY>
</HTML>
 
メモ

Session オブジェクトの Contents コレクションを繰り返し使用する場合は、Abandon メソッドが便利です。たとえば、多くの異なるユーザー設定をセッション変数として持っていて、例のようにそれらをすべて削除し、ユーザーがまったく新しい設定を選択できるようにするとします。Abandon メソッドを使用しないと、Contents コレクションから各変数を手動で削除する必要があります。複数の変数がある場合、これは時間がかかり、煩雑な処理となります。Abandon メソッドを使用すると、1 行のコードですべてを削除できます。

実際には、Abandon メソッドは現在のページのスクリプトの残りが処理された後に、Web サーバーによって処理されます。ただし、現在のページの処理が完了した後にユーザーからのページ要求があると、Web サーバーで新しいセッションが開始されます。

次の例では、セッション変数 intUserAge は、ページの最後までスクリプトに対して利用できます。Abandon メソッドは、ページの最後までメモリから変数を削除しません。

Session("intUserAge") = 23
Session.Abandon
[...More Code...]
' The current line successfully retrieves the value of 
' intUserAge.
intAgeCategory = CInt(Session("intUserAge") / 10)
[...End of Script. Session information is removed from web memory now...]

 
Session_OnEnd  
Session_OnEnd
 

ユーザーのセッションがタイムアウトするか、スクリプトが Session オブジェクトの Abandon メソッドを呼び出したときに起動されます。

OnEnd イベントプロシージャが存在する場合は、要求されたページを含むアプリケーションの GLOBAL.ASA ファイルにあります。

 
パラメータ

なし

 
<SCRIPT LANGUAGE = "VBScript" RUNAT = Server>

Sub Session_OnEnd

   ' If the user has a search results recordset open, close
   ' it:
   If IsObject(adoRSResults) Then
      Set adoRSResults = Nothing
   End If

End Sub

</SCRIPT>
 
メモ

OnEnd イベントロシージャのコードでは、Application、Server、および Session オブジェクトのみにアクセスできます。最も重要なことは、Response オブジェクトまたは Request オブジェクトにはアクセスできません。このために、クライアントをリダイレクトするか、クライアントと Cookie を送受信することはできません。

OnEnd イベントの可能な使用の 1 つは、後で使用するためにサーバー上のログファイルまたはテキストファイルにユーザーに関する情報を書き込むことです。この操作を行う場合、覚えておく必要があるいくつかの重要なポイントがあります。最初に、情報を保存する前に、その情報はセッション変数に保存する必要があります。これは、既に説明したように、ユーザー情報の最も一般的なソースである Request オブジェクトにアクセスできないためです。次のコードは、セッションレベル変数を保存する 1 つの可能な方法を示しています。

<SCRIPT LANGUAGE = "VBScript" RUNAT = Server>

Sub Session_OnEnd
   
   ' Assume that SessionVar1 contains some user-preference 
   ' information.

   ' It is not important that you understand exactly what is
   ' happening in the following code (you can learn more about 
   ' File objects in Chapter 19). Just suffice it to say 
   ' that these lines of code write the value of the 
   ' SessionVar1 Session variable to the text file 
   ' UserPref.txt.
   Set fs = Server.CreateObject("Scripting.FileSystemObject")
   Set f = fs.GetFile("d:\UserPref.txt")
   Set ts = f.OpenAsTextStream(ForAppending,_
                    TristateUseDefault)
   ts.Write Session(SessionVar1)
   ts.Close

   ' Note that more often than not, if you want to save this
   ' information to the server at the end of a user's session, 
   ' it may very well be more efficient to store it to a 
   ' database than to a text file. However, the general
   ' principal (of storing Session variable information in
   ' the OnEnd event) is similar.

End Sub

</SCRIPT>

Response オブジェクトは利用できないため、Response オブジェクトの AppendToLog メソッドを使用することはできません。さらに、Web サーバーのハードドライブに直接書き込みを行う場合は、書き込み先となるファイルの物理パスを知っている必要があります。これは、Server オブジェクトにアクセスできても、OnEnd イベントでその MapPath メソッドを使用できないためです。MapPath メソッドの詳細については、第 9 章の「MapPath」を参照してください。

 
Session_OnStart  
Session_OnStart
 

Web サーバーでインスタンス化されたセッションを持っていないユーザーがそのサーバーにページを要求するたびに起動されます。Session オブジェクトの OnStart イベントにコードが存在する場合、要求されたページの任意のコードよりも前に処理されます。

OnStart イベントプロシージャが存在する場合は、要求されたページを含むアプリケーションの GLOBAL.ASA ファイルにあります。

 
パラメータ

なし

 
<SCRIPT LANGUAGE = "VBScript" RUNAT = Server>

Sub Session_OnStart

   Dim strSiteStartPage
   Dim strCurrentPage
   Dim timUserStartTime
   Dim strUserIPAddress
   Dim strUserLogon

   ' Use the OnStart event to initialize session-level
   ' variables that your scripts can use throughout the
   ' the duration of the user's session.
   Session("timUserStartTime") = Now( )
   Session("strUserIPAddress") = _
           Request.ServerVariables("REMOTE_ADDR")

   ' Use the OnStart event to redirect the client if
   ' she attempts to enter the site from somewhere
   ' other than the site's home page.
   strCurrentPage = Request.ServerVariables("SCRIPT_NAME")
   strSiteStartPage = "/apps/home/startpage.asp"

   If StrComp(strCurrentPage, strSiteStartPage, 1) Then
      Response.Redirect(strSiteStartPage)
   End If

   ' You can also use the OnStart event of the Session
   ' object to assess user security access from the very
   ' beginning of the user's session. Note this code requires
   ' use of either the Basic authentication or Windows 
   ' NT Challenge Response access control on the web server.
   strUserLogon = Request.ServerVariables("LOGON_USER")
   [...Code to Determine Security Level...]

End Sub

</SCRIPT>
 
メモ

クライアントのブラウザが Cookie をサポートしていないか、ユーザーが手動で Cookie をオフにしている場合、ユーザーがサイトからページを要求するたびに、Session_OnStart イベントが処理されます。セッションは開始または維持されません。

OnEnd イベントのように、OnStart イベントの可能な使用の 1 つは、ユーザーに関する情報を後で使用するために、 ログファイルまたはサーバー上の他のテキストファイルに書き込むことです。この操作を行う場合は、Response オブジェクトの AppendToLog メソッドを使用できず、Web サーバーのハードドライブに直接書き込みを行う場合は、書き込み先となるファイルの物理パスを知っている必要があります。これは、Session オブジェクトの OnEnd イベントのように Server オブジェクトにアクセスできますが、Session_OnStart イベントでは Server オブジェクトの MapPath メソッドを使用できないためです。