Deshabilite el caché del navegador para todo el sitio web ASP.NET

199

Estoy buscando un método para deshabilitar la memoria caché del navegador para todo un sitio web ASP.NET MVC

Encontré el siguiente método:

Response.Cache.SetCacheability(System.Web.HttpCacheability.NoCache);
Response.Cache.SetNoStore();

Y también un método de metaetiqueta (no funcionará para mí, ya que algunas acciones de MVC envían HTML / JSON parcial a través de Ajax, sin una metaetiqueta de cabecera).

<meta http-equiv="PRAGMA" content="NO-CACHE">

Pero estoy buscando un método simple para deshabilitar la memoria caché del navegador para todo un sitio web.

Palani
fuente

Respuestas:

92
HttpContext.Current.Response.Cache.SetExpires(DateTime.UtcNow.AddDays(-1));
HttpContext.Current.Response.Cache.SetValidUntilExpires(false);
HttpContext.Current.Response.Cache.SetRevalidation(HttpCacheRevalidation.AllCaches);
HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.NoCache);
HttpContext.Current.Response.Cache.SetNoStore();

Todas las solicitudes se enrutan a través de default.aspx primero, por lo que suponiendo que pueda ingresar el código detrás de allí.

Squiggs
fuente
17
Lo pondría en Global.asax.cs en Application_BeginRequest (). No confío en esta cosa default.aspx ... Otra pregunta: ¿esto tiene prioridad sobre los atributos [OutputCache]?
chris166
55
Me gusta la idea de simplemente crear un filtro de acción global y poner esto de esa manera. Niega la necesidad de preocuparse por Default.aspx y Global.asax.
Keith Adler
13
Poner esto en Application_BeingRequest puede causar algunos problemas. Si sus imágenes se enrutan a través del tiempo de ejecución de .net (lo que puede suceder si está utilizando la asignación de comodines para urls agradables), entonces no se almacenará ninguna imagen en el navegador. Esto REALMENTE puede ralentizar los tiempos de carga de su página ya que cada solicitud de página volverá a descargar todas las imágenes.
herbrandson
44
Usar cualquier cosa mediante programación siempre anulará cualquier atributo declarado. En otras palabras, el uso del código del OP anulará cualquier atributo [OutputCache] declarado.
Dave Black el
¿Alguna idea sobre cómo hacer una prueba de humo y verificar que la desactivación de caché realmente esté funcionando?
paaone
366

Cree una clase que herede de IActionFilter.

public class NoCacheAttribute : ActionFilterAttribute
{  
    public override void OnResultExecuting(ResultExecutingContext filterContext)
    {
        filterContext.HttpContext.Response.Cache.SetExpires(DateTime.UtcNow.AddDays(-1));
        filterContext.HttpContext.Response.Cache.SetValidUntilExpires(false);
        filterContext.HttpContext.Response.Cache.SetRevalidation(HttpCacheRevalidation.AllCaches);
        filterContext.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache);
        filterContext.HttpContext.Response.Cache.SetNoStore();

        base.OnResultExecuting(filterContext);
    }
}

Luego ponga atributos donde sea necesario ...

[NoCache]
[HandleError]
public class AccountController : Controller
{
    [NoCache]
    [Authorize]
    public ActionResult ChangePassword()
    {
        return View();
    }
}
JKG
fuente
19
En lugar de HttpContext.Current.Response, probablemente debería usar filterContext.HttpContext.Response ya que HttpContext.Current devuelve el objeto HttpContext anterior a MVC y el filterContext.HttpContext devuelve el HttpContextBase posterior a MVC. Aumenta la capacidad de prueba y la consistencia.
mkedobbs
55
IActionFilter ya está implementado en ActionFilterAttribute, por lo que no necesita repetirlo.
Andrew Davey
104
En las versiones actuales de ASP.NET MVC, simplemente puede usar OutputCacheAttribute para evitar el almacenamiento en caché: [OutputCache (NoStore = true, Duration = 0, VaryByParam = "None")]
Ashley Tate
9
Me gustaría señalar que acabo de pasar varios días utilizando cada solución "poner esto en su código para detener el almacenamiento en caché" bajo el sol para ASP.NET MVC, incluida la respuesta aceptada a esta pregunta, sin ningún resultado. Esta respuesta, el atributo, funcionó. + 1M representante si pudiera ...
Tom Kidd
55
Es posible que desee agregar if (filterContext.IsChildAction) return;en la parte superior; esto evitará que la acción externa no se almacene en caché si llama a una acción secundaria que está decorada con un NoCacheatributo. En otras palabras, el NoCacheatributo no se filtrará a otras acciones si ejecutan acciones secundarias. Además, el nombre de la clase debe NoCacheAttributecumplir con la convención de nomenclatura generalmente aceptada para los atributos.
Jakub Konecki
132

En lugar de rodar el suyo, simplemente use lo que se le proporciona.

Como se mencionó anteriormente, no deshabilite el almacenamiento en caché para todo. Por ejemplo, los scripts jQuery que se usan mucho en ASP.NET MVC deben almacenarse en caché. En realidad, idealmente debería usar un CDN para esos de todos modos, pero mi punto es que algún contenido debe almacenarse en caché.

Lo que encuentro funciona mejor aquí en lugar de rociar el [OutputCache] en todas partes es usar una clase:

