<html>
<head>
<title>Session Object</title>
</head>
<body bgcolor="#FFFFFF" text="#000000">
<div id="Description">
<table cellpadding="0" cellspacing="0" border="0" width="100%" class="main">
<tr>
<td valign="top" class="NAME">Session Object</td>
<td valign="top" class="COMPATIBILITY">&nbsp;</td>
</tr>
<tr>
<td colspan="2" class="divider"><img src="dwres:18084" width="100%" height="1"></td>
</tr>
<tr>
<td valign="top" colspan="2" class="description">







<p><!--<primary>Session object</primary>-->
<!--<primary>user
sessions</primary>-->One of the greatest challenges you face
in constructing a full-featured web application is keeping track of
user-specific information while a user navigates your site without
asking her to identify herself at every request from the server.
Among other pieces of information that you need to maintain are a
user's identification, a user's security clearance if
applicable, and, in more advanced applications, user preferences that
allow you to customize your web site's look and feel in
response to selections made by the user. The primary problem with
maintaining user-specific information is limitations in the currently
standard HTTP 1.0 protocol.</p>




<p>Although HTTP 1.0 does provide a mechanism for persistent connections
that allows you to maintain user identification and user-specific
data, its utility is limited. Without getting into the technical
details, the Hypertext Transfer Protocol 1.0 allows client browsers
to send Keep-Alive messages to proxy servers. These messages
basically tell the proxy server to maintain an open connection with
the requesting client. However, these connection requests are often
unrecognized by the proxy server. This problem in the proxy server
results in a hung connection between the proxy server and the
requested web server. In a nutshell, maintaining connections with web
servers is prone to error and thus is unreliable in HTTP 1.0, still
by far the protocol most commonly used by client browsers.</p>




<p>Microsoft Internet Information Server's (and other web
servers') solution to this problem is to use the HTTP
Persistent Client State Mechanism—better known as
<!--<primary>cookies</primary>-->cookies—to
identify the user. IIS handles this mechanism through the use of the
Session built-in object.</p>




<p>The Session object represents the current user's session on the
<!--<primary>web servers</primary><secondary>sessions
on</secondary><see>user sessions</see>-->web server. It is
user specific, and its properties and methods allow you to manipulate
the information on the server that is specific to that user for the
duration of that user's connection. This duration is defined as
the time from the client's first request of a page within your
web application until 20 minutes (20 minutes is a default value that
can be changed—see the section "Timeout", later
in this chapter) after the user's last request to the web
server.</p>




<p>A user session can be initiated in one of three
ways:<!--<primary>initiating user
sessions</primary>--></p>




<ul><dd><p>A user not already connected to the server requests an Active Server
Page that resides in an application containing a
<filename>GLOBAL.ASA</filename> file with code for the
Session_OnStart event.</p></dd><dd><p>A user requests an Active Server Page whose script stores information
in any session-scoped variable.</p></dd><dd><p>A user requests an Active Server Page in an application whose
<filename>GLOBAL.ASA</filename> file instantiates an object using the
<span class="LITERAL">&lt;OBJECT&gt;</span> tag with the
<span class="LITERAL">SCOPE</span> parameter set to Session.</p></dd></ul>
<p>Note that a user session is specific to a given
<!--<primary>applications</primary><secondary>user sessions
and</secondary>-->application on your web site. In fact, it
is possible to maintain session information for more than one
application at a time if one application is rooted in a virtual
directory that resides under the virtual directory designating
another application.</p>




<p>The web server identifies each user with a unique
<!--<primary>SessionID property
(Session)</primary>--> <!--<primary>user
sessions</primary><secondary>session
identifiers</secondary>-->
<!--<primary>cookies</primary><secondary>session
identifiers</secondary>-->SessionID value. This SessionID
variable is assigned to each user at the beginning of his session on
the web server and is stored in memory on the web server. The
SessionID is stored on the client by writing a cookie containing the
SessionID to the user's machine. This cookie is sent to the
server each time the user makes a request. To identify the user, the
server retrieves the cookie and matches it up with a SessionID held
in memory.</p>




<p>In addition to the SessionID variable, you can store other
information specific to individual users. You can initialize (or
change) any <!--<primary>session-level
scope</primary><secondary>user-specific
information</secondary>--> <!--<primary>users,
information on</primary>-->
<!--<primary>scope</primary><secondary>user-specific
information</secondary>-->session-level variable anywhere in
any Active Server Pages script. To ensure that a session-level
variable is initialized to a specific value, you can script code in
the Session_OnStart event procedure in the
<filename>GLOBAL.ASA</filename> file. This event procedure is fired
when the user's session starts. The
<filename>GLOBAL.ASA</filename> file (see <link linkend="ch11-1-fm2xml">Chapter 11</link>) is a special file that you can code specific
to each ASP application. This file's code is processed when the
user session begins.</p>




<p>As discussed earlier, the Session object is very important in
maintaining information about individual users. You also can use the
Session object to handle some of the special issues that are specific
to non-English-speaking clients requesting information from your web
site.</p>




<!--
<p class="TITLE">Session Object Summary</p>




<dl>
<dt>Properties</dt>
<dd><p>CodePage</p>






<p>LCID</p>




<p>SessionID</p>




<p>Timeout</p>
</dd>





<dt>Collections</dt>
<dd><p>Contents</p>






<p>StaticObjects</p>
</dd>




<dt>Methods</dt>
<dd><p>Abandon</p>






<p>Contents.Remove</p>




<p>Contents.RemoveAll</p>
</dd>




<dt>Events</dt>
<dd><p>Session_OnEnd</p>






<p>Session_OnStart</p>
</dd>
</dl>

-->
</td></tr>
</table>
</div>
<div id="CommentsTroubleshooting">
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tr valign="top">
<td class="NAME">
Comments/Troubleshooting</td>
<td class="COMPATIBILITY">&nbsp;</td>
</tr>
<tr>
<td colspan="2" class="divider"><img src="dwres:18084" width="100%" height="1"></td>
</tr>
<tr>
<td class="usage" colspan="2">&nbsp;</td></tr>
<tr><td colspan="2" class="CLEARSEPARATION">&nbsp;</td>
</tr>
<tr><td colspan="2" class="description">




<p><!--<primary>comments and
troubleshooting</primary><secondary>Session
object</secondary>--> <!--<primary>session-level
scope</primary>--> <!--<primary>scope</primary><secondary>session-level</secondary>-->One
of the most important things that you need to keep in mind when using
the Session object is its scope. Any information you store with
session-level scope is in scope for the duration of the user's
session in a given application. This is a fine point. For example,
assume your code deals with a session-level variable that was defined
in the context of the Search application on your web site. This
application's virtual directory, <filename>/search</filename>,
reflects the following physical directory:</p>




<span class="PROGRAMLISTING"><pre>D:\www\apps\search</pre></span>




<p>The current script, <filename>SearchStart.ASP</filename>, resides in
this directory. Assume that you have initialized a session-level
variable, <var class="replaceable">strSearchPref</var>, in this script.
Now the user moves to another application script,
<filename>ContribMain.ASP</filename>, that resides in a separate
application whose virtual directory, <filename>/contrib</filename>,
reflects the following physical directory:</p>




<span class="PROGRAMLISTING"><pre>D:\www\apps\contrib</pre></span>




