In ASP.NET, the HTTP response information is encapsulated in the HttpResponse
class. An instance of the class is created when the HTTP pipeline is
set up to serve the request. The instance is then linked to the HttpContext object associated with the request and exposed via the Response property. The HttpResponse
class defines methods and properties to manipulate the text that will
be sent to the browser. Although user-defined ASP.NET code never needs
to use the HttpResponse constructor, looking at it is still useful to get the gist of the class:
public HttpResponse(TextWriter writer);
As you can see, the
constructor takes a writer object, which will then be used to accumulate
the response text. All calls made to Response.Write (and similar output methods) are resolved in terms of internal calls to the specified writer object.
Properties of the HttpResponse Class
All properties of the class are grouped and described in Table 1.
You set a few of these properties to configure key fields on the HTTP
response packet, such as content type, character set, page expiration,
and status code.
Table 1. HttpResponse Properties
Property | Description |
---|
Buffer | Indicates
whether the response text should be buffered and sent only at the end
of the request. This property is deprecated and provided only for
backward compatibility with classic ASP. ASP.NET applications should
instead use BufferOutput. |
BufferOutput | Gets or sets a Boolean value that indicates whether response buffering is enabled. The default is true. |
Cache | Gets the caching policy set for the page. The caching policy is an HttpCachePolicy object that can be used to set the cache-specific HTTP headers for the current response. |
CacheControl | Sets the Cache-Control HTTP header. Acceptable values are Public, Private, or No-Cache. The property is deprecated in favor of Cache. |
Charset | Gets or sets a string for the HTTP character set of the output stream. If set to null, it suppresses the Content-Type header. |
ContentEncoding | Gets or sets an object of type Encoding for the character encoding of the output stream. |
ContentType | Gets
or sets the string that represents the Multipurpose Internet Mail
Extensions (MIME) type of the output stream. The default value is text/html. |
Cookies | Gets a collection (HttpCookieCollection) object that contains instances of the HttpCookie class generated on the server. All the cookies in the collection will be transmitted to the client through the set-cookie HTTP header. |
Expires | Gets
or sets the number of minutes before a page cached on a browser
expires. Provided for compatibility with ASP, the property is deprecated
in favor of Cache. |
ExpiresAbsolute | Gets
or sets the absolute date and time at which the page expires in the
browser cache. Provided for compatibility with ASP, the property is
deprecated in favor of Cache. |
Filter | Gets or sets a filter Stream object through which all HTTP output is directed. |
IsClientConnected | Indicates whether the client is still connected. |
IsRequestBeingRedirected | Indicates whether the request is being redirected. Not available in ASP.NET 1.x. |
Output | Gets the writer object used to send text out. |
OutputStream | Gets the Stream object used to output binary data to the response stream. |
RedirectLocation | Gets or a sets a string for the value of the Location header. |
Status | Sets
the string returned to the client describing the status of the
response. Provided for compatibility with ASP, the property is
deprecated in favor of StatusDescription. |
StatusCode | Gets or sets an integer value for the HTTP status code of the output returned to the client. The default value is 200. |
StatusDescription | Gets
or sets the HTTP status string, which is a description of the overall
status of the response returned to the client. The default value is OK. |
SuppressContent | Gets or sets a Boolean value that indicates whether HTTP content should be sent to the client. This is set to false by default; if it is set to true, only headers are sent. |
As you can see, a few of the HttpResponse properties are provided only for backward compatibility with classic ASP. In some cases (for example, BufferOutput),
the property has just been renamed; in other cases, the deprecated
properties have been replaced by a more general and powerful APIs. This
is certainly the case for cache and expiration properties.
Setting the Response Cache Policy
The response object has
three properties dedicated to controlling the ability of the page being
sent to the browser to be cached. The Expires and ExpiresAbsolute
properties define relative and absolute times at which the page cached
on the client expires and is no longer used by the browser to serve a
user request. In fact, if the user navigates to a currently cached page,
the cached version is displayed and no roundtrip occurs to the server. A
third property somehow related to page caching is CacheControl. The property sets a particular HTTP header—the Cache-Control header. The Cache-Control
header controls how a document is to be cached across the network.
These properties represent the old-fashioned programming style and exist
mostly for compatibility with classic ASP applications.
In ASP.NET, all caching capabilities are grouped in the HttpCachePolicy
class. With regard to page caching, the class has a double role. It
provides methods for both setting cache-specific HTTP headers and
controlling the ASP.NET page output cache.
To set the visibility of a page in a client cache, use the SetCacheability method of the HttpCachePolicy class. To set an expiration time, use the SetExpires method, which takes for input an absolute DateTime object. Finally, to set a lifetime for the cached page, pass to SetExpires the current time plus the desired interval.
Note
In
the case of conflicting cache policies, ASP.NET maintains the most
restrictive settings. For example, if a page contains two controls that
set the Cache-Control header to public and private, the most restrictive policy will be used. In this case, Cache-Control: Private is what will be sent to the client. |
Setting an Output Filter
In ASP.NET, a new component makes its debut—the response filter. A response filter is a Stream-derived object associated with the HttpResponse object. It monitors and filters any output being generated by the page. If you set the Filter property with the instance of a class derived from Stream, all output being written to the underlying HTTP writer first passes through your output filter.
The custom filter, if any, is invoked during the HttpResponse’s Flush
method before the actual text is flushed to the client. An output
filter is useful for applying the final touches to the markup, and it is
sometimes used to compact or fix the markup generated by controls.
Building
a response filter is a matter of creating a new stream class and
overriding some of the methods. The class should have a constructor that
accepts a Stream
object. In light of this, a response filter class is more a wrapper
stream class than a purely inherited stream class. If you simply try to
set Response.Filter with a new instance of, say, MemoryStream or FileStream, an exception is thrown.
The following listing
shows how to create a stream class that works as a response filter. For
simplicity, the class inherits from MemoryStream. You might want to make it inherit from Stream, but in this case you need to override (because they are abstract) a number of methods, such as CanRead, CanWrite, CanSeek, and Read. The class converts lowercase characters to uppercase ones.
public class MyFilterStream : MemoryStream
{
private Stream m_Stream;
public MyFilterStream(Stream filterStream)
{
m_Stream = filterStream;
}
// The Write method actually does the filtering
public override void Write(byte[] buffer, int offset, int count)
{
// Grab the output as a string
string buf = UTF8Encoding.UTF8.GetString(buffer, offset, count);
// Apply some changes
// Change lowercase chars to uppercase
buf = buf.ToUpper();
// Write the resulting string back to the response stream
byte[] data = UTF8Encoding.UTF8.GetBytes(buf.ToString());
m_Stream.Write(data, 0, data.Length);
}
}
Use the following code to associate this output filter with the Response.Filter property. Here’s a sample page:
void Page_Load(object sender, EventArgs e)
{
Response.Filter = new MyFilterStream(Response.Filter);
}
Figure 1 shows a page that uses the sample filter.
Response
filters provide an interesting opportunity for developers to build more
powerful applications, but I caution you to be careful when considering
this option. As the sample demonstrates, changing the case of the
entire output is not a smart move. If done without care, the change ends
up affecting the view state and the internal script code, both of which
consist of case-sensitive text, seriously compromising the
functionality of the page. Second, filters must be activated on a
per-page basis. If you need to filter all the pages in a Web site,
you’re better off writing an HTTP module.
Methods of the HttpResponse Class
Table 2 lists all the methods defined on the HttpResponse class.
Table 2. HttpResponse Methods
Method | Description |
---|
AddCacheDependency | Adds
an array of cache dependencies to make the cached page output invalid
if any dependency gets broken. In the array, you can have any class that
inherits from CacheDependency. Not available in ASP.NET 1.x. |
AddCacheItemDependencies | Adds an array of strings representing names of items in the ASP.NET Cache. When any of the specified items vary, the cached page output becomes invalid. |
AddCacheItemDependency | Description is the same as for the previous item, except that AddCacheItemDependency adds a single cache item name. |
AddFileDependencies | Adds
a group of file names to the collection of file names on which the
current page is dependent. When any of the files are modified, the
cached output of the current page is deemed invalid. |
AddFileDependency | Adds
a single file name to the collection of file names on which the current
page is dependent. If the file is modified, the cached output of the
current page becomes invalid. |
AddHeader | Adds
an HTTP header to the output stream. It is provided for compatibility
with previous versions of ASP. In ASP.NET, you should use AppendHeader. |
AppendCookie | Adds an HTTP cookie to the cookie collection. |
AppendHeader | Adds an HTTP header to the output stream. |
AppendToLog | Adds custom log information to the IIS log file. |
ApplyAppPathModifier | Adds
a session ID to the specified virtual path, and returns the result. It
is mostly used with cookieless sessions to construct absolute HREFs for hyperlinks. |
BinaryWrite | Writes
binary characters to the HTTP output stream. It is subject to failures
with very large files. |
Clear | Clears all content output from the buffer stream. |
ClearContent | Calls into Clear. |
ClearHeaders | Clears all headers from the buffer stream. |
Close | Closes the socket connection with the client. |
End | Sends all buffered text to the client, stops execution, and raises the end event for the request. |
Flush | Sends all currently buffered output to the client. |
Pics | Appends a PICS-Label HTTP header to the output. PICS stands for Platform for Internet Content Selection
and is a World Wide Web Consortium (W3C) standard for rating pages. Any
string is acceptable as long as it doesn’t exceed 255 characters. |
Redirect | Redirects a client to a new URL. Needs a roundtrip. |
RemoveOutputCacheItem | A static method that takes a file system path and removes from the cache all cached items associated with the specified path. |
SetCookie | Updates an existing cookie in the cookie collection. |
TransmitFile | Just like BinaryWrite and WriteFile, it writes the specified file directly to the output stream. You can safely use TransmitFile regardless of the size of the file that you want to transmit. Available in ASP.NET 1.x through the Service Pack 1. |
Write | Writes
content to the underlying output stream. The method can write a string,
a single character, or an array of characters, as well as an object. In
this case, though, what gets written is the output of the object’s ToString method. |
WriteFile | Writes
the specified file (or a portion of it) directly to the output stream.
The file can be identified with its path or a Win32 handle (an IntPtr object). It is subject to failures with very large files.
|
WriteSubstitution | Allows fragments of a page to be substituted and sent to the output cache. Not available in ASP.NET 1.x. |
Output Caching Features
The HttpResponse class has several methods to make the page response it represents dependent on files or cache item changes. The methods AddFileDependency and AddCacheItemDependency
(and their versions that handle multiple dependencies) make the page
response invalid when the specified file(s) or cached item(s) are
modified.
Starting with ASP.NET 2.0 the new method AddCacheDependency
completes the offering, as it gives you the possibility to make the
page response dependent on any dependency object available to your
application, including custom dependency objects.
Large File Transmission
As you can see, there are three methods for writing potentially large chunks of data down to the output stream—BinaryWrite, WriteFile, and TransmitFile. The TransmitFile
method was introduced years ago through a hot-fix package for ASP.NET
1.x, as documented in Microsoft KnowledgeBase article KB823409. It was
later incorporated in the .NET Framework 1.x SP1 and newer versions of
ASP.NET. In summary, TransmitFile is the most stable and reliable of the three methods, although you won’t notice any significant difference for most files.
Both the WriteFile and BinaryWrite
methods seem perfect for streaming binary data down to the client.
However, both can put the Web server memory under pressure if called to
work on very large files. Why? It’s because both methods load the entire
data block (the contents of the file or the byte array) into the Web
server’s memory. For large files, this can cause severe problems that
can culminate in the recycling of the ASP.NET process. The TransmitFile
method is designed to elegantly work around the problem. It sends
output directly from a file to the ASP.NET ISAPI extension and then down
to the client, without passing a humongous string to the ISAPI
extension.
Note
Although TransmitFile
makes large file downloads more stable than ever and fixes the problem
of recycling, it is far from being a full solution to the problem of
tracking and resuming large file downloads. For example, if a download
fails, for whatever reason, TransmitFile
can start it again only from the beginning. |