Deshabilitar el almacenamiento en caché del navegador para todos los navegadores de ASP.NET

87

Estoy buscando una referencia definitiva a qué código ASP.NET se requiere para que los navegadores deshabiliten el almacenamiento en caché de la página. Hay muchas formas de afectar los encabezados HTTP y las metaetiquetas y tengo la impresión de que se requieren diferentes configuraciones para que los diferentes navegadores se comporten correctamente. Sería realmente bueno que se comentara un fragmento de código de referencia para indicar cuál funciona para todos los navegadores y cuál es necesario para un navegador en particular, incluidas las versiones.

Hay una gran cantidad de información sobre este tema, pero todavía tengo que encontrar una buena referencia que describa los beneficios de cada método y si una técnica en particular ha sido reemplazada por una API de nivel superior.

Estoy particularmente interesado en ASP.NET 3.5 SP1, pero también sería bueno obtener respuestas para la versión anterior.

Esta entrada de blog Dos diferencias importantes entre el almacenamiento en caché de Firefox e IE describe algunas diferencias de comportamiento del protocolo HTTP.

El siguiente código de muestra ilustra el tipo de cosas que me interesan

public abstract class NoCacheBasePage : System.Web.UI.Page
{
    protected override void OnInit(EventArgs e)
    {
        base.OnInit(e);

        DisableClientCaching();
    }

    private void DisableClientCaching()
    {
        // Do any of these result in META tags e.g. <META HTTP-EQUIV="Expire" CONTENT="-1">
        // HTTP Headers or both?

        // Does this only work for IE?
        Response.Cache.SetCacheability(HttpCacheability.NoCache);

        // Is this required for FireFox? Would be good to do this without magic strings.
        // Won't it overwrite the previous setting
        Response.Headers.Add("Cache-Control", "no-cache, no-store");

        // Why is it necessary to explicitly call SetExpires. Presume it is still better than calling
        // Response.Headers.Add( directly
        Response.Cache.SetExpires(DateTime.UtcNow.AddYears(-1));
    }
}
Martin Hollingsworth
fuente
5
Intentaría responder si no supiera cuán horriblemente imposible es tu tarea. Controlar la memoria caché del cliente es como intentar usar palillos de 10 pies de largo para reorganizar los muebles.
Jeff Meatball Yang
Un montón de respuestas que cubran solo una parte del problema seguirían siendo muy valiosas. Incluya su valor de 2 centavos.
Martin Hollingsworth

Respuestas:

96

Esto es lo que usamos en ASP.NET:

// Stop Caching in IE
Response.Cache.SetCacheability(System.Web.HttpCacheability.NoCache);

// Stop Caching in Firefox
Response.Cache.SetNoStore();

Deja de almacenar en caché en Firefox e IE, pero no hemos probado otros navegadores. Estas declaraciones agregan los siguientes encabezados de respuesta:

Cache-Control: no-cache, no-store
Pragma: no-cache
HttpWatchSupport
fuente
5
+1 Esto me está funcionando en Chrome, muchas gracias. También uso Response.Cache.SetAllowResponseInBrowserHistory (true); para evitar que el historial almacene una entrada para cada solicitud de la misma página.
daniloquio
12
Al parecer, alguien ha descubierto que el uso de SetCacheability con NoCache también desactiva la caché de salida ASP.NET (caché del lado del servidor). Sugieren usar la opción ServerAndNoCache en su lugar. codeclimber.net.nz/archive/2007/04/01/…
md1337
1
Para aclarar los comentarios en el fragmento de código, el método principal es SetCacheability. SetNoStorees una solución temporal de IE6. Consulte ¿Por qué se deben usar tanto sin caché como sin almacenamiento en la respuesta HTTP? .
Edward Brey
3
FWIW ... Necesario agregar SetNoStore para IE10
felickz
Para aquellos que lean esta página y que generarán archivos PDF dinámicos a través de https y establecerán los encabezados de caché como este, tengan cuidado con el siguiente error de IE8 y menor: stackoverflow.com/questions/1038707/…
Paddy
41

