Response Object  

Just as the Request object allows you to retrieve and manipulate information sent by the client browser in its HTTP request, the Response object gives you a great deal of control over the HTTP response to the client. This control comes in three broad categories:

    Control over what data and data types are sent to the client in the headers of the HTTP response

    Control over what data and data types are sent to the client in the body of the HTTP response

    Control over when and how that data is sent

Control over the HTTP response headers includes setting cookies on the client machine, setting various preexisting HTTP header values (such as the content type and expiration information for a given page), and, finally, adding your own custom headers to the HTTP response.

You control the HTTP response body directly through the Write and BinaryWrite methods. As you might infer from the names, these methods of the Response object allow you to write information directly to the response body, which will be received by the client just like any other information received in an HTML request response.

Finally, the Response object allows you to control how and when the response is sent to the client. For example, using the properties and methods involved in buffering the response, you can determine whether to send the HTTP response as a single unit to the client or to send the results of the request piecemeal. You can dynamically determine whether the client is still connected to your web site. You can redirect her request as though she requested something else. Finally, you can use the Response object to write entries into the web server log.

Buffer  
Response.Buffer[=blnSetting]
 

The Buffer property determines whether the content created by your script is delivered to the client browser as a whole or sent immediately to the client browser as each line is created and entered into the HTML stream. If set to True, then all scripts on the page are run before the results of that script are sent to the client browser.

The default value for the Buffer property is False unless you set ASPBufferingOn in the metabase (through a Windows Scripting Host script or through the Microsoft Management Console for your web site). If set in the metabase, the value there can be overridden using the Buffer property on a page. For example, if you set ASPBufferingOn to True, you could later use the Buffer property to override this behavior and force IIS not to buffer the page.

 
Parameters
blnSetting

Specifies whether the HTTP response that results from the web server's processing of your script is buffered and then sent to the client or sent to the client as it is created:

True

Causes the web server to buffer all results of your script until all processing is complete or until the Flush or End method of the Response object is invoked. Note that even if buffering is set to True, if you call the End method, the contents of the buffer are sent to the client and all subsequent results from the processing of your script are not sent to the client.

False

Instructs the web server to send information to the client as your script is processed, instead of waiting until all processing is complete. Note that if Buffer is set to False, any call to the Clear, End, or Flush methods of the Response object will result in a runtime error.

 
Example

Consider the following example. Note that we haven't set the Buffer property of the Response object explicitly, so it's False:

<%@ LANGUAGE="VBScript" %>
<HTML>

<%
CODE THAT RETRIEVES A FIELD VALUE FROM A DATABASE
%>

The response is not buffered before it is sent to the requesting browser. For this reason, if the previous database action results in an error, the user will see half a page ending in an error notice. Now examine the second code example:

<%@ LANGUAGE="VBScript" %>
<%Response.Buffer = True %>
<HTML>

<%
On Error Resume Next
' CODE THAT RETRIEVES A FIELD VALUE FROM A DATABASE
If Err.Number <> 0 Then
   Response.Clear
   Response.Write "There has been an error. Here is the SQL"
   Response.Write "statement that caused the problem: "
   Response.Write strSQL
   Response.End
End If
%>

In this second example, the response is buffered first and completed before it is sent to the requesting browser. For this reason, we have the opportunity to clear the buffer and place a simple error notice in it that provides more information than does the unbuffered example shown earlier. The code here doesn't provide much interaction, but you get the idea.

If the response is not buffered, the client will receive the HTTP response to its request as it is built—even if that building results in errors.

 
Notes

The first thing to remember is that the Buffer property must be set before the <HTML> tag is generated for the HTTP response. Attempting to set the Buffer property after the <HTML> tag will result in a runtime error.

If your script includes a preprocessing directive setting the language for the page, for example, this directive must be placed before you attempt to set the Buffer property's value. If you attempt to set the language for the page after setting the value for the Buffer property, you will experience an error.

If the Buffer property is set to True and your script does not call the Flush method anywhere, then the web server will honor Keep-Alive requests sent by the client. Keep-Alive requests from the browser inform the server that it should maintain a connection between itself and the client. If the client's Keep-Alive request is honored on the server, it is not forced to reestablish the connection each time it makes an HTTP request. It is, in effect, already connected. This saves the client from having to resolve the URL again.

If the Buffer property is set to False or if you use the Flush method somewhere in your script, the server will be forced to create a new connection to the client in response to each request.

When should you buffer your scripts? The answer to this question depends on two things: how long is too long for your clients to wait, and how complex your scripts are.

If your clients are introductory-level users of the Internet, their patience is typically fairly low; these clients need immediate action upon clicking the Submit button in your forms. More experienced users understand more about the back end of Internet applications and are, perhaps, more understanding of lag times in script results.

More important than this is how important it is for you to present the response as a single unit. For scripts that do a great deal of iterative processing, where each loop is directly affected by the loop before, it may be important to present the final result as a single unit. However, if your script consists of several definable sections, each of which is easily capable of being displayed on its own, then buffering may be less important.

One strategy for dealing with the lag times for complex scripts whose results are required in a single unit is to provide a "please wait" page in some form. This interim page informs the user that his request was received and that the script is processing.

For example, suppose the client browser requests an ASP script that retrieves and formats data from a very complex query requiring a long load time (30 seconds, for example). Rather than forcing the client to click on a link and have nothing happen for 30 seconds (in which time the inexperienced web user might very well click on the same link or button repeatedly), you might first display a page like the following:

<HTML>
<HEAD><TITLE>Please Wait</TITLE></HEAD>
<BODY LANGUAGE = "VBScript" OnLoad = "WinLoad( )">
Your request is being processed, please wait...
<SCRIPT LANGUAGE = "VBScript">
Sub WinLoad( )
   Parent.Location.HREF = "/Reports/Longreport.asp"
