$ .getJSON che restituisce dati memorizzati nella cache in IE8


102

Al momento sto giocando con ASP.net MVC e JQuery. Mi sono imbattuto in comportamenti che non sembrano avere senso.

Sto chiamando la $.getJSONfunzione di JQuery per popolare alcuni div. L'evento viene attivato $(document).readysull'evento. Funziona perfettamente.

C'è un piccolo AJAX.BeginFormche aggiunge un altro valore da usare quando si popolano i div. Chiama correttamente la funzione remota e in caso di successo chiama la funzione javascript originale per ripopolare i div.

Ecco la parte strana: in FireFox e Chrome: tutto funziona. MA In IE8 (Beta) questa seconda chiamata allo script Div popolato (che chiama la funzione $ .getJSON) ottiene i dati memorizzati nella cache e non chiede al server!

Spero che questa domanda abbia senso: in poche parole, perché si $.getJSONottengono dati memorizzati nella cache? E perché ha effetto solo su IE8?


Stranamente, vedo questo bug non solo in IE, ma anche in Firefox. La disabilitazione del caching ajax in jquery mi ha aiutato.
Josef Sábl

Risposte:


67

Solo per farti sapere, Firefox e Chrome considerano tutte le richieste Ajax come non cachable. IE (tutte le versioni) trattano le chiamate Ajax come le altre richieste web. Ecco perché vedi questo comportamento.
Come forzare IE a scaricare i dati ad ogni richiesta:

  • Come hai detto, usa l'opzione "cache" o "nocache" in JQuery
  • Aggiungi un parametro casuale alla richiesta (brutto, ma funziona :))
  • Sul lato server, imposta la cachability (ad esempio utilizzando un attributo, vedi sotto)

Codice:

public class NoCacheAttribute : ActionFilterAttribute
{
    public override void OnActionExecuted(ActionExecutedContext context)
    {
        context.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache);
    }
}

1
Questa soluzione mi piace. Mi piace molto l'eleganza di applicare un attributo in MVC
Andrew Harry il

1
Al giorno d'oggi c'è un OutputCacheAttribute OOTB.
bzlm

1
@bzlm ma è più facile da cercare
Simon_Weaver

controlla formatinternet.wordpress.com/2010/01/14/… per una soluzione lato client
Ivo

1
In realtà, è il contrario, ma sono d'accordo come sviluppatore IE richiede pazienza :)
Nico

107

Ecco come ha funzionato per me ...

$.ajaxSetup({ cache: false });
$.getJSON("/MyQueryUrl",function(data,item) {
     // do stuff with callback data
     $.ajaxSetup({ cache: true });
   });

Stavo lottando con questo problema e la tua soluzione ha fornito un modo rapido per risolverlo. :) Ho una domanda, sai quali opzioni possono essere utilizzate per $ .ajaxSetup? La documentazione di jQuery non fornisce dettagli purtroppo ...
Achimnol

1
Le opzioni disponibili sono identiche a $ .ajax Vedi docs.jquery.com/Ajax/jQuery.ajax#options per maggiori informazioni
Dan Esparza

12
Un piccolo avvertimento per il codice precedente: contiene una condizione di gara. Poiché la chiamata e la sua risposta sono asincrone, è necessario chiamare $.ajaxSetup({ cache: true });subito dopo getJSON()e non nel callback.
sax

16

Grazie Kent per la tua risposta. Utilizzando $ .ajax ('{cache: no}'); ha funzionato perfettamente. [modificare]

O almeno pensavo di averlo fatto. Sembra che jquery $ .getJSON non stia leggendo le modifiche apportate all'oggetto $ .ajax.

La soluzione che ha finito per funzionare è stata l'aggiunta manuale di un nuovo parametro

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

la risoluzione della data è solo al minuto; il che significa che questa soluzione è ancora memorizzata nella cache fino a un minuto. Questo è accettabile per i miei scopi.


9
var noCache = new Date (). getTime (); // ti darò a ms
scunliffe il

grazie Scunliffe! - Sono abbastanza nuovo in javascript, ASP MVC ha aperto nuovi orizzonti per me
Andrew Harry,

Puoi anche provare qualcosa come Math.Random ().
Falkayn

@Falkayn - Math.Random()potrebbe essere usato duro , i suoi risultati saranno sconosciuti e potresti ottenere lo stesso numero due volte di seguito (o più). l'utilizzo new Date().getTime()farà in modo che non venga mai ripetuto. (a meno che tu non sia in grado di tornare indietro nel tempo;))
Demenza

11

Ho risolto lo stesso problema inserendo il seguente attributo nell'azione nel controller:

[OutputCache(Duration = 0, VaryByParam = "None")]

Meraviglioso! Ottimo per avere alternative (ho scelto questa). Grazie a tutti i collaboratori!
Anders Juul

Funziona bene con Asp.Net MVC 4.0
Mayank

4

Se stai usando ASP.net MVC, considera l'aggiunta di un metodo di estensione per implementare facilmente nessuna memorizzazione nella cache in questo modo:

    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");
    }

Bella idea, quindi chiami questo metodo di estensione sul server durante la richiamata, giusto?
Guy

2

Potrebbe essere necessario inviare un interruttore di cache.

Consiglierei di usare $ .ajax ({cache: no}) per ogni evenienza (aggiunge un suffisso casuale alla richiesta get)

(Tendo a usare $ .ajax ovunque in questi giorni, più sintonizzabile)


Grazie per la tua risposta! ... non l'ho ancora provato. Fornirà feedback a breve
Andrew Harry,

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.