CHAPTER 9
Session Object
Chapter 9Session Object

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 userspecific
information is limitations in the currently standard HTTP 1.0 protocol.
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.
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
cookies—to identify the user. IIS handles this mechanism through the use of the
Session built-in object.
The Session object represents the current user’s session on the 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 “Timeout,” later in this chapter) after the user’s last
request to the web server.
Comments/Troubleshooting 123
Session Object
Comments/Troubleshooting
ASP in a Nutshell: A Desktop Quick Reference, eMatter Edition
Copyright © 2000 O’Reilly & Associates, Inc. All rights reserved.
A user session can be initiated in one of three ways:
• A user not already connected to the server requests an Active Server Page that
resides in an application containing a GLOBAL.ASA file with code for the
Session_OnStart event.
• A user requests an Active Server Page whose script stores information in any
session-scoped variable.
• A user requests an Active Server Page in an application whose GLOBAL.ASA
file instantiates an object using the <OBJECT> tag with the SCOPE parameter
set to Session.
Note that a user session is specific to a given 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.
The web server identifies each user with a unique 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.
In addition to the SessionID variable, you can store other information specific to
individual users. You can initialize (or change) any 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 GLOBAL.ASA file. This event procedure is fired when the user’s
session starts. The GLOBAL.ASA file (see Chapter 10, Preprocessing Directives,
Server-Side Includes, and GLOBAL.ASA) is a special file that you can code specific
to each ASP application. This file’s code is processed when the user session
begins.
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.
Comments/Troubleshooting
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, /search, reflects the following physical directory:
D:\www\apps\search
The current script, SearchStart.ASP, resides in this directory. Assume that you have
initialized a session-level variable, strSearchPref, in this script. Now the user
moves to another application script, ContribMain.ASP, that resides in a separate
124 Chapter 9 – Session Object
Comments/Troubleshooting
ASP in a Nutshell: A Desktop Quick Reference, eMatter Edition
Copyright © 2000 O’Reilly & Associates, Inc. All rights reserved.
application whose virtual directory, /contrib, reflects the following physical
directory:
D:\www\apps\contrib
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 strSearchPref session-level variable value is reset. This is an important
source of errors in complex web applications. 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.
One way to avoid this problem is to nest applications. For example, you can place
the /contrib virtual directory underneath the search directory, as reflected in the
following path:
D:\www\apps\search\contrib
Using this configuration, all requests to the contribution application’s virtual path, /
contrib, remain in the context of the search application.
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 “Timeout,” later in this chapter, for how to set this information
differently from the default.
Session Object Summary
Properties
CodePage
LCID
SessionID
Timeout
Collections
Contents
StaticObjects
Methods
Abandon
Events
Session_OnEnd
Session_OnStart
CodePage 125
Session Object
CodePage
ASP in a Nutshell: A Desktop Quick Reference, eMatter Edition
Copyright © 2000 O’Reilly & Associates, Inc. All rights reserved.
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
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.
Properties Reference
CodePage
Session.CodePage (= intCodePageValue)
Specifies or retrieves the code page that will be used by the web server to display
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.
Parameters
intCodePageValue
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:
Example
<%
' 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
CodePage
Value Language
932 Japanese Kanji
950 Chinese
1252 American English (and most European languages)
126 Chapter 9 – Session Object
LCID
ASP in a Nutshell: A Desktop Quick Reference, eMatter Edition
Copyright © 2000 O’Reilly & Associates, Inc. All rights reserved.
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
%>
Notes
Remember that, by default, Active Server Pages uses whatever character set you
set for the script page using the CODEPAGE directive (see Chapter 10). 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 CODEPAGE directive.
LCID
Session.LCID (= intLCID)
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.
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.
Parameters
intLCID
A valid 32-bit locale identifier
Example
<%
' 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
SessionID 127
Session Object
SessionID
ASP in a Nutshell: A Desktop Quick Reference, eMatter Edition
Copyright © 2000 O’Reilly & Associates, Inc. All rights reserved.
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
%>
Notes
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.
If you use the ASP LCID 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.
SessionID
Session.SessionID
A read-only value that uniquely identifies each current user’s session. This value is
of data type Long and is stored as a 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.
Parameters
None
Example
<%
' The following code retrieves the current SessionID for
' a given user:
Dim lngUserSessionId
lngUserSessionId = Session.SessionID
%>
128 Chapter 9 – Session Object
Timeout
ASP in a Nutshell: A Desktop Quick Reference, eMatter Edition
Copyright © 2000 O’Reilly & Associates, Inc. All rights reserved.
Notes
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.
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.
This last point is important and is worth noting. Only 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.
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 EnableSessionState
preprocessor directive (for more details, see Chapter 10).
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.
Timeout
Session.Timeout (= intMinutes)
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.
Parameters
intMinutes
The number of minutes for which the web server will maintain session
information
Example
<%
Contents Collection 129
Session Object
Contents Collection
ASP in a Nutshell: A Desktop Quick Reference, eMatter Edition
Copyright © 2000 O’Reilly & Associates, Inc. All rights reserved.
' The following code resets the Timeout property of the
' Session object from its default of 20 minutes to 5
' minutes.
Session.Timeout = 5
%>
Notes
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 memory consumption on the web server that each user session
requires.
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.
Note that, unlike most properties of the Session object, this property affects all
user sessions, not just the current session. If you set the value of the Timeout
property of the Session object to 120 minutes, every user’s session information will
remain in memory on the web server until 120 minutes after he last requests or
refreshes a page.
Collections Reference
Contents Collection
Session.Contents(Key)
Contains all of the variables and objects added with session-level scope through
script (i.e., not through the use of the <OBJECT> tag).
The Contents collection of the Session object, like other ASP collections, has the
following properties:
Item
Represents the value of a specific element in the collection. To specify an
item, you can use an index number or a key.
Key
Represents the name of a specific element in the collection. For example, you
could receive the name of the first element in the collection like this:
strElementName = Session.Contents.Key(1)
You 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 “UserSecurityCode.”
Then the code:
strKey = Session.Contents.Key(1)
Session.Contents.Item(strKey) = "Admin"
sets the value of the UserSecurityCode element in the Contents collection.
130 Chapter 9 – Session Object
Contents Collection
ASP in a Nutshell: A Desktop Quick Reference, eMatter Edition
Copyright © 2000 O’Reilly & Associates, Inc. All rights reserved.
Count
Returns the current number of elements in the collection.
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:
strSecurityCode = Session("UserSecurityCode")
is an abbreviated form of:
strSecurityCode = Session.Contents.Item("UserSecurityCode")
For more information on the Item, Key, and Count properties of a
collection, see the discussion in the section “Contents Collection” in
Chapter 4, Application Object.
Example
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 sessionlevel
variables are created (SessionVar1, SessionVar2, and 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>
In this second script, we’ll take a look at the current elements in the Contents
collection of the Session object.
<HTML>
<HEAD><TITLE>Session Contents Example Page2</TITLE></HEAD>
<BODY>
<%
Contents Collection 131
Session Object
Contents Collection
ASP in a Nutshell: A Desktop Quick Reference, eMatter Edition
Copyright © 2000 O’Reilly & Associates, Inc. All rights reserved.
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.
132 Chapter 9 – Session Object
Contents Collection
ASP in a Nutshell: A Desktop Quick Reference, eMatter Edition
Copyright © 2000 O’Reilly & Associates, Inc. All rights reserved.
' (NOTE: For more on the Server object, see Chapter 8.)
'************************************************************
' 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>
Notes
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:
Dim datLastUpdatet
Set Session.Contents(objSessionMyObj) = _
Server.CreateObject("MyCompanyDLL.MyServerComp")
datLastUpdated = Session.Contents(objSessionMyObj).LastUpdated
When adding an 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:
<% 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
Contents Collection 133
Session Object
Contents Collection
ASP in a Nutshell: A Desktop Quick Reference, eMatter Edition
Copyright © 2000 O’Reilly & Associates, Inc. All rights reserved.
' 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>
Objects created in the GLOBAL.ASA file are not actually instantiated on the server
until the first time a property or method of that object is called.
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.
You will notice that the Contents (and StaticObjects) collection for the Session
object is very similar to the Contents collection of the Application object.
Although the 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.
Suppose you have the following code:
<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]
Because the Contents collection is the default collection of the Session object, you
can refer to Item2 using the following line of code:
strNewVar = Session("Item2")
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
134 Chapter 9 – Session Object
StaticObjects Collection
ASP in a Nutshell: A Desktop Quick Reference, eMatter Edition
Copyright © 2000 O’Reilly & Associates, Inc. All rights reserved.
either be ignored or will raise an error, depending on the variable you are trying
to retrieve:
strNewVar = Session(2)
However,
strNewVar = Session.Contents.Item(2)
or,
strNewVar = Session.Contents(2)
work just fine.
I was unable to find this behavior documented anywhere, but I found it to be
consistent on IIS and Personal Web Server.
StaticObjects Collection
Session.StaticObjects(Key)
Contains all of the objects with session-level scope that are added to the application
through the use of the <OBJECT> 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.
The StaticObjects collection of the Session object, like other ASP collections, has
the following properties:
Item
Represents the value of a specific element in the collection. To specify an
item, you can use an index number or a key.
Key
Represents the name of a specific element in the collection. For example:
strFirstObjName = _
Session.StaticObjects.Key(1)
retrieves the name of the first element in the StaticObjects collection of the
Session object.
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 objMyObject. The
code:
strKey = Session.StaticObjects.Key(1)
Session.StaticObjects.Item(strKey).Printer = "Epson 540"
then sets the value of the Printer property of the objMyObject element in the
StaticObjects collection of the Session object.
Count
Returns the current number of elements in the collection.
As with other ASP collections, you can retrieve the value of any field of the Static-
Objects collection through the use of the Item property. However, as in other
StaticObjects Collection 135
Session Object
StaticObjects Collection
ASP in a Nutshell: A Desktop Quick Reference, eMatter Edition
Copyright © 2000 O’Reilly & Associates, Inc. All rights reserved.
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:
strPrinterName = Session.StaticObjects("objMyObj").Printer
is an abbreviated form of:
strPrinterName = Session.StaticObjects.Item("objMyObj").Printer
For more information on the Item, Key, and Count properties of a
collection, see the discussion in the section “Contents Collection” in
Chapter 4.
Example
' <<<<<<<<<<<<<<< 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 10 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%>
136 Chapter 9 – Session Object
Methods Reference
ASP in a Nutshell: A Desktop Quick Reference, eMatter Edition
Copyright © 2000 O’Reilly & Associates, Inc. All rights reserved.
<%
Next
%>
There are <%= Session.StaticObjects.Count %> items
in the Session's StaticObjects collection.
Notes
The Session object’s StaticObjects collection allows you to access any given object
instantiated with session scope through the use of an <OBJECT> tag. Objects
instantiated using Server.CreateObject are not accessible through this collection.
The StaticObjects example in the IIS 4.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:
<%= Session.StaticObjects(objInfo).PersonalName%>
This line of code works because Session.StaticObjects(objInfo) returns a
reference to the objInfo object.
Objects created in the GLOBAL.ASA 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.
If you intend to use a given object in a transaction using the 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.
Methods Reference
Abandon
Session.Abandon
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.
Parameters
None
Abandon 137
Session Object
Abandon
ASP in a Nutshell: A Desktop Quick Reference, eMatter Edition
Copyright © 2000 O’Reilly & Associates, Inc. All rights reserved.
Example
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:
<HTML>
<HEAD><TITLE>Session Abandom Example Page1</TITLE></HEAD>
<BODY>
Click <A HREF = "/SessionAbandonPage2.asp">here</A> to reset
your user preferences.
</BODY>
</HTML>
The following script actually clears the session variables:
<HTML>
<HEAD><TITLE>Session Abandom 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>
Notes
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.
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.
In the following example, the session variable intUserAge 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:
Session("intUserAge") = 23
Session.Abandon
[...More Code...]
' The current line successfully retrieves the value of
' intUserAge.
intAgeCategory = CInt(Session("intUserAge") / 10)
138 Chapter 9 – Session Object
Events Reference
ASP in a Nutshell: A Desktop Quick Reference, eMatter Edition
Copyright © 2000 O’Reilly & Associates, Inc. All rights reserved.
[...End of Script. Session information is removed from web
memory now...]
Events Reference
Session_OnEnd
Session_OnEnd
Triggered when the user’s session times out or when your scripts call the Abandon
method of the Session object.
The OnEnd event procedure, if it exists, resides in the GLOBAL.ASA file for the
application that contains the requested page.
Parameters
None
Example
<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>
Notes
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.
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:
<SCRIPT LANGUAGE = "VBScript" RUNAT = Server>
Sub Session_OnEnd
Session_OnStart 139
Session Object
Session_OnStart
ASP in a Nutshell: A Desktop Quick Reference, eMatter Edition
Copyright © 2000 O’Reilly & Associates, Inc. All rights reserved.
' 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 18). 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>
Note that you cannot use the 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 MapPath method in the OnEnd event (for more
information about the MapPath method, see “MapPath” in Chapter 8, Server Object).
Session_OnStart
Session_OnStart
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.
The OnStart event procedure, if it exists, resides in the GLOBAL.ASA file for the
application that contains the requested page.
Parameters
None
Example
<SCRIPT LANGUAGE = "VBScript" RUNAT = Server>
Sub Session_OnStart
140 Chapter 9 – Session Object
Session_OnStart
ASP in a Nutshell: A Desktop Quick Reference, eMatter Edition
Copyright © 2000 O’Reilly & Associates, Inc. All rights reserved.
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>
Notes
If the client’s browser does not support cookies or if the user has manually turned
cookies off, the Session_OnStart event is processed every time the user requests a
page from the site. No session is started or maintained.
Like the OnEnd event, one of the possible uses of the OnStart 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, 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.
141
Directives & GLOBAL.ASA
ASP in a Nutshell: A Desktop Quick Reference, eMatter Edition
Copyright © 2000 O’Reilly & Associates, Inc. All rights reserved.
br>\par has been moved or that does not exist.
\par 5xx
\par The 500 range is set aside for sending notices of server error to the \par client.
\par For example, attempts to reach pages on a server that is unable to handle
\par the request due to temporary overloading or server maintenance could
\par result in the response status 503 Service Not Available.
\par Example
\par <%
\par ' The following code sets the Status property of the
\par ' Response object to 404 Not Found. Unless other content is
\par ' generated for the page, the status code will be
\par ' interpreted by itself by the client.
\par strStatusText = _
\par "404 Not Found The Web server cannot find the "
\par strStatusText = strStatusText & "file or script you asked "
\par * The latest version of the HTTP specification can be found at http://www.w3c.org/protocols.
\par Cookies 99
\par Response Object
\par Cookies
\par ASP in a Nutshell: A Desktop Quick Reference, eMatter Edition
\par Copyright © 2000 O’Reilly & Associates, Inc. All rights \par reserved.
\par strStatusText = strStatusText & "for. Please check the URL "
\par strStatusText = strStatusText & "to ensure that the path "
\par strStatusText = strStatusText & "is correct."
\par Response.Status = strStatusText
\par %>
\par Notes
\par As with setting other Response headers, each subsequent setting of the \par Status
\par property value resets the last setting.
\par Like other properties that result in a change to the HTTP response header \par values,
\par the Status property must be set before the server sends the <HTML> \par tag to the
\par client unless the response is buffered.
\par Collections Reference
\par Cookies
\par Response.Cookies.Item(Key)[(SubKey) | .attribute] = strCookieValue
\par The Cookies collection of the Response object enables your ASP application \par to use
\par the Set-Cookie HTTP response header to write cookies to the client’s \par machine. If
\par you attempt to set the value of a cookie that does not yet exist, it is \par created. If it
\par already exists, the new value you set overwrites the old value already \par written to
\par the client machine.
\par As with the Cookies collection of the Request object, each cookie in the \par Cookies
\par collection of the Response object can also represent a cookie dictionary. \par Recall
\par from Chapter 6, Request Object, that a cookie dictionary is a construct \par that is
\par similar to an associative array in that each element of the array is identifiable \par by its
\par name. For more information on cookie dictionaries, see the section on \par the Cookies
\par collection of the Request object in Chapter 6.
\par The Cookies collection of the Response object, like other ASP collections, \par has the
\par following properties:
\par Item
\par Returns the value of a specific element in the collection. To specify \par an item,
\par you can use an index number or a key.
\par Key
\par Returns the name of a specific element in the Cookies collection. Just \par as each
\par element’s value is represented by the Item property, so each element’s \par name
\par is represented by its Key property.
\par If you do not know the name of a specific key, you can obtain it using \par its
\par ordinal reference. For example, assume that you want to learn the key \par name
\par for the third element in the collection and, subsequently, that element’s \par value.
\par You could use the following code:
\par strKeyName = Response.Cookies.Key(3)
\par strKeyValue = Response.Cookies.Item(strKeyName)
\par 100 Chapter 7 – Response Object
\par Cookies
\par ASP in a Nutshell: A Desktop Quick Reference, eMatter Edition
\par Copyright © 2000 O’Reilly & Associates, Inc. All rights \par reserved.
\par If, on the other hand, you know that the third element’s key name \par is COLOR_
\par PREF, you could simply use the following code to retrieve the value of \par that
\par element:
\par strKeyValue = Response.Cookies.Item("COLOR_PREF")
\par Count
\par The Count property of the Cookies collection represents the current number
\par of cookies in the collection.
\par As with other ASP collections, you can retrieve the value of any field \par of the
\par Cookies collection through the use of the Item property. However, as in \par other
\par places in this book, in the following examples, the syntax has been abbreviated \par so
\par that it does not explicitly show the use of the Item property. For example:
\par Response.Cookies("UserPref") = "Red"
\par is an abbreviated form of:
\par Response.Cookies.Item("UserPref") = "Red"
\par To set the value of a cookie, you would use code similar to the following:
\par strLastSearch = Response.Cookies("LastSearch") = _
\par "SELECT * FROM Details WHERE Color = 'Red'"
\par For more information on the Item, Key, and Count properties of a
\par collection, see the discussion in the section “Contents Collection” \par in
\par Chapter 4, Application Object.
\par The previous code would create the cookie UserPref if it doesn’t \par already exist
\par (or overwrite the original value if it does). This cookie would translate \par into a SETCOOKIE
\par response header being added to the response sent back to the client
\par browser. The client browser would receive this response header and create \par (or
\par overwrite) a UserPref cookie on the user machine.
\par Each element in the Cookies collection (or subkey, if the cookie is a \par cookie dictionary)
\par also has the following cookie-specific attributes:
\par Domain
\par Sets the cookie so that the client sends the cookie’s value only \par to pages in the
\par domain set in the Domain property. The Domain property is write-only. \par For
\par example, suppose we wanted to add the domain “mycorp.com” to \par the
\par following LastSearch cookie. This would cause the client to send this
\par cookie’s value to the mycorp.com domain when it requests pages from \par it:
\par Response.Cookies("LastSearch").Domain = "mycorp.com"
\par Expires
\par The date on which the cookie expires and is discarded on the client machine.
\par For example, suppose we want the cookie to expire on January 29, 2000. \par We
\par could use the following code:
\par Response.Cookies("LastSearch").Expires = #1/29/2000#
\par Cookies 101
\par Response Object
\par Cookies
\par ASP in a Nutshell: A Desktop Quick Reference, eMatter Edition
\par Copyright © 2000 O’Reilly & Associates, Inc. All rights \par reserved.
\par If you do not set the Expires property value, the cookie resides on the \par client
\par machine for the duration of the client’s session. The cookie also \par will reside on
\par the client machine only for the duration of the client’s session \par if the date
\par value you set for the Expires property is earlier than the current date. \par The
\par Expires property is write-only.
\par HasKeys
\par As previously mentioned, a cookie in the Cookies collection also can represent
\par a cookie dictionary. To determine whether a specific cookie has subkeys,
\par you must use the HasKeys property of that cookie, as in the following:
\par blnHasKeys = Response.Cookies("Colors").HasKeys
\par If blnHasKeys Then
\par strColor3 = Response.Cookies("Colors")("color3")
\par End If
\par The HasKeys property is read-only.
\par Path
\par The Path property represents the virtual directory on the server to which \par the
\par cookie will be sent by the client browser when the client browser requests \par a
\par page from within that virtual path. For example, if we want the client \par to send
\par this cookie to only those scripts in the /Apps/SearchApps virtual directory,
\par we’d use the following line of code:
\par Response.Cookies("LastSearch").Path = "/Apps/SearchApps"
\par If the cookie’s Path attribute is not set, the path defaults to the \par path of the
\par current ASP application. The Path property is write-only.
\par Secure
\par The Secure property allows you to specify whether the cookie is sent from
\par the client only if the client is using the Secure Sockets Layer. For example,
\par suppose we have stored some sensitive information in a cookie (this is \par not
\par wise, but there are occasions when you might do so), and you want the \par user’s
\par browser to send this information only if it is using the Secure Sockets \par Layer.
\par This will significantly decrease the probability that a sensitive cookie \par could be
\par intercepted. You would use the following simple line of code:
\par Response.Cookies("SensitiveCookie").Secure = True
\par The Secure property takes a Boolean value. The Secure property is write-only.
\par Example
\par The following is a more complete example of the use of the Cookies collection \par of
\par the Response object. It demonstrates many of the items discussed earlier.
\par <HTML>
\par <HEAD><TITLE>Search Cookie Example</TITLE></HEAD>
\par <BODY>
\par <H3>Welcome to the Search Results Options Page.</H3>
\par You can use the following form to select your search results
\par display options. These options will be saved on your machine as
\par a set of cookies.
\par <FORM ACTION="/SaveSearchCookie.asp" METHOD = POST>
\par First Name:<INPUT TYPE = TEXT NAME = "txtFirstName"><BR>
\par 102 Chapter 7 – Response Object
\par Cookies
\par ASP in a Nutshell: A Desktop Quick Reference, eMatter Edition
\par Copyright © 2000 O’Reilly & Associates, Inc. All rights \par reserved.
\par Last Name:<INPUT TYPE = TEXT NAME = "txtLastName"><BR>
\par User ID:<INPUT TYPE = TEXT NAME = "txtUserId"><BR>
\par Check All that Apply:
\par Show Descriptions:
\par <INPUT TYPE = CHECKBOX NAME = "chkUserPrefs"VALUE = "Desc">
\par Show Hit Count (display how many matches found per result):
\par <INPUT TYPE = CHECKBOX NAME = "chkUserPrefs"VALUE = "Count">
\par Show Relevance with Graph:
\par <INPUT TYPE = CHECKBOX NAME = "chkUserPrefs"
\par VALUE = "Graph">
\par Use Small Fonts(will show more results per page):
\par <INPUT TYPE = CHECKBOX NAME = "chkUserPrefs"
\par VALUE = "Small">
\par <INPUT TYPE = SUBMIT VALUE = "Save Selections">
\par </FORM>
\par </BODY>
\par </HTML>
\par The following code (SaveSearchCookie.asp) will retrieve the values selected \par in the
\par previous form and save them to the user’s machine as cookies:
\par <%
\par ' The following code retrieves user information from the
\par ' Form collection of the Request object (see Chapter 6) and
\par ' then writes the information to a set of cookies on the
\par ' client machine.
\par Dim strFirstName
\par Dim strLastName
\par Dim strUserId
\par Dim intCounter
\par Dim intPrefCounter
\par Dim strKeyName
\par Dim arstrUserPrefs()
\par ' Retrieve user information...
\par strFirstName = Request.Form("txtFirstName")
\par strLastName = Request.Form("txtLastName")
\par strUserId = Request.Form("txtUserId")
\par intPrefCounter = 1
\par For intCounter = 1 to Request.Forms("chkUserPrefs").Count
\par ReDim Preserve arstrUserPrefs(intPrefCounter)
\par arstrUserPrefs(intPrefCounter – 1) = _
\par Request.Form("chkUserPrefs")(intCounter)
\par intPrefCounter = intPrefCounter + 1
\par Next
\par ' Write the user information to the client machine.
\par ' Save all the information in cookies, but set the
\par ' Expires property only for the UserId. We'll want
\par ' that to remain on the client machine after the session
\par ' is complete.
\par Response.Cookies("UserFirstName") = strFirstName
\par Response.Cookies("UserLastName") = strLastName
\par Cookies 103
\par Response Object
\par Cookies
\par ASP in a Nutshell: A Desktop Quick Reference, eMatter Edition
\par Copyright © 2000 O’Reilly & Associates, Inc. All rights \par reserved.
\par For intCounter = 1 to intPrefCounter – 1
\par strKeyName = "Pref" & CStr(intCounter)
\par Response.Cookies("UserPrefs")(strKeyName) = _
\par arstrUserPrefs(intCounter – 1)
\par Next
\par ' Note in the first line below, that when no property
\par ' is specified, the value of the cookie is set.
\par Response.Cookies("UserId") = strUserId
\par Response.Cookies("UserId").Expires = #December 31, 1999#
\par Response.Cookies("UserId").Domain = "www.customsearch.com"
\par Response.Cookies("UserId").Path = "/usersearch/"
\par Response.Cookies("UserId").Secure = True
\par %>
\par Notes
\par In the example, the UserFirstName cookie is sent to the client machine. \par For this
\par example, let’s assume the value of the strFirstName variable is the \par string “David.”
\par The actual HTTP response header sent to the client machine is:
\par Set-Cookie:USERFIRSTNAME=david
\par Also for this example, assume the three values sent are 800 (for client \par browser
\par width), 8 (for color depth in bits), and English (for English language \par preference).
\par The actual HTTP response header sent to the client is the following:
\par Set-Cookie:USERPREFS=PREF1=800&PREF2=8&PREF3=english
\par If the string value sent for a value of a cookie contains spaces, those \par spaces are
\par replaced with plus signs (+) in the HTTP response header.
\par If you sent a subsequent cookie value to the UserPrefs cookie on the client
\par machine without specifying a SubKey, as in the following:
\par Response.Cookies("UserPrefs") = "german"
\par the two values for PREF1 and PREF2 will be overwritten and the Count property
\par for the UserPrefs cookie will return 1.
\par Alternatively, if you send a subsequent cookie value and specify a SubKey \par to a
\par client machine where the cookie has a value but no keys, the value already \par in
\par place on the client machine is overwritten.
\par If, while you are generating values for the Cookies collection of the \par Response
\par object, you need to determine if there are already subkeys defined for \par a given
\par cookie, you can evaluate the HasKeys property of the cookie. If the cookie \par has
\par subkeys defined, the HasKeys property evaluates to True.
\par Like other properties that result in a change to the HTTP response header \par values,
\par the Cookies collection values must be set before the server sends the \par <HTML> tag
\par to the client unless the response is buffered.
\par 104 Chapter 7 – Response Object
\par Methods Reference
\par ASP in a Nutshell: A Desktop Quick Reference, eMatter Edition
\par Copyright © 2000 O’Reilly & Associates, Inc. All rights \par reserved.
\par Methods Reference
\par AddHeader
\par Response.AddHeader strName, strValue
\par Allows you to add your own HTTP response header with a corresponding value. \par If
\par you add an HTTP header with the same name as a previously added header, \par the
\par second header will be sent in addition to the first; adding the second \par header does
\par not overwrite the value of the first header with the same name. Also, \par once the
\par header has been added to the HTTP response, it cannot be removed.
\par If the client sends the web server an HTTP header other than those listed \par in the
\par section on the ServerVariables collection in Chapter 6, you can use HTTP_
\par HeaderName to retrieve it. For example, if the client sends the HTTP header:
\par ClientCustomHeader:CustomHeaderValue
\par then you could retrieve the value for this element using the following \par syntax:
\par <%
\par Request.ServerVariables("HTTP_ClientCustomHeader")
\par %>
\par This is an advanced method and should not be used without careful planning. \par If
\par another method of the Response object will meet your needs, use it instead \par of
\par using the AddHeader method.
\par Parameters
\par strName
\par The name of the HTML header you wish to add to the response header
\par strValue
\par The initial value of the new header you are adding to the response header
\par Example
\par <%
\par ' The following code adds the CUSTOM-ERROR HTML header to
\par ' the HTTP response headers.
\par Response.AddHeader "CUSTOM-ERROR", "Your browser is not \par IE."
\par %>
\par Notes
\par Like the other methods and properties of the Response object that alter \par the HTTP
\par response headers, you must call the AddHeader method before sending the
\par <HTML> tag to the client. If you have previously set the Buffer \par property value of
\par the Response object to True, you can use AddHeader unless you have previously
\par called the Flush method. If you call AddHeader after sending the <HTML> \par tag to
\par the client or calling the Flush method, your call to AddHeader will result \par in a
\par runtime error.
\par You should not use underscores in your custom headers. Doing so will increase
\par your chances of ambiguity with headers already present. Use hyphens to \par separate
\par AppendToLog 105
\par Response Object
\par AppendToLog
\par ASP in a Nutshell: A Desktop Quick Reference, eMatter Edition
\par Copyright © 2000 O’Reilly & Associates, Inc. All rights \par reserved.
\par multiple words instead. Also, note that to retrieve the value of a custom \par header
\par with hyphens, you replace them with underscores when retrieving the values \par of
\par your custom headers.
\par AppendToLog
\par Response.AppendToLog strLogEntry
\par Adds a string to the web server log entry for the current client request. \par You can
\par only add up to 80 characters at a time, but you are able to call the AppendToLog
\par method multiple times.
\par Logging web site activity
\par IIS allows you to log user activity into a text file* or into an ODBC-compliant \par database.
\par This logging is separate from Windows NT logging, and the records in the
\par IIS log cannot be viewed using the Windows NT Event Viewer tool. To view \par the
\par IIS log files, you must open them as you would any other ASCII text file, \par import
\par them into a spreadsheet or database program, or, if you’ve been logging \par to an
\par ODBC database, view them through queries to that database.
\par Specifically, you can log the following aspects of users’ visits \par to your web site,
\par among other things:
\par • Date/time of user visit
\par • Requested pages
\par • IP address of user
\par • Length of time connected to server
\par Using this information and information your application adds to this log \par through
\par Response.AppendToLog, you can plan future development for your site, plan
\par security, and plan for new servers if the load warrants it.
\par Parameters
\par strLogEntry
\par The string you want added to the current client request’s entry in \par the web
\par server. This string can be up to 80 characters in length. Note that the \par string
\par you append to the web server log entry cannot contain commas, since the
\par fields in the IIS web log entries are comma delimited.
\par Example
\par <%
\par ' Assume you have constructed one string containing all that
\par ' you'd like logged to the web's server. This string is
\par ' declared as strOrigLogContent. The following Do...While
\par ' loop code will loop through your content and log it to the
\par ' web server 79 characters at a time.
\par * The log files for IIS are found in winnt\\system32\\LogFiles\\W3svc1\\ex[date].log. \par Each entry
\par into the (IIS default) log contains time, caller IP, caller method (GET/POST), \par uri-stem (no server
\par path), and resulting status.
\par 106 Chapter 7 – Response Object
\par BinaryWrite
\par ASP in a Nutshell: A Desktop Quick Reference, eMatter Edition
\par Copyright © 2000 O’Reilly & Associates, Inc. All rights \par reserved.
\par Do While Len(strOrigLogContent) > 0
\par If Len(strOrigLogContent) >= 79 Then
\par strLogString = Left(strOrigLogContent, 79)
\par Else
\par strLogString = strOrigLogContent
\par End If
\par ' Log the content.
\par Response.AppendToLog strLogString
\par If Len(strOrigLogContent) > Len(strLogString) Then
\par strOrigLogContent = _
\par Right(strOrigLogContent, _
\par Len(strOrigLogContent) - Len(strLogString))
\par Else
\par strOrigLogContent = ""
\par End If
\par Loop
\par %>
\par Notes
\par Before you are able to append information to the web server log in IIS, \par you must
\par enable the URL Query option of the Extended Logging Properties sheet for \par the
\par web site whose activity the log files are being used to record.
\par This method can be an invaluable time saver in maintaining detailed information
\par about actions on your web site. If you have a unique identifier for each \par user that
\par is stored in the log file with the entry (which contains an IP address, \par possibly a
\par Windows NT account name, and the date and time of the visit), you can \par quickly
\par determine who was visiting the site at the time of an unexpected error \par on your
\par site. This method cannot be relied on for security, since you cannot be \par 100%
\par certain of the user’s identity, but it can help.
\par BinaryWrite
\par Request.BinaryWrite arbyteData
\par Writes information directly to the response content without any character \par conversion.
\par If your application involves writing binary data to the client, you must \par use
\par this method to ensure that data you send is not converted to character \par data from
\par the original binary.
\par Parameters
\par arbyteData
\par An array of bytes you wish to write to the response content
\par Example
\par The following example code is lengthy for the simple call to BinaryWrite, \par but it
\par demonstrates a very useful concept, especially if you are forced to deal \par with
\par binary data from a database.
\par BinaryWrite 107
\par Response Object
\par BinaryWrite
\par ASP in a Nutshell: A Desktop Quick Reference, eMatter Edition
\par Copyright © 2000 O’Reilly & Associates, Inc. All rights \par reserved.
\par <%
\par ' The following code retrieves a binary object
\par ' (in this case a JPG image) and writes it to the
\par ' client using BinaryWrite. (For more information
\par ' on ActiveX Data Objects usage, see Chapter 11.)
\par ' Create an ADO connection object.
\par Set adoCon = Server.CreateObject("ADODB.Connection")
\par ' Use the Open method of the Connection object
\par ' to open an ODBC connection with the database
\par ' represented by the DSN ImageDatabase.
\par adoCon.Open "ImageDatabase"
\par ' Use the Execute method of the ADO Connection object
\par ' to retrieve the binary data field from the database.
\par Set adoRecImgData = adoCon.Execute _
\par ("SELECT ImageData FROM Images WHERE ImageId = 1234")
\par ' Create a Field object by setting one equal to a
\par ' specific field in the recordset created previously.
\par Set adoFldImage = adoRecImgData("ImageData")
\par ' Use the ActualSize property of Field object to retrieve
\par ' the size of the data contained in the Field object. After
\par ' this line you will know how many bytes of data reside in
\par ' the Field object.
\par lngFieldDataLength = adoFldImage.ActualSize
\par ' Use the BinaryWrite method to write 4K bytes of binary
\par ' data at a time. So, first we need to determine how many
\par ' 4K blocks the data in the Field object represents.
\par lngBlockCount = lngFieldDataLength / 4096
\par ' Now let’s get how many bytes are left over after removing
\par ' lngBlockCount number of bytes.
\par lngRemainingData = lngFieldDataLength Mod 4096
\par ' We now must set the HTTP content type Response header
\par ' so that the browser will recognize the data being sent
\par ' as being JPEG image data.
\par Response.ContentType = "image/JPEG"
\par ' Loop through and write the first lngBlockCount number
\par ' of binary blocks of data.
\par For intCounter = 1 to lngBlockCount
\par Response.BinaryWrite adoFldImage.GetChunk(4096)
\par Next
\par ' Now write the last remainder of the binary data.
\par Response.BinaryWrite adoFldImage.GetChunk(lngRemainingData)
\par 108 Chapter 7 – Response Object
\par Clear
\par ASP in a Nutshell: A Desktop Quick Reference, eMatter Edition
\par Copyright © 2000 O’Reilly & Associates, Inc. All rights \par reserved.
\par ' Close the recordset.
\par adoRecImgData.Close
\par %>
\par Notes
\par At first, the BinaryWrite method seems to be of limited use, until you \par have binary
\par data stored in a database that must be sent to the client; then, BinaryWrite \par is
\par invaluable. As the code sample demonstrates, one example of this is the \par display of
\par image data that is stored and retrieved from a DBMS capable of storing \par binary
\par data.
\par I have used this method to display JPEG images stored in a Microsoft SQL \par Server
\par database (using code similar to the preceding), and it works quite well. \par Because
\par you are sending the HTTP response containing only the image data (not \par a link
\par request to the image), it may even be faster than sending images to the \par client
\par upon a straight client request, assuming your database access is suitably \par fast.
\par Clear
\par Response.Clear
\par Empties the current contents of the Response buffer. It does so without \par sending
\par any of the buffered response to the client.
\par Parameters
\par None
\par Example
\par <% Response.Buffer = True%>
\par <HTML>
\par <HEAD><TITLE>Response Clear Method Example</TITLE></HEAD>
\par <BODY>
\par <%
\par On Error Resume Next
\par [CODE TO DO SOME CALCULATIONS]
\par lngFormulaElement1 = 47
\par lngFormulaElement2 = lngFormulaElement1 – 47
\par lngFormulaElement3 = 23
\par ' This next line results in a division-by-zero error
\par ' (Error Number 11).
\par lngNewCalcTotal = lngFormulaElement3 / lngFormulaElement2
\par ' This next line will still be processed because we used
\par ' ON ERROR RESUME NEXT.
\par If Err <> 0 Then
\par ' The following code clears the Response buffer, writes
\par ' an error message, and ends the response, forcing IIS to
\par ' send the response to the client. Note that the Buffer
\par ' property has to be set to True for the following code
\par ' to work properly.
\par End 109
\par Response Object
\par End
\par ASP in a Nutshell: A Desktop Quick Reference, eMatter Edition
\par Copyright © 2000 O’Reilly & Associates, Inc. All rights \par reserved.
\par Response.Clear
\par Response.Write "Your request resulted in the error: " & \par _
\par Err.Description
\par Response.Write " Error Number: " & Err.Number
\par Response.Write "<BR>Call your web admin at 555-HELP for "
\par Response.Write "more information."
\par Response.End
\par End If
\par %>
\par ...[additional code]
\par Notes
\par The Clear method of the Response object does not clear any HTTP headers, \par only
\par the content. As noted in the example, the Buffer property of the Response \par object
\par must be set to True or the use of this method will result in a runtime \par error.
\par One of the most important uses for the Clear method is to clear the buffer \par and
\par send to the client browser something else instead, often error information, \par as is the
\par case with the example.
\par For errors to be caught and error information to be sent to the client \par in this
\par fashion, not only must the Buffer property be set to True, but also you \par must use
\par the following line of code to ensure that your error trap will be processed:
\par On Error Resume Next
\par End
\par Response.End
\par Ends all storage of information in the response buffer and sends the current
\par contents of the buffer immediately to the client. Any code present after \par the call to
\par the End method is not processed. Any memory set aside by the script up \par until the
\par call to End (such as database objects previously used in the script) is \par released.
\par Parameters
\par None
\par Example
\par See the previous example for the Clear method.
\par Notes
\par If the Buffer property is set to True, calling the End method will flush \par the
\par Response buffer exactly as if you had called the Flush method (see the \par next
\par section). However, unlike calling the Flush method, no code after the \par call to End
\par is processed by the web server.
\par 110 Chapter 7 – Response Object
\par Flush
\par ASP in a Nutshell: A Desktop Quick Reference, eMatter Edition
\par Copyright © 2000 O’Reilly & Associates, Inc. All rights \par reserved.
\par Flush
\par Response.Flush
\par Immediately sends all data currently in the response buffer to the client. \par Unless the
\par Buffer property of the Response object is set to True, this method will \par result in a
\par runtime error. This method allows you to send various portions of the \par response to
\par the client at your discretion.
\par Parameters
\par None
\par Example
\par <% Response.Buffer = True%>
\par <HTML>
\par <HEAD><TITLE>Response Flush Method Example</TITLE></HEAD>
\par <BODY>
\par <%
\par ' Suppose for this example that this first part of the
\par ' script retrieves some information from a database and
\par ' that retrieval takes a long time, say 30 seconds.
\par ' (Don't worry about the details of the ActiveX Data Object
\par ' calls. They are covered later in the book and serve only
\par ' as an example here of something that might take a long time.)
\par Set adoCon = Server.CreateObject("ADODB.Connection")
\par adoCon.Open MyDatabase
\par Set adoRec = adoCon.Execute([BIG SQL STATEMENT])
\par ' Rather than continue to the second part of the script, in
\par ' which a second slow SQL statement (say another 15 seconds)
\par ' executes, first we'll use the Flush method to force the
\par ' first part of the script results to the client. This way,
\par ' the user can be looking at the results of the first query
\par ' while waiting for the second.
\par Response.Flush
\par ' [Second LONG SQL statement.]
\par Set adoRec2 = adoCon.Execute([BIG SQL STATEMENT])
\par %>
\par </BODY></HTML>
\par Notes
\par Using the buffering capacity of the Response object, you are able to send \par the
\par response to the client in parts. For example, suppose you are presenting \par a description
\par of your worldwide organization followed by a list of offices derived from
\par information in a database. The organization description is straight text, \par and thus it
\par takes very little time to prepare and send it to the client. The second \par part takes
\par more time. You could use the Flush method of the Response object to send \par the
\par organizational description to the client first and then send the list \par when it is
\par complete. Without this approach, the user can get the impression that \par the page is
\par slow to download.
\par Write 111
\par Response Object
\par Write
\par ASP in a Nutshell: A Desktop Quick Reference, eMatter Edition
\par Copyright © 2000 O’Reilly & Associates, Inc. All rights \par reserved.
\par One caution, however: if you use the Flush method on an Active Server \par Page, the
\par server will ignore Keep-Alive requests sent by the client for that page. \par This will
\par force a new connection to be made for each piece of information sent to \par the
\par client.
\par Redirect
\par Response.Redirect strURL
\par Redirects the client’s request to another URL.
\par Parameters
\par strURL
\par The Universal Resource Locator string for the new location to which you \par wish
\par to redirect the client
\par Example
\par <%
\par ' The following code determines whether the client has
\par ' security clearance for a certain page. If not, it
\par ' is redirected to another URL.
\par [...Code to determine user's clearance for the current page...]
\par If Not(strUserSecurity = "ADMIN" or "SUPERADMIN") \par Then
\par Response.Redirect "/security/noclearance.asp?usrid=09563"
\par End If
\par %>
\par Notes
\par The strURL value you use when calling the Redirect method can be an exact \par URL
\par with DNS or a virtual directory and filename. It also can be the name \par of a file that
\par resides in the same folder as the requested page.
\par If your script has written any content to the HTTP response body, that \par content is
\par ignored by the script once the call to the Redirect method is executed.
\par Calling the Redirect method is conceptually the same as setting the Status \par property
\par to “302 Object Moved” and sending the user to a new location \par using the
\par Location HTTP header.
\par Note that upon redirection, some older (HTTP 1.0) client browsers will \par mistakenly
\par change POST requests to GET requests when the new URL is called. This \par is an
\par important consideration when the client’s POSTed information contains \par more data
\par than the GET method can handle. It is assumed that new browsers supporting \par the
\par HTTP 1.1 protocol have fixed this problem.
\par Write
\par Response.Write vntData
\par Writes information directly to the HTTP response body.
\par 112 Chapter 7 – Response Object
\par Write
\par ASP in a Nutshell: A Desktop Quick Reference, eMatter Edition
\par Copyright © 2000 O’Reilly & Associates, Inc. All rights \par reserved.
\par Parameters
\par vntData
\par The information to be inserted into the HTML text stream that will be \par received
\par by the client browser. This includes text, HTML tags, client-side script, \par and so
\par on. The data variables in the ASP script itself are of the data type variant. \par The
\par value cannot contain the %> character sequence; the web server will \par interpret
\par it as the end of your active server script. If your script requires this \par character
\par sequence, use the escape sequence %\\> instead.
\par Example
\par <%
\par strDirCommand = "Dir /w"
\par ' The following code writes an entire HTML table to the HTTP
\par ' response body.
\par Response.Write "<TABLE>"
\par Response.Write "<TR>"
\par Response.Write "<TD WIDTH = 50%\\>"
\par Response.Write "Command"
\par Response.Write "</TD>"
\par Response.Write "<TD WIDTH = 50%\\>"
\par Response.Write "Description"
\par Response.Write "</TD>"
\par Response.Write "</TR>"
\par Response.Write "<TR>"
\par Response.Write "<TD WIDTH = 50%\\>"
\par Response.Write Chr(34) & strDirCommand & Chr(34)
\par Response.Write "</TD>"
\par Response.Write "<TD WIDTH = 50%\\>"
\par Response.Write "This allows you to see a list of the "
\par Response.Write "files in <BR> your current folder."
\par Response.Write "</TD>"
\par Response.Write "</TR>"
\par Response.Write "</TABLE>"
\par %>
\par Notes
\par As demonstrated in the example program, you can use the Write method to \par write
\par HTML and client-side script to the response body that the client browser \par will interpret
\par as plain HTML.
\par To send a carriage return/line feed or a quotation mark, use the Chr function, \par as
\par demonstrated the following code:
\par ' Note: Chr(34) is a quotation mark. Chr(10) & Chr(13) is
\par ' the equivalent of a carriage return, followed by a
\par ' linefeed.
\par Response.Write "Hamlet said, " & Chr(34) & _
\par "To be, or not to be." & Chr(34) & Chr(10) & Chr(13)
\par Finally, you can use the Write method to send the value of a server-side \par script to
\par the client browser. This method is sometimes cleaner in your code than \par going
\par back and forth between server-side code and client code using the <%=…%> \par nota-
\par Write 113
\par Response Object
\par Write
\par ASP in a Nutshell: A Desktop Quick Reference, eMatter Edition
\par Copyright © 2000 O’Reilly & Associates, Inc. All rights \par reserved.
\par tion. For example, the following code displays the value of the strHighestPrice
\par data value using both the <%=…%> and the Response.Write methods:
\par <%
\par Response.Write "The highest price is " & strHighestPrice
\par Response.Write ".<BR>"
\par ' The same line as the preceding using the other format:
\par %>
\par The highest price is <%=strhighestPrice%>.<BR>
\par 114
\par ASP in a Nutshell: A Desktop Quick Reference, eMatter Edition
\par Copyright © 2000 O’Reilly & Associates, Inc. All rights \par reserved.
} following stream to the server:
\par [73:send:(179)]GET /hello.htm HTTP/1.0
\par Connection: Keep-Alive
\par User-Agent: Mozilla/3.0 (Win95; I)
\par Host: pc229.west.ora.com
\par Accept: image/gif, image/x-xbitmap, image/jpeg,
\par image/pjpeg, */*
\par Figure 6-1: HELLO.HTM, a simple HTML form
\par Figure 6-2: HELLOCGI.HTM, an HTML page created by a CGI application
\par * send in the following output listing is a sockets function that sends \par a stream in a connected
\par socket. In the output, 73 identifies the socket, while 179 is the value \par returned by the function
\par and represents the total number of bytes sent.
\par 50 Chapter 6 – Request Object
\par How HTTP Works
\par ASP in a Nutshell: A Desktop Quick Reference, eMatter Edition
\par Copyright © 2000 O’Reilly & Associates, Inc. All rights \par reserved.
\par This is a request header. The browser indicates that it wants the server \par to get
\par the document /HELLO.HTM. Get is more than a generic description of what
\par the server should do; it indicates the HTTP request type. (For details, \par see
\par “HTTP Request Types,” later in this chapter.) The browser also \par indicates that
\par it’s using version 1.0 of the Hypertext Transfer Protocol.
\par Note that the first line in this HTTP header is actually an artifact of
\par the TCP/IP packet sniffer used in this demonstration and not part of
\par the actual HTTP request sent. The same is true for all HTTP segments
\par in this chapter.
\par 2. The server receives* the headers sent by the browser, as shown in the
\par following output produced by our spy program, and processes the request:
\par [21:recv: completed (179)]GET /hello.htm HTTP/1.0
\par Connection: Keep-Alive
\par User-Agent: Mozilla/3.0 (Win95; I)
\par Host: pc229.west.ora.com
\par Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*
\par 3. The server sends the document HELLO.HTM to the browser:
\par [21:send:(535)]HTTP/1.0 200 OK
\par Date: Monday, 30-Sep-98 23:33:00 GMT
\par Server: WebSite/1.1
\par Allow-ranges: bytes
\par Accept-ranges: bytes
\par Connection: Keep-Alive
\par Content-type: text/html
\par Last-modified: Monday, 30-Sep-98 23:30:38 GMT
\par Content-length: 297
\par <HTML>
\par <HEAD><TITLE>Hello, World!</TITLE></HEAD>
\par <BODY>
\par <FORM ACTION="/cgi-win/hello.exe" METHOD="POST">
\par What is your name? <INPUT TYPE="text" NAME="name" \par SIZE=60><BR>
\par <INPUT TYPE="submit" VALUE="Submit the form">
\par <INPUT TYPE="reset" VALUE="Clear all fields">
\par </FORM>
\par </BODY> </HTML>
\par Here, WebSite sends a total of 535 bytes to the browser. This consists \par of a
\par response header, followed by a blank line, followed by the HTML document
\par itself. The header fields indicate, among other things, the number of \par bytes
\par (the Content-length header) and the format (the Content-type header) of \par the
\par * The recv function is used to receive data from a socket. In the output, \par the initial number, 21,
\par represents the socket used by the server. “Completed (179)” \par indicates the function’s return value,
\par in this case that it completed normally by receiving 179 bytes. Note that \par this corresponds
\par to the number of bytes sent by the browser.
\par How HTTP Works 51
\par Request Object
\par How HTTP Works
\par ASP in a Nutshell: A Desktop Quick Reference, eMatter Edition
\par Copyright © 2000 O’Reilly & Associates, Inc. All rights \par reserved.
\par transmitted data. “200 OK” is a status code indicating that \par the browser’s
\par request was fulfilled. The server also indicates that, like the browser, \par it’s using
\par version 1.0 of HTTP.
\par 4. The browser reads the headers and data sent by the server:
\par [73:recv: posted]
\par [73:recv: completed (260)]HTTP/1.0 200 OK
\par Date: Monday, 30-Sep-98 23:33:00 GMT
\par Server: WebSite/1.1
\par Allow-ranges: bytes
\par Accept-ranges: bytes
\par Connection: Keep-Alive
\par Content-type: text/html
\par Last-modified: Monday, 30-Sep-98 23:30:38 GMT
\par Content-length: 297
\par <HTML>
\par <HEAD><TITLE>H
\par [73:recv: posted]
\par [73:recv: completed (275)]ello, World!</TITLE></HEAD>
\par <BODY>
\par <FORM ACTION="/cgi-win/hello.exe" METHOD="POST">
\par What is your name? <INPUT TYPE="text" NAME="name" \par SIZE=60><BR>
\par <INPUT TYPE="submit" VALUE="Submit the form">
\par <INPUT TYPE="reset" VALUE="Clear all fields">
\par </FORM>
\par </BODY> </HTML>
\par Although two recv operations are required to retrieve the header records
\par along with the document, the total number of bytes read in these two operations
\par equals the total number of bytes sent by the server.
\par 5. The browser displays the form asking for the user’s name and, \par when the user
\par fills it out and clicks the Submit button, sends the following to the \par server:
\par [70:send:(232)]POST /cgi-win/hello.exe HTTP/1.0
\par Referer: http://pc229.west.ora.com/hello.htm
\par Connection: Keep-Alive
\par User-Agent: Mozilla/3.0 (Win95; I)
\par Host: pc229.west.ora.com
\par Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*
\par [70:send:(69)]Content-type: application/x-www-form-urlencoded
\par Content-length: 14
\par [70:send:(2)]
\par [70:send:(16)]name=Jayne+Doe
\par Because the browser is transmitting form data, the HTTP request type is
\par “POST,” as the very first header record indicates. Similarly, \par the Content-length
\par and Content-type records indicate that the browser is transmitting 14 \par bytes of
\par x-www-form-urlencoded data in the body of the request. This consists of
\par the information input by the user in the form’s single data field, \par the name text
\par box.
\par 6. The server receives the header records and form data transmitted by \par the
\par browser in the previous step. (Since it’s basically identical to \par the text sent by
\par 52 Chapter 6 – Request Object
\par How HTTP Works
\par ASP in a Nutshell: A Desktop Quick Reference, eMatter Edition
\par Copyright © 2000 O’Reilly & Associates, Inc. All rights \par reserved.
\par the browser, we won’t duplicate it here.) The URL (/cgi-win/hello.exe) \par causes
\par the server to launch the CGI application HELLO.EXE and to transmit the
\par form’s data to it. The CGI application may do some back-end processing, \par then
\par builds an HTML document on the fly and returns it to the server.
\par 7. The server returns the HTML document to the browser along with the \par necessary
\par header records, as the following output from WSock32 Spy shows:
\par [18:send:(422)]HTTP/1.0 200 OK
\par Date: Monday, 30-Sep-98 23:33:10 GMT
\par Server: WebSite/1.1
\par Allow-ranges: bytes
\par Accept-ranges: bytes
\par Connection: Keep-Alive
\par Content-type: text/html
\par Content-length: 231
\par <HTML><HEAD>
\par <TITLE>Welcome to this Web Page!</TITLE></HEAD>
\par <BODY><H1>Welcome to Our Web Server!</H1><p><p>
\par Hello, Jayne Doe! We're glad that you took
\par the time out of your busy day to visit us!
\par <HR></PRE></BODY></HTML>
\par Notice that the server indicates to the browser that it’s sending \par 231 bytes of an
\par HTML document.
\par 8. The browser receives the data stream send by the server and uses it \par to render
\par the HTML page.
\par Hopefully, this gives you a fairly good sense of what’s involved \par in the interchange
\par between browser and server. It’s important, though, to take a more \par in-depth look
\par at some of the points that we’ve touched on only briefly, as well \par as to cover some
\par additional features that are not included in this simple example.
\par HTTP Request Types
\par The request type is passed by the client to the server to indicate what \par the server
\par should do with the URL that’s also supplied by the browser. Although \par the HTTP
\par specification details a number of request types, like PUT and DELETE, \par only two are
\par supported by all servers and in common use: GET and POST. A GET request \par asks
\par the server to “get” a piece of information, typically a document, \par and return it to
\par the client. If the request includes any additional information, these \par are appended
\par as arguments to the URL. A POST request, on the other hand, provides the \par server
\par with information to be “posted” to the URL; typically, it’s \par used to send the contents
\par of an HTML form to the server, or to provide the server with information \par that’s
\par needed for back-end processing. The information itself is contained in \par the body of
\par the request.
\par Most servers cannot handle data received from either the POST or GET methods
\par internally. Normally, POST requests, as well as GET requests that also \par send data to
\par the server, are handled by accessory programs or DLLs (CGI and ISAPI applica-
\par How HTTP Works 53
\par Request Object
\par How HTTP Works
\par ASP in a Nutshell: A Desktop Quick Reference, eMatter Edition
\par Copyright © 2000 O’Reilly & Associates, Inc. All rights \par reserved.
\par tions and ISAPI filters). Both POST and GET requests can return any kind \par of data of
\par any size.
\par While it may seem when transmitting data to a web server that GET and \par POST are
\par similar, one rule is hard and fast: A GET request must never change anything.
\par Don’t write an ASP script that makes changes to a database, for instance, \par in
\par response to a GET request. The reason for this is discussed in greater \par detail in the
\par following section, “Form Submission.”
\par Form Submission
\par A user enters input into the fields of a form. When the form is submitted, \par the data
\par contained in each field of the form is transferred to the server, which \par then passes
\par it to ASP. This data is sent in the format name=value, where name is the \par name
\par assigned to the field by the NAME= attribute of the <INPUT> tag, \par and value is the
\par value entered in that field. For example, if the user enters “Archie” \par in a field
\par prompting for his first name, the browser may send along the string first_
\par name=Archie.
\par If the form is written to use METHOD=GET, the form data is appended to \par the URL as
\par an argument string. If the form contains many fields or if fields contain \par long strings
\par of text, the complete URL can become very large and unwieldy. In addition, \par the
\par limit of the number of characters submitted in a GET—typically about \par 2000—is
\par much lower than in a POST.
\par If the form instead uses METHOD=POST, the name=value pairs are sent as \par the body
\par of the request instead of being appended to the URL. In addition to the \par greater
\par ease of handling of POST requests, most servers offer better performance \par when
\par extracting data from the body of a request than from a URL in the request \par header.
\par Always use the POST method with forms that change something or cause any \par irreversible
\par action (most do). POST is safer and more efficient; GET should never be
\par used to change anything. In developing your ASP scripts, you can decide \par whether
\par you want to support data passed to your program using the GET method.
\par GET Versus POST
\par In the event that you’re confused about the difference between these \par two
\par methods, GET can be used to retrieve any document, POST cannot. On the
\par other hand, both GET and POST can be used to pass data to the object indicated
\par by the URL. When GET is used for this purpose, the data is included in
\par the URL as the argument string; in order to extract this data with Win-CGI,
\par you have to parse the argument string. When POST is used, the data is
\par passed to the server in the body of the request message. So, in cases \par in
\par which data is sent to the server, GET and POST differ in the method used \par to
\par transmit that data.
\par 54 Chapter 6 – Request Object
\par How HTTP Works
\par ASP in a Nutshell: A Desktop Quick Reference, eMatter Edition
\par Copyright © 2000 O’Reilly & Associates, Inc. All rights \par reserved.
\par HTTP Request and Response
\par Headers are the most misunderstood part of HTTP, yet understanding their \par role
\par can make understanding the properties and methods of both the ASP Request \par and
\par Response objects much easier.
\par Take a look at any Internet email message. It consists of two parts, the \par header and
\par the body. The header consists of several lines that describe the body \par of the
\par message and perhaps the way the message was handled as it was routed to \par you.
\par The header and body are separated by a blank line. (For more information \par on
\par header syntax, consult RFC-822.)
\par An HTTP message (either a request or a response) is structured the same \par way. The
\par first line is special, but the rest of the lines up to the first blank \par line are headers
\par just like in a mail message. The header describes the request and its \par content, if
\par any, or the response and its content.
\par The request
\par In an earlier section, “HTTP: A Simple Example,” we saw a number \par of requests
\par from the browser. Here is another example of a simple HTTP request:
\par POST /cgi-win/hello.exe HTTP/1.0
\par Accept: image/gif, image/jpeg, */*
\par User-Agent: Mozilla/2.0N (Windows; I; 32Bit)
\par Content-type: application/x-www-form-urlencoded
\par Content-length: 14
\par [mandatory blank line]
\par name=Jayne+Doe
\par The first line, which is known as the request-line, describes the type \par of request (or
\par method)—in this case POST, the URL, and, finally, the version of \par the HTTP
\par protocol that the client uses. The second line describes the types of \par documents
\par that the client can accept. The third line is an “extra” header \par that’s not required by
\par HTTP. It gives the name and version of the client software. Following \par this, as
\par discussed in the section “HTTP: A Simple Example,” are two lines \par describing the
\par information contained in the body of the request.
\par Everything up to the mandatory blank line is part of the HTTP request \par header. In
\par addition to the example lines here, there can be other lines in this section. \par For
\par example, if the browser is sending information contained in a “cookie,” \par that information
\par also will be in the request header.
\par Below the mandatory blank line is the HTTP request body. In most cases, \par this
\par section of the request is empty (for example, when the browser is requesting \par only
\par a static page and is not sending any information). However, when the POST
\par method is used, the information sent to the web server is located in this \par section of
\par the request.
\par The response
\par Here is an example of a simple HTTP response:
\par HTTP/1.0 200 OK
\par How HTTP Works 55
\par Request Object
\par How HTTP Works
\par ASP in a Nutshell: A Desktop Quick Reference, eMatter Edition
\par Copyright © 2000 O’Reilly & Associates, Inc. All rights \par reserved.
\par Date: Thursday, 02-Nov-95 08:44:52 GMT
\par Server: WebSite/1.1
\par Last-Modified: Wednesday, 01-Nov-95 02:04:33 GMT
\par Content-Type: text/html
\par Content-length: 8151
\par [mandatory blank line]
\par <HTML><HEAD>
\par <TITLE>...
\par The first line of the response is also special and is known as the status-line. \par It
\par contains the protocol version the server uses, plus a status code and \par a reason
\par phrase. The server uses the status code and reason phrase to inform the \par browser
\par whether it was able to respond to the browser’s request; in this \par case, it’s successfully
\par filled the browser’s request for a document. The second line contains \par the date
\par and time the server handled the request. Third is a header line describing \par the
\par server software and version. The fourth line indicates the date and time \par when the
\par requested document was last modified. The last two lines describe the \par type of data
\par and the number of bytes in the requested document. This is followed by \par exactly
\par one blank line, then the body of the message, which contains the document \par data
\par that the server is sending back for the browser to display.
\par As with the HTTP request, everything above the mandatory blank line is \par considered
\par part of the HTTP response header. Everything below this line is part of \par the
\par response body.
\par This chapter covers the ASP Request object, which you can use to access \par both the
\par header and the body of the HTTP request. The next chapter discusses the \par ASP
\par Response object, which you use in manipulating the HTTP response from \par the web
\par server.
\par The HTTP Request and the ASP Request Object
\par As mentioned earlier, the ASP Request object allows you to access both \par the header
\par and body of the HTTP request sent to the web server by the client’s \par browser. The
\par method of retrieving information from the HTTP request is basically the \par same for
\par an ASP script as it is for a CGI application. The exceptions come not \par from the
\par actual request mechanics but from how each type of application is loaded \par into the
\par web server (CGI versus an ISAPI filter), as described in the first two \par chapters of
\par this book.
\par Just as with CGI applications, the client browser can send information \par to an ASP
\par script in two different manners. First, it also can send information by \par means of an
\par HTML form using the GET method:
\par <HTML>
\par <HEAD><TITLE>Welcome to the Corp.</TITLE></HEAD>
\par <BODY>
\par <FORM ACTION=" http://mycorp.com/secure.asp" METHOD="GET">
\par First name: <INPUT TYPE="text" NAME="first_name" \par SIZE=60><BR>
\par Last name: <INPUT TYPE="text" NAME="last_name" \par SIZE=60><BR>
\par <INPUT TYPE="submit" VALUE="Submit the form">
\par <INPUT TYPE="reset" VALUE="Clear all fields">
\par </FORM>
\par </BODY> </HTML>
\par 56 Chapter 6 – Request Object
\par How HTTP Works
\par ASP in a Nutshell: A Desktop Quick Reference, eMatter Edition
\par Copyright © 2000 O’Reilly & Associates, Inc. All rights \par reserved.
\par When the client submits a GET request, the information about the request \par is
\par appended to the end of the request URL as name/value pairs separated by \par ampersands
\par and preceded by a question mark. Each name corresponds to an element in
\par the form. For example, suppose the user entered Horatia and Thompson into \par the
\par two fields in the last example and clicked on the Submit button. The submission
\par of the preceding form is, as far as the server is concerned, identical \par to the
\par following:
\par http://mycorp.com/secure.asp?first_name=horatia&last_
\par name=thompson
\par This is an important point. Following this example, consider the following \par line of
\par code:
\par http://mycorp.com/secure.asp?first_name=horatia&last_
\par name=thompson
\par If the user were to type this into the address line or click on a link \par containing the
\par preceding as a URL, the web server would treat that resulting HTTP request
\par exactly as if the information had been sent as part of a form using the \par GET request.
\par From within your ASP application, you can access this information through \par the
\par QueryString collection of the Request object. For example:
\par <%
\par strFirstName = Request.QueryString("first_name")
\par %>
\par will initialize the strFirstName variable to the value sent in the first_name
\par parameter. The QueryString collection is discussed in detail later in \par this chapter.
\par Just as with CGI applications, you also can send information to an ASP \par script using
\par the POST method. In this case, instead of being part of the HTTP request \par header,
\par the information would be in the body of the request object:
\par <HTML>
\par <HEAD><TITLE>Welcome to the Corp.</TITLE></HEAD>
\par <BODY>
\par <FORM ACTION="http://mycorp.com/secure.asp" METHOD="POST">
\par First name: <INPUT TYPE="text" NAME="first_name" \par SIZE=60><BR>
\par First name: <INPUT TYPE="text" NAME="last_name" \par SIZE=60><BR>
\par <INPUT TYPE="submit" VALUE="Submit the form">
\par <INPUT TYPE="reset" VALUE="Clear all fields">
\par </FORM>
\par </BODY> </HTML>
\par This form’s submission would result in an HTTP request similar to \par the following:
\par POST /secure.asp HTTP/1.0
\par Accept: image/gif, image/jpeg, */*
\par User-Agent: Mozilla/2.0N (Windows; I; 32Bit)
\par Content-type: application/x-www-form-urlencoded
\par Content-length: 35
\par [mandatory blank line]
\par first_name=horatio&last_name=aubrey
\par For your application to manipulate the information sent in that HTTP request, \par you
\par would have to use the Form collection of the Request object:
\par Comments/Troubleshooting 57
\par Request Object
\par Comments/Troubleshooting
\par ASP in a Nutshell: A Desktop Quick Reference, eMatter Edition
\par