Search Search

#1 worldwide
FREE Coding Lessons

since 1996
   THE BEST WAY to learn ASP & Asp.net!
Advertise Here!
click for details
Credits Host:
DiscountASP.net
Server Admin:
The "Team"
Contact Info.
Charles M. Carroll

my Blog
[prev. Lesson]  Database in Session or App. Say NO!
     [next Lesson]  advice:Option Explicit

Cache No More by Phil Paxton and John Sheppard

Page Cache Prevention Basics

Here are the the commands to place at the top of your ASP scripts to ensure that the page is not cached:

<%
Response.Expires = 60
Response.Expiresabsolute = Now() - 1
Response.AddHeader "pragma","no-cache"
Response.AddHeader "cache-control","private"
Response.CacheControl = "no-cache"
%>

Response.Expires = 60
is said to expire at 60 seconds, not 0. Also, Khin Zaw (from /asplists/aspadvanced.asp) has posted research from time spent with some IIS internals experts revealing this can be a very touchy parameter to rely upon and usually requires a rather "large" negative number or pedantically, that would be a very small number).

Response.Expiresabsolute=Now()-2
(my own creation) says "expire this page 48 hours ago", allowing for time differences, rather than specify a static date. If your page is being viewed by a browser in a very different time-zone it 

Response.AddHeader "pragma","no-cache"
Response.AddHeader "cache-control","private"
Response.CacheControl = "no-cache"
their use originates rom an MS KB article. The code is correct but there are some incorrect statements in the article itself.

Some related KB articles include:
<http://support.microsoft.com/?kbid=189409>
<http://support.microsoft.com/?kbid=172896>
<http://support.microsoft.com/?kbid=165150>


John Shepard writes us... "Use no-store, instead of no-cache."

The only way to prevent the user from using the back button after they have logged out is to set:

<%
	Response.AddHeader "Pragma", "no-store" 'SSL: prevent cache, however Firefox will not cache SSL with Cache-Control: no-cache or no-store.
	Response.Cache-Control = "no-store" 'HTTP prevent back button
	Response.Expires = -1
%>

 

Resources:
HTTP/1.1: Header Field Definitions: Cache-Control <http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9>
Firefox 1.5 caching <http://developer.mozilla.org/en/docs/Using_Firefox_1.5_caching>
Prevent caching when you download active documents over SSL <http://support.microsoft.com/?kbid=815313>
Disable Mozilla (Gekco) from caching pages <http://forums.aspfree.com/showpost.php?p=230022&postcount=28>

Should: Ought to, but not necessarily will.


CacheBuster Tactics

If the above techniques do not work in every instance, a "cache-buster" can be employed.

<a href=whatever.asp?Nocache=<%=rnd()%>>
or
<a href=whatever.asp?Nocache=<%=server.URLencode(now())%>>

Another thing to remember: Netscape will continue to cache, even if you turn all caching off. This behavior persisted through 4.5 PR1, PR2, and now in the released version of 4.5.

CacheBuster Simplified Via A Library

If you fear you might have to deal with caching later, you might want to build contingencies into your app as you go. Retrofitting #5 throughout even a medium-sized app would take a rather sizeable effort. You could retrofit #1-#4 (inclusive) rather quickly with a single pass through the application, but #5 takes a lot of extra effort. And to that end, I don't ever Response.Redirect anywhere in my code except sample code I post to the lists (then again, the only time I use Response.Write is to the list because I rely on my Utilities-Form.inc library (see a sample of such a library for Display() and HTML()). Everything is Redirect(NewURL) where the Redirect function looks like this:

   Function Redirect( NewURL )
      '
      If Not IsEmpty( NewURL & "" ) Then
         Dim QuestionMark
         '
         QuestionMark = Instr( NewURL, "?" )
         '
         If QuestionMark = 0 Then
            Response.Redirect NewURL & "?" & NoCacheURL()
            Response.End
         Else
            Response.Redirect NEWURL & "&" & NoCacheURL()
            Response.End
         End If
      End If
      '
   End Function

and NoCacheURL looks like this:

   Function NoCacheURL()
      '
      On Error Resume Next
      '
      Randomize
      ' Randomize not needed if you use Now()
      '
      NoCacheURL = "NoCache=" & Server.URLEncode(rnd)
      '
      ' or NoCacheURL = "NoCache=" & Server.URLEncode(Now())
      ' per Bill
      '
   End Function

I've learned that I approach things a little differently (sometimes better, sometimes worse, but overall, just differently) and have gotten used to a bunch of tiny little routines scattered throughout my app with a bunch of #include statements. Some of this might seem like overkill, but you have to understand just how pervasive and frustrating caching can be in a scripted app environment. Caching is great for pure HTML because it reduces server overhead. But if you do much scripting against databases, or time-based functions, it's not unusual to see rather bizarre things happen. Shopping cart applications will suddenly "lose" items already purchased; they'll "regain" items previously deleted. Starting a new order with an assigned "OrderID" (to use as a temporary confirmation number for the sake of the user) will suddenly show items from a previous order. It can be maddening the first time you have to deal with it. And if you don't deal with it head-on in your code, your users may be dealing with it for you -- you can turn caching off for your application in IIS [itself], but what if you are behind a firewall or proxy server which does caching for you? Or, if the user has caching turned on in their browser or they could be behind one or more layers of firewalls or proxy servers, all of which have been sold under the premise of delivering better performance through caching? Unless and until you can control every layer of access to your app, telling your server not to cache isn't a solution because requests may not be making it back to said server.

End-user magazines continue to extol the benefits of caching, demonstrating they are still thinking of an HTML-only world. Scripting and caching are rarely synergistic and are almost always like oil & water: both have a purpose, but rarely together.

You're almost always better off to just turn all caching off and take the performance hit than to try & retrofit all of this into an app which "mysteriously" begins misbehaving.

There are many worthy charities!!. But perhaps help starving children in Africa or South America AND help Charles too. a $5 tip buys him lunch at McDonalds, a $20 tip buys his kid Hitoshi a new computer game, a $39 tip buys his daughter Michiko a few nice outfits. See our donor list.