<p>If this user does not return to a script in the virtual directory
encompassing the Search application within 20 minutes (or whatever
the session duration is set to), the
<var class="replaceable">strSearchPref</var> session-level variable value
is reset. This is an important source of errors in complex web
applications. <!--<primary>expiring</primary><secondary>user
session-level variables</secondary>-->
<!--<primary>variables</primary><secondary>user-specific,
expiring</secondary>-->A user session's session-level
variables expire when the session ends, even if the time spent away
from the application was spent in applications on the same web site.</p>




<p>One way to avoid this problem is to nest applications. For example,
you can place the <filename>/contrib</filename> virtual directory
underneath the search directory, as reflected in the following path:</p>




<span class="PROGRAMLISTING"><pre>D:\www\apps\search\contrib</pre></span>




<p>Using this configuration, all requests to the contribution
application's virtual path, <filename>/contrib</filename>,
remain in the context of the search application.</p>




<p>I've noted that you can change the default length of time after
which a user session ends. Why would you want to do this? There are
two possible reasons. The first is that you want to save the
user's session information for longer than 20 minutes. For
example, you may know beforehand that a user will leave your site for
more than 20 minutes and then return. The second possibility is that
you want to terminate the user's session information sooner.
For example, say you know your users do not stay connected to your
site for very long and you want to minimize the impact on server
memory consumption that saving session information in memory
consumes. See the section "Timeout", later in this
chapter, for how to set this information differently from the
default.</p>




<p>All of this session-level information storage is based on the use of
cookies sent to the client and then sent back to the server. What if
the user has cookies turned off or is using an older browser that
does not support the use of cookies? Well, if you are using Windows
NT or Basic Authentication, you can identify the user from the
<!--<primary>LOGON_USER element
(Request)</primary>--> <!--<primary>users,
information on</primary>-->LOGON_USER element of the Request
object's ServerVariables collection. From this information, you
can retrieve user-specific data from a database or text files on the
server. If you are not using Windows NT or Basic Authentication, you
will likely not be able to identify the user. In the past, you could
use a user's IP address as an identifier, but with dynamically
generated IP addresses using DHCP and firewalls, the IP address
should be considered useless for the purpose of user
identification.  </p>
</td>
</tr>
</table>
</div>
<div id="CodePage">
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tr valign="top">
<td class="NAME">
CodePage</td>
<td class="COMPATIBILITY">&nbsp;</td>
</tr>
<tr>
<td colspan="2" class="divider"><img src="dwres:18084" width="100%" height="1"></td>
</tr>
<tr>
<td class="usage" colspan="2"><span class="LITERAL">Session.CodePage</span> <span class="LITERAL">(=</span> <var class="replaceable">intCodePageValue</var><command role="literal">)</command>
</td></tr>
<tr><td colspan="2" class="CLEARSEPARATION">&nbsp;</td>
</tr>
<tr><td colspan="2" class="description">
<p><!--<primary>Session
object</primary><secondary>properties
reference</secondary>--> <!--<primary>CodePage property
(Session)</primary>-->Specifies or retrieves the code page
that will be used by the web server to display
<!--<primary>dynamic content</primary><secondary>code page
for</secondary>--> <!--<primary>content,
dynamic</primary><secondary>code page for</secondary>-->
<!--<primary>character sets</primary><secondary>code page for
dynamic content</secondary>-->dynamic content in the current
script. A code page is a character set containing all the
alphanumeric characters and punctuation used by a specific locale.</p>



</td>
</tr>
<tr><td colspan="2" class="CLEARSEPARATION">&nbsp;</td></tr>
<tr>
<td colspan="2" class="DESCRIPTIONTITLE">Parameters</td>
</tr>
<tr>
<td colspan="2" class="description">




<dl>
<dt><var class="replaceable">intCodePageValue</var></dt>
<dd><p>An unsigned integer corresponding to a specific character set
installed on the server. Setting the CodePage property will cause the
system to display content using that character set. The following
table lists only a few of the possible valid values for this
parameter:</p></dd>

</dl>




<table border="1">



<thead>
<tr valign="top">
<td>
<p><em>CodePage Value</em></p></td>
<td>
<p>Language</p></td>
</tr>



</thead>



<tbody>
<tr valign="top">
<td>
<p>932</p></td>
<td>
<p>Japanese Kanji</p></td>
</tr>



<tr valign="top">
<td>
<p>950</p></td>
<td>
<p>Chinese</p></td>
</tr>



<tr valign="top">
<td>
<p>1252</p></td>
<td>
<p>American English (and most European languages)</p></td>
</tr>



</tbody>

</table>

</td>
</tr>
<tr>
<td colspan="2" class="CLEARSEPARATION">&nbsp;</td>
</tr>
<tr>
<td colspan="2" class="DESCRIPTIONTITLE">Example</td>
</tr>
<tr>
<td colspan="2" class="description">




<span class="PROGRAMLISTING"><pre>&lt;%

' 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
%&gt;
' +-----------------------------------------------------------+
' | This text is sent to the client browser using the         |
' | Chinese character set.                                    |
' +-----------------------------------------------------------+
&lt;%

' 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

%&gt;</pre></span>




</td>
</tr>
<tr>
<td colspan="2" class="CLEARSEPARATION">&nbsp;</td>
</tr>
<tr>
<td colspan="2" class="DESCRIPTIONTITLE">Notes</td>
</tr>
<tr>
<td colspan="2" class="description">




<p>Remember that, by default, Active Server Pages uses whatever
character set you set for the script page using the
<span class="LITERAL">CODEPAGE</span><!--<primary>CODEPAGE
directive</primary>--> directive (see <link linkend="ch11-1-fm2xml">Chapter 11</link>). Setting the CodePage property overrides this
only for text sent to the browser. Script text is still communicated
between ASP and your script or your script and ActiveX components
using the same character set declared using the
<span class="LITERAL">CODEPAGE</span> directive. </p>




</td>
</tr>
<tr>
<td colspan="2" class="CLEARSEPARATION">&nbsp;</td>
</tr>
</table>
</div>
<div id="LCID">
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tr valign="top">
<td class="NAME">
LCID</td>
<td class="COMPATIBILITY">&nbsp;</td>
</tr>
<tr>
<td colspan="2" class="divider"><img src="dwres:18084" width="100%" height="1"></td>
</tr>
<tr>
<td class="usage" colspan="2"><span class="LITERAL">Session.LCID (=</span> <var class="replaceable">intLCID</var><command role="literal">)</command>
</td></tr>
<tr><td colspan="2" class="CLEARSEPARATION">&nbsp;</td>
</tr>
<tr><td colspan="2" class="description">
<p><!--<primary>LCID
property (Session)</primary>--> <!--<primary>locale</primary>-->
<!--<primary>web
pages</primary><secondary>locale-specific
formatting</secondary>--> <!--<primary>dynamic
content</primary><secondary>locale for</secondary>-->
<!--<primary>content,
dynamic</primary><secondary>locale for</secondary>-->The
locale represents a user preference for how certain information is
formatted. For example, some locales have dates formatted in the
Month/Day/Year format. This is the standard U.S. locale. Each locale
is identified by that locale's unique LCID, or locale ID. This
code is defined in the operating system.</p>




<p>You can set the locale identifier for your script's content
using the LCID property of the Session object. The LCID property
represents the valid locale identifier that will be used to display
dynamic content to the web browser.</p>



</td>
</tr>
<tr><td colspan="2" class="CLEARSEPARATION">&nbsp;</td></tr>
<tr>
<td colspan="2" class="DESCRIPTIONTITLE">Parameters</td>
</tr>
<tr>
<td colspan="2" class="description">




