Unerwartetes Caching von AJAX führt zu IE8

135

Ich habe ein ernstes Problem mit dem Zwischenspeichern von Internet Explorer-Ergebnissen aus einer JQuery Ajax-Anforderung.

Ich habe eine Kopfzeile auf meiner Webseite, die jedes Mal aktualisiert wird, wenn ein Benutzer zu einer neuen Seite navigiert. Sobald die Seite geladen ist, mache ich das

$.get("/game/getpuzzleinfo", null, function(data, status) {
    var content = "<h1>Wikipedia Maze</h1>";
    content += "<p class='endtopic'>Looking for <span><a title='Opens the topic you are looking for in a separate tab or window' href='" + data.EndTopicUrl + "' target='_blank'>" + data.EndTopic + "<a/></span></p>";
    content += "<p class='step'>Step <span>" + data.StepCount + "</span></p>";
    content += "<p class='level'>Level <span>" + data.PuzzleLevel.toString() + "</span></p>";
    content += "<p class='startover'><a href='/game/start/" + data.PuzzleId.toString() + "'>Start Over</a></p>";

    $("#wikiheader").append(content);

}, "json");

Es werden nur Header-Informationen in die Seite eingefügt. Sie können es überprüfen, indem Sie auf www.wikipediamaze.com gehen und sich dann anmelden und ein neues Puzzle starten.

In jedem von mir getesteten Browser (Google Chrome, Firefox, Safari, Internet Explorer) funktioniert es hervorragend, außer im Internet Explorer . Alles wird beim ersten Mal in IE gut injiziert, aber danach wird es nicht einmal mehr angerufen /game/getpuzzleinfo. Es ist, als hätte es die Ergebnisse zwischengespeichert oder so.

