$ .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?


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

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

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.


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")]

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

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)


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

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.