Evite el almacenamiento en caché en ASP.NET MVC para acciones específicas utilizando un atributo

Tengo una aplicación ASP.NET MVC 3. Esta aplicación solicita registros a través de JQuery. JQuery devuelve la llamada a una acción del controlador que devuelve resultados en formato JSON. No he podido probar esto, pero me preocupa que mis datos puedan estar en caché.

Solo quiero que el almacenamiento en caché se aplique a acciones específicas, no para todas las acciones.

¿Hay algún atributo que pueda poner en acción para garantizar que los datos no se almacenen en caché? Si no, ¿cómo me aseguro de que el navegador obtenga un nuevo conjunto de registros cada vez, en lugar de un conjunto en caché?

Para asegurarse de que JQuery no almacena en caché los resultados, en sus métodos ajax, coloque lo siguiente:

$.ajax({ cache: false //rest of your ajax setup }); 

O para evitar el almacenamiento en caché en MVC, creamos nuestro propio atributo, podrías hacer lo mismo. Aquí está nuestro código:

 [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] public sealed 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 solo decora tu controlador con [NoCache] . O para hacerlo para todo, simplemente podría poner el atributo en la clase de la clase base de la que hereda sus controladores (si tiene uno) como la que tenemos aquí:

 [NoCache] public class ControllerBase : Controller, IControllerBase 

También puede decorar algunas de las acciones con este atributo si necesita que no sean almacenables en caché, en lugar de decorar todo el controlador.

Si su clase o acción no tiene NoCache cuando se NoCache en su navegador y desea verificar que esté funcionando, recuerde que después de comstackr los cambios, debe hacer una “actualización” (Ctrl + F5) en su navegador. Hasta que lo haga, su navegador conservará la versión antigua en caché y no la actualizará con una “actualización normal” (F5).

Puede usar el atributo de caché incorporado para evitar el almacenamiento en caché.

Para .Net Framework: [OutputCache(NoStore = true, Duration = 0)]

Para .net Core: [ResponseCache(NoStore = true, Duration = 0)]

Tenga en cuenta que es imposible obligar al navegador a desactivar el almacenamiento en caché. Lo mejor que puede hacer es proporcionar sugerencias que la mayoría de los navegadores respetarán, generalmente en forma de encabezados o metatags. Este atributo de decorador deshabilitará el almacenamiento en memoria caché del servidor y también agregará este encabezado: Cache-Control: public, no-store, max-age=0 . No agrega metatags. Si lo desea, se pueden agregar manualmente en la vista.

Además, JQuery y otros marcos de trabajo del cliente intentarán engañar al navegador para que no use su versión en caché de un recurso añadiendo cosas a la url, como una indicación de fecha y hora o un GUID. Esto es efectivo al hacer que el navegador solicite nuevamente el recurso, pero realmente no previene el almacenamiento en caché.

En una nota final. Debe tener en cuenta que los recursos también se pueden almacenar en caché entre el servidor y el cliente. Los ISP, los proxies y otros dispositivos de red también almacenan en caché recursos y, a menudo, usan reglas internas sin mirar el recurso real. No hay mucho que puedas hacer sobre esto. La buena noticia es que normalmente almacenan en caché para marcos de tiempo más cortos, como segundos o minutos.

Todo lo que necesitas es:

 [OutputCache(Duration=0)] public JsonResult MyAction( 

o, si desea deshabilitarlo para un Controlador completo:

 [OutputCache(Duration=0)] public class MyController 

A pesar del debate en los comentarios aquí, esto es suficiente para desactivar el almacenamiento en caché del navegador: esto hace que ASP.Net emita encabezados de respuesta que le dicen al navegador que el documento caduca de inmediato:

OutputCache Duration = 0 Headers de respuesta: max-age = 0, s-maxage = 0

En la acción del controlador, agregue al encabezado las siguientes líneas

  public ActionResult Create(string PositionID) { Response.AppendHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1. Response.AppendHeader("Pragma", "no-cache"); // HTTP 1.0. Response.AppendHeader("Expires", "0"); // Proxies. 

Aquí está el atributo NoCache propuesto por mattytommo, simplificado al usar la información de la respuesta de Chris Moschini:

 [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] public sealed class NoCacheAttribute : OutputCacheAttribute { public NoCacheAttribute() { this.Duration = 0; } } 

Para MVC6 ( DNX ), no hay System.Web.OutputCacheAttribute

Nota: cuando configura el parámetro NoStore Duration no se considera. Es posible establecer una duración inicial para el primer registro y anular esto con atributos personalizados.

Pero tenemos Microsoft.AspNet.Mvc.Filters.ResponseCacheFilter

  public void ConfigureServices(IServiceCollection services) ... services.AddMvc(config=> { config.Filters.Add( new ResponseCacheFilter( new CacheProfile() { NoStore=true })); } ... ) 

Es posible anular el filtro inicial con un atributo personalizado

  [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] public sealed class NoCacheAttribute : ActionFilterAttribute { public override void OnResultExecuting(ResultExecutingContext filterContext) { var filter=filterContext.Filters.Where(t => t.GetType() == typeof(ResponseCacheFilter)).FirstOrDefault(); if (filter != null) { ResponseCacheFilter f = (ResponseCacheFilter)filter; f.NoStore = true; //f.Duration = 0; } base.OnResultExecuting(filterContext); } } 

Aquí hay un caso de uso

  [NoCache] [HttpGet] public JsonResult Get() { return Json(new DateTime()); } 

Almacenamiento en caché de salida en MVC

 [OutputCache (NoStore = true, Duration = 0, Location = "None", VaryByParam = "*")]

 O
 [OutputCache (NoStore = true, Duration = 0, VaryByParam = "None")]

El valor de atributo correcto para Asp.Net MVC Core para evitar el almacenamiento en caché del navegador (incluido Internet Explorer 11 ) es:

 [ResponseCache(Location = ResponseCacheLocation.None, NoStore = true)] 

como se describe en la documentación de Microsoft:

Almacenamiento en caché de respuestas en ASP.NET Core – NoStore y Location.None