<dl>
<dt><var class="replaceable">intLCID</var></dt>
<dd><p>A valid 32-bit locale identifier.</p></dd>

</dl>




</td>
</tr>
<tr>
<td colspan="2" class="CLEARSEPARATION">&nbsp;</td>
</tr>
<tr>
<td colspan="2" class="DESCRIPTIONTITLE">Example</td>
</tr>
<tr>
<td colspan="2" class="description">




<span class="PROGRAMLISTING"><pre>&lt;%

' 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
%&gt;
' +-----------------------------------------------------------+
' | 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.                                  |
' +-----------------------------------------------------------+
&lt;%

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

%&gt;</pre></span>




</td>
</tr>
<tr>
<td colspan="2" class="CLEARSEPARATION">&nbsp;</td>
</tr>
<tr>
<td colspan="2" class="DESCRIPTIONTITLE">Notes</td>
</tr>
<tr>
<td colspan="2" class="description">




<p>Similar to the CodePage property in syntax, the LCID property allows
you to set the formatting rules for times and dates, and it also sets
rules for alphabetizing strings.</p>




<p>If you use the ASP <span class="LITERAL">LCID</span> directive, you are setting
the locale identifier for the script's environment on the
server. The Session.LCID property uses this value as a default. If
you wish to send string or date/time information to the client using
different formatting rules, you must set the LCID property of the
Session object. However, doing so has no impact on how the strings
and date/time values are formatted internally to the
script.



</p>




</td>
</tr>
<tr>
<td colspan="2" class="CLEARSEPARATION">&nbsp;</td>
</tr>
</table>
</div>
<div id="SessionID">
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tr valign="top">
<td class="NAME">
SessionID</td>
<td class="COMPATIBILITY">&nbsp;</td>
</tr>
<tr>
<td colspan="2" class="divider"><img src="dwres:18084" width="100%" height="1"></td>
</tr>
<tr>
<td class="usage" colspan="2"><span class="LITERAL">Session.SessionID</span> 
</td></tr>
<tr><td colspan="2" class="CLEARSEPARATION">&nbsp;</td>
</tr>
<tr><td colspan="2" class="description">
<p><!--<primary>SessionID property
(Session)</primary>--> <!--<primary>user
sessions</primary><secondary>session
identifiers</secondary>-->A read-only value that uniquely
identifies each current user's session. This value is of data
type Long and is stored as a
<!--<primary>cookies</primary><secondary>session
identifiers</secondary>-->cookie on the client machine.
During a user's session, the user's browser sends this
cookie to the web server as a means of identifying the user.</p>



</td>
</tr>
<tr><td colspan="2" class="CLEARSEPARATION">&nbsp;</td></tr>
<tr>
<td colspan="2" class="DESCRIPTIONTITLE">Parameters</td>
</tr>
<tr>
<td colspan="2" class="description">




<p>None</p>




</td>
</tr>
<tr>
<td colspan="2" class="CLEARSEPARATION">&nbsp;</td>
</tr>
<tr>
<td colspan="2" class="DESCRIPTIONTITLE">Example</td>
</tr>
<tr>
<td colspan="2" class="description">




<span class="PROGRAMLISTING"><pre>&lt;%

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

Dim lngUserSessionId

lngUserSessionId = Session.SessionID

%&gt;</pre></span>




</td>
</tr>
<tr>
<td colspan="2" class="CLEARSEPARATION">&nbsp;</td>
</tr>
<tr>
<td colspan="2" class="DESCRIPTIONTITLE">Notes</td>
</tr>
<tr>
<td colspan="2" class="description">




<p>The SessionID property is generated the first time a user requests a
page from the web server. The web server creates a value for the
SessionID property using a complex algorithm and then stores this
value in the form of a cookie on the user's machine.
Subsequently, each time the user requests a page from the web server,
this cookie is sent to the server in the HTTP request header. The
server is then able to identify the user according to her SessionID.
The cookie is reinitialized only when the client restarts her browser
or when the webmaster restarts the web server.</p>




<p>Note that the SessionID cookie lasts on the client browser and is
sent to (and recognized by) the web server until one of the two
machines (client or web server) is restarted. This time period has
nothing to do with the Timeout property of the Session object. For
example, assume a user's session ends or is abandoned by using
the Abandon method of the Session object. Then the user (without
having restarted her browser) revisits the site. Assuming also that
the web server has not been restarted since the end of the last
session, the web server will start a new session for the user but
will use the same SessionID, which is again sent to the web server as
part of the HTTP request.</p>




<p>This last point is important and is worth noting.
<em>Only</em> if both the client browser and the web
server applications have not been restarted can you assume a
SessionID uniquely identifies a user. Do not use this value as a
primary key, for example, as it is reset anytime either browser or
server is stopped and restarted.</p>




<p>Remember also that a browser that does not support cookies or that
has cookies turned off will not send the SessionID as part of the
HTTP request header. In this case, you must rely on some other method
to identify users. You also can prevent the web application from
using cookies by using the <span class="LITERAL">EnableSessionState</span>
preprocessor directive (for more details, see <link linkend="ch11-1-fm2xml">Chapter 11</link>).</p>




<p>To maintain information without using cookies, you could either
append information from each request onto the QueryString or post the
identifying information from a hidden form element on your
page.
</p>




</td>
</tr>
<tr>
<td colspan="2" class="CLEARSEPARATION">&nbsp;</td>
</tr>
</table>
</div>
<div id="Timeout">
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tr valign="top">
<td class="NAME">
Timeout</td>
<td class="COMPATIBILITY">&nbsp;</td>
</tr>
<tr>
<td colspan="2" class="divider"><img src="dwres:18084" width="100%" height="1"></td>
</tr>
<tr>
<td class="usage" colspan="2"><span class="LITERAL">Session.Timeout (=</span><var class="replaceable">intMinutes</var><span class="LITERAL">)</span>
</td></tr>
<tr><td colspan="2" class="CLEARSEPARATION">&nbsp;</td>
</tr>
<tr><td colspan="2" class="description">
<p><!--<primary>Timeout property (Session)</primary>-->
<!--<primary>expiring</primary><secondary>user sessions
(inactive)</secondary>--> <!--<primary>user
sessions</primary><secondary>maintaining
inactive</secondary>-->The length of time in minutes the web
server will maintain a user's session information without
requesting or refreshing a page. This value is set to 20 minutes by
default.</p>



</td>
</tr>
<tr><td colspan="2" class="CLEARSEPARATION">&nbsp;</td></tr>
<tr>
<td colspan="2" class="DESCRIPTIONTITLE">Parameters</td>
</tr>
<tr>
<td colspan="2" class="description">




<dl>
<dt><var class="replaceable">intMinutes</var></dt>
<dd><p>The number of minutes for which the web server will maintain session
information</p></dd>

</dl>




</td>
</tr>
<tr>
<td colspan="2" class="CLEARSEPARATION">&nbsp;</td>
</tr>
<tr>
<td colspan="2" class="DESCRIPTIONTITLE">Example</td>
</tr>
<tr>
<td colspan="2" class="description">




<span class="PROGRAMLISTING"><pre>&lt;%

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

Session.Timeout = 5

%&gt;</pre></span>




</td>
</tr>
<tr>
<td colspan="2" class="CLEARSEPARATION">&nbsp;</td>
</tr>
<tr>
<td colspan="2" class="DESCRIPTIONTITLE">Notes</td>
</tr>
<tr>
<td colspan="2" class="description">




