Ajax request returning the same results in Internet Explorer.

The other day, I was having a mental breakdown, all because of Internet Explorer and its ridiculous way of dealing with Ajax requests!

Basically, I created a form that allowed users to add data to a dynamic list. Whenever the form was submitted, an Ajax GET request was made and the list in question was refreshed. Seems pretty straight forward, right?

Nope!

Unfortunately, a number of IE users got in contact with me to say that the form wasn’t working for them. They said that the “form didn’t work” and that “nothing was happening” when they pressed the submit button. At first, I thought that my JavaScript was throwing up errors in some of the earlier versions of Internet Explorer. However, after testing it out on IE7, IE8 and IE9, I saw that the console log was completely blank. No errors… no warnings… nothing.

After that, I began to suspect CakePHP’s method of session checking. You see, the results in the list were temporarily tied to the user’s session ID and I had previously read about an issue where CakePHP would sometimes drop sessions belonging to Internet Explorer users.

Apparently, in order to fix said issue, you need to place the following line into your Config/core.php file:

Configure::write('Session.checkAgent', false);

For the purpose of clarity, this is what CakePHP’s documentation said about the Session.checkAgent issue:

// Do you want the user agent to be checked when starting sessions?
// You might want to set the value to false, when dealing with older versions
// of IE, Chrome Frame or certain web-browsing devices and AJAX.

To my dismay, I made the recommended change and it didn’t seem to fix anything. Internet Explorer users were still complaining about the fact that the form was not working, even though it was working perfectly fine on my end.

The Culprit: Ajax Caching

Yes! Ajax caching! Apparently, Internet Explorer is notorious for caching the results of Ajax GET requests. What was happening in my particular case:

  1. An IE user lands on the page and an Ajax request loads the contents of the dynamic list. In the vast majority of cases, this list is blank, simply because this is the first time that the user is visiting the page. i.e. They haven’t added anything to their list.
  2. They fill out the form and press submit.
  3. An Ajax call is made and the cached results from the first call are returned by Internet Explorer. Because the first call returned an empty JSON string, the second (cached) call also returns an empty JSON string. This is because the request never reaches the server.
  4. The user scratches their head because the list is still empty. They automatically assume that the form isn’t working, even though it is.

To be honest, I stumbled upon the issue by mistake. During one of my (many) tests, I submitted two items, only to be greeted with a blank list. Although I was glad that I had finally been able to reproduce the issue, the fact that the console log was still blank raised some concerns. As you probably already know, fixing an intermittent bug that doesn’t produce any errors can be an absolute nightmare.

After refreshing the page and navigating to other parts of the website, I returned to the form in question, only to realize that the two items that I had originally added to my list were now being displayed.

Bingo!

Cache Busting

Cache Busting refers to any method that is used to prevent the browser from caching a particular resource. In this case; the results of an Ajax request.

The solution is actually pretty simple. If you’re using JQuery to perform your Ajax requests, you can add cache: false to the parameter list like so:

$.ajax({
    url: url,
    cache: false,
    dataType: 'json',
    type: "GET",
    data: data,
    success: func,
    error: ajaxError
});

This will automatically change the URL of the request from my-ajax-data.php to something like my-ajax-data.php?_=1406054687992

The appended timestamp is appended in order to fool IE and other browsers into thinking that each Ajax call is being made to a unique resource.

If you have a lot of Ajax requests and you don’t feel like manually editing each one, you can use the following piece of code:

$.ajaxSetup({ cache: false });

Do note that you should probably decide on what calls need to be cached / not-cached on a case-by-case basis, as certain calls could be returning content that never changes.

If you’re not using JQuery, then you can manually append a timestamp onto the end of your URL. An example using raw JavaScript:

var url = 'http://example.com/page.php';
url = url + '?t=' + new Date().getTime();
console.log(url);

//Output similar to:
//http://example.com/page.php?t=1406105985591

Using POST instead of GET.

Some developers will use a POST request instead of a GET request, simply because IE doesn’t cache the results of an AJAX POST request. However, this is bad practise, simply because POST requests should only be used when you are submitting data or modifying a resource on the server.

Conclusion

This is one of those issues / caveats that can drive you insane, simply because it can be intermittent and there are no errors. Luckily enough, once you’ve experienced it (or read about it, for that matter), it’s a pretty simple thing to guard against. I have no idea why IE is so hell-bent on caching the results of Ajax GET requests. To me, it makes no sense, especially if the content of the request has actually changed since the first request was made.