253
votes

All the ajax calls that are sent from the IE are cached by Angular and I get a 304 response for all the subsequent calls. Although the request is the same, the response is not going be the same in my case. I want to disable this cache. I tried adding the cache attribute to $http.get but still it didn't help. How can this issue be resolved?

17

17 Answers

439
votes

Instead of disabling caching for each single GET-request, I disable it globally in the $httpProvider:

myModule.config(['$httpProvider', function($httpProvider) {
    //initialize get if not there
    if (!$httpProvider.defaults.headers.get) {
        $httpProvider.defaults.headers.get = {};    
    }    

    // Answer edited to include suggestions from comments
    // because previous version of code introduced browser-related errors

    //disable IE ajax request caching
    $httpProvider.defaults.headers.get['If-Modified-Since'] = 'Mon, 26 Jul 1997 05:00:00 GMT';
    // extra
    $httpProvider.defaults.headers.get['Cache-Control'] = 'no-cache';
    $httpProvider.defaults.headers.get['Pragma'] = 'no-cache';
}]);
69
votes

You can either append a unique querystring (I believe this is what jQuery does with the cache: false option) to the request.

$http({
    url: '...',
    params: { 'foobar': new Date().getTime() }
})

A perhaps better solution is if you have access to the server, then you can make sure that necessary headers are set to prevent caching. If you're using ASP.NET MVC this answer might help.

28
votes

you may add an interceptor .

myModule.config(['$httpProvider', function($httpProvider) {
 $httpProvider.interceptors.push('noCacheInterceptor');
}]).factory('noCacheInterceptor', function () {
            return {
                request: function (config) {
                    console.log(config.method);
                    console.log(config.url);
                    if(config.method=='GET'){
                        var separator = config.url.indexOf('?') === -1 ? '?' : '&';
                        config.url = config.url+separator+'noCache=' + new Date().getTime();
                    }
                    console.log(config.method);
                    console.log(config.url);
                    return config;
               }
           };
    });

you should remove console.log lines after verifying.

14
votes

I simply added three meta tags into index.html on angular project, and cache issue was solved on IE.

<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Cache-Control" content="no-cache">
<meta http-equiv="Expires" content="Sat, 01 Dec 2001 00:00:00 GMT">
14
votes

Duplicating my answer in another thread.

For Angular 2 and newer, the easiest way to add no-cache headers by overriding RequestOptions:

import { Injectable } from '@angular/core';
import { BaseRequestOptions, Headers } from '@angular/http';

@Injectable()
export class CustomRequestOptions extends BaseRequestOptions {
    headers = new Headers({
        'Cache-Control': 'no-cache',
        'Pragma': 'no-cache',
        'Expires': 'Sat, 01 Jan 2000 00:00:00 GMT'
    });
}

And reference it in your module:

@NgModule({
    ...
    providers: [
        ...
        { provide: RequestOptions, useClass: CustomRequestOptions }
    ]
})
9
votes

The guaranteed one that I had working was something along these lines:

myModule.config(['$httpProvider', function($httpProvider) {
    if (!$httpProvider.defaults.headers.common) {
        $httpProvider.defaults.headers.common = {};
    }
    $httpProvider.defaults.headers.common["Cache-Control"] = "no-cache";
    $httpProvider.defaults.headers.common.Pragma = "no-cache";
    $httpProvider.defaults.headers.common["If-Modified-Since"] = "Mon, 26 Jul 1997 05:00:00 GMT";
}]);

I had to merge 2 of the above solutions in order to guarantee the correct usage for all methods, but you can replace common with get or other method i.e. put, post, delete to make this work for different cases.

8
votes

This only line helped me (Angular 1.4.8):

$httpProvider.defaults.headers.common['Pragma'] = 'no-cache';

UPD: The problem is IE11 does aggressive caching. When I was looking into Fiddler I noticed that in F12 mode requests are sending "Pragma=no-cache" and endpoint is requested every time I visit a page. But in normal mode endpoint was requested only once at the first time when I visited the page.

7
votes

To avoid caching, one option is to give different URL for the same resource or data. To generate different URL, you can add a random query string to the end of the URL. This technique works for JQuery, Angular or other type ajax requests.

myURL = myURL +"?random="+new Date().getTime();
6
votes

I get it resolved appending datetime as an random number:

$http.get("/your_url?rnd="+new Date().getTime()).success(function(data, status, headers, config) {
    console.log('your get response is new!!!');
});
4
votes

Solution above will work (make the url unique by adding in the querystring a new param) but I prefer the solution propose [here]: Better Way to Prevent IE Cache in AngularJS?, which handle this at server level as it's not specific to IE. I mean, if that resource should not be cached, do it on the server (this as nothing to do with the browser used; it's intrisic to the resource).

For example in java with JAX-RS do it programatically for JAX-RS v1 or declativly for JAX-RS v2.

I'm sure anyone will figure out how to do it

1
votes

This is a little bit to old but: Solutions like is obsolete. Let the server handle the cache or not cache (in the response). The only way to guarantee no caching (thinking about new versions in production) is to change the js or css file with a version number. I do this with webpack.

1
votes

also you can try in your servce to set headers like for example:

...
import { Injectable } from "@angular/core";
import { HttpClient, HttpHeaders, HttpParams } from "@angular/common/http";
...
 @Injectable()
export class MyService {

    private headers: HttpHeaders;


    constructor(private http: HttpClient..) 
    {


        this.headers = new HttpHeaders()
                    .append("Content-Type", "application/json")
                    .append("Accept", "application/json")
                    .append("LanguageCulture", this.headersLanguage)
                    .append("Cache-Control", "no-cache")
                    .append("Pragma", "no-cache")                   
    }
}
....
1
votes

The correct, server-side, solution: Better Way to Prevent IE Cache in AngularJS?

[OutputCache(NoStore = true, Duration = 0, VaryByParam = "None")]
public ActionResult Get()
{
    // return your response
}
0
votes

This issue is due to the IE caching problem as you said, you can test it in IE debug mode by pressing f12 (this will work fine in debug mode).IE will not take the server data in each time the page calls, it takes the data from cache. To disable this do either of the following:

  1. append the following with your http service request url

//Before (issued one)

this.httpService.get(this.serviceUrl + "/eAMobileService.svc/ValidateEngagmentName/" + engagementName , {})

//After (working fine)

this.httpService.get(this.serviceUrl + "/eAMobileService.svc/ValidateEngagmentName/" + engagementName + "?DateTime=" + new Date().getTime() + '', { cache: false })

  1. disable the cache for the entire Module :-

$httpProvider.defaults.headers.common['Pragma'] = 'no-cache';

0
votes
meta http-equiv="Cache-Control" content="no-cache"

I just added this to View and it started working on IE. Confirmed to work on Angular 2.

0
votes

An option is to use the simple approach of adding a Timestamp with each request no need to clear cache.

    let c=new Date().getTime();
    $http.get('url?d='+c)
-2
votes

Try this, it worked for me in a similar case:-

$http.get("your api url", {
headers: {
    'If-Modified-Since': '0',
    "Pragma": "no-cache",
    "Expires": -1,
    "Cache-Control": "no-cache, no-store, must-revalidate"
 }
})