End Sub
</SCRIPT>
</BODY>
</HTML>

The short page will take very little time to load, and when it does, the user will see a "please wait" message until the next script has been processed and the report is ready for viewing, at which time the "please wait" page is unloaded and the report is loaded.

Finally, if you find that most of your scripts require buffering, you might consider setting the metabase ASPBufferingOn (using the App Options Configuration page for your virtual directory; see Appendix D ) so that all scripts are buffered by default.

 
CacheControl  
Response.CacheControl[=ProxyCacheControlSetting]
 

The CacheControl allows you to set whether proxy servers serving your pages can cache your page. If your page's content is large and doesn't change often, you might want to allow proxy servers to cache the page and thus serve it faster to requesting client browsers.

 
Parameters
ProxyCacheControlSetting

Determines whether proxy servers used to access your web site can cache your pages. The default for this property is Private, indicating that the proxy servers cannot cache your page. If this value is Public, however, proxy servers can cache the page. Note that Private and Public are string values.

 
Example

Setting this property is a simple affair, as the following code demonstrates. You may be asking yourself if there is any way to determine if the client is accessing the web page through a proxy server. Although there is, if you know ahead of time of the existence of the possible proxy servers, this is problematic and cumbersome. Furthermore, there is no need to determine this before setting this property. Either the client request is being handled by a proxy server and this property will affect the caching of the page, or this property is completely ignored.

<% 

' The following code sets the HTTP cache control header so 
' that this page can be cached by the proxy servers being 
' used to access the page.
Response.CacheControl = "Public"
%>
<HTML>
<%
' Note that the CacheControl property was set BEFORE the 
' <HTML> tag was constructed.
%>
 
Notes

Clearly, if the proxy server can cache your page, then the client's access times when accessing the page though a proxy server will be decreased. However, this is less useful if the page changes frequently. Also note that just because you set the value of the CacheControl property to Public, the proxy server is not required to cache your page(s). This must be configured on the proxy server.

Setting a value for CacheControl alters the value in the cache control HTTP header sent to the client upon a request.

If you use this property, you must do so before sending any response to the client (i.e., before the <HTML> tag is generated for your page). If you attempt to set the value for this (or any other HTTP header) after the <HTML> tag has already been sent to the client, an error will result unless the response is buffered.

Keep in mind that setting this property does not guarantee caching on the proxy server. The proxy server itself must be configured to cache these pages before this property will have any effect.

 
Charset  
Response.Charset(strCharsetName)
 

The Charset allows you to specify a character set for the HTTP response content. The name of this character set is added to the end of the Content-Type header/value pair in the HTTP response headers.

 
Parameters
strCharsetName

The strCharsetName is a string corresponding to a character set. The default character set is ISO-LATIN-1.

 
Example

If you do not set the Charset property, the Content-Type HTTP response header looks like the following:

content-type:text/html

If you set the Charset property, as in the following line of code:

<%
Response.Charset("ISO-LATIN-7")
%>

the value you use to set the Charset property value (the string "ISO-LATIN-7" in the preceding code) is appended to the end of the Content-Type HTTP response header value:

content-type:text/html;charset=ISO-LATIN-7
 
Notes

Although Charset is referred to in both this book and the Microsoft documentation as a property, it is really a method that takes a string argument representing the name of the charset to be added to the end of the Content-Type HTTP response header. For this reason, if you attempt to set the value of the Charset "property" as you would any other Response object property, you will receive an error:

<%
' Next line will NOT work:
Response.Charset = "ISO-LATIN-7"
%>

If the value you set for the Charset property does not represent a valid character set, this value is ignored by the client's browser, and the default character set is used instead.

Note that you can append the name of only one character set to the end of the Content-Type header/value pair. Each subsequent change of the Charset property's value simply replaces the last setting. For example, the following code:

<%
Response.Charset("ISO-LATIN-7")
Response.Charset("ISO-LATIN-3")
%>

results in the following Content-Type HTTP response header/value pair:

content-type:text/html;charset=ISO-LATIN-3

Also note that if your content type is exclusively nontext (image data, for example), the character set value is ignored by the browser.

Finally, the default character set for the Apple Macintosh and compatibles is not ISO-LATIN-1, as it is for IBM PCs and compatibles. If you do not set the Charset property, all Macintosh browsers will interpret requested pages to be in the Macintosh character set. Microsoft's Personal Web Server for Macintosh automatically converts the character set of the requested content to ISO-LATIN-1 and will ignore any other Charset property settings you provide in your script.

Like other properties that result in a change to the HTTP response header values, the Charset property must be set before the server sends the <HTML> tag to the client unless the response is buffered.

 
ContentType  
Response.ContentType[=strContentType]
 

The ContentType allows you to set the value for the Content-Type setting in the HTTP response header. This value defines the type of data being sent in the Response body. The client browser uses this information to determine how to interpret downloaded HTTP response content.

 
Parameters
strContentType

Represents the content type. This string is in a type/subtype format. The type portion of the value represents the general content category and the subtype represents the specific type of content.

 
Example
<% 

' The following code sets the value of the Content-Type
' HTTP response header according to the value of a
' local variable.
If strData = "jpg" Then
   Response.ContentType = "image/JPEG"
Else
   Response.ContentType = "text/plain"
End If

%>
 
Notes

Some of the possible values for ContentType type/subtype pairs are listed in Table 8.1.

Available Content-Type HTTP Header Values

Type

SubType

Description

Text

Plain, RichText

Textual information

Multipart

Mixed, Alternative, Parallel, Digest