<p>The Timeout property is straightforward in use. You can set this
property's value as high as you like, but note that the value
for the Timeout property directly affects the
<!--<primary>memory</primary><secondary>user
sessions</secondary><tertiary>Timeout property
and</tertiary>--> <!--<primary>user
sessions</primary><secondary>memory for</secondary><tertiary>Timeout
property and</tertiary>-->memory consumption on the web
server that each user session requires.</p>




<p>Consider setting this number lower (as in the example) when your
site's users visit for only brief periods. If, however, each
page is visited for a longer period of time (for example, one page
may provide a client-side scripted calculator), you may want to
consider increasing this value.</p>




<p>Note that, unlike most properties of the Session object, this
property affects <em>all</em> user sessions, not just the
current session. If you set the value of the Timeout property of the
Session object to 120 minutes, <em>every</em>
user's session information will remain in memory on the web
server until 120 minutes after he last requests or refreshes a
page.</p>



</td>
</tr>
<tr>
<td colspan="2" class="CLEARSEPARATION">&nbsp;</td>
</tr>
</table>
</div>
<div id="ContentsCollection">
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tr valign="top">
<td class="NAME">
Contents Collection</td>
<td class="COMPATIBILITY">&nbsp;</td>
</tr>
<tr>
<td colspan="2" class="divider"><img src="dwres:18084" width="100%" height="1"></td>
</tr>
<tr>
<td class="usage" colspan="2"><span class="PROGRAMLISTING"><pre>Session.Contents.Item("Pi") = 3.14</pre></span></td></tr>
<tr><td colspan="2" class="CLEARSEPARATION">&nbsp;</td>
</tr>
<tr><td colspan="2" class="description">
<p><!--<primary>Session
object</primary><secondary>collections
reference</secondary>--> <!--<primary>Contents
collection</primary><secondary>Session
object</secondary>-->Contains all of the variables and
objects added with session-level scope through script (i.e.,
<em>not</em> through the use of the
<span class="LITERAL">&lt;OBJECT&gt;</span> tag).</p>




<p>The Contents collection of the Session object, like other ASP
collections, has the following properties:</p>




<dl>
<dt>Item</dt>
<dd><p><!--<primary>Item property</primary><secondary>Contents
collection</secondary>-->Retrieves the value of a specific
member of the Contents collection. You specify which member using a
string key (whose value is obtainable using the index through the Key
property, described later in this section) or using an index number.
For example, if you wish to initialize an element in the Contents
collection with a value of Pi, you might use a line of code similar
to the following:</p>




<span class="PROGRAMLISTING"><pre>Session.Contents.Item("Pi") = 3.14</pre></span>




<p>In the preceding line of code, the desired element in the collection
is specified using the key value "Pi." Thus initialized,
you can then retrieve the value of this element of the Contents
collection using the following line of code:</p>




<span class="PROGRAMLISTING"><pre>dblMyVar = Session.Contents.Item("Pi")</pre></span>




<p>For reasons that will become clear in a moment, let's assume
that this is the first element added to the Contents collection.</p>




<p>You could also retrieve the value of an element in the Contents
collection using its index in the collection rather than a key, as
demonstrated in the following line of code:</p>




<span class="PROGRAMLISTING"><pre>dblMyVar = Session.Contents.Item(1)</pre></span>




<p>Note that you use a 1 (one), not a
(zero), to represent the first element in the Contents collection.
This is a subtle point, since using a zero in this line of code will
result in the variable <var class="replaceable">dblMyVar</var> being
initialized with an undefined value. Unfortunately, this will not
result in an error. It will result only in an improperly initialized
variable:</p>




<span class="PROGRAMLISTING"><pre>dblMyVar = Session.Contents.Item(0) ' WRONG.</pre></span>




<p>Item is the default property of the Contents collection and the
Contents collection is the default collection of the Application
object. This means that each of the following three lines of code is
interpreted in exactly the same manner in your application:</p>




<span class="PROGRAMLISTING"><pre>Session.Contents.Item("Pi") = 3.14
Session.Contents("Pi") = 3.14
Session("Pi") = 3.14</pre></span>




<p>Correspondingly, you would assume that the following three lines of
code are also equivalent:</p>




<span class="PROGRAMLISTING"><pre>Session.Contents.Item(1) = 3.14159
Session.Contents(1) = 3.14159
Session(1) = 3.14159</pre></span>




<p>However, this is only the case if the first element in the Contents
collection has previously been defined using a key. Although not
mentioned in the documentation that accompanies ASP, to use either of
the preceding first two lines of code, the element must have been
previously defined using a key. For example, assume you decide to add
a second element to the Contents collection. You cannot initialize
this element using either of the following lines of code:</p>




<span class="PROGRAMLISTING"><pre>Session.Contents.Item(2) = 3.14159     ' WRONG.
Session.Contents(2) = 3.14159          ' WRONG.</pre></span>




<p>Unfortunately, even this exception has an exception. You
<em>can</em> use the following code to initialize a
second variable:</p>




<span class="PROGRAMLISTING"><pre>Session(2) = 3.14159</pre></span>




<p>When you consider these inconsistencies, it becomes quickly apparent
that it is always safest to use a key rather than an index when
referencing the value of a specific element in the Contents
collection.</p>




<p>Also, it is important to use a key when referring to a specific
member of the Contents collection because that member's index
may change. For example, suppose you have the following code in your
application:</p>




<span class="PROGRAMLISTING"><pre>Session("strFirstName") = "Arthur"
Session("strMiddleName") = "Keyton"
Session("strLastName") = "Weissinger"</pre></span>




<p>Assuming these variables are the first three added to the Contents
collection, you could later refer to each using its index:</p>




<span class="PROGRAMLISTING"><pre>strFirst = Session(1) 
strMiddle = Session(2)
strLast = Session(3)</pre></span>




<p>However, if you use the Remove method, which completely removes a
variable from the collection (see later in this chapter), to remove
the <var class="replaceable">strMiddleName</var> variable, the index
numbers will change:</p>




<span class="PROGRAMLISTING"><pre>Session.Contents.Remove("strMiddleName")

strFirst = Session(1)       ' Initializes to "Arthur" 
strMiddle = Session(2)      ' Initializes to "Weissinger"
strLast = Session(3)        ' Initializes to Undefined.</pre></span></dd>




<dt>Key</dt>
<dd><p><!--<primary>Key property</primary><secondary>Contents
collection</secondary>-->Represents the name of a specific
element in the Contents collection. Remember from earlier that each
element's value is represented by the Item property. Similarly,
each element's name is represented by its Key property.</p>




<p>If you do not know the name of a specific key, you can obtain it
using its ordinal reference. For example, assume that you want to
learn the key name for the third element in the collection and,
subsequently, retrieve that element's value. You could use the
following code:</p>




<span class="PROGRAMLISTING"><pre>strKeyName = Session.Contents.Key(3)
strKeyValue = Session.Contents.Item(strKeyName)</pre></span></dd>




<dt>Count</dt>
<dd><p><!--<primary>Count property</primary><secondary>Contents
collection (Session)</secondary>-->Returns the current
number of elements in the collection.</p></dd>

</dl>




<p>As with other ASP collections, you can retrieve the value of any
field of the Contents collection through the use of the Item
property. However, as in other places in this book, in the following
examples, the syntax has been abbreviated so that it does not
explicitly show the use of the Item property. For example:</p>




<span class="PROGRAMLISTING"><pre>strSecurityCode = Session("UserSecurityCode")</pre></span>




<p>is an abbreviated form of:</p>




