$ .getJSON gibt zwischengespeicherte Daten in IE8 zurück

102

Ich spiele gerade mit ASP.net MVC und JQuery herum. Ich bin auf ein Verhalten gestoßen, das keinen Sinn ergibt.

Ich rufe die $.getJSONFunktion von JQuery auf , um einige Divs zu füllen. Das Ereignis wird für das $(document).readyEreignis ausgelöst . Das funktioniert perfekt.

Es gibt einen kleinen AJAX.BeginFormWert, der einen weiteren Wert hinzufügt, der beim Auffüllen der Divs verwendet werden soll. Es ruft die Remote-Funktion korrekt auf und ruft bei Erfolg die ursprüngliche Javascript-Funktion auf, um die Divs neu zu füllen.

Hier ist der seltsame Teil: In FireFox und Chrome - Alles funktioniert. ABER In IE8 (Beta) werden bei diesem zweiten Aufruf des Populate Div-Skripts (das die Funktion $ .getJSON aufruft) zwischengespeicherte Daten abgerufen und der Server nicht gefragt!

Hoffe, diese Frage macht Sinn: Kurz gesagt - Warum werden $.getJSONzwischengespeicherte Daten abgerufen? Und warum wirkt es sich nur auf IE8 aus?

Andrew Harry
quelle
Seltsamerweise sehe ich diesen Fehler nicht nur im IE, sondern auch in Firefox. Das Deaktivieren des Ajax-Caching in jquery hat mir geholfen.
Josef Sábl

Antworten:

67

Nur um Sie wissen zu lassen, betrachten Firefox und Chrome alle Ajax-Anfragen als nicht zwischenspeicherbar. IE (alle Versionen) behandeln Ajax-Aufruf genauso wie andere Webanfragen. Deshalb sehen Sie dieses Verhalten.
So zwingen Sie den IE, bei jeder Anforderung Daten herunterzuladen:

  • Verwenden Sie, wie gesagt, die Option "Cache" oder "Nocache" in JQuery
  • Fügen Sie der Anfrage einen zufälligen Parameter hinzu (hässlich, funktioniert aber :))
  • Legen Sie auf der Serverseite die Cachfähigkeit fest (z. B. mithilfe eines Attributs, siehe unten).

Code:

public class NoCacheAttribute : ActionFilterAttribute
{
    public override void OnActionExecuted(ActionExecutedContext context)
    {
        context.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache);
    }
}
Nico
quelle
1
Diese Lösung gefällt mir. Ich mag die Eleganz, ein Attibute in MVC anzuwenden
Andrew Harry
1
Heutzutage gibt es ein OutputCacheAttribute OOTB.
bzlm
1
@bzlm aber das ist einfacher zu suchen
Simon_Weaver
Schauen Sie sich formatinternet.wordpress.com/2010/01/14/… für eine clientseitige Lösung an
Ivo
1
Eigentlich ist es umgekehrt, aber ich stimme zu, dass ein Entwickler-IE Geduld erfordert :)
Nico
107

So hat es bei mir funktioniert ...

$.ajaxSetup({ cache: false });
$.getJSON("/MyQueryUrl",function(data,item) {
     // do stuff with callback data
     $.ajaxSetup({ cache: true });
   });
Jitesh Patil
quelle
Ich hatte mit diesem Problem zu kämpfen und Ihre Lösung gab einen schnellen Weg, es zu lösen. :) Ich habe eine Frage, wissen Sie, welche Optionen für $ .ajaxSetup verwendet werden können? jQuery Dokumentation enthält leider keine Details ...
Achimnol
1
Die verfügbaren Optionen sind identisch mit $ .ajax. Weitere Informationen finden Sie unter docs.jquery.com/Ajax/jQuery.ajax#options
Dan Esparza
12
Eine kleine Warnung für den obigen Code - er enthält die Rennbedingungen. Da der Anruf und seine Antwort asynchron sind, sollten Sie $.ajaxSetup({ cache: true });direkt nach dem getJSON()und nicht im Rückruf anrufen .
Sax
16

Danke Kent für deine Antwort. Using $ .ajax ('{cache: no}'); hat perfekt funktioniert. [bearbeiten]

Zumindest dachte ich, ich hätte es getan. Scheint, dass die Abfrage $ .getJSON keine Änderungen liest, die am $ .ajax-Objekt vorgenommen wurden.

Die Lösung bestand darin, manuell einen neuen Parameter hinzuzufügen

var noCache = Date();
$.getJSON("/somepage/someaction", { "noCache": noCache }, Callback);

Die Datumsauflösung ist nur auf die Minute genau. Dies bedeutet effektiv, dass diese Lösung noch bis zu einer Minute zwischengespeichert wird. Dies ist für meine Zwecke akzeptabel.

Andrew Harry
quelle
9
var noCache = neues Datum (). getTime (); // wird Sie zur ms
scunliffe
danke Scunliffe! - Ich bin ziemlich neu in Javascript, ASP MVC hat mir neue Horizonte eröffnet
Andrew Harry
Sie können auch etwas wie Math.Random () ausprobieren.
Falkayn
@Falkayn - hart Math.Random()könnte verwendet werden, seine Ergebnisse sind unbekannt und Sie erhalten möglicherweise zweimal hintereinander dieselbe Nummer (oder mehr). Mit new Date().getTime()wird sichergestellt, dass es niemals wiederholt wird. (es sei denn, Sie können in der Zeit zurückgehen;))
Dementic
11

Ich habe dasselbe Problem gelöst, indem ich das folgende Attribut für die Aktion im Controller platziert habe:

[OutputCache(Duration = 0, VaryByParam = "None")]
Kerl
quelle
Wunderbar! Großartig, Alternativen zu haben (ich habe diese gewählt). Vielen Dank an alle Mitwirkenden!
Anders Juul
Funktioniert gut mit Asp.Net MVC 4.0
Mayank
4

Wenn Sie ASP.net MVC verwenden, sollten Sie eine Erweiterungsmethode hinzufügen, um auf einfache Weise kein Caching wie folgt zu implementieren:

    public static void NoCache(this HttpResponse Response)
    {
        Response.Cache.SetNoStore();
        Response.Cache.SetExpires(DateTime.MinValue);
        Response.Cache.SetCacheability(HttpCacheability.NoCache);
        Response.Cache.SetValidUntilExpires(false);

        Response.Expires = -1;
        Response.ExpiresAbsolute = DateTime.MinValue;
        Response.AddHeader("Cache-Control", "no-cache");
        Response.AddHeader("Pragma", "no-cache");
    }
Josh
quelle
Gute Idee - also rufen Sie diese Erweiterungsmethode während des Rückrufs auf dem Server auf, oder?
Guy
2

Möglicherweise müssen Sie einen Cache-Breaker senden.

Ich würde empfehlen, $ .ajax ({cache: no}) nur für den Fall zu verwenden (fügt der get-Anfrage ein zufälliges Suffix hinzu)

(Ich benutze heutzutage überall $ .ajax, besser abstimmbar)

Kent Fredric
quelle
Danke für deine Antwort! ... ich habe es noch nicht ausprobiert. Wird in Kürze Feedback geben
Andrew Harry