Data in response consists of multiple parts of independent data

Message

Partial, External-body

An encapsulated message

Image

JPEG, GIF

Image data

Audio

Basic

Audio data

Video

MPEG

Video data

Application

ODA, PostScript, Active

Typically uninterpreted binary data or data to be processed by a mail-based application

The number of subtypes is expected to grow significantly over time. The best reference for the available subtypes is the latest MIME RFC (RFC 2231 as of this writing). Many of the new subtypes are expected to come from industry. For example, Microsoft has already added the x-cdf subtype to the application type for its Channel Definition Format.

Like other properties that result in a change to the HTTP response header values, the ContentType property must be set before the server sends the <HTML> tag to the client unless the response is buffered.

As another example of the ContentType property, see the code example for the Response object's BinaryWrite method later in this chapter.

 
Expires  
Response.Expires[=intNumMinutes]
 

The Expires property specifies the length of time (in minutes) that the client machine will cache the current page. If the user returns to the page within the amount of time set for the Expires property, the user will view the cached version of the page. If the Expires property is not set, content expiration set for the virtual directory (through the Properties page for the virtual directory on the Microsoft Management Console) will be used. Its default is 24 hours.

 
Parameters
intNumMinutes

The number of minutes you wish the client's browser to cache the current page

 
Notes

If you wish to prevent the client's browser from caching the page, use a value of for intNumMinutes. Doing so will force the client to rerequest the page from the web server every time the client navigates to the page.

If you attempt to set the Expires property more than once in a script, the shortest setting is used. For example, the page that includes the following script will result in the client caching the page for five minutes, even though the last setting of the Expires property is 20 minutes:

<% 

Response.Expires = 10
Response.Expires = 5
Response.Expires = 20

%>

Like other properties that result in a change to the HTTP response header values, the Expires property must be set before the server sends the <HTML> tag to the client unless the response is buffered.

 
ExpiresAbsolute  
Response.ExpiresAbsolute[=[ Date ] [ Time ] ]
 

Specifies a date and time on which the content of the current page will cease being cached on the client machine. If no time is specified when setting the ExpiresAbsolute property, the time is taken to be midnight on the date specified. Before the date specified in the ExpiresAbsolute property, the client will display the cached version of the current page if the user navigates to it.

 
Parameters
Date

A calendar date after which the current page will no longer remain cached. The date value you use should be in the standard month/day/year format. However, the value sent in the Response header will conform in format to the RFC 1123 date format.

Time

Specifies the exact time on Date after which the current page will no longer be cached on the user machine. If no date is specified, the client browser will expire the page at midnight of the current day. The web server converts the time you use to GMT before sending this header to the client.

 
Example
<% 
' The following code sets the current page's caching on the 
' client machine to end at 9 P.M. on 7 May 1998 GMT. NOTE 
' the use of the "#" to designate the date and time.
Response.ExpiresAbsolute=#May 7, 1998 21:00:00#
%>
 
Notes