<span class="PROGRAMLISTING"><pre>strSecurityCode = Session.Contents.Item("UserSecurityCode")</pre></span>




<tip id="ch10-23-fm2xml" role="ora">
<p>For more information on the Item, Key, and Count properties of a
collection, see the discussion in <link linkend="ch04-3-fm2xml">Section 4.2</link> in <link linkend="ch04-40130">Chapter 4</link>.</p>



</tip>

<p>Until ASP 3.0, items stored to the Contents collection remained in
memory until the user session ended. ASP 3.0, on the other hand, adds
two methods that allow members of the collection to be removed.</p>


</td>
</tr>
</table>
</div>
<div id="Remove">
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tr valign="top">
<td class="NAME">
Remove</td>
<td class="COMPATIBILITY">&nbsp;</td>
</tr>
<tr>
<td colspan="2" class="divider"><img src="dwres:18084" width="100%" height="1"></td>
</tr>
<tr>
<td class="usage" colspan="2"><span class="LITERAL">Session.Contents.Remove(</span><var class="replaceable">Key</var> <span class="LITERAL">|</span> <var class="replaceable">Index</var><span class="LITERAL">)</span>
</td></tr>
<tr><td colspan="2" class="CLEARSEPARATION">&nbsp;</td>
</tr>
<tr><td colspan="2" class="description">
<p>Removes a specific member from the Contents collection. An addition
in IIS 5.0, the Remove method allows you to remove from memory a
specific variable from the Session's Contents collection
without removing all the others.</p>




<p>The Remove method is an important addition to the Contents collection
because it allows for better memory control and cleanup. It allows
you to remove from memory some of your collection's elements
without abandoning the user's session. As discussed under the
Item property of the Contents collection, it is very important to use
a string key instead of an index when calling the Remove method. An
element's index may change over the life of the application,
and your call to Remove may lead to unpredictable results.</p>



</td>
</tr>
<tr><td colspan="2" class="CLEARSEPARATION">&nbsp;</td></tr>
<tr>
<td colspan="2" class="DESCRIPTIONTITLE">Parameters</td>
</tr>
<tr>
<td colspan="2" class="description">




<dl>
<dt>Key</dt>
<dd><p>A string variable that specifies the name of the specific member of
the Contents collection to be removed.</p></dd>




<dt>Index</dt>
<dd><p>An integer variable that specifies the index of the specific member
of the Contents collection to be removed.</p></dd>

</dl>




</td>
</tr>
<tr>
<td colspan="2" class="CLEARSEPARATION">&nbsp;</td>
</tr>
<tr>
<td colspan="2" class="DESCRIPTIONTITLE">Example </td>
</tr>
<tr>
<td colspan="2" class="description">




<p>The following script removes two members of the Contents collection:</p>




<span class="PROGRAMLISTING"><pre>&lt;%
' 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")
.
.
.
%&gt;</pre></span>




</td>
</tr>
<tr>
<td colspan="2" class="CLEARSEPARATION">&nbsp;</td>
</tr>
</table>
</div>
<div id="RemoveAll">
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tr valign="top">
<td class="NAME">
RemoveAll</td>
<td class="COMPATIBILITY">&nbsp;</td>
</tr>
<tr>
<td colspan="2" class="divider"><img src="dwres:18084" width="100%" height="1"></td>
</tr>
<tr>
<td class="usage" colspan="2"><span class="LITERAL">Session.Contents.RemoveAll</span>
</td></tr>
<tr><td colspan="2" class="CLEARSEPARATION">&nbsp;</td>
</tr>
<tr><td colspan="2" class="description">
<p><!--<primary>RemoveAll method, Contents
collection</primary>-->Removes all members from the Contents
collection. An addition in IIS 5.0, the RemoveAll method allows you
to remove from memory all Session-scoped variables without abandoning
the Session.</p>




<p>Like the Remove method, the RemoveAll method is an important addition
to the Contents collection because it allows for better memory
control and cleanup. It allows you to remove all Session-scoped
variables without abandoning the session itself.</p>



</td>
</tr>
<tr><td colspan="2" class="CLEARSEPARATION">&nbsp;</td></tr>
<tr>
<td colspan="2" class="DESCRIPTIONTITLE">Parameters</td>
</tr>
<tr>
<td colspan="2" class="description">




<p>None</p>




</td>
</tr>
<tr>
<td colspan="2" class="CLEARSEPARATION">&nbsp;</td>
</tr>
<tr>
<td colspan="2" class="DESCRIPTIONTITLE">Examples</td>
</tr>
<tr>
<td colspan="2" class="description">




<p>The following script removes all members of the Contents collection:</p>




<span class="PROGRAMLISTING"><pre>&lt;%
' 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
.
.
.
%&gt;</pre></span>




<p>The following script is the first of two ASP scripts that the user
will visit (the first redirects the user's browser to the
second). In this first script, the user's session-level
variables are created (<var class="replaceable">SessionVar1</var>,
<var class="replaceable">SessionVar2</var>, and
<var class="replaceable">SessionVar3</var>).</p>




<span class="PROGRAMLISTING"><pre>&lt;HTML&gt;
&lt;HEAD&gt;&lt;TITLE&gt;Session Contents Example Page1&lt;/TITLE&gt;&lt;/HEAD&gt;
&lt;BODY&gt;
&lt;%
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
%&gt;
&lt;/BODY&gt;
&lt;/HTML&gt;</pre></span>




<p>In this second script, we'll take a look at the current
elements in the Contents collection of the Session object.</p>




<span class="PROGRAMLISTING"><pre>&lt;HTML&gt;
&lt;HEAD&gt;&lt;TITLE&gt;Session Contents Example Page2&lt;/TITLE&gt;&lt;/HEAD&gt;
&lt;BODY&gt;
&lt;%
Dim intContentsCount
Dim strAppStatus
Dim strKey
Dim intCounter
Dim objMyComponent
Dim arystrNames( )


intContentsCount = Session.Contents.Count
strAppStatus = "Open"
%&gt;
There are <strong class="userinput">&lt;%= intContentsCount %&gt;</strong> items in the 
Session's Contents collection. &lt;BR&gt;
&lt;%
For Each strKey in Session.Contents
%&gt;
   The next item in Session's Contents collection&lt;BR&gt;
   has <strong class="userinput">&lt;%= strKey %&gt;</strong> as its key and
   &lt;%= Session.Contents(strKey) %&gt;
   as its value.&lt;BR&gt;
&lt;%
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

%&gt;
The first three elements of the Session's Contents 
collection are as follows: &lt;BR&gt;
&lt;%
' Retrieve the first three elements of the Contents 
' collection.
For intCounter = 1 to 3
%&gt;
   <strong class="userinput">&lt;%=</strong> Session<strong class="userinput">.Contents(intCounter) %&gt;</strong> &lt;BR&gt;
&lt;%
Next
%&gt;
A second trip through the first three items.
&lt;%
' This could just as accurately have been written 
' like this:
For intCounter = 1 to 3
%&gt;
   <strong class="userinput">&lt;%=</strong> Session<strong class="userinput">.Contents.Item(intCounter) %&gt;</strong> &lt;BR&gt;
&lt;%
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 <link linkend="ch09-1-fm2xml">Chapter 9</link>.)

'************************************************************
' 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
%&gt;
&lt;/BODY&gt;
&lt;/HTML&gt;</pre></span>




</td>
</tr>
<tr>
<td colspan="2" class="CLEARSEPARATION">&nbsp;</td>
</tr>
<tr>
<td colspan="2" class="DESCRIPTIONTITLE">Notes</td>
</tr>
<tr>
<td colspan="2" class="description">