Wenn ich den Anruf in $.post("/game/getpuzzleinfo", ...IE ändere , wird er gut angenommen. Aber dann hört Firefox auf zu arbeiten.

Kann jemand bitte etwas Licht ins Dunkel bringen, warum der IE meine $.getAjax-Anrufe zwischenspeichert?

AKTUALISIEREN

Gemäß dem folgenden Vorschlag habe ich meine Ajax-Anfrage in diese geändert, wodurch mein Problem behoben wurde:

$.ajax({
    type: "GET",
    url: "/game/getpuzzleinfo",
    dataType: "json",
    cache: false,
    success: function(data) { ... }
});
Micah
quelle
8
Danke, dass du das gefragt hast. Ich bin sprachlos, dass dieses Browserverhalten.
John
1
Gute Frage und wirklich coole Website. Gute Idee.
Mike Murko

Antworten:

177

IE ist bekannt für sein aggressives Caching von Ajax-Antworten. Während Sie jQuery verwenden, können Sie eine globale Option festlegen:

$.ajaxSetup({
    cache: false
});

Dadurch fügt jQuery der Anforderungsabfragezeichenfolge einen zufälligen Wert hinzu, wodurch verhindert wird, dass der IE die Antwort zwischenspeichert.

Beachten Sie, dass wenn Sie andere Ajax-Aufrufe ausführen, bei denen Sie das Caching durchführen möchten, dies auch für diese deaktiviert wird. Wechseln Sie in diesem Fall zur Verwendung der Methode $ .ajax () und aktivieren Sie diese Option explizit für die erforderlichen Anforderungen.

Weitere Informationen finden Sie unter http://docs.jquery.com/Ajax/jQuery.ajaxSetup .

NickFitz
quelle
1
Sie können dem Ende Ihrer URLs auch einen Zeitstempel hinzufügen. Ich bin mir nicht sicher, warum jQuery diesen Ansatz nicht verwendet.
Eric Johnson
14
@Eric: Das macht jQuery intern - die Option "cache: false" weist es nur an, dies zu tun.
NickFitz
Warum ist bei jquery dies nicht standardmäßig aktiviert?
Speedplane
Ich habe gerade festgestellt, dass die Cache-Optionen nicht funktionieren, wenn Sie versuchen, die Homepage in IE 8 mit einem Aufruf von anzufordern /. Ändern Sie es in /index.phpoder was auch immer die vollständige URL sein könnte. Oder fügen Sie selbst einige gefälschte Parameter hinzu/?f=f
Hugo Delsing
8

Wie bereits erwähnt, GETwerden sie zwischengespeichert.

Es gibt verschiedene Möglichkeiten, dies zu bekämpfen. Neben dem Ändern des Antwortheaders können Sie auch eine zufällig generierte Abfragezeichenfolgenvariable an das Ende der Ziel-URL anhängen. Auf diese Weise glaubt der IE, dass es sich bei jeder Anforderung um eine andere URL handelt.

Es gibt mehrere Möglichkeiten, dies zu tun (z. B. Verwendung Math.random(), Variation des Datums usw.).

Hier ist eine Möglichkeit, wie Sie dies tun können:

var oDate = new Date();
var sURL = "/game/getpuzzleinfo?randomSeed=" + oDate.getMilliseconds();
$.get(sURL, null, function(data, status) {
    // your work
});
Tom
quelle
3

Gets sind immer zwischenspeicherbar. Eine Strategie, die möglicherweise funktioniert, besteht darin, den Antwortheader zu bearbeiten und den Client anzuweisen, die Informationen nicht zwischenzuspeichern oder den Cache sehr bald abzulaufen.

marr75
quelle
Das klingt nach einer guten Idee. Wie würde ich das machen?
Micah
1
Das ist eine geladene Frage, die von Ihrem serverseitigen Code abhängt. Eine kurze Anleitung finden Sie im Wikipedia-Eintrag "Liste der HTTP-Header". Beispiele: Cache-Kontrolle: kein Cache Läuft ab: Do, 01. Dezember 1994 16:00:00 GMT Grundsätzlich müssen Sie diese Antwortheader an Ihre http-Antwort anhängen. In ASP.NET, Ruby und PHP ist das ziemlich einfach. Suchen Sie einfach nach der verwendeten serverseitigen Sprache und ändern Sie die Antwortheader.
März 75
3
Auch und dies ist überhaupt keine Kritik an Jquery (ich liebe diese Bibliothek), ist die Methode zum Hinzufügen eines zufälligen Abfragezeichenfolgenparameters sicher, aber für den Client unhöflich (sie kann dazu führen, dass sie Elemente im Cache behalten, die niemals verwendet werden nochmal).
marr75
2

Wenn Sie ashx page aufrufen, können Sie das Caching auf dem Server auch mit dem folgenden Code deaktivieren:

context.Response.Cache.SetCacheability(HttpCacheability.NoCache);
context.Response.Cache.SetRevalidation(HttpCacheRevalidation.AllCaches); 
Andrej Benedik
quelle
1

Das mache ich für Ajax-Anrufe:

var url = "/mypage.aspx";
// my other vars i want to add go here
url = url + "&sid=" + Math.random();
// make ajax call

es funktioniert ziemlich gut für mich.

Jason
quelle
1

NickFitz gibt eine gute Antwort, aber Sie müssen das Caching auch in IE9 deaktivieren. Um nur auf IE8 und IE9 abzuzielen, können Sie dies tun;

<!--[if lte IE 9]>
<script>
    $.ajaxSetup({
        cache: false
    });
</script>
<![endif]-->
Stuart Hallows
quelle
0

Die Antworten hier sind sehr hilfreich für diejenigen, die jQuery verwenden oder aus irgendeinem Grund direkt das xmlHttpRequest-Objekt verwenden ...

Wenn Sie den automatisch generierten Microsoft Service Proxy verwenden, ist dies nicht so einfach zu lösen.

Der Trick besteht darin, die Sys.Net.WebRequestManager.add_invokingRequest-Methode im Ereignishandler zu verwenden, um die Anforderungs-URL zu ändern:

networkRequestEventArgs._webRequest._url = networkRequestEventArgs._webRequest._url + '&nocache=' + new Date().getMilliseconds(); 

Ich habe darüber gebloggt: http://yoavniran.wordpress.com/2010/04/27/ie-caching-ajax-results-how-to-fix/

poeticGeek
quelle
0

Ich habe gerade einen Blog zu diesem Thema nur mit ExtJS geschrieben ( http://thecodeabode.blogspot.com/2010/10/cache-busting-ajax-requests-in-ie.html) ).

Das Problem war, dass ich bei der Verwendung eines bestimmten URL-Umschreibformats keine herkömmlichen Abfragezeichenfolgenparameter (? Param = value) verwenden konnte, sodass ich stattdessen den Cache-Busting-Parameter als veröffentlichte Variable geschrieben hatte ..... Ich hätte gedacht Die Verwendung von POST-Variablen ist etwas sicherer als die von GET, einfach weil viele MVC-Frameworks das Muster verwenden

Protokoll: // Host / Controller / Aktion / Parameter1 / Parameter2

und so geht die Zuordnung des Variablennamens zum Wert verloren und die Parameter werden einfach gestapelt ... also bei Verwendung eines GET-Cache-Buster-Parameters

dh Protokoll: // Host / Controller / Aktion / param1 / param2 / no_cache122300201

no_cache122300201 kann mit einem $ param3-Parameter verwechselt werden, der einen Standardwert haben kann

dh

öffentliche Funktionsaktion ($ param1, $ param2, $ param3 = "Standardwert") {//..//}

Bei POSTED-Cache-Bustern ist dies nicht möglich

Ben
quelle
0

Wenn Sie ASP.NET MVC verwenden, reicht es aus, diese Zeile über der Controller-Aktion hinzuzufügen:

[OutputCache(NoStore=true, Duration = 0, VaryByParam = "None")]
public ActionResult getSomething()
{

}
Batmaci
quelle
Das fragliche Verhalten ist auf der Browserseite; Diese Antwort bezieht sich auf das Caching auf der Serverseite.
Mark Sowul
@MarkSowul Outputcache bietet 3 Optionen: Client, Server und alle. IE verwendet standardmäßig OutputCache, was hauptsächlich als clientseitiges Caching dient. Sie können mehr Details hier sehen dougwilsonsa.wordpress.com/2011/04/29/…
batmaci
@ MarkSowul Sie können auch die verwandte Frage und Antwort hier sehen. Denken Sie, dass dies auch auf der Serverseite ist? stackoverflow.com/questions/2653092/…
Batmaci
1
Ja, tut mir leid, Sie haben Recht. Ich wusste nicht, dass Ihre Antwort sowohl den serverseitigen als auch den clientseitigen Cache betreffen kann .
Mark Sowul
-1

IE hat das Recht, dieses Caching durchzuführen. Um sicherzustellen, dass das Element nicht zwischengespeichert wird, sollten die Überschriften entsprechend festgelegt werden.

Wenn Sie ASP.NET MVC verwenden, können Sie eine ActionFilter; in OnResultExecuted, überprüfenfilterContext.HttpContext.Request.IsAjaxRequest() . Wenn ja, setzen Sie den Ablauf-Header der Antwort:filterContext.HttpContext.Response.Expires = -1;

Gemäß http://www.dashbay.com/2011/05/internet-explorer-caches-ajax/ :

Einige Leute bevorzugen es, den Cache-Control: no-Cache-Header zu verwenden, anstatt abzulaufen. Hier ist der Unterschied:
Cache-Kontrolle: kein Cache - absolut KEIN Caching
Läuft ab: -1 - Der Browser kontaktiert "normalerweise" den Webserver, um Aktualisierungen dieser Seite über eine bedingte If-Modified-Since-Anforderung zu erhalten. Die Seite verbleibt jedoch im Festplatten-Cache und wird in geeigneten Situationen verwendet, ohne den Remote-Webserver zu kontaktieren, z. B. wenn die Schaltflächen BACK und FORWARD für den Zugriff auf den Navigationsverlauf verwendet werden oder wenn sich der Browser im Offline-Modus befindet.

Mark Sowul
quelle