Active Server Pages: "Talking Back" With the Response Object

Objects are an integral part of the Active Server Pages environment. As we discussed, you can either extend ASP with your own objects, or you can use intrinsic objects provided by the ASP runtime environment.

In our last episode, we explored some of the features of the Request object, an intrinsic object providing an encapsulation of the data made available in the HTTP Request header, and learned how to access that information using several of its exposed collections. We also discussed how elements of this object, such as the Form and QueryString collections, allowed information to be passed, via form submission, from an HTML document to an ASP script on the server, giving us the capability to perform fundamental data processing operations such as input data collection and validation.

This article is the first of several that will focus on managing the stream of data sent to the client browser using methods and collections of the Response object.

HTTP Responses

In its simplest form, the Response object provides a high-level abstraction of the HTTP Response message. Like the Request, the Response object contains publicly exposed properties in the form of collections that are readable and writable at runtime. However, unlike the Request, the Response object provides a number of methods, or functions, that make up much of the machinery for constructing and modifying aspects of the HTTP Response message.

Per The Spec

An HTTP Response is basically a message sent from the server to a client browser that contains information regarding, and in response to, an earlier HTTP Request message. Per its definition in the HTTP 1.1 specification, it consists of a status line, followed by one of three types of headers, a carriage-return/line-feed pair, followed by the body of the message, sometimes known as its payload. This, in effect, is how all data, in one way, form, or fashion returns to the client browser after a request is made.

Why All The Details?

You may be wondering why such an intense investigation of this protocol and how it relates to Active Server Pages is necessary and why it matters to your everyday application development. Those were my sentiments exactly until I began to understand some of the powerful programming features it possessed. After some investigation, it became clear how the proper use of this specification, through some of the built-in features of ASP, can help you create robust, extensible web applications that exist and operate on the most pervasive and efficient distributed computing platform of our time.

Piecing It Together

What all of this means is that through the use of the Response object, you have a great deal of control over how messages are pieced together and sent back to the requesting client browser. This control is achieved through several properties and methods that deal explicitly with modifying aspects of the status line, the header and the message body.

These properties and methods are as follows:

Property/Method Description
ContentType Specifies the HTTP content type for the response. Modifies the HTTP General header "Content-Type" to contain the value of this property.   If no ContentType is specified, the default is “text/HTML”.
Expires/ExpiresAbsolute Specifies the length of time before a page cached on a browser expires. If the user returns to the same page before it expires, the cached version is displayed.
Status Specifies the value of the status line returned by the server.  Refers to the status that will appear as the HTTP status-line indicating information about the current response.
AddHeader Adds an HTML header with a specified value. This method always adds a new HTTP header to the response and does not overwrite an existing one.
Write Writes a specified string to the current HTTP output.  Inserts this information into the HTTP entity body.
BinaryWrite Writes the specified information to the current HTTP output without any character conversion. This method is useful for writing nonstring information such as binary data required by a custom application.
Cookies Sets the value and scope of one or more cookies. If the specified cookie does not exist, it is created. Used to add "Set-Cookie" headers to the current Response.
Redirect Causes the browser to attempt to connect to a different URL by placing a "Redirect" header in the Reponse containing a URL to which the browser should redirect to.

The Response object supports several additional methods and properties not specifically related to header management which we will cover in a later installment.

Writing Information To The Output Stream

Using everything we've talked about to date, you can see how a reasonably sophisticated application can be developed. First, we could use some of the standard mechanisms of HTML forms and form submission to gather input, just as we would with any standard client/server application. Upon submission of that data to an ASP script residing on the server, we could use various aspects of the Request Object to extract field data from the request message and perform logical operations using either VBScript, JScript or another scripting language implementation to decide how we will respond.

Given the above example, one potential application could involve soliciting a string containing a SQL statement from the client, making the request of the database and then writing some tabular results to the browser using the Write method of the Response object.

The Write Method

The Write method writes a specified string to the current HTTP output. The string passed to the Write method will be written to the HTTP Response message body. Its syntax is as follows:

Response.Write variant

In the above example, the variant argument can be any data type supported by the Visual Basic® Scripting Edition VARIANT data type, including characters, strings, and integers. However, if you 're using a static string such as "ABC", remember that VBScript limits static strings to 1022 characters and better results will be achieved if a variable is used instead. For example, the following code will write a string consisting of the repeating character 'a' that is 4096 characters in length:

<%
AString = String(4096, "a")
Response.Write(AString)
%>

There are obviously many uses for the Write method. Consider the fundamental need to generate HTML in the HTTP output stream. The following example uses VBScript to generate an error page in response to a hypothetical logon error that is detected when the Session variable 'UserName' is found to be uninitialized:

<%
If Session("UserName") = "" Then
Response.Write("<h1>You Need to Log On!</h1>")
End If
%>

The BinaryWrite Method

This method writes the specified information to the current HTTP output without any character conversion making it possible to write nonstring information such as binary data.   The syntax for BinaryWrite is as follows:

Response.BinaryWrite data

While generating textual information possibly covers the majority of situations in which we may need to generate HTML, there may be a time when we need to send binary information back to the client.  For instance, you may want to generate an image on the server containing, for example, the results of an SQL query presented as a bar or column chart.  You may want to send binary data to the browser in the form of an Excel spreadsheet or a Word document that opens inside the browser via the use of a predefined MIME type instead of providing an explicit hyperlink to the document.

BinaryWrite can also be used from within a server-based COM component that has access to the ScriptingContext interface passed to the page level events, OnStartPage and OnEndPage, in your ASP script. We'll see more of these techniques in a later article based on utilizing BinaryWrite in conjunction with predefined MIME types in your browser.