<p>If you add an object variable to the Session object's Contents
collection, you can access that object's methods and properties
through the Contents syntax. For example, the following code creates
an instance of the MyServerComp object and then refers to its
LastUpdated property:</p>




<span class="PROGRAMLISTING"><pre>Dim datLastUpdated
Set Session.Contents(objSessionMyObj)  =  _ 
   Server.CreateObject("MyCompanyDLL.MyServerComp")
datLastUpdated = Session.Contents(objSessionMyObj).LastUpdated</pre></span>




<p>When adding an <!--<primary>arrays, adding to Contents
collection</primary>-->array to the Contents collection, add
the entire array. When changing an element of the array, retrieve a
copy of the array, change the element, and then add the array as a
whole to the Contents collection again. The following example
demonstrates this point:</p>




<span class="PROGRAMLISTING"><pre>&lt;% Response.Buffer = True%&gt;
&lt;HTML&gt;
&lt;HEAD&gt;&lt;TITLE&gt;Session Array Example&lt;/TITLE&gt;&lt;/HEAD&gt;
&lt;BODY&gt;
&lt;%
' 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
%&gt;
The second name in the User Names array is &lt;BR&gt;
&lt;%= Session("arystrUserNames")(1) %&gt;
&lt;%

' 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.
%&gt;
&lt;BR&gt;&lt;BR&gt;Now, the second name in the User Names array is &lt;BR&gt;
&lt;%= Session("arystrUserNames")(1) %&gt;&lt;BR&gt;
&lt;BR&gt;&lt;BR&gt;&lt;BR&gt;&lt;BR&gt;&lt;BR&gt;
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:&lt;BR&gt;&lt;BR&gt;
&lt;%= Session.Contents(1)(0)%&gt; &lt;BR&gt;
&lt;/BODY&gt;&lt;/HTML&gt;</pre></span>




<p>Objects created in the <filename>GLOBAL.ASA</filename> file are not
actually instantiated on the server until the first time a property
or method of that object is called.</p>




<p>If you intend to use a given object in a transaction using the
ObjectContext object, do not give that object application or session
scope. An object used in a transaction is destroyed at the end of the
transaction, and any subsequent reference to its properties or calls
to its methods will result in an error.</p>




<p>You will notice that the Contents (and StaticObjects) collection for
the Session object is very similar to the Contents collection of the
Application object.</p>




