An IE AJAX gotcha: page caching

💬 28

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.

Post a comment

💬   28 comments

Tony

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!!!!

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.

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.

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

Jaza

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.

Chris

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!

Kurapica

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("<r>"+Calendar.getInstance().getTime().getTime()+"</r>");
out.flush();
out.close();

Now it works fine!! Thank you again guys!

Ben

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.

Christiaan

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.

Anonymous

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

Anonymous

hey, just another person adding a 'thanks'.

WTF IE!!!

:)

Tom Chappell

...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.

Tom Chappell

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.

Anonymous

did it for me!!

Nice 1......big thanks.

joran

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?

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. :)

villiard

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

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" />

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.

George

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)

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

alfa

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..:)

Anil

Thanks your suggestion is very helpfull to me

Yes

God is great!

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.

THANKS ^10241024000999192992810982 ok?

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.

Stuart

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!

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();

Balaji

Hi,

Excellent

Thanks,
P.Balaji

nsfzor

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 !!!