Modifying Aspects of the Page

It's often useful to be able to tweak certain internal aspects of the HTTP response message.  Although this sounds complex, the ASP environment provides us with properties and methods that let us determine how the information in the main body of the page is translated by the browser.

In a nutshell, these properties and methods let us modify the HTTP message headers.  Each header in HTTP has a unique number, also known as the status code which is contained on the HTTP status line.

The complete list of all possible headers is outside of the scope of this article, however, for those of you looking for additional bedtime reading material, they can be found in the HTTP 1.1 specification at www.w3.org/pub/www/protocols/rfc2068/rfc2068.txt.

Explicitly and Implicitly Working With Headers

There are several ways to add new headers to and HTTP response.  You may choose to explicitly add a header, either an existing header listed in the specification or one that you've dreamed up yourself, or you may implicitly set a header by utilizing some of the specific properties and methods of the Repsonse object.

The AddHeader Method

This method adds an HTML header to the current output stream with a specified value.   The syntax of this method is as follows:

<% Response.AddHeader name, value %>

Where name is the identifier for the header you wish to add, and value is the textual information you wish to include in the header.  An example would be the following request to set a user-defined header named "WARNING" with the value of some message:

<% Response.AddHeader "WARNING", "Error Message" %>

Remember that this method always adds a new HTTP header to the response. It will not replace an existing header of the same name. Once a header has been added, it cannot be removed largely due to the face that it has already been committed to the HTTP stream and has been written to the browser.

Using Other Properties and Methods

There are other ways to modify header information in the HTTP response.   Fortunately, there are several properties that when set, will change some of the more standard header information.  Let's take a look a several of them:

ContentType

This property specifies the HTTP content type for the response, in effect, setting the HTTP header Content-Type to the valued specified as its argument. Obviously, the most popular content type might be “text/HTML”, which is the default if none is specified.  The syntax of the ContentType property is as follows:

<% Response.ContentType [= ContentType ]%>

HTTP uses Internet Media Types in the Content-Type  header field in order to provide open and extensible data typing and type negotiation.  This gives the creator of the Response flexibility in providing new types of Responses instead of simply text and HTML.

This string identifying  the ContentType is usually formatted, type/subtype where type is the general content category and subtype is the specific content type.  Usually for a full list of these media types, go to your Windows NT Explorer Options and browse the file types.

An example of using this property is as follows:

<% Response.ContentType = "text/plain" %>

The following examples set the ContentType property to other common values.

<% Response.ContentType = "text/HTML" %>
<% Response.ContentType = "image/GIF" %>
<% Response.ContentType = "image/JPEG" %>
 

Expires and ExpiresAbsolute

An interesting feature of most browsers is that they cache pages locally on your machine, up to some predefined threshold amount, after they are loaded.  A side-effect of this feature is that page-to-page movement in your web application may behave unpredictably because frequently modified pages that you send to the browser may be loaded from the cache instead.

There are two properties that can be used to prevent this phenomenon and give you more control over when this page is either loaded from the cache or requested from the server, Expires and ExpiresAbsolute.

Try the following, if you want the page to expire in 100 minutes:

Response.Expires = 100

or, if for some reason you would like the page to expire after my wife's birthday (she thinks I forget) for example, use the ExpiresAbsolute property to specify the date and time of expiry as follows:

Response.ExpiresAbsolute = #7/30/98 00:00:00#

Your Mission If You Choose to Accept It

Your programming assignment for next week, if you choose to accept it, will be to explore the properties and methods of the Response object.  Modify values for properties such as Expires and ExpiresAbsolute and see the effect of the caching that takes place in your browser.  If you have a utility, such as NetMon, that comes with Microsoft's Systems Management Server, and you are reasonably well versed with the art of packet sniffing, you can see the actual HTTP packets that go from client to server.   Check out the header information as you make changes with the Response object and notice how various settings change in the protocol when their corresponding property is changed in the Response object.

** ASP TIP OF THE WEEK **

When writing VBScript, take advantage of a well know module-level VB setting: Option Explicit.   Even for the best VBScript developers, this setting will help you with undeclared variable references in your code.  To take advantage of this setting, place the following line of script at the top of your Active Server Page:

<% Option Explicit %>

Then, try to use variables without a corresponding Dim statement.  You'll see that an error will occur in your script until you officially Dim the variable prior to its usage.

Why is this helpful?  For those of you new to the BASIC language, a  feature provided for you by the language called implicit variable declaration can have some interesting side effects. What this means is that if, when writing code, you specify a variable not yet declared, it is declared on your behalf by the BASIC runtime and set to an initial value.  Notice in the following example how this could effect your code:

Public Sub CalculateGross()
  HoursWorked = 40
  HourlyRate = 25
  GrossWages = HourlyRate * HourWorked
  Response.Write "Wages:" & GrossWages & "<BR>"
End Sub

Will the result be zero or 1000?  If you look close, and you assume that all variables are local to this subroutine, you'll see that HoursWorked is misspelled as HourWorked, producing the unfortunate side effect of initializing a new local variable, HourWorked, to zero in this calculation.

Summary

For the most part, we've begun our discussion of the Response object and found that there's more to just generating HTML on the server.  We can control many aspects of how the actual message we generate is interpreted by the browser by looking inside the HTTP headers and changing a phrase here or there.

Next week we'll dig even deeper with an example of a good use of the Content-Type header and how we can combine that with a server based component to dispense binary data, such as a Word document,  in response to a browser request.

As always, I appreciate having you along as my guest and would be even more appreciative of any feedback you may have.  See you next time!

Author: Keith Cox
Date: 02/09/98

More articles about Active Server Pages
More articles by Keith Cox
Author Biography

body>