I ran into an interesting issue with output caching. If you have a page that uses output caching and that page conditionally sends a redirect response, you need to be careful.

Let’s say that you have a page that redirects to the mobile version of your website if they have a mobile browser. Let’s suppose that you’re using a standard, generic output caching directive:
<%@ OutputCache Duration="300" VaryByParam="*" %>
When the page renders, the rendered HTML will be cached. The next incoming request will get the cached HTML, and the page rendering and code execution will be completely avoided. If you get a visitor that is using a mobile device, your code to determine if the request should be redirected will never get executed.
Here is another way to look at this scenario:
- Request #1: Page makes the decision to redirect to another page.
- Result: Page not cached.
- Request #2: Page makes the decision to render HTML.
- Result: This HTML is now rendered and cached.
- Request #3: Doesn’t matter.
- Result: The cached HTML from request #2 is rendered, even if the page should be redirecting.
There are a couple of workarounds to keep your redirects working:
Turn off caching
Of course the simplest option is to simply turn of output caching for the page that needs to perform a conditional redirect. It goes without saying that you’ll lose all the wonderful advantages of output caching.
Use a caching seed
Another option is to write some code in your applications "GetVaryByCustomString" method that determines if it’s a request that will be redirected. If so, a unique value is returned. This forces the page to re-render because it is not found in the page cache. Unfortunately, the code in your custom string method may get complicated very quickly.
If you’re lucky, you’ll be making the redirect decision based on something that can be automatically used to vary the output caching. For example, if your page redirects based on a URL parameter, you can simply use the VaryByParam="*" in your output cache directive (or specify the specific parameter). Keep in mind that each set of parameters supplied to the page will result in a separate cache entry. This could lead to excessive memory usage for some pages.
Use fragment caching
Of course you could avoid using output caching on the page itself. You simply use the page as a place for your redirect logic, not the content generation. Then, put the actual page generation logic and content into a UserControl. When you use output caching on that control, it won’t affect the redirect logic in the page. The disadvantage of this technique is that you may have to do extra work separating your content into controls. You also won’t get the full benefit of caching since some of the control tree still needs to be processed, and some parts of the page such as the MasterPage will not get cached.
Conclusion
Remember, this is only an issue if the page being cached makes a decision to redirect. If the page always performs a redirect, the page will not be cached (why are you using output caching then?). Obviously this issue isn’t unique to Response.Redirect, but it is an issue you should be aware of.
One mischievous aspect of this issue is that if you test your site in a certain order, you won’t see a problem. For example, if you first view the page under the circumstances needed to make it redirect, it will work. You’ll only see the issue if you cause it to not redirect, and then try to get it to redirect.

For the mobile browser example, couldn’t you also use < %@ OutputCache Duration="120" VaryByParam="*" VaryByHeader="User-Agent" %>. Then all browsers with the same user agent would have the same behavior be it a redirect or a cached page being rendered?
Personally I think you should always be varying a page by the user agent because certain third party (and I think even .NET Framework) controls render differently depending on the browser you are using.
Shawn, that will fix the issue. However, there are dozens of mobile device user agents (even more on the desktop).
This has 2 effects:
1. Excessive memory is used (not sure how substantial)
2. More importantly, you’re losing the likelihood of hitting the cache. You want users to hit the cache for the benefit of the server, AND for a quick response on their end.
You could certainly focus on varying by browser and version to help out a little bit.
It goes without saying that you’ll have to determine which method is going to work for your project.
Nice post…
Is there any that can actually cache the output result of a redirect page? for instance, i have a page that query something first and then redirect user to that result. Is there anyway to apply cache to this?
I tried output cache on the action, but when check it up in Linq2sql profiler, i got queries everytime without caching…
Thanks,
BTW, can you add the function to automatic send an email if there is respond to this? If not i will be having a lot of hardtime tracing back your page. or you could reply to my email: duc at ducdigital dot com… Thanks
Ta Duc, I don’t know of a way to cache the redirect. Caching usually applies to the content, not the headers. It wouldn’t save you much anyway since the server has to process the headers anyway.