Logo: TechTrax...brought to you by MouseTrax Computing Solutions

Everything You Need to Know About Response.Redirect

by Adrian Forbes, MVP
Skill rating level 10.

Basics of Response.Redirect

When you request a page from a web server, the response you get has some headers at the top, followed by the body of the page. When viewed in your browser the headers are never seen, but are used by the browser application. I have the following page called test.asp

<%@ Language=VBScript %>
 <HTML>
 <HEAD>
 <META NAME="GENERATOR" Content="Microsoft Visual Studio 6.0">
 </HEAD>
 <BODY>
 
   <p>Hello</p>
 
 </BODY>
 </HTML> 

When I request that from the web server this is the reply I get;

HTTP/1.1 200 OK
 Server: Microsoft-IIS/5.0
 			Date: Mon, 19 Mar 2001 15:07:44 GMT
 Connection: close
 Content-Length: 134
 Content-Type: text/html
 Set-Cookie: ASPSESSIONIDQQGQQJWO=OMCJFABDNCDLLBKAPNHJBKHD; path=/
 Cache-control: private
 
 
 <HTML>
 <HEAD>
 <META NAME="GENERATOR" Content="Microsoft Visual Studio 6.0">
 </HEAD>
 <BODY>
 
 
 <p>Hello</p> 
 
 </BODY>
 </HTML>
 

The first line returns the status of the response, in this case "200 OK" which means everything is fine. The following lines are headers, these are in the format of

 Name: Content 

So in our example the web server is identifying itself as Microsoft-IIS/5.0, it also sends its date and time, the content type and it also instructs the browser to store a cookie. This cookie contains your session ID and is used by IIS to remember who you are. After the headers there is a blank line then the actual HTML to be shown in the browser.

If I request a page that does not exist then we get this back;