<p>Although the <!--<primary>Contents
collection</primary><secondary>Application
object</secondary>-->Contents collection is the default
collection of the Session object, there is one unusual behavior that
differentiates it from the Contents collection of the Application
object: You cannot retrieve an item directly from the Session object,
because your implicit references to the Contents collection (the
Session object's default collection) and the Item method (the
collection's default value) cannot be resolved successfully.</p>




<p>Suppose you have the following code:</p>




<span class="PROGRAMLISTING"><pre>&lt;HTML&gt;
&lt;HEAD&gt;&lt;TITLE&gt;Strange Behaviour&lt;/TITLE&gt;&lt;/HEAD&gt;
&lt;BODY&gt;
&lt;%
Session.Contents.Item("Item1") = "SessionVar1"
Session.Contents.Item("Item2") = "SessionVar2"
Session.Contents.Item("Item3") = "SessionVar3"
%&gt;
<lineannotation>. . . [additional code]</lineannotation></pre></span>




<p>Because the Contents collection is the default collection of the
Session object, you can refer to Item2 using the following line of
code:</p>




<span class="PROGRAMLISTING"><pre>strNewVar = Session("Item2")</pre></span>




<p>However, unlike the Contents collection of the Application object,
you cannot refer to the same element using the following line of
code. This line of code will either be ignored or will raise an
error, depending on the variable you are trying to retrieve:</p>




<span class="PROGRAMLISTING"><pre>strNewVar = Session(2)</pre></span>




<p>However:</p>




<span class="PROGRAMLISTING"><pre>strNewVar = Session.Contents.Item(2)</pre></span>




<p>or:</p>




<span class="PROGRAMLISTING"><pre>strNewVar = Session.Contents(2)</pre></span>




<p>work just fine.</p>




<p>I was unable to find this behavior documented anywhere, but I found
it to be consistent on IIS and Personal Web Server.</p>




</td>
</tr>
<tr>
<td colspan="2" class="CLEARSEPARATION">&nbsp;</td>
</tr>
</table>
</div>
<div id="StaticObjectsCollection">
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tr valign="top">
<td class="NAME">
StaticObjects Collection</td>
<td class="COMPATIBILITY">&nbsp;</td>
</tr>
<tr>
<td colspan="2" class="divider"><img src="dwres:18084" width="100%" height="1"></td>
</tr>
<tr>
<td class="usage" colspan="2"><span class="PROGRAMLISTING"><pre>strFirstObjName = _
   Session.StaticObjects.Key(1)</pre></span></td></tr>
<tr><td colspan="2" class="CLEARSEPARATION">&nbsp;</td>
</tr>
<tr><td colspan="2" class="description">
<p><!--<primary>StaticObjects
collection</primary><secondary>Session object</secondary>-->
<!--<primary>session-level
scope</primary><secondary>objects added with</secondary>-->
<!--<primary sortas="OBJECT tags">tags</primary><secondary>session-level objects
added with</secondary>--> <!--<primary>scope</primary><secondary>session-level</secondary>-->Contains
all of the objects with session-level scope that are added to the
application through the use of the <span class="LITERAL">&lt;OBJECT&gt;</span>
tag. You can use the StaticObjects collection to retrieve properties
of a specific object in the collection. You also can use the
StaticObjects collection to use a specific method of a given object
in the collection.</p>




<p>The StaticObjects collection of the Session object, like other ASP
collections, has the following properties:</p>




<dl>
<dt>Item</dt>
<dd><p><!--<primary>Item property</primary><secondary>StaticObjects
collection</secondary><tertiary>Session
object</tertiary>-->Represents the value of a specific
element in the collection. To specify an item, you can use an index
number or a key.</p></dd>




<dt>Key</dt>
<dd><p><!--<primary>Key property</primary><secondary>StaticObjects
collection</secondary><tertiary>Session
object</tertiary>-->Represents the name of a specific
element in the collection. For example:</p>




<span class="PROGRAMLISTING"><pre>strFirstObjName = _
   Session.StaticObjects.Key(1)</pre></span>




<p>retrieves the name of the first element in the StaticObjects
collection of the Session object.<emphasis role="bold"/></p>




<p>Use the value of the Key property to retrieve the value of an element
by name. For example, suppose the first element's name is
<var class="replaceable">objMyObject</var>. The code:</p>




<span class="PROGRAMLISTING"><pre>strKey = Session.StaticObjects.Key(1)
Session.StaticObjects.Item(strKey).Printer = "Epson 540"</pre></span>




<p>then sets the value of the Printer property of the
<var class="replaceable">objMyObject</var> element in the StaticObjects
collection of the Session object.</p></dd>




<dt>Count</dt>
<dd><p><!--<primary>Count property</primary><secondary>StaticObjects
collection</secondary><tertiary>Session
object</tertiary>-->Returns the current number of elements
in the collection.</p></dd>

</dl>




<p>As with other ASP collections, you can retrieve the value of any
field of the StaticObjects collection through the use of the Item
property. However, as in other places in this book, in the following
examples, the syntax has been abbreviated so that it does not
explicitly show the use of the Item property. For example:</p>




<span class="PROGRAMLISTING"><pre>strPrinterName = Session.StaticObjects("objMyObj").Printer</pre></span>




<p>is an abbreviated form of:</p>




<span class="PROGRAMLISTING"><pre>strPrinterName = Session.StaticObjects.Item("objMyObj").Printer</pre></span>




<tip id="ch10-32-fm2xml" role="ora">
<p>For more information on the Item, Key, and Count properties of a
collection, see the discussion in <link linkend="ch04-3-fm2xml">Section 4.2</link> in <link linkend="ch04-40130">Chapter 4</link>.</p>



</tip>
</td>
</tr>
<tr>
<td colspan="2" class="DESCRIPTIONTITLE">Example</td>
</tr>
<tr>
<td colspan="2" class="description">




<span class="PROGRAMLISTING"><pre>' &lt; FROM GLOBAL.ASA &gt;
' This code resides in the GLOBAL.ASA file at the
' root of the current application. The following
' &lt;OBJECT&gt; tag is only processed once for the current
' application.
' See <link linkend="ch11-1-fm2xml">Chapter 11</link> for more details on the GLOBAL.ASA file.

&lt;OBJECT RUNAT=Server 
SCOPE=Session
ID=AppInfo1 
PROGID="MSWC.MyInfo"&gt;
&lt;/OBJECT&gt;

&lt;OBJECT RUNAT=Server 
SCOPE=Session
ID=AppInfo2 
PROGID="MSWC.MyInfo"&gt;
&lt;/OBJECT&gt;

' &lt;&gt;


&lt;%
' 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
%&gt;
   The personal name is &lt;BR&gt;
   &lt;%= Session.StaticObjects(objInfo).PersonalName%&gt;
&lt;%
Next
%&gt;

There are &lt;%= Session.StaticObjects.Count %&gt; items
in the Session's StaticObjects collection.</pre></span>




</td>
</tr>
<tr>
<td colspan="2" class="CLEARSEPARATION">&nbsp;</td>
</tr>
<tr>
<td colspan="2" class="DESCRIPTIONTITLE">Notes</td>
</tr>
<tr>
<td colspan="2" class="description">




<p>The Session object's StaticObjects collection allows you to
access any given object instantiated with session scope through the
use of an <span class="LITERAL">&lt;OBJECT&gt;</span> tag. Objects instantiated
using Server.<!--<primary>CreateObject method
(Server)</primary><secondary>StaticObjects collection
and</secondary>--> <!--<primary>StaticObjects
collection</primary><secondary>CreateObject method
and</secondary>-->CreateObject are not accessible through
this collection.</p>




<p>The StaticObjects example in the IIS 5.0 documentation by Microsoft
suggests that if you iterate through this collection, you will be
able to reference each object's properties. This is somewhat
misleading, as it suggests that the collection actually represents
all the properties of the objects rather than the objects themselves.
If you want to access the properties or methods of objects in the
StaticObjects collection, you must use the dot operator outside of
the parentheses around the Key, followed by the property or method
name, as demonstrated here:</p>




<span class="PROGRAMLISTING"><pre>&lt;%= Session.StaticObjects(objInfo).PersonalName%&gt;</pre></span>




<p>This line of code works because
<span class="LITERAL">Session.StaticObjects(objInfo)</span> returns a reference
to the <var class="replaceable">objInfo</var> object.</p>




<p>Objects created in the <filename>GLOBAL.ASA</filename> file are not
actually instantiated on the server until the first time a property
or method of that object is called. For this reason, the
StaticObjects collection cannot be used to access these
objects' properties and methods until some other code in your
application has caused them to be instantiated on the server.</p>




<p><!--<primary>scope</primary><secondary>transactional
objects</secondary>--> <!--<primary>application-level
scope</primary><secondary>transactional objects
and</secondary>--> <!--<primary>global
variables</primary><secondary>transactional objects
and</secondary>--> <!--<primary>session-level
scope</primary><secondary>transactional objects
and</secondary>-->If you intend to use a given object in a
transaction using the <!--<primary>ObjectContext
object</primary><secondary>object scope and</secondary>-->
<!--<primary>transactions, object scope
and</primary>-->ObjectContext object, do not give that
object application or session scope. Objects used in transactions are
destroyed at the end of the transaction and any subsequent reference
to their properties or calls to their methods will result in an



error.</p>



</td>
</tr>
<tr>
<td colspan="2" class="CLEARSEPARATION">&nbsp;</td>
</tr>
</table>
</div>
<div id="Abandon">
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tr valign="top">
<td class="NAME">
Abandon</td>
<td class="COMPATIBILITY">&nbsp;</td>
</tr>
<tr>
<td colspan="2" class="divider"><img src="dwres:18084" width="100%" height="1"></td>
</tr>
<tr>
<td class="usage" colspan="2"><span class="LITERAL">Session.Abandon</span>
</td></tr>
<tr><td colspan="2" class="CLEARSEPARATION">&nbsp;</td>
</tr>
<tr><td colspan="2" class="description">
<p><!--<primary>memory</primary><secondary>user
sessions</secondary><tertiary>releasing</tertiary>-->
<!--<primary>user
sessions</primary><secondary>memory
for</secondary><tertiary>releasing</tertiary>--> <!--<primary>Session
object</primary><secondary>Abandon method</secondary>-->
<!--<primary>Abandon method
(Session)</primary>-->Releases the memory used by the web
server to maintain information about a given user session. It does
not, however, affect the session information of other users. If the
Abandon method is not explicitly called, the web server will maintain
all session information until the session times out.</p>



</td>
</tr>
<tr><td colspan="2" class="CLEARSEPARATION">&nbsp;</td></tr>
<tr>
<td colspan="2" class="DESCRIPTIONTITLE">Parameters</td>
</tr>
<tr>
<td colspan="2" class="description">




<p>None</p>




</td>
</tr>
<tr>
<td colspan="2" class="CLEARSEPARATION">&nbsp;</td>
</tr>
<tr>
<td colspan="2" class="DESCRIPTIONTITLE">Example</td>
</tr>
<tr>
<td colspan="2" class="description">




<p>The following script allows the user to click on a link that will
redirect his browser to a page that will clear his session variables:</p>




<span class="PROGRAMLISTING"><pre>&lt;HTML&gt;
&lt;HEAD&gt;&lt;TITLE&gt;Session Abandon Example Page1&lt;/TITLE&gt;&lt;/HEAD&gt;
&lt;BODY&gt;
Click &lt;A HREF = "/SessionAbandonPage2.asp"&gt;here&lt;/A&gt; to reset your user preferences.
&lt;/BODY&gt;
&lt;/HTML&gt;</pre></span>




<p>The following script actually clears the session variables:</p>




<span class="PROGRAMLISTING"><pre>&lt;HTML&gt;
&lt;HEAD&gt;&lt;TITLE&gt;Session Abandon Example Page2&lt;/TITLE&gt;&lt;/HEAD&gt;
&lt;BODY&gt;
&lt;%

' 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

%&gt;
Your user preferences have now been reset.
&lt;/BODY&gt;
&lt;/HTML&gt;</pre></span>




</td>
</tr>
<tr>
<td colspan="2" class="CLEARSEPARATION">&nbsp;</td>
</tr>
<tr>
<td colspan="2" class="DESCRIPTIONTITLE">Notes</td>
</tr>
<tr>
<td colspan="2" class="description">




<p>If you make heavy use of the Session object's Contents
collection, the Abandon method can come in very handy. Suppose, for
example, that you have many different user preferences saved as
session variables and, as in the example, you want to remove them all
and allow the user to select all new ones. Without the Abandon
method, you would have to remove each variable from the Contents
collection by hand—a slow and laborious prospect if you have
several variables. The Abandon method allows you to remove them all
in one line of code.</p>




<p>The Abandon method is actually processed by the web server after the
rest of the current page's script is processed. After the
current page's processing is complete, however, any page
request by the user initiates a new session on the web server.</p>




<p>In the following example, the session variable
<var class="replaceable">intUserAge</var> is available to your script
until the end of the page. The Abandon method does not remove the
variable from memory until the end of the page:</p>




<span class="PROGRAMLISTING"><pre>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...]

