13
Mar

An IE AJAX gotcha: page caching

While doing some AJAX programming, I discovered a serious and extremely frustrating bug when using XMLHTTP in Internet Explorer. It appears that IE is prone to malfunctioning, unless a document accessed through AJAX has its HTTP header set to disallow caching. Beware!

I was working on the Drupal activeselect module, which allows one select box on a form to update the options in another form dynamically, through AJAX. I was having a very strange problem, where the AJAX worked fine when I first loaded the page in IE, but then refused to work properly whenever I refreshed or re-accessed the page. Only closing and re-opening the browser window would make it work again. Past the first time / first page load, everything went haywire.

I was tearing my hair out trying to work out the cause of this problem. I was searching on Google for anything I could think of to help me solve the problem. One page suggested setting all JavaScript variables that reference page elements to null (Google cache version), as soon as the user leaves the page. I tried this: no effect.

Another page led me to believe that changing the encoding from UTF-8 to iso-8859-1 (Google HTML version) would end my woes. Once again, no cigar.

Finally, I found a page suggesting that I set the HTTP response headers to disallow caching. It worked! My beautiful AJAX is now working in IE, just as well as it is working in decent browsers (i.e. Firefox et al). What I did was put the following response headers in the page (using the PHP header() function):

<?php header("Expires: Sun, 19 Nov 1978 05:00:00 GMT");
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
header("Cache-Control: no-store, no-cache, must-revalidate");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");
?>

These are the same response headers that the Drupal core uses for cached pages (that's where I copied them from). Evidently, when IE is told to invoke an AJAX HTTP request on a page that it thinks it should 'cache', it simply can't handle it.

So, for anyone else that finds that their AJAX code is bizarrely not working in IE after the first page load, this may be the answer! May this post end your troubles sooner rather than later.

Comments are closed

Comments

27
Mar
2006

Thank you! Thank You! Thank You!

I too have been stumped on why my AJAX code was working in Firefox and not in IE. Yes, I knew it was cache-related, but not how to fix it. Many suggestions on the web, like your experience, were ineffective.

Thank You!!!!

07
Apr
2006
darkfrog

After adding all the headers above it was still caching in IE for me, so I ended up adding a '&count=' + ++count; to the end of my URL I'm querying so every request made is determined by IE to be a different page request.

13
Apr
2006
Anonymous

darkfrog, you saved my life with the ++count suggestion.

IE sucks big time mang. I waste so much time ensuring things work in both FF and IE.

13
Apr
2006
Anonymous

actually one more MEGA catcha, is that u HAVEEEEEEEEE to flush ur cache anytime u make changes to ur JS in IE.

This is another thing which caused me tons of heartache headache stomach ache

13
Apr
2006
Jeremy Epstein

I've heard of the technique of adding a random number to the end of the AJAX URL, to make it 'unique' so that IE doesn't cache it. But I found that in my case, I didn't need to do this: just setting the HTTP headers did it for me. It's possible that IE is so crap, that you need to use different techniques for different individual examples of JS. Perhaps sometimes you need to set the headers, sometimes you need a unique URL, sometimes you need both.

14
Apr
2006

Thanks for posting this. Just today I was stuck on the same thing: Firefox worked great, but not IE. I'm coding in C#, so in case someone stumbles upon this, this is what I used:

Response.AddHeader("Cache-Control", "no-store, no-cache, must-revalidate");

That did the trick!

25
Jul
2006
I use java and have the same problem with you. Thank you very much for tipping.
Depending on my expierence on AJAX, only setting 'no-cache' may not affect SILLY IE. So I add a timestamp to the XML:

response.setContentType("text/xml; charset=UTF-8");
response.setHeader("Cache-Control", "no-cache");
PrintWriter out = response.getWriter();
out.println(""+Calendar.getInstance().getTime().getTime()+"");
out.flush();
out.close();

Now it works fine!! Thank you again guys!

18
Aug
2006

I ran around in circles on this for a while, none of the above worked for me in IE when hitting the refresh button.

Of course, the answer was right in the AJAX documentation:

Page Caching

We have implemented a method to prevent page cacheing from undermining the AJAX methods in a page. If you send in an input argument to a CGI::Ajax-exported function called 'NO_CACHE', the a special parameter will get attached to the end or your url with a random number in it. This will prevent a browser from caching your request.

exported_func(['input1','NO_CACHE'],['result1']);

The extra param is called pjxrand, and won't interfere with the order of processing for the rest of your parameters.

22
Sep
2006

I had the same problem but when I used POST for the Ajax call instead of GET, IE didn't cache it anymore. I haven't seen this anywhere else yet and I've just started using it so I'm not completely sure if it works in all cases but so far it's working fine for me.

11
Nov
2006
Anonymous

I thought that would work bur it didn't. Unique'ing the URL did it however.

30
Nov
2006
Anonymous

hey, just another person adding a 'thanks'.

WTF IE!!!

:)

