It looks like if I load dynamic content using $.get()
, the result is cached in browser.
Adding some random string in QueryString seems to solve this issue (I use new Date().toString()
), but this feels like a hack.
Is there any other way to achieve this?
Or, if unique string is the only way to achieve this, any suggestions other than new Date()
?
This question is related to
javascript
jquery
ajax
browser-cache
The real question is why you need this to not be cached. If it should not be cached because it changes all the time, the server should specify to not cache the resource. If it just changes sometimes (because one of the resources it depends on can change), and if the client code has a way of knowing about it, it can append a dummy parameter to the url that is computed from some hash or last modified date of those resources (that's what we do in Microsoft Ajax script resources so they can be cached forever but new versions can still be served as they appear). If the client can't know of changes, the correct way should be for the server to handle HEAD requests properly and tell the client whether to use the cached version or not. Seems to me like appending a random parameter or telling from the client to never cache is wrong because cacheability is a property of the server resource, and so should be decided server-side. Another question to ask oneself is should this resource really be served through GET or should it go through POST? That is a question of semantics, but it also has security implications (there are attacks that work only if the server allows for GET). POST will not get cached.
For those of you using the cache
option of $.ajaxSetup()
on mobile Safari, it appears that you may have to use a timestamp for POSTs, since mobile Safari caches that too. According to the documentation on $.ajax()
(which you are directed to from $.ajaxSetup()
):
Setting cache to false will only work correctly with HEAD and GET requests. It works by appending "_={timestamp}" to the GET parameters. The parameter is not needed for other types of requests, except in IE8 when a POST is made to a URL that has already been requested by a GET.
So setting that option alone won't help you in the case I mentioned above.
Maybe you should look at $.ajax() instead (if you are using jQuery, which it looks like). Take a look at: http://docs.jquery.com/Ajax/jQuery.ajax#options and the option "cache".
Another approach would be to look at how you cache things on the server side.
another way is to provide no cache headers from serverside in the code that generates the response to ajax call:
response.setHeader( "Pragma", "no-cache" );
response.setHeader( "Cache-Control", "no-cache" );
response.setDateHeader( "Expires", 0 );
Now, it's easy to do it by enabling/disabling cache option in your ajax request, just like this
$(function () {
var url = 'your url goes here';
$('#ajaxButton').click(function (e) {
$.ajax({
url: url,
data: {
test: 'value'
},
cache: true, //cache enabled, false to reverse
complete: doSomething
});
});
});
//ToDo after ajax call finishes
function doSomething(data) {
console.log(data);
}
});
Of course "cache-breaking" techniques will get the job done, but this would not happen in the first place if the server indicated to the client that the response should not be cached. In some cases it is beneficial to cache responses, some times not. Let the server decide the correct lifetime of the data. You may want to change it later. Much easier to do from the server than from many different places in your UI code.
Of course this doesn't help if you have no control over the server.
As @Athasach said, according to the jQuery docs, $.ajaxSetup({cache:false})
will not work for other than GET and HEAD requests.
You are better off sending back a Cache-Control: no-cache
header from your server anyway. It provides a cleaner separation of concerns.
Of course, this would not work for service urls that you do not belong to your project. In that case, you might consider proxying the third party service from server code rather than calling it from client code.
Of course "cache-breaking" techniques will get the job done, but this would not happen in the first place if the server indicated to the client that the response should not be cached. In some cases it is beneficial to cache responses, some times not. Let the server decide the correct lifetime of the data. You may want to change it later. Much easier to do from the server than from many different places in your UI code.
Of course this doesn't help if you have no control over the server.
Basically just add cache:false;
in the ajax where you think the content will change as the progress go on. And the place where the content wont change there u can omit this. In this way u will get the new response every time
The following will prevent all future AJAX requests from being cached, regardless of which jQuery method you use ($.get, $.ajax, etc.)
$.ajaxSetup({ cache: false });
All the answers here leave a footprint on the requested URL which will show up in the access logs of server.
I needed a header based solution with no side effect and I found it can be achieved by setting up the headers mentioned in How to control web page caching, across all browsers?.
The result, working for Chrome at least, would be:
$.ajax({_x000D_
url: url, _x000D_
headers: {_x000D_
'Cache-Control': 'no-cache, no-store, must-revalidate', _x000D_
'Pragma': 'no-cache', _x000D_
'Expires': '0'_x000D_
}_x000D_
});
_x000D_
Maybe you should look at $.ajax() instead (if you are using jQuery, which it looks like). Take a look at: http://docs.jquery.com/Ajax/jQuery.ajax#options and the option "cache".
Another approach would be to look at how you cache things on the server side.
Following the documentation: http://api.jquery.com/jquery.ajax/
you can use the cache
property with:
$.ajax({
method: "GET",
url: "/Home/AddProduct?",
data: { param1: value1, param2: value2},
cache: false,
success: function (result) {
// TODO
}
});
Personally I feel that the query string method is more reliable than trying to set headers on the server - there's no guarantee that a proxy or browser won't just cache it anyway (some browsers are worse than others - naming no names).
I usually use Math.random()
but I don't see anything wrong with using the date (you shouldn't be doing AJAX requests fast enough to get the same value twice).
add header
headers: {
'Cache-Control':'no-cache'
}
The real question is why you need this to not be cached. If it should not be cached because it changes all the time, the server should specify to not cache the resource. If it just changes sometimes (because one of the resources it depends on can change), and if the client code has a way of knowing about it, it can append a dummy parameter to the url that is computed from some hash or last modified date of those resources (that's what we do in Microsoft Ajax script resources so they can be cached forever but new versions can still be served as they appear). If the client can't know of changes, the correct way should be for the server to handle HEAD requests properly and tell the client whether to use the cached version or not. Seems to me like appending a random parameter or telling from the client to never cache is wrong because cacheability is a property of the server resource, and so should be decided server-side. Another question to ask oneself is should this resource really be served through GET or should it go through POST? That is a question of semantics, but it also has security implications (there are attacks that work only if the server allows for GET). POST will not get cached.
Of course "cache-breaking" techniques will get the job done, but this would not happen in the first place if the server indicated to the client that the response should not be cached. In some cases it is beneficial to cache responses, some times not. Let the server decide the correct lifetime of the data. You may want to change it later. Much easier to do from the server than from many different places in your UI code.
Of course this doesn't help if you have no control over the server.
The following will prevent all future AJAX requests from being cached, regardless of which jQuery method you use ($.get, $.ajax, etc.)
$.ajaxSetup({ cache: false });
What about using a POST request instead of a GET...? (Which you should anyway...)
If you are using .net ASP MVC, disable the caching on the controller action by adding the following attribute on the end point function:
[OutputCacheAttribute(VaryByParam = "*", Duration = 0, NoStore = true)]
append Math.random()
to the request url
Maybe you should look at $.ajax() instead (if you are using jQuery, which it looks like). Take a look at: http://docs.jquery.com/Ajax/jQuery.ajax#options and the option "cache".
Another approach would be to look at how you cache things on the server side.
another way is to provide no cache headers from serverside in the code that generates the response to ajax call:
response.setHeader( "Pragma", "no-cache" );
response.setHeader( "Cache-Control", "no-cache" );
response.setDateHeader( "Expires", 0 );
If you are using IE 9, then you need to use the following in front of your controller class definition:
[OutputCache(NoStore = true, Duration = 0, VaryByParam = "*")]
public class TestController : Controller
This will prevent the browser from caching.
Details on this link: http://dougwilsonsa.wordpress.com/2011/04/29/disabling-ie9-ajax-response-caching-asp-net-mvc-3-jquery/
Actually this solved my issue.
What about using a POST request instead of a GET...? (Which you should anyway...)
If you are using .net ASP MVC, disable the caching on the controller action by adding the following attribute on the end point function:
[OutputCacheAttribute(VaryByParam = "*", Duration = 0, NoStore = true)]
add header
headers: {
'Cache-Control':'no-cache'
}
If you are using IE 9, then you need to use the following in front of your controller class definition:
[OutputCache(NoStore = true, Duration = 0, VaryByParam = "*")]
public class TestController : Controller
This will prevent the browser from caching.
Details on this link: http://dougwilsonsa.wordpress.com/2011/04/29/disabling-ie9-ajax-response-caching-asp-net-mvc-3-jquery/
Actually this solved my issue.
Personally I feel that the query string method is more reliable than trying to set headers on the server - there's no guarantee that a proxy or browser won't just cache it anyway (some browsers are worse than others - naming no names).
I usually use Math.random()
but I don't see anything wrong with using the date (you shouldn't be doing AJAX requests fast enough to get the same value twice).
As @Athasach said, according to the jQuery docs, $.ajaxSetup({cache:false})
will not work for other than GET and HEAD requests.
You are better off sending back a Cache-Control: no-cache
header from your server anyway. It provides a cleaner separation of concerns.
Of course, this would not work for service urls that you do not belong to your project. In that case, you might consider proxying the third party service from server code rather than calling it from client code.
All the answers here leave a footprint on the requested URL which will show up in the access logs of server.
I needed a header based solution with no side effect and I found it can be achieved by setting up the headers mentioned in How to control web page caching, across all browsers?.
The result, working for Chrome at least, would be:
$.ajax({_x000D_
url: url, _x000D_
headers: {_x000D_
'Cache-Control': 'no-cache, no-store, must-revalidate', _x000D_
'Pragma': 'no-cache', _x000D_
'Expires': '0'_x000D_
}_x000D_
});
_x000D_
What about using a POST request instead of a GET...? (Which you should anyway...)
Internet Explorer’s Ajax Caching: What Are YOU Going To Do About It? suggests three approaches:
- Add a cache busting token to the query string, like ?date=[timestamp]. In jQuery and YUI you can tell them to do this automatically.
- Use POST instead of a GET
- Send a HTTP response header that specifically forbids browsers to cache it
JQuery's $.get() will cache the results. Instead of
$.get("myurl", myCallback)
you should use $.ajax, which will allow you to turn caching off:
$.ajax({url: "myurl", success: myCallback, cache: false});
Internet Explorer’s Ajax Caching: What Are YOU Going To Do About It? suggests three approaches:
- Add a cache busting token to the query string, like ?date=[timestamp]. In jQuery and YUI you can tell them to do this automatically.
- Use POST instead of a GET
- Send a HTTP response header that specifically forbids browsers to cache it
Personally I feel that the query string method is more reliable than trying to set headers on the server - there's no guarantee that a proxy or browser won't just cache it anyway (some browsers are worse than others - naming no names).
I usually use Math.random()
but I don't see anything wrong with using the date (you shouldn't be doing AJAX requests fast enough to get the same value twice).
Maybe you should look at $.ajax() instead (if you are using jQuery, which it looks like). Take a look at: http://docs.jquery.com/Ajax/jQuery.ajax#options and the option "cache".
Another approach would be to look at how you cache things on the server side.
What about using a POST request instead of a GET...? (Which you should anyway...)
Following the documentation: http://api.jquery.com/jquery.ajax/
you can use the cache
property with:
$.ajax({
method: "GET",
url: "/Home/AddProduct?",
data: { param1: value1, param2: value2},
cache: false,
success: function (result) {
// TODO
}
});
another way is to provide no cache headers from serverside in the code that generates the response to ajax call:
response.setHeader( "Pragma", "no-cache" );
response.setHeader( "Cache-Control", "no-cache" );
response.setDateHeader( "Expires", 0 );
Of course "cache-breaking" techniques will get the job done, but this would not happen in the first place if the server indicated to the client that the response should not be cached. In some cases it is beneficial to cache responses, some times not. Let the server decide the correct lifetime of the data. You may want to change it later. Much easier to do from the server than from many different places in your UI code.
Of course this doesn't help if you have no control over the server.
append Math.random()
to the request url
For those of you using the cache
option of $.ajaxSetup()
on mobile Safari, it appears that you may have to use a timestamp for POSTs, since mobile Safari caches that too. According to the documentation on $.ajax()
(which you are directed to from $.ajaxSetup()
):
Setting cache to false will only work correctly with HEAD and GET requests. It works by appending "_={timestamp}" to the GET parameters. The parameter is not needed for other types of requests, except in IE8 when a POST is made to a URL that has already been requested by a GET.
So setting that option alone won't help you in the case I mentioned above.
Now, it's easy to do it by enabling/disabling cache option in your ajax request, just like this
$(function () {
var url = 'your url goes here';
$('#ajaxButton').click(function (e) {
$.ajax({
url: url,
data: {
test: 'value'
},
cache: true, //cache enabled, false to reverse
complete: doSomething
});
});
});
//ToDo after ajax call finishes
function doSomething(data) {
console.log(data);
}
});
JQuery's $.get() will cache the results. Instead of
$.get("myurl", myCallback)
you should use $.ajax, which will allow you to turn caching off:
$.ajax({url: "myurl", success: myCallback, cache: false});
A small addition to the excellent answers given: If you're running with a non-ajax backup solution for users without javascript, you will have to get those server-side headers correct anyway. This is not impossible, although I understand those that give it up ;)
I'm sure there's another question on SO that will give you the full set of headers that are appropriate. I am not entirely conviced miceus reply covers all the bases 100%.
Personally I feel that the query string method is more reliable than trying to set headers on the server - there's no guarantee that a proxy or browser won't just cache it anyway (some browsers are worse than others - naming no names).
I usually use Math.random()
but I don't see anything wrong with using the date (you shouldn't be doing AJAX requests fast enough to get the same value twice).
A small addition to the excellent answers given: If you're running with a non-ajax backup solution for users without javascript, you will have to get those server-side headers correct anyway. This is not impossible, although I understand those that give it up ;)
I'm sure there's another question on SO that will give you the full set of headers that are appropriate. I am not entirely conviced miceus reply covers all the bases 100%.
Basically just add cache:false;
in the ajax where you think the content will change as the progress go on. And the place where the content wont change there u can omit this. In this way u will get the new response every time
A small addition to the excellent answers given: If you're running with a non-ajax backup solution for users without javascript, you will have to get those server-side headers correct anyway. This is not impossible, although I understand those that give it up ;)
I'm sure there's another question on SO that will give you the full set of headers that are appropriate. I am not entirely conviced miceus reply covers all the bases 100%.
another way is to provide no cache headers from serverside in the code that generates the response to ajax call:
response.setHeader( "Pragma", "no-cache" );
response.setHeader( "Cache-Control", "no-cache" );
response.setDateHeader( "Expires", 0 );
Source: Stackoverflow.com