$ .getJSON devolviendo datos en caché en IE8

102

Estoy jugando con ASP.net MVC y JQuery en este momento. Me he encontrado con un comportamiento que no parece tener sentido.

Estoy llamando a la $.getJSONfunción de JQuery para completar algunos div. El evento se activa en el $(document).readyevento. Esto funciona perfectamente.

Hay un pequeño AJAX.BeginFormque agrega otro valor para usar al completar los divs. Llama a la función remota correctamente y, si tiene éxito, llama a la función javascript original para volver a llenar los divs.

Aquí está la parte extraña: en FireFox y Chrome, todo funciona. PERO en IE8 (Beta) esta segunda llamada al script Div (que llama a la función $ .getJSON) obtiene datos en caché y no pregunta al servidor.

Espero que esta pregunta tenga sentido: En pocas palabras: ¿Por qué se $.getJSONobtienen datos almacenados en caché? ¿Y por qué solo afecta a IE8?

Andrew Harry
fuente
Curiosamente, veo este error no solo en IE, sino también en Firefox. Deshabilitar el almacenamiento en caché de Ajax en jquery me ayudó.
Josef Sábl

Respuestas:

67

Solo para informarle, Firefox y Chrome consideran que todas las solicitudes de Ajax no se pueden almacenar en caché. IE (todas las versiones) trata la llamada Ajax como cualquier otra solicitud web. Por eso ves este comportamiento.
Cómo forzar a IE a descargar datos en cada solicitud:

  • Como dijiste, usa la opción 'cache' o 'nocache' en JQuery
  • Agregue un parámetro aleatorio a la solicitud (feo, pero funciona :))
  • En el lado del servidor, configure la capacidad de caché (por ejemplo, usando un atributo, ver más abajo)

Código:

public class NoCacheAttribute : ActionFilterAttribute
{
    public override void OnActionExecuted(ActionExecutedContext context)
    {
        context.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache);
    }
}
Nico
fuente
1
Esta solución me atrae. Me gusta mucho la elegancia de aplicar un atributo en MVC
Andrew Harry
1
Existe un OutputCacheAttribute OOTB hoy en día.
bzlm
1
@bzlm pero esto es más fácil de buscar
Simon_Weaver
consulte formatinternet.wordpress.com/2010/01/14/… para una solución del lado del cliente
Ivo
1
En realidad, es al revés, pero estoy de acuerdo como desarrollador, IE requiere paciencia :)
Nico
107

Así es como funcionó para mí ...

$.ajaxSetup({ cache: false });
$.getJSON("/MyQueryUrl",function(data,item) {
     // do stuff with callback data
     $.ajaxSetup({ cache: true });
   });
Jitesh Patil
fuente
Estaba luchando con este problema y su solución me brindó una forma rápida de resolverlo. :) Tengo una pregunta, ¿sabe qué opciones se pueden usar para $ .ajaxSetup? La documentación de jQuery no proporciona detalles desafortunadamente ...
Achimnol
1
Las opciones disponibles son idénticas a $ .ajax Consulte docs.jquery.com/Ajax/jQuery.ajax#options para obtener más información
Dan Esparza
12
Una pequeña advertencia para el código anterior: contiene condición de carrera. Debido a que la llamada y su respuesta son asincrónicas, debe llamar $.ajaxSetup({ cache: true });justo después del getJSON()y no en la devolución de llamada.
saxo
16

Gracias Kent por tu respuesta. Usando $ .ajax ('{cache: no}'); funcionó perfectamente. [editar]

O al menos pensé que sí. Parece que jquery $ .getJSON no está leyendo ningún cambio realizado en el objeto $ .ajax.

La solución que terminó funcionando fue agregar un nuevo parámetro manualmente

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

la resolución de la fecha es solo al minuto; lo que significa que esta solución todavía se almacena en caché durante un minuto. Esto es aceptable para mis propósitos.

Andrew Harry
fuente
9
var noCache = new Date (). getTime (); // te dará el ms
scunliffe
gracias Scunliffe! - Soy bastante nuevo en javascript, ASP MVC me ha abierto nuevos horizontes
Andrew Harry
También puede probar algo como Math.Random ().
Falkayn
@Falkayn: se Math.Random()podría usar resistente , sus resultados serán desconocidos y es posible que obtenga el mismo número dos veces seguidas (o más). el uso new Date().getTime()se asegurará de que nunca se repita. (a menos que pueda retroceder en el tiempo;))
Dementic
11

Resolví este mismo problema colocando el siguiente atributo en la Acción en el Controlador:

[OutputCache(Duration = 0, VaryByParam = "None")]
Chico
fuente
¡Maravilloso! Genial tener alternativas (elegí esta). ¡Gracias a todos los colaboradores!
Anders Juul
Funciona bien con Asp.Net MVC 4.0
Mayank
4

Si está utilizando ASP.net MVC, considere agregar un método de extensión para implementar fácilmente sin almacenamiento en caché como este:

    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
fuente
Buena idea, entonces llama a este método de extensión en el servidor durante la devolución de llamada, ¿verdad?
Guy
2

Es posible que deba enviar un eliminador de caché.

Recomendaría usar $ .ajax ({cache: no}) por si acaso (agrega un sufijo aleatorio a la solicitud de obtención)

(Tiendo a usar $ .ajax en todas partes estos días, más sintonizable)

Kent Fredric
fuente
¡Gracias por tu respuesta! ... aún no lo he probado. Proporcionará retroalimentación en breve
Andrew Harry