As the example demonstrates, you must use the pound character (#) to designate the date and time used in the ExpiresAbsolute property value.

Like the Expires property, setting this property multiple times results in the current page's caching ending on the earliest date and time specified in the script.

Like other properties that result in a change to the HTTP response header values, the ExpiresAbsolute property must be set before the server sends the <HTML> tag to the client unless the response is buffered.

 
IsClientConnected  
Response.IsClientConnected
 

A read-only property that evaluates to True if the client is still connected to the web server since the last use of the Response object's Write method and returns False otherwise.

 
Parameters

None

 
Example
<% 
' The following code determines whether the client
' is still connected to the server. If it is still
' connected, then the SessionID (see Chapter 10) will be 
' used to retrieve the user information from a database.
If Response.IsClientConnected Then
   strUserName = fn_strGetUserName(Session.SessionId)
End If
%>
 
Notes

The IsClientConnected property gives you the ability to determine whether the client has disconnected. This is very important if the current script is long. If the client is no longer connected, it may be important to discontinue processing a script.

The following example demonstrates checking for the client connection before continuing in a long script. If the client is no longer connected, the easiest way to stop all processing is to use the Response object's End method.

<%Response.Buffer = True%>
<HTML>
<HEAD><TITLE>One Long Script</TITLE></HEAD>
<BODY>
<% 

' The following code is the first of two segments
' in this script that will take a long time to process:
[SOME LONG CODE]

' Now before performing the second half of this long script,
' check to see if the client is still connected.
If Response.IsClientConnected Then
   [SECOND LONG CODE SEGMENT]
Else
   ' The client is no longer connected, end the script's
   ' processing.
   Response.End
End If
%>
</BODY></HTML>

This property is useful only for those clients using HTTP 1.1. If the browser uses HTTP 1.0, IIS tracks the session using individual HTTP requests and Keep-Alive requests by the client, not a constant connection that is only consistent with the later (1.1+) version of HTTP.

If your ASP file in which you use IsClientConnected is running under IIS 4.0, then the property value is only accurate if the file sends content to the client (i.e., if it is a file containing only server-side code, the resulting value of IsClientConnected is not correct). However, in IIS 5.0, IsClientConnected works regardless of whether or not the current file sends content to the client.

 
PICS  
Response.PICS(strPICSLabel)
 

Adds a PICS (Platform for Internet Content Selection) label to the HTTP response header. This PICS system labels your web content to enable rating services (such as the Recreational Software Advisory Council (RSAC) and SafeSurf, a parents' organization) to rate that content according to various criteria set by content control software such as NetNanny and CyberWatch.

 
Parameters
strPICSLabel

A string value that contains the entire contents of the PICS label you wish to add. A PICS label consists of the following parts:

    The URL of the rating service that produced the label.

    The set of PICS-defined (and extensible) attribute/value pairs that contains information about the rating of the content itself, such as the date it was assigned and an expiration date for the rating.

    A set of attribute/value pairs designed by the rating service that represents the rating given the content. For example, the RSAC has four attributes for which they rate software: violence, sexual content, language, and nudity. These four attributes and their corresponding values would appear similar to the following: (V 0 S 1 L 3 N 0).

 
Example
<% 
' The following piece of code sets a PICS label for the 
' content of this page corresponding to the rating discussed
' earlier.
Dim strPicsLabel 

strPicsLabel = _
       "(PICS-1.1 <HTTP://www.rsac.org/ratingsv01.html> "
strPicsLabel = strPicsLabel & "labels on " & Chr(34)
strPicsLabel = strPicsLabel & "2000.07.20T06:00-0000" & _
               Chr(34)
strPicsLabel = strPicsLabel & " until " & Chr(34)
strPicsLabel = strPicsLabel & "2000.12.31T23:59-0000" & _
               Chr(34)
strPicsLabel = strPicsLabel & "ratings (V 0 S 1 L 3 N 0))"

Response.PICS(strPicsLabel)
%>
 
Notes

The PICS label in the example states that:

    The PICS draft used is 1.1.

    The rating service is RSAC.

    The URL for the rating service is http://www.rsac.org/ratingsv01.html.

    The content label is to go into effect at 6 A.M. GMT 7/20/2000.

    The content label expires at 11:59 P.M. GMT on 12/31/2000.

    In the content label, the violence level is 0, the sexual content level is 1, the adult language level is 3, and the nudity level is 0.

The actual PICS label that is added to the HTTP response header is the following:

PICS-label:(PICS-1.1 http://www.rsac.org/ratingsv01.html 
labels on "1998.03.20T06:00-0000" until 
"1999.12.31T023:59-0000" ratings (v 0 s 1 l 3 n 0))

If you attempt to add an invalid PICS label to the HTTP header, the client machine will ignore it. Note that each subsequent setting of the PICS property value overwrites the last value. Only the final setting is actually sent to the client machine.

Note also that the dates in the PICS label are in quotation marks. For this reason you must use the Chr(34) character (34 is the ASCII equivalent to the quotation mark). This is easiest to handle by simply typing out the label as it should appear in the final PICS label and then replacing each quotation mark in the line of code with the following:

" & Chr(34) & "

Like other properties that result in a change to the HTTP response header values, adding a PICS label must be done before the server sends the <HTML> tag to the client unless the response is buffered.

 
Status  
Response.Status(strStatusDescSetting)
 

Specifies the HTTP status line that is returned to the client machine from the web server.

 
Parameters
strStatusDescSetting

The strStatusDescSetting is a string value containing a three-digit status code that indicates the status of the HTTP request and a short explanation of the status code.

The possible values of the strStatusDescSetting parameter are described in the current HTTP specification and fall into the following high-level categories:

The latest version of the HTTP specification can be found at http://www.w3c.org/protocols.

1xx

The 100 range is set aside for sending information-only response statuses to the client.

2xx

The 200 range is set aside for sending successful response statuses to the client.

3xx

The 300 range is set aside for redirection of the client. This status range should be used for requested pages that have been moved temporarily or permanently.

4xx

The 400 range is set aside for sending notices of client error to the client. For example, you have undoubtedly seen the 404 Not Found error status sent back to your browser when you attempt to navigate to a page that has been moved or that does not exist.

5xx

The 500 range is set aside for sending notices of server error to the client. For example, attempts to reach pages on a server that is unable to handle the request due to temporary overloading or server maintenance could result in the response status 503 Service Not Available.

 
Example
<% 
' The following code sets the Status property of the 
' Response object to 404 Not Found. Unless other content is 
' generated for the page, the status code will be 
' interpreted by itself by the client.
strStatusText = _
      "404 Not Found The Web server cannot find the "
strStatusText = strStatusText & "file or script you asked "
strStatusText = strStatusText & "for. Please check the URL "
strStatusText = strStatusText & "to ensure that the path "
strStatusText = strStatusText & "is correct."
Response.Status = strStatusText
%>
 
Notes

As with setting other Response headers, each subsequent setting of the Status property value resets the last setting.

Like other properties that result in a change to the HTTP response header values, the Status property must be set before the server sends the <HTML> tag to the client unless the response is buffered.

 
Cookies  
strKeyName = Response.Cookies.Key(3)
strKeyValue = Response.Cookies.Item(strKeyName)
 

The Cookies collection of the Response object enables your ASP application to use the Set-Cookie HTTP response header to write cookies to the client's machine. If you attempt to set the value of a cookie that does not yet exist, it is created. If it already exists, the new value you set overwrites the old value already written to the client machine.

As with the Cookies collection of the Request object, each cookie in the Cookies collection of the Response object can also represent a cookie dictionary. Recall from Chapter 7, that a cookie dictionary is a construct that is similar to an associative array in that each element of the array is identifiable by its name. For more information on cookie dictionaries, see the section on the Cookies collection of the Request object in Chapter 7.

The Cookies collection of the Response object, like other ASP collections, has the following properties:

Item

Returns the value of a specific element in the collection. To specify an item, you can use an index number or a key.

Key

Returns the name of a specific element in the Cookies collection. Just as each element's value is represented by the Item property, so each element's name is represented by its Key property.

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

strKeyName = Response.Cookies.Key(3)
strKeyValue = Response.Cookies.Item(strKeyName)

If, on the other hand, you know that the third element's key name is COLOR_PREF, you could simply use the following code to retrieve the value of that element:

strKeyValue = Response.Cookies.Item("COLOR_PREF")
Count

The Count property of the Cookies collection represents the current number of cookies in the collection.

As with other ASP collections, you can retrieve the value of any field of the Cookies 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:

Response.Cookies("UserPref") = "Red"

is an abbreviated form of:

Response.Cookies.Item("UserPref") = "Red"

To set the value of a cookie, you would use code similar to the following:

Response.Cookies("LastSearch") = _
   "SELECT * FROM Details WHERE Color = 'Red'"

For more information on the Item, Key, and Count properties of a collection, see the discussion in Section 4.2 in Chapter 4.

The previous code would create the cookie UserPref if it doesn't already exist (or overwrite the original value if it does). This cookie would translate into a SET-COOKIE response header being added to the response sent back to the client browser. The client browser would receive this response header and create (or overwrite) a UserPref cookie on the user machine.

Each element in the Cookies collection (or subkey, if the cookie is a cookie dictionary) also has the following cookie-specific attributes:

Domain

Sets the cookie so that the client sends the cookie's value only to pages in the domain set in the Domain property. The Domain property is write-only. For example, suppose we wanted to add the domain "mycorp.com" to the following LastSearch cookie. This would cause the client to send this cookie's value to the mycorp.com domain when it requests pages from it:

Response.Cookies("LastSearch").Domain = "mycorp.com"
Expires

The date on which the cookie expires and is discarded on the client machine. For example, suppose we want the cookie to expire on January 29, 2000. We could use the following code:

Response.Cookies("LastSearch").Expires = #1/29/2000#

If you do not set the Expires property value, the cookie resides on the client machine for the duration of the client's session. The cookie also will reside on the client machine only for the duration of the client's session if the date value you set for the Expires property is earlier than the current date. The Expires property is write-only.

HasKeys

As previously mentioned, a cookie in the Cookies collection also can represent a cookie dictionary. To determine whether a specific cookie has subkeys, you must use the HasKeys property of that cookie, as in the following:

blnHasKeys = Response.Cookies("Colors").HasKeys
If blnHasKeys Then
   strColor3 = Response.Cookies("Colors")("color3")
End If

The HasKeys property is read-only.

Path

The Path property represents the virtual directory on the server to which the cookie will be sent by the client browser when the client browser requests a page from within that virtual path. For example, if we want the client to send this cookie to only those scripts in the /Apps/SearchApps virtual directory, we'd use the following line of code:

Response.Cookies("LastSearch").Path = "/Apps/SearchApps"

If the cookie's Path attribute is not set, the path defaults to the path of the current ASP application. The Path property is write-only.

Secure

The Secure property allows you to specify whether the cookie is sent from the client only if the client is using the Secure Sockets Layer. For example, suppose we have stored some sensitive information in a cookie (this is not wise, but there are occasions when you might do so), and you want the user's browser to send this information only if it is using the Secure Sockets Layer. This will significantly decrease the probability that a sensitive cookie could be intercepted. You would use the following simple line of code:

Response.Cookies("SensitiveCookie").Secure = True

The Secure property takes a Boolean value. The Secure property is write-only.

 
Example

The following is a more complete example of the use of the Cookies collection of the Response object. It demonstrates many of the items discussed earlier.

<HTML>
<HEAD><TITLE>Search Cookie Example</TITLE></HEAD>
<BODY>
<H3>Welcome to the Search Results Options Page.</H3>
You can use the following form to select your search results display
options. 
These options will be saved on your machine as a set of cookies.
<FORM ACTION="/SaveSearchCookie.asp" METHOD = POST>
First Name:<INPUT TYPE = TEXT NAME = "txtFirstName"><BR>
Last Name:<INPUT TYPE = TEXT NAME = "txtLastName"><BR>
User ID:<INPUT TYPE = TEXT NAME = "txtUserId"><BR>
Check All that Apply:
Show Descriptions:
<INPUT TYPE = CHECKBOX NAME = "chkUserPrefs"VALUE = "Desc">
Show Hit Count (display how many matches found per result):
<INPUT TYPE = CHECKBOX NAME = "chkUserPrefs"VALUE = "Count">
Show Relevance with Graph:
<INPUT TYPE = CHECKBOX NAME = "chkUserPrefs" 
VALUE = "Graph">
Use Small Fonts(will show more results per page):
<INPUT TYPE = CHECKBOX NAME = "chkUserPrefs" 
VALUE = "Small">
<INPUT TYPE = SUBMIT VALUE = "Save Selections">
</FORM>
</BODY>
</HTML>

The following code (SaveSearchCookie.ASP) will retrieve the values selected in the previous form and save them to the user's machine as cookies:

<% 
' The following code retrieves user information from the 
' Form collection of the Request object (see Chapter 7) and  
' then writes the information to a set of cookies on the
' client machine.
Dim strFirstName
Dim strLastName
Dim strUserId
Dim intCounter
Dim intPrefCounter
Dim strKeyName
Dim arstrUserPrefs( )

' Retrieve user information...
strFirstName   = Request.Form("txtFirstName")
strLastName    = Request.Form("txtLastName")
strUserId      = Request.Form("txtUserId")

intPrefCounter = 1

For intCounter = 1 to Request.Form("chkUserPrefs").Count
   ReDim Preserve arstrUserPrefs(intPrefCounter)
   arstrUserPrefs(intPrefCounter - 1) = _
      Request.Form("chkUserPrefs")(intCounter)
   intPrefCounter = intPrefCounter + 1
Next

' Write the user information to the client machine.
' Save all the information in cookies, but set the
' Expires property only for the UserId. We'll want
' that to remain on the client machine after the session
' is complete.
Response.Cookies("UserFirstName") = strFirstName
Response.Cookies("UserLastName") = strLastName

For intCounter = 1 to intPrefCounter - 1
   strKeyName = "Pref" & CStr(intCounter)
   Response.Cookies("UserPrefs")(strKeyName) = _
      arstrUserPrefs(intCounter - 1)
Next

' Note in the first line below, that when no property
' is specified, the value of the cookie is set.
Response.Cookies("UserId") = strUserId
Response.Cookies("UserId").Expires = #December 31, 1999#
Response.Cookies("UserId").Domain = "www.customsearch.com"
Response.Cookies("UserId").Path = "/usersearch/"
Response.Cookies("UserId").Secure = True
%>
 
Notes

In the example, the UserFirstName cookie is sent to the client machine. For this example, let's assume the value of the strFirstName variable is the string "David." The actual HTTP response header sent to the client machine is:

Set-Cookie:USERFIRSTNAME=david

Also for this example, assume the three values sent are 800 (for client browser width), 8 (for color depth in bits), and English (for English language preference). The actual HTTP response header sent to the client is the following:

Set-Cookie:USERPREFS=PREF1=800&PREF2=8&PREF3=english

If the string value sent for a value of a cookie contains spaces, those spaces are replaced with plus signs (+) in the HTTP response header.

If you sent a subsequent cookie value to the UserPrefs cookie on the client machine without specifying a SubKey, as in the following:

Response.Cookies("UserPrefs") = "german"

the two values for PREF1 and PREF2 will be overwritten and the Count property for the UserPrefs cookie will return 1.

Alternatively, if you send a subsequent cookie value and specify a SubKey to a client machine where the cookie has a value but no keys, the value already in place on the client machine is overwritten.

If, while you are generating values for the Cookies collection of the Response object, you need to determine if there are already subkeys defined for a given cookie, you can evaluate the HasKeys property of the cookie. If the cookie has subkeys defined, the HasKeys property evaluates to True.

Like other properties that result in a change to the HTTP response header values, the Cookies collection values must be set before the server sends the <HTML> tag to the client unless the response is buffered.

 
AddHeader  
ClientCustomHeader:CustomHeaderValue
 

Allows you to add your own HTTP response header with a corresponding value. If you add an HTTP header with the same name as a previously added header, the second header will be sent in addition to the first; adding the second header does not overwrite the value of the first header with the same name. Also, once the header has been added to the HTTP response, it cannot be removed.

If the client sends the web server an HTTP header other than those listed in the section on the ServerVariables collection in Chapter 7, you can use HTTP_HeaderName to retrieve it. For example, if the client sends the HTTP header:

ClientCustomHeader:CustomHeaderValue

then you could retrieve the value for this element using the following syntax:

<%
Request.ServerVariables("HTTP_ClientCustomHeader")
%>

This is an advanced method and should not be used without careful planning. If another method of the Response object will meet your needs, use it instead of using the AddHeader method.

 
Parameters
strName

The name of the HTML header you wish to add to the response header

strValue

The initial value of the new header you are adding to the response header

 
Example
<% 
' The following code adds the CUSTOM-ERROR HTML header to 
' the HTTP response headers.
Response.AddHeader "CUSTOM-ERROR", "Your browser is not IE."
%>
 
Notes

Like the other methods and properties of the Response object that alter the HTTP response headers, you must call the AddHeader method before sending the <HTML> tag to the client. If you have previously set the Buffer property value of the Response object to True, you can use AddHeader unless you have previously called the Flush method. If you call AddHeader after sending the <HTML> tag to the client or calling the Flush method, your call to AddHeader will result in a runtime error.

You should not use underscores in your custom headers. Doing so will increase your chances of ambiguity with headers already present. Use hyphens to separate multiple words instead. Also, note that to retrieve the value of a custom header with hyphens, you replace them with underscores when retrieving the values of your custom headers.

 
AppendToLog  
Response.AppendToLog strLogEntry
 

Adds a string to the web server log entry for the current client request. You can only add up to 80 characters at a time, but you are able to call the AppendToLog method multiple times.

 
Logging web site activity

IIS allows you to log user activity into a text file or into an ODBC-compliant database. This logging is separate from Windows NT logging, and the records in the IIS log cannot be viewed using the Windows NT Event Viewer tool. To view the IIS log files, you must open them as you would any other ASCII text file, import them into a spreadsheet or database program, or, if you've been logging to an ODBC database, view them through queries to that database.

The log files for IIS are found in winnt\system32\LogFiles\W3svc1\ex[date].log. Each entry into the (IIS default) log contains time, caller IP, caller method (GET/POST), uri-stem (no server path), and resulting status.

Specifically, you can log the following aspects of users' visits to your web site, among other things:

    Date/time of user visit

    Requested pages

    IP address of user

    Length of time connected to server

Using this information and information your application adds to this log through Response.AppendToLog, you can plan future development for your site, plan security, and plan for new servers if the load warrants it.

 
Parameters
strLogEntry

The string you want added to the current client request's entry in the web server. This string can be up to 80 characters in length. Note that the string you append to the web server log entry cannot contain commas, since the fields in the IIS web log entries are comma delimited.

 
Example
<%
' Assume you have constructed one string containing all that 
' you'd like logged to the web's server. This string is 
' declared as strOrigLogContent. The following Do...While 
' loop code will loop through your content and log it to the
' web server 79 characters at a time.
Do While Len(strOrigLogContent) > 0 
   If Len(strOrigLogContent) >= 79 Then
      strLogString = Left(strOrigLogContent, 79)
   Else
      strLogString = strOrigLogContent
   End If
   
   ' Log the content.
   Response.AppendToLog strLogString 

   If Len(strOrigLogContent) > Len(strLogString) Then
      strOrigLogContent = _
         Right(strOrigLogContent, _
         Len(strOrigLogContent) - Len(strLogString))
   Else
      strOrigLogContent = "
   End If
Loop
%>
 
Notes

Before you are able to append information to the web server log in IIS, you must enable the URL Query option of the Extended Logging Properties sheet for the web site whose activity the log files are being used to record.

This method can be an invaluable time saver in maintaining detailed information about actions on your web site. If you have a unique identifier for each user that is stored in the log file with the entry (which contains an IP address, possibly a Windows NT account name, and the date and time of the visit), you can quickly determine who was visiting the site at the time of an unexpected error on your site. This method cannot be relied on for security, since you cannot be 100% certain of the user's identity, but it can help.

 
BinaryWrite  
Request.BinaryWrite arbyteData
 

Writes information directly to the response content without any character conversion. If your application involves writing binary data to the client, you must use this method to ensure that data you send is not converted to character data from the original binary.

 
Parameters
arbyteData

An array of bytes you wish to write to the response content

 
Example

The following example code is lengthy for the simple call to BinaryWrite, but it demonstrates a very useful concept, especially if you are forced to deal with binary data from a database.

<% 

' The following code retrieves a binary object
' (in this case a JPG image) and writes it to the
' client using BinaryWrite. (For more information
' on ActiveX Data Objects usage, see Chapter 12.)

' Create an ADO connection object.
Set adoCon = Server.CreateObject("ADODB.Connection")

' Use the Open method of the Connection object
' to open an ODBC connection with the database
' represented by the DSN ImageDatabase.
adoCon.Open "ImageDatabase"

' Use the Execute method of the ADO Connection object
' to retrieve the binary data field from the database.
Set adoRecImgData = adoCon.Execute _
   ("SELECT ImageData FROM Images WHERE ImageId = 1234")

' Create a Field object by setting one equal to a
' specific field in the recordset created previously.
Set adoFldImage = adoRecImgData("ImageData")

' Use the ActualSize property of Field object to retrieve
' the size of the data contained in the Field object. After
' this line you will know how many bytes of data reside in
' the Field object.
lngFieldDataLength = adoFldImage.ActualSize

' Use the BinaryWrite method to write 4K bytes of binary
' data at a time. So, first we need to determine how many
' 4K blocks the data in the Field object represents.
lngBlockCount = lngFieldDataLength / 4096

' Now let's get how many bytes are left over after removing
' lngBlockCount number of bytes.
lngRemainingData = lngFieldDataLength Mod 4096

' We now must set the HTTP content type Response header
' so that the browser will recognize the data being sent
' as being JPEG image data.
Response.ContentType = "image/JPEG"

' Loop through and write the first lngBlockCount number
' of binary blocks of data.
For intCounter = 1 to lngBlockCount
   Response.BinaryWrite adoFldImage.GetChunk(4096)
Next

' Now write the last remainder of the binary data.
Response.BinaryWrite adoFldImage.GetChunk(lngRemainingData)

' Close the recordset.
adoRecImgData.Close
%>
 
Notes

At first, the BinaryWrite method seems to be of limited use, until you have binary data stored in a database that must be sent to the client; then, BinaryWrite is invaluable. As the code sample demonstrates, one example of this is the display of image data that is stored and retrieved from a DBMS capable of storing binary data.

I have used this method to display JPEG images stored in a Microsoft SQL Server database (using code similar to the preceding), and it works quite well. Because you are sending the HTTP response containing only the image data (not a link request to the image), it may even be faster than sending images to the client upon a straight client request, assuming your database access is suitably fast.

 
Clear  
Response.Clear
 

Empties the current contents of the Response buffer. It does so without sending any of the buffered response to the client.

 
Parameters

None

 
Example
<% Response.Buffer = True%>
<HTML>
<HEAD><TITLE>Response Clear Method Example</TITLE></HEAD>
<BODY>
<%
On Error Resume Next

[CODE TO DO SOME CALCULATIONS]
lngFormulaElement1 = 47
lngFormulaElement2 = lngFormulaElement1 - 47
lngFormulaElement3 = 23

' This next line results in a division-by-zero error 
' (Error Number 11).
lngNewCalcTotal = lngFormulaElement3 / lngFormulaElement2

' This next line will still be processed because we used
' ON ERROR RESUME NEXT.
If Err <> 0 Then
   ' The following code clears the Response buffer, writes 
   ' an error message, and ends the response, forcing IIS to 
   ' send the response to the client. Note that the Buffer 
   ' property has to be set to True for the following code
   ' to work properly.
   Response.Clear
   Response.Write "Your request resulted in the error: " & _
      Err.Description
   Response.Write " Error Number: " & Err.Number
   Response.Write "<BR>Call your web admin at 555-HELP for "
   Response.Write "more information."
   Response.End
End If
%>
. . . [additional code]
 
Notes

The Clear method of the Response object does not clear any HTTP headers, only the content. As noted in the example, the Buffer property of the Response object must be set to True or the use of this method will result in a runtime error.

One of the most important uses for the Clear method is to clear the buffer and send to the client browser something else instead, often error information, as is the case with the example.

For errors to be caught and error information to be sent to the client in this fashion, not only must the Buffer property be set to True, but also you must use the following line of code to ensure that your error trap will be processed:

On Error Resume Next
 
End  
Response.End
 

Ends all storage of information in the response buffer and sends the current contents of the buffer immediately to the client. Any code present after the call to the End method is not processed. Any memory set aside by the script up until the call to End (such as database objects previously used in the script) is released.

 
Parameters

None

 
Example

See the previous example for the Clear method.

 
Notes

If the Buffer property is set to True, calling the End method will flush the Response buffer exactly as if you had called the Flush method (see the next section). However, unlike calling the Flush method, no code after the call to End is processed by the web server.

 
Flush  
Response.Flush
 

Immediately sends all data currently in the response buffer to the client. Unless the Buffer property of the Response object is set to True, this method will result in a runtime error. This method allows you to send various portions of the response to the client at your discretion.

 
Parameters

None

 
Example
<% Response.Buffer = True%>
<HTML>
<HEAD><TITLE>Response Flush Method Example</TITLE></HEAD>
<BODY>
<%
' Suppose for this example that this first part of the
' script retrieves some information from a database and
' that retrieval takes a long time, say 30 seconds.
' (Don't worry about the details of the ActiveX Data Object
' calls. They are covered later in the book and serve only
' as an example here of something that might take a long time.)
Set adoCon = Server.CreateObject("ADODB.Connection")
adoCon.Open MyDatabase
Set adoRec = adoCon.Execute([BIG SQL STATEMENT])

' Rather than continue to the second part of the script, in
' which a second slow SQL statement (say another 15 seconds)
' executes, first we'll use the Flush method to force the
' first part of the script results to the client. This way,
' the user can be looking at the results of the first query 
' while waiting for the second.
Response.Flush

' [Second LONG SQL statement.]
Set adoRec2 = adoCon.Execute([BIG SQL STATEMENT])
%>
</BODY></HTML>
 
Notes

Using the buffering capacity of the Response object, you are able to send the response to the client in parts. For example, suppose you are presenting a description of your worldwide organization followed by a list of offices derived from information in a database. The organization description is straight text, and thus it takes very little time to prepare and send it to the client. The second part takes more time. You could use the Flush method of the Response object to send the organizational description to the client first and then send the list when it is complete. Without this approach, the user can get the impression that the page is slow to download.

One caution, however: if you use the Flush method on an Active Server Page, the server will ignore Keep-Alive requests sent by the client for that page. This will force a new connection to be made for each piece of information sent to the client.

 
Redirect  
Response.Redirect strURL
 

Redirects the client's request to another URL.

 
Parameters
strURL

The Universal Resource Locator string for the new location to which you wish to redirect the client

 
Example
<% 
' The following code determines whether the client has
' security clearance for a certain page. If not, it 
' is redirected to another URL.
[...Code to determine user's clearance for the current page...]

If Not(strUserSecurity = "ADMIN" or strUserSecurity = "SUPERADMIN") Then
   Response.Redirect "/security/noclearance.asp?usrid=09563"
End If
%>
 
Notes

The strURL value you use when calling the Redirect method can be an exact URL with DNS or a virtual directory and filename. It also can be the name of a file that resides in the same folder as the requested page.

If your script has written any content to the HTTP response body, that content is ignored by the script once the call to the Redirect method is executed.

Calling the Redirect method is conceptually the same as setting the Status property to "302 Object Moved" and sending the user to a new location using the Location HTTP header.

Note that upon redirection, some older (HTTP 1.0) client browsers will mistakenly change POST requests to GET requests when the new URL is called. This is an important consideration when the client's POSTed information contains more data than the GET method can handle. It is assumed that new browsers supporting the HTTP 1.1 protocol have fixed this problem.

If your ASP file is running under IIS 5.0, you should consider using the Server method Execute or Transfer. Neither of these methods involve the costly trip to the client and back to the server that Redirect requires.

 
Write  
Response.Write vntData
 

Writes information directly to the HTTP response body.

 
Parameters
vntData

The information to be inserted into the HTML text stream that will be received by the client browser. This includes text, HTML tags, client-side script, and so on. The data variables in the ASP script itself are of the data type variant. The value cannot contain the %> character sequence; the web server will interpret it as the end of your active server script. If your script requires this character sequence, use the escape sequence %\> instead.

 
Example
<% 
strDirCommand = "Dir /w"

' The following code writes an entire HTML table to the HTTP
' response body.
Response.Write "<TABLE>"
Response.Write "<TR>"
Response.Write "<TD WIDTH = 50%\>"
Response.Write "Command"
Response.Write "</TD>"
Response.Write "<TD WIDTH = 50%\>"
Response.Write "Description"
Response.Write "</TD>"
Response.Write "</TR>"
Response.Write "<TR>"
Response.Write "<TD WIDTH = 50%\>"
Response.Write Chr(34) & strDirCommand & Chr(34)
Response.Write "</TD>"
Response.Write "<TD WIDTH = 50%\>"
Response.Write "This allows you to see a list of the "
Response.Write "files in <BR> your current folder."
Response.Write "</TD>"
Response.Write "</TR>"
Response.Write "</TABLE>"
%>
 
Notes

As demonstrated in the example program, you can use the Write method to write HTML and client-side script to the response body that the client browser will interpret as plain HTML.

To send a carriage return/line feed or a quotation mark, use the Chr function, as demonstrated the following code:

' Note:  Chr(34) is a quotation mark. Chr(13) & Chr(10) is 
' the equivalent of a carriage return, followed by a 
' linefeed.
Response.Write "Hamlet said, " & Chr(34) & _
   "To be, or not to be." & Chr(34) & Chr(13) & Chr(10)

Finally, you can use the Write method to send the value of a server-side script to the client browser. This method is sometimes cleaner in your code than going back and forth between server-side code and client code using the <%=...%> notation. For example, the following code displays the value of the strHighestPrice data value using both the <%=...%> and the Response.Write methods: %>

<%
Response.Write "The highest price is " & strHighestPrice
Response.Write ".<BR>"

' The same line as the preceding using the other format:
%>
The highest price is <%=strhighestPrice%>.<BR>