13
Dec
2006

...and yet another 'thanks'. WTF, IE, indeed. Using POST instead of GET solved it for me, AND clearing the cache in my client so that the cached JavaScript would be flushed. That's absolutely retarded, I'm going to have to find a solution so that my clients don't have to clear their caches when I fix a bug in my JavaScript. Maybe put the JavaScript in a separate import file, and/or adding no-cache headers, and/or changing the URL each time, as other posters have mentioned.

13
Dec
2006

And indeed, as the main poster points out in "An IE AJAX gotcha: page caching", simply including the relevant no-cache headers in the XML content of your AJAX responses does prevent IE from caching THAT content. I can use GET, rather than POST, for my AJAX requests, if my AJAX response includes those headers. There's still the issue of bugs in the JavaScript being cached, but surely some of the solutions posted here will address that.

09
Feb
2007
Anonymous

did it for me!!

Nice 1......big thanks.

18
Apr
2007
whats so hard about just appending time to the end of the URL?
"http://www.whatever.com/?var1=".$svar."&time=".time();

and it should never cache?

06
Jun
2007
Anonymous

While I hate IE 6+ I still think it is unfair to put the whole blame on it just because it uses cache more often than FF. It is the combination of server response headers and IE cache handling that is causing the trouble. For those interested I suggest reading this caching tutorial. It is very well written.

About JS files caching - check the response headers of JS files to see if they are correct and don't blame IE until you do so. :)

30
Jul
2007

AH! OK, This is just want I wanted to know! Thanks a lot! Geez I hate Microsoft.. :-)

16
Nov
2007
John U.

coldfusion if anyone wants it

By the way a good way to check caching issues in ie is to go to
Tools
Internet options
Browsing History (Settings)

Check for newer versions of stored pages: Every time I visit the page

This will make it work if its a caching issue.

16
Nov
2007
John U.
<cfheader name="Cache-Control" value="no-store" />
<cfheader name="Pragma" value="no-cache" />

<cfheader name="Expires" value="Tue, 16 Oct 1973 00:00:00 GMT" />

29
Dec
2007
There is an easier way instead of wacky header modifications.
Add a dummy variable to your GET request.
Example:

var randomnumber = Math.floor(Math.random()*1000001)
var file = 'ajaxfile.php?dummy=' + randomnumber;
xmlhttp.open('GET', file , true);

This forces all browsers to resubmit (well, it doesn't work once in a million)

21
Apr
2008
franferns
Hi,
Im using the XMLHttpRequest object which calls an XML file i am using a HTML file where my Javascript AJAX code is present..!!

I call this function every 5 sec and any change made to the XML file needs to be reflected in the browser..! Its works all fine but only in Mozilla,Netscape and Safari but not on IE 6 and Opera...!!! Please suggest me with something..!!! As to i think this is the caching problem associated ..!!

Regards,

Ferns

03
May
2008
no cache with headers didn't work for me ...however
adding a random no in URL worked for me...

Thanx a lot for this input..:)

25
Sep
2008
Thanks your suggestion is very helpfull to me
Yes

God is great!

25
Sep
2008

Right sire

God is great!

30
Mar
2010
Jolly Dutchman
AT 2.46AM local time I come accross this and it kills my problem i've been having for about a month.

Here's an Add On, for those of you who also ran into the need for making a unique url for the Ajax call to fetch, when you call your JavaScript:

var d=new Date();

ajaxcall.open("GET",pagename+"&currtime="+d.getTime(),true);

More detail on that cute getTime func is here: http://www.w3schools.com/js...

THANKS ^10241024000999192992810982 ok?

30
Mar
2010
FreeLiveNet

There is a quick but effective solution to this, which you can use a random number at the end of ajax url. you can use something like ....php?Math.rand()

this will force IE to load from the server.

01
Apr
2010

I'm coding in java and add the following into my serlvet:

response.addHeader("Cache-Control", "no-store, no-cache, must-revalidate");

and it worked! Thank you!

09
Apr
2010
Anonymous

I employ the same method when working with callbacks from php pages... It keeps it from using any cached pages... The resolution of the random number should make it damn near impossible for the sid to repeat

var url="phpPage.php"
url=url+"?value1="+value1;

url=url+"&sid="+Math.random();

23
Apr
2010

Hi,

Excellent

Thanks,

P.Balaji

27
Apr
2010

after adding the headers

header("Expires: Tue, 03 Jul 2001 06:00:00 GMT");
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0");
header("Cache-Control: post-check=0, pre-check=0", false);

header("Pragma: no-cache");

IE still refused to work . But adding the '&count=' + ++count; to the end of the

calling URL, IE finally started obeying Ajax.

1000 thanks to you DarkFrog !!!