[System.Web.Mvc.OutputCache(NoStore = true, Duration = 0, VaryByParam = "*")]
public class NoCacheController  : Controller
{
}

Todos los controladores para los que desea deshabilitar el almacenamiento en caché heredan de este controlador.

Si necesita anular los valores predeterminados en la clase NoCacheController, simplemente especifique la configuración de caché en su método de acción y la configuración en su método de Acción tendrá prioridad.

[HttpGet]
[OutputCache(NoStore = true, Duration = 60, VaryByParam = "*")]
public ViewResult Index()
{
  ...
}
Adam Tuliper - MSFT
fuente
44
@Ozziepeeps, tu comentario no es correcto. Los documentos msdn analizan el almacenamiento en caché del navegador y una prueba simple mostrará que este atributo cambia el encabezado de respuesta de control de caché a "Cache-Control: public, no-store, max-age = 0" de "Cache-Control: private" sin utilizando el atributo
Adam Tuliper - MSFT
2
también para su información: puede controlar las tres ubicaciones (servidor, proxy, cliente) con este atributo para que pueda controlar más allá del caché del servidor. Ver asp.net/mvc/tutorials/… para algunos detalles adicionales.
Adam Tuliper - MSFT
1
+1 "Si necesita anular los valores predeterminados en la clase NoCacheController, simplemente especifique las configuraciones de caché en su método de acción y las configuraciones en su método de Acción tendrán prioridad".
Korayem el
2
Tenga en cuenta que si usa [System.Web.Mvc.OutputCache(NoStore = true, Duration = 0, VaryByParam = "*")]a nivel de clase, no puede tener PartialViews en su clase.
Vivian River
1
El método OutputCache no evitó el almacenamiento en caché de IE cuando existían dos condiciones: 1) la acción no tomó parámetros y 2) la acción solo devolvió texto a través de Contenido (someText). Cuando devuelvo JSON y tomo un parámetro, el almacenamiento en caché de IE se derrota correctamente.
Kasey Speakman
10

Es posible que desee deshabilitar el almacenamiento en caché del navegador para todas las páginas representadas por los controladores (es decir, páginas HTML), pero mantenga el almacenamiento en caché en su lugar para recursos como secuencias de comandos, hojas de estilo e imágenes . Si está utilizando la agrupación y minificación MVC4 +, querrá mantener las duraciones de caché predeterminadas para scripts y hojas de estilo (duraciones muy largas, ya que la caché se invalida en función de un cambio en una URL única, no en función del tiempo).

En MVC4 +, para deshabilitar el almacenamiento en caché del navegador en todos los controladores, pero retenerlo para cualquier cosa que no sea servida por un controlador, agregue esto a FilterConfig.RegisterGlobalFilters:

filters.Add(new DisableCache());

Definir de la DisableCachesiguiente manera:

class DisableCache : ActionFilterAttribute
{
    public override void OnResultExecuting(ResultExecutingContext filterContext)
    {
        filterContext.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache);
    }
}
Edward Brey
fuente
Desafortunadamente, esto no parece funcionar, ya que presionar el botón Atrás después de cerrar sesión muestra la página.
ʙᴀᴋᴇʀ ʙᴀᴋᴇʀ
6

Sé que esta respuesta no está 100% relacionada con la pregunta, pero podría ayudar a alguien.

Si desea deshabilitar la memoria caché del navegador para todo el sitio web ASP.NET MVC , pero solo desea hacerlo TEMPORALMENTE, entonces es mejor deshabilitar la memoria caché en su navegador.

Aquí hay una captura de pantalla en Chrome

Carlos Martinez T
fuente
Esto es exactamente lo que estaba buscando ... durante el desarrollo, si cambio un archivo .js, es un gran problema conseguirlo de inmediato cuando tengo problemas para solucionar problemas pequeños / actualizar / ciclos de prueba. Esto es perfecto, gracias! Acabo de hacer mi vida de depuración del lado del cliente mucho más fácil
jleach
2

Implementé todas las respuestas anteriores y aún tenía una vista que no funcionaba correctamente.

Resultó que el nombre de la vista con la que estaba teniendo el problema se llamaba 'Reciente'. Aparentemente esto confundió el navegador Internet Explorer.

Después de cambiar el nombre de la vista (en el controlador) a un nombre diferente (elegí 'Reciente5'), las soluciones anteriores comenzaron a funcionar.

DrHooverCraft
fuente
0

Puede probar el siguiente código en el archivo Global.asax.

protected void Application_BeginRequest()
    {
        Response.Cache.SetCacheability(HttpCacheability.NoCache);
        Response.Cache.SetExpires(DateTime.UtcNow.AddHours(-1));
        Response.Cache.SetNoStore();
    }
NidhinSPradeep
fuente
-1

UI

<%@ OutPutCache Location="None"%>
<%
    Response.Buffer = true;
    Response.Expires = -1;
    Response.ExpiresAbsolute = System.DateTime.Now.AddSeconds(-1);
    Response.CacheControl = "no-cache";
%>

Antecedentes

Context.Response.Cache.SetCacheability(HttpCacheability.NoCache); 
Response.Expires = -1;          
Response.Cache.SetNoStore();
Alfa
fuente
1
las necesidades de la prosa de motivos, incluso si es técnicamente correcto
rmalayter