El almacenamiento en caché inesperado de los resultados de AJAX en IE8

135

Tengo un problema grave con los resultados de almacenamiento en caché de Internet Explorer de una solicitud JQuery Ajax.

Tengo un encabezado en mi página web que se actualiza cada vez que un usuario navega a una nueva página. Una vez cargada la página hago esto

$.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");

Simplemente inyecta información de encabezado en la página. Puede verificarlo yendo a www.wikipediamaze.com y luego iniciando sesión y comenzando un nuevo rompecabezas.

En todos los navegadores que he probado (Google Chrome, Firefox, Safari, Internet Explorer) funciona muy bien, excepto en IE. Todo se inyecta bien en IE la primera vez, pero después de eso ni siquiera hace la llamada /game/getpuzzleinfo. Es como si hubiera almacenado en caché los resultados o algo así.

Si cambio la llamada a $.post("/game/getpuzzleinfo", ...IE, la contesta muy bien. Pero luego Firefox deja de funcionar.

¿Alguien puede arrojar algo de luz sobre por qué IE está almacenando en caché mis $.getllamadas ajax?

ACTUALIZAR

Según la sugerencia a continuación, he cambiado mi solicitud de ajax a esto, lo que solucionó mi problema:

$.ajax({
    type: "GET",
    url: "/game/getpuzzleinfo",
    dataType: "json",
    cache: false,
    success: function(data) { ... }
});
Micah
fuente
8
Gracias por preguntar esto. Estoy sin palabras que este comportamiento del navegador.
jjohn
1
Buena pregunta y sitio web realmente genial. Buena idea.
MikeMurko

Respuestas:

177

IE es conocido por su almacenamiento en caché agresivo de las respuestas de Ajax. Mientras usa jQuery, puede establecer una opción global:

$.ajaxSetup({
    cache: false
});

lo que hará que jQuery agregue un valor aleatorio a la cadena de consulta de solicitud, evitando que IE almacene en caché la respuesta.

Tenga en cuenta que si tiene otras llamadas Ajax en curso donde desea almacenar en caché, esto también lo deshabilitará. En ese caso, cambie a usar el método $ .ajax () y habilite esa opción explícitamente para las solicitudes necesarias.

Consulte http://docs.jquery.com/Ajax/jQuery.ajaxSetup para obtener más información.

NickFitz
fuente
1
También puede agregar una marca de tiempo al final de sus URL. No estoy seguro de por qué jQuery no va con este enfoque en su lugar.
Eric Johnson
14
@Eric: eso es lo que jQuery hace internamente: la opción "caché: falso" simplemente le dice que haga eso.
NickFitz
¿Por qué jquery no tiene esto activado por defecto?
Speedplane
Acabo de notar que las opciones de caché no funcionan cuando intenta solicitar la página de inicio en IE 8, con una llamada a /. Cámbielo /index.phpo sea cual sea la URL completa. O agregue algunos parámetros falsos como usted mismo/?f=f
Hugo Delsing
8

Como mencionó marr75 , GETse almacenan en caché.

Hay un par de formas de combatir esto. Además de modificar el encabezado de respuesta, también puede agregar una variable de cadena de consulta generada aleatoriamente al final de la URL de destino. De esta manera, IE pensará que es una URL diferente cada vez que se solicita.

Hay varias formas de hacer esto (como usar Math.random(), una variación en la fecha, etc.).

Aquí hay una manera de hacerlo:

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

Las gets siempre se pueden almacenar en caché. Una estrategia que puede funcionar es editar el encabezado de respuesta y decirle al cliente que no guarde en caché la información o que expire el caché muy pronto.

marr75
fuente
Eso suena como una buena idea. ¿Cómo voy a hacer eso?
Micah
1
Esa es una pregunta cargada, depende del código del lado del servidor. Consulte la entrada de Wikipedia "Lista de encabezados HTTP" para obtener una pequeña guía. Ejemplos: Cache-Control: no-cache Caduca: jue, 01 dic 1994 16:00:00 GMT Básicamente, necesita agregar estos encabezados de respuesta a su respuesta http. Es bastante simple en ASP.NET, Ruby y PHP. Simplemente busque el idioma del lado del servidor que está usando + modifique los encabezados de respuesta.
marr75
3
Además, y esto no es una crítica de Jquery en absoluto (me encanta esa biblioteca), el método de agregar un parámetro de cadena de consulta aleatoria es seguro pero descortés para el cliente (puede dejarlos reteniendo elementos en caché que nunca se usarán de nuevo).
marr75
2

Si está llamando a la página ashx, también puede deshabilitar el almacenamiento en caché en el servidor con el siguiente código:

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

esto es lo que hago para llamadas ajax:

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

Funciona bastante bien para mí.

Jason
fuente
1

NickFitz da una buena respuesta, pero también deberá desactivar el almacenamiento en caché en IE9. Para apuntar solo a IE8 e IE9, puede hacer esto;

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

Las respuestas aquí son muy útiles para aquellos que usan jQuery o por alguna razón usan directamente el objeto xmlHttpRequest ...

Si está utilizando el proxy de servicio de Microsoft generado automáticamente, no es tan fácil de resolver.

El truco es usar el método Sys.Net.WebRequestManager.add_invokingRequest en el controlador de eventos y cambiar la url de solicitud:

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

He blogueado sobre esto: http://yoavniran.wordpress.com/2010/04/27/ie-caching-ajax-results-how-to-fix/

poeticGeek
fuente
0

Acabo de escribir un blog sobre este tema exacto solo usando ExtJS ( http://thecodeabode.blogspot.com/2010/10/cache-busting-ajax-requests-in-ie.html )

El problema era que estaba usando un formato de reescritura de URL específico. No podía usar los parámetros de cadena de consulta convencionales (? Param = value), así que en su lugar había escrito el parámetro de eliminación de caché como una variable publicada ... Pensé que el uso de variables POST es un poco más seguro que GET, simplemente porque muchos marcos MVC usan el patrón

protocolo: // host / controller / action / param1 / param2

y así se pierde la asignación del nombre de la variable al valor, y los parámetros simplemente se apilan ... así que cuando se usa un parámetro GET buster

es decir, protocolo: // host / controller / action / param1 / param2 / no_cache122300201

no_cache122300201 puede confundirse con un parámetro $ param3 que podría tener un valor predeterminado

es decir

acción de función pública ($ param1, $ param2, $ param3 = "valor predeterminado") {//..//}

no hay posibilidad de que eso suceda con los buscadores de caché PUBLICADOS

Ben
fuente
0

Si está utilizando ASP.NET MVC, es suficiente agregar esta línea en la parte superior de la acción del controlador:

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

}
batmaci
fuente
El comportamiento en cuestión está en el lado del navegador; Esta respuesta se refiere al almacenamiento en caché en el lado del servidor.
Mark Sowul el
@MarkSowul Outputcache tiene 3 opciones Cliente, Servidor y cualquiera. IE usa OutputCache como predeterminado, lo que se aplica principalmente como almacenamiento en caché del lado del cliente. Puede ver más detalles aquí dougwilsonsa.wordpress.com/2011/04/29/…
batmaci
@ MarkSowul también puede ver la pregunta y la respuesta relacionadas aquí. ¿Crees que esto también está en el lado del servidor? stackoverflow.com/questions/2653092/…
batmaci
1
Sí, lo siento, tienes razón: no me di cuenta de que tu respuesta puede afectar tanto la caché del lado del servidor como la caché del lado del cliente.
Mark Sowul
-1

IE tiene derecho a hacer este almacenamiento en caché; Para asegurarse de que el elemento no se almacena en caché, los encabezados se deben configurar en consecuencia.

Si está utilizando ASP.NET MVC, puede escribir un ActionFilter; en OnResultExecuted, comprobar filterContext.HttpContext.Request.IsAjaxRequest(). Si es así, configure el encabezado de caducidad de la respuesta:filterContext.HttpContext.Response.Expires = -1;

Según http://www.dashbay.com/2011/05/internet-explorer-caches-ajax/ :

Algunas personas prefieren usar el encabezado Cache - Control: no - cache en lugar de caducar. Aquí está la diferencia:
Cache-Control: no-cache - absolutamente NO caching
Caduca: -1 - el navegador "generalmente" se pone en contacto con el servidor web para actualizaciones a esa página a través de una solicitud condicional If-Modified-Since. Sin embargo, la página permanece en el caché del disco y se usa en situaciones apropiadas sin contactar al servidor web remoto, como cuando se usan los botones ATRÁS y ADELANTE para acceder al historial de navegación o cuando el navegador está en modo fuera de línea.

Mark Sowul
fuente