</pre></span>



</td>
</tr>
<tr>
<td colspan="2" class="CLEARSEPARATION">&nbsp;</td>
</tr>
</table>
</div>
<div id="Session_OnEnd">
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tr valign="top">
<td class="NAME">
Session_OnEnd</td>
<td class="COMPATIBILITY">&nbsp;</td>
</tr>
<tr>
<td colspan="2" class="divider"><img src="dwres:18084" width="100%" height="1"></td>
</tr>
<tr>
<td class="usage" colspan="2"><span class="LITERAL">Session_OnEnd</span><!--<primary>Session object</primary><secondary>OnStart and OnEnd events</secondary>-->
<!--<primary>events</primary><secondary>Session object</secondary>-->
<!--<primary>OnEnd event</primary><secondary>Session object</secondary>-->
</td></tr>
<tr><td colspan="2" class="CLEARSEPARATION">&nbsp;</td>
</tr>
<tr><td colspan="2" class="description">
<p>Triggered when the user's session times out or when your
scripts call the Abandon method of the Session object.</p>




<p>The OnEnd event procedure, if it exists, resides in the
<filename>GLOBAL.ASA</filename> file for the application that
contains the requested page.</p>



</td>
</tr>
<tr><td colspan="2" class="CLEARSEPARATION">&nbsp;</td></tr>
<tr>
<td colspan="2" class="DESCRIPTIONTITLE">Parameters</td>
</tr>
<tr>
<td colspan="2" class="description">




<p>None</p>




</td>
</tr>
<tr>
<td colspan="2" class="CLEARSEPARATION">&nbsp;</td>
</tr>
<tr>
<td colspan="2" class="DESCRIPTIONTITLE">Example</td>
</tr>
<tr>
<td colspan="2" class="description">




<span class="PROGRAMLISTING"><pre>&lt;SCRIPT LANGUAGE = "VBScript" RUNAT = Server&gt;

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

&lt;/SCRIPT&gt;</pre></span>




</td>
</tr>
<tr>
<td colspan="2" class="CLEARSEPARATION">&nbsp;</td>
</tr>
<tr>
<td colspan="2" class="DESCRIPTIONTITLE">Notes</td>
</tr>
<tr>
<td colspan="2" class="description">




<p>In the code for the OnEnd event procedure, you have access only to
the Application, Server, and Session objects. Most important, you
have no access to the Response object or Request object, and, for
this reason, you cannot redirect the client or send cookies to (or
receive cookies from) the client machine.</p>




<p><!--<primary>logging</primary><secondary>when sessions
start/end</secondary>-->One of the possible uses of the
OnEnd event is to write information concerning the user to a log file
or other text file on the server for later use. If you intend to do
this, there are several important points you must remember. First,
before you can save any information, that information must be saved
to a session variable because, as mentioned earlier, you do not have
access to the Request object, which is the most common source of user
information. The following code demonstrates one possible method of
storing a session-level variable:</p>




<span class="PROGRAMLISTING"><pre>&lt;SCRIPT LANGUAGE = "VBScript" RUNAT = Server&gt;

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 <link linkend="ch19-1-fm2xml">Chapter 19</link>). 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

&lt;/SCRIPT&gt;</pre></span>




<p>Note that you cannot use the <!--<primary>AppendToLog method
(Response)</primary>-->AppendToLog method of the Response
object, because the Response object is unavailable. In addition, if
you intend to write directly to the web server's hard drive,
you must know the physical path of the file to which you want to
write. This is because, although you do have access to the Server
object, you cannot use its <!--<primary>MapPath method
(Server)</primary>-->MapPath method in the OnEnd event (for
more information about the MapPath method, see "MapPath"
in <link linkend="ch09-1-fm2xml">Chapter 9</link>).</p>




</td>
</tr>
<tr>
<td colspan="2" class="CLEARSEPARATION">&nbsp;</td>
</tr>
</table>
</div>
<div id="Session_OnStart">
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tr valign="top">
<td class="NAME">
Session_OnStart</td>
<td class="COMPATIBILITY">&nbsp;</td>
</tr>
<tr>
<td colspan="2" class="divider"><img src="dwres:18084" width="100%" height="1"></td>
</tr>
<tr>
<td class="usage" colspan="2"><span class="LITERAL">Session_OnStart</span>
</td></tr>
<tr><td colspan="2" class="CLEARSEPARATION">&nbsp;</td>
</tr>
<tr><td colspan="2" class="description">
<p><!--<primary>OnStart
event</primary><secondary>Session
object</secondary>-->Triggered any time a user who does not
already have a session instantiated on the web server requests any
page from the server. The code in the OnStart event of the Session
object, if it exists, is processed before any code on the requested
page.</p>




<p>The OnStart event procedure, if it exists, resides in the
<filename>GLOBAL.ASA</filename> file for the application that
contains the requested page.</p>



</td>
</tr>
<tr><td colspan="2" class="CLEARSEPARATION">&nbsp;</td></tr>
<tr>
<td colspan="2" class="DESCRIPTIONTITLE">Parameters</td>
</tr>
<tr>
<td colspan="2" class="description">




<p>None</p>




</td>
</tr>
<tr>
<td colspan="2" class="CLEARSEPARATION">&nbsp;</td>
</tr>
<tr>
<td colspan="2" class="DESCRIPTIONTITLE">Example</td>
</tr>
<tr>
<td colspan="2" class="description">




<span class="PROGRAMLISTING"><pre>&lt;SCRIPT LANGUAGE = "VBScript" RUNAT = Server&gt;

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

&lt;/SCRIPT&gt;</pre></span>




</td>
</tr>
<tr>
<td colspan="2" class="CLEARSEPARATION">&nbsp;</td>
</tr>
<tr>
<td colspan="2" class="DESCRIPTIONTITLE">Notes</td>
</tr>
<tr>
<td colspan="2" class="description">




<p>If the client's browser does not support cookies or if the user
has manually turned cookies off, the Session_OnStart event is
processed <em>every</em> time the user requests a page
from the site. No session is started or maintained.</p>




<p>Like the OnEnd event, one of the possible uses of the OnStart event
is to write information concerning the user to a
<!--<primary>logging</primary><secondary>when sessions
start/end</secondary>-->log file or other text file on the
server for later use. If you intend to do this, note that you cannot
use the AppendToLog method of the Response object, and if you intend
to write directly to the web server's hard drive, you must know
the physical path of the file to which you want to write. This is
because, although you do have access to the Server object, just as in
the OnEnd event of the Session object, you cannot use the MapPath
method of the Server object in the Session_OnStart
  event. </p>




</td>
</tr>
<tr>
<td colspan="2" class="CLEARSEPARATION">&nbsp;</td>
</tr>
</table>
</div>
</body>
</html>