Por lo que vale, tuve que manejar esto en mi aplicación ASP.NET MVC 3. Aquí está el bloque de código que usé en el archivo Global.asax para manejar esto para todas las solicitudes.

    protected void Application_BeginRequest()
    {
        //NOTE: Stopping IE from being a caching whore
        HttpContext.Current.Response.Cache.SetAllowResponseInBrowserHistory(false);
        HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.NoCache);
        HttpContext.Current.Response.Cache.SetNoStore();
        Response.Cache.SetExpires(DateTime.Now);
        Response.Cache.SetValidUntilExpires(true);
    }
Adam Carr
fuente
El HttpContext.Current.Response.Cache.SetAllowResponseInBrowserHistory(false)hizo la diferencia para evitar el almacenamiento en caché en bith IE y Firefox
Michael Kniskern
2
-1, la configuración en estos Application_BeginRequest () hace que los encabezados sin caché se envíen para los elementos que probablemente desee almacenar en caché (archivos JavaScript, imágenes, etc.). No lo he probado todavía, pero la ubicación del OP (configurando los encabezados en la página ASP) es probablemente mejor.
Evan Haas
Esperaba que esta respuesta funcionara, ya que es la forma más ordenada de configurarla en glabal.asax, pero aún no hay alegría
lawphotog
5
@Evan, Application_BeginRequest solo se llamará para las solicitudes que se envían desde IIS a ASP.NET. Muchas veces, los archivos estáticos como CSS, JS, imágenes, fuentes, etc. son extensiones que se consideran archivos estáticos de IIS y no se envían al tiempo de ejecución de ASP.NET. Si IIS está configurado para enviar todas las solicitudes al tiempo de ejecución de ASP.NET, entonces sí, esto se aplicaría a todas las solicitudes, incluso si los archivos son estáticos y deben almacenarse en caché.
Adam Carr
@ Adam, tiene sentido. Deshacería mi -1 pero SO dice que mi voto está bloqueado :-(
Evan Haas
2

Probé varias combinaciones y fallaron en FireFox. Ha pasado un tiempo, por lo que la respuesta anterior puede funcionar bien o puede que me haya perdido algo.

Lo que siempre me ha funcionado es agregar lo siguiente al encabezado de cada página, o la plantilla (Página maestra en .net).

<script language="javascript" type="text/javascript">
    window.onbeforeunload = function () {   
        // This function does nothing.  It won't spawn a confirmation dialog   
        // But it will ensure that the page is not cached by the browser.
    }  
</script>

Esto ha desactivado todo el almacenamiento en caché en todos los navegadores sin falta.

Steve
fuente
7
No estoy seguro de qué se supone que debe hacer esto, pero parece un gran truco que seguramente fallará en la próxima actualización de cualquiera de estos navegadores.
md1337
Se explica en, por ejemplo, web.archive.org/web/20160112095216/http://www.hunlock.com/blogs/… - en resumen, el evento onbeforeunload se implementó para ser utilizado por los bancos y evita que la página se almacene en caché.
ChrisW
1

Hay dos enfoques que conozco. La primera es decirle al navegador que no almacene la página en caché. Establecer la Respuesta en sin caché se encarga de eso, sin embargo, como sospecha, el navegador a menudo ignorará esta directiva. El otro enfoque es establecer la fecha y hora de su respuesta en un punto en el futuro. Creo que todos los navegadores corregirán esto a la hora actual cuando agreguen la página al caché, pero mostrará la página como más nueva cuando se haga la comparación. Creo que puede haber algunos casos en los que no se haga una comparación. No estoy seguro de los detalles y cambian con cada nueva versión del navegador. Nota final He tenido más suerte con las páginas que se "actualizan" por sí mismas (otra directiva de respuesta). Parece menos probable que la actualización provenga del caché.

Espero que ayude.

Pat O
fuente
0

Voy a probar la adición de la etiqueta no-store a nuestro sitio para ver si esto hace una diferencia en el almacenamiento en caché del navegador (Chrome a veces ha estado almacenando en caché las páginas). También encontré este artículo muy útil sobre documentación sobre cómo y por qué funciona el almacenamiento en caché y veré ETag a continuación si el no-store no es confiable:

http://www.mnot.net/cache_docs/

http://en.wikipedia.org/wiki/HTTP_ETag

El codificador
fuente