HTTP/1.1 404 Object Not Found
 Server: Microsoft-IIS/5.0
 			Date: Mon, 19 Mar 2001 15:11:54 GMT
 Connection: close
 Content-Type: text/html
 Content-Length: 3243
 
 
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
 <html dir=ltr>
 
 <head>
 <style>
 a:link   {font:8pt/11pt verdana; color:FF0000}
 a:visited  {font:8pt/11pt verdana; color:#4e4e4e}
 </style>
 
 <META NAME="ROBOTS" CONTENT="NOINDEX">
 
 <title>The page cannot be found</title>
 ... 

As you can see, the status is now "404 Object Not Found" and the HTML is generated for us by the web server. So the web server uses different response status types to inform the browser the nature of the response itself. Let's modify our test.asp code to read this;

<%@ Language=VBScript %>
 <%
 response.redirect "test2.asp"
 %>
 <HTML>
 <HEAD>
 <META NAME="GENERATOR" Content="Microsoft Visual Studio 6.0">
 </HEAD>
 <BODY>
 
 <p>Hello</p>
 
 </BODY>
 </HTML>
 

Note the code at the top of the page that does a "response.redirect". If we request this page we get the following;

HTTP/1.1 302 Object moved
 Server: Microsoft-IIS/5.0
 Date: Mon, 19 Mar 2001 15:16:35 GMT
 Connection: close
 Location: test2.asp
 Content-Length: 130
 Content-Type: text/html
 Set-Cookie: ASPSESSIONIDQQGQQJWO=ANCJFABDFLBLHMKIJOIOKJDM; path=/
 Cache-control: private
 
 <head><title>Object moved</title></head>
 <body><h1>Object Moved</h1>
   This object may be found <a HREF="test2.asp">here</a>.
 </body>
 

The status is "302 Object moved" and note that the actual HTML following the Response.Redirect is not sent to the client. After all, if the page is going to be redirected why send any content? When Internet Explorer gets this type of response it gets the file to be directed to via the Location header

 Location: test2.asp 

And issues another request to get test2.asp. IIS does something clever for us here as well; just in case your browser does not understand 302 headers it generates HTML giving the user a link that they can manually click on. If you are going through a firewall you may have actually seen this code sometimes in your browser. However Internet Explorer does understand 302 headers so shows no page, but simply requests the new page instead.

That is the simple mechanism where by the web server responds to your requests for pages, however IIS gives us two delivery mechanisms; buffered or non-buffered. When buffering is off IIS sends HTML to the client as it is generated. With buffering on, IIS holds all HTML in a buffer until the page has finished processing, it then hands the HTML to the client in one big batch.

Try this code;

<%@ Language=VBScript %>
 <%Response.Buffer = true%>
 <HTML>
 <HEAD>
 <META NAME="GENERATOR" Content="Microsoft Visual Studio 6.0">
 </HEAD>
 <BODY>
 
 <%
 for i = 1 to 10000
 	Response.Write i & "<br>" & vbCRLF
 next
 %>
 </BODY>
 </HTML> 

Notice that we are programmatically setting the buffering mode to True, i.e. we want the page buffered. When you navigate to this page the browser will sit and wait, and all of a sudden you'll see 10000 lines in your browser. If you update the code to turn buffering off;

<%Response.Buffer = false%> 

Then you will see the page gradually grow in size until all 10000 lines have been written. Note that IIS4 and IIS5 have different default options for buffering. In IIS4 it is off by default, and in IIS5 it is on by default. This means that if you omit the "Response.Buffer =" code then IIS4 will default to false, and IIS5 to true.

Lets look at how buffering and redirection can come into conflict. In the following sections I'll explicitly turn buffering on or off so that the code works the same under IIS4 and IIS5.

Update test.asp to read;

<%@ Language=VBScript %>
 <%Response.Buffer = false%>
 <HTML>
 			<HEAD>
 <META NAME="GENERATOR" Content="Microsoft Visual Studio 6.0">
 </HEAD>
 <BODY>
 
 <p>Hello</p>
 
 <%
 response.redirect "test2.asp"
 %>
 
 </BODY>
 </HTML> 

The response.redirect is now mid-way through the page. If we view this page we see the following in the browser;

Hello
 			
 Response object error 'ASP 0156 : 80004005' 
 
 Header Error 
 
 /Examples/test.asp, line 12 
 
The HTTP headers are already written to the client browser. 
Any HTTP header modifications must be made before writing page content.

Why do we get this error? Remember that a normal page is sent with "200 OK" in its response headers, and a redirect is "302 Object moved". When IIS hits the first piece of HTML output;

 <HTML> 

it deduces that this is a standard "200 OK" page and that the browser should be sent output as it is generated. So it sends this;

HTTP/1.1 200 OK
 Server: Microsoft-IIS/5.0
 Date: Mon, 19 Mar 2001 15:07:44 GMT
 Connection: close
 Content-Length: 134
 Content-Type: text/html
 Set-Cookie: ASPSESSIONIDQQGQQJWO=OMCJFABDNCDLLBKAPNHJBKHD; path=/
 Cache-control: private
 			
 <HTML> 

As more HTML is generated it is also sent to the browser to be displayed. When it hits the response.redirect command it has a problem. In order to re-direct it needs to send a "302 Object moved" header but it can't as it has already sent a "200 OK" header, thus the error about not being able to modify the headers.

Now change the code so that buffering is on;

<%@ Language=VBScript %>
 <%Response.Buffer = true%>
 <HTML>
 <HEAD>
 <META NAME="GENERATOR" Content="Microsoft Visual Studio 6.0">
 </HEAD>
 <BODY>
 
 <p>Hello</p>
 			
 <%
 response.redirect "test2.asp"
 %>
 
 </BODY>
 </HTML>
 

And try again, this time it works. With buffering on, IIS stores all output in a buffer until the page has completed. So by the time it gets to the redirect it will have this in its buffer;

HTTP/1.1 200 OK
 			Server: Microsoft-IIS/5.0
 Date: Mon, 19 Mar 2001 15:07:44 GMT
 Connection: close
 Content-Length: 134
 Content-Type: text/html
 Set-Cookie: ASPSESSIONIDQQGQQJWO=OMCJFABDNCDLLBKAPNHJBKHD; path=/
 Cache-control: private
 
 <HTML>
 <HEAD>
 <META NAME="GENERATOR" Content="Microsoft Visual Studio 6.0">
 </HEAD>
 <BODY>
 
 <p>Hello</p> 

However it has not sent anything to the client yet. So when it hits your redirect it simply throws away anything in it's buffer and replaces it with this instead;

HTTP/1.1 302 Object moved
 Server: Microsoft-IIS/5.0
 Date: Mon, 19 Mar 2001 15:16:35 GMT
 Connection: close
 Location: test2.asp
 Content-Length: 130
 Content-Type: text/html
 Set-Cookie: ASPSESSIONIDQQGQQJWO=ANCJFABDFLBLHMKIJOIOKJDM; path=/
 Cache-control: private
 			
 <head><title>Object moved</title></head>
 <body><h1>Object Moved</h1>
   This object may be found <a HREF="test2.asp">here</a>.
 </body> 

That is sent to the client and the browser can be redirected.

So to avoid the error when doing a redirect, either put the redirect before any output, or turn on buffering. Remember that if you are using IIS4 you have to turn on buffering programmatically, if you use IIS5 it is done by default. However if you rely on buffering being turned on you should always explicitly add it to your code. That way you won't get problems when you move to a different web server or when Microsoft decides to change the default again. You can also configure buffering to be on or off by default via the IIS MMC.

Go up to the top of this page.

Why can't I...

...redirect to a frame?

HTTP is a request/response technology. The browser requests a page from the server, and the browser displays the response. For a page to appear in a frame, it is that frame that must make the request. You can't make a request in one frame and have the response piped to another. Only the requester can get the response.

To work around this you should create HTML that does the frame manipulation on the client;

<html>
<body>
 
 <p>My page is here</p>
 
 <script>
 parent.targetframename.location.replace('page2.asp');
 </script>
 
</body>
</html> 

This will cause "targetframename" to request page2.asp, thus showing the response in that frame.

Go up to the top of this page.

...POST variables when doing a redirect?

When you submit a FORM with the GET method, your browser does not do anything clever, it simply appends the FORM elements to the end of the page in the ACTION parameter. When you submit a FORM using the POST method an entirely different mechanism is used. When your browser gets the 302 response, it reads the new location from the Location header and simply requests that page. You can simulate a GET submission by simply tagging on the parameters yourself, thereby emulating what the browser does. So if you do;
<%
 Response.Redirect "test2.asp?myparam=123"
%> 

the resulting header looks like this;

HTTP/1.1 302 Object moved
 Server: Microsoft-IIS/5.0
 Date: Mon, 19 Mar 2001 15:16:35 GMT
 Connection: close
 Location: test2.asp?myparam=123
 Content-Length: 130
 Content-Type: text/html
 Set-Cookie: ASPSESSIONIDQQGQQJWO=ANCJFABDFLBLHMKIJOIOKJDM; path=/
 Cache-control: private
 
 <head><title>Object moved</title></head>
 <body><h1>Object Moved</h1>
This object may be found<a HREF="test2.asp?myparam=123">here</a>.</body>

So the browser requests "test2.asp?myparam=123", thus passing on your parameters. Emulating a POST, however, is not that simple and the Redirect process simply does not support it.

The workaround is similar though, you should generate the appropriate HTML to do the job yourself;

<html>
 <body>
 
 <form name=frmTest action=page2.asp method=POST>
 <input type=hidden name=txtMyVar value="Hello">
 </form>
 
 <script>
   document.frmTest.submit();
 </script>
 
 </body>
 </html> 

The problem with this is that you are relying on scripting support from the client.

Go up to the top of this page.

Is There an Alternative?

Yes, IIS5 gives us an alternative to doing a response.redirect. You can now use the Transfer or Execute method of the Server object. So instead of doing response.redirect "page2.asp" you can simply server.transfer "page2.asp". It is all done at the server so will work even if you have already sent some output to the client.

Another option is to emulate a redirect using a COM object that lets us request another ASP page within our script code. For more details on this see the FAQ article at;

How do I read the contents of a remote web page?

 

Go up to the top of this page.
This site powered by the Logical Web Publisher™: Content management by Logical Expressions, Inc.