Impedir o cache no ASP.NET MVC para ações específicas usando um atributo

Eu tenho um aplicativo ASP.NET MVC 3. Este aplicativo solicita registros por meio do JQuery. O JQuery chama de volta a uma ação do controlador que retorna resultados no formato JSON. Não consegui provar isso, mas estou preocupado com o fato de meus dados estarem sendo armazenados em cache.

Eu só quero que o cache seja aplicado a ações específicas, não a todas as ações.

Existe um atributo que eu possa colocar em uma ação para garantir que os dados não sejam armazenados em cache? Se não, como posso garantir que o navegador receba um novo conjunto de registros a cada vez, em vez de um conjunto em cache?

Para garantir que o JQuery não esteja armazenando em cache os resultados, em seus methods ajax, coloque o seguinte:

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

Ou para evitar o cache no MVC, criamos nosso próprio atributo, você poderia fazer o mesmo. Aqui está nosso 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); } } 

Em seguida, basta decorar seu controlador com [NoCache] . OU para fazer isso para todos você poderia simplesmente colocar o atributo na class da class base da qual você herda seus controllers (se você tiver um) como nós temos aqui:

 [NoCache] public class ControllerBase : Controller, IControllerBase 

Você também pode decorar algumas das ações com esse atributo se precisar que elas não sejam armazenáveis ​​em cache, em vez de decorar o controlador inteiro.

Se a sua class ou ação não tiver NoCache quando foi renderizada no seu navegador e você quiser verificar se está funcionando, lembre-se de que, depois de compilar as mudanças, você precisa fazer uma “hard refresh” (Ctrl + F5) no seu navegador. Até que você faça isso, seu navegador manterá a versão antiga em cache e não a atualizará com uma “atualização normal” (F5).

Você pode usar o atributo de cache interno para impedir o armazenamento em cache.

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

Para núcleo .net: [ResponseCache(NoStore = true, Duration = 0)]

Esteja ciente de que é impossível forçar o navegador a desativar o armazenamento em cache. O melhor que você pode fazer é fornecer sugestões que a maioria dos navegadores honrará, geralmente na forma de headers ou metatags. Esse atributo decorator desativará o armazenamento em cache do servidor e também adicionará este header: Cache-Control: public, no-store, max-age=0 . Não adiciona meta tags. Se desejado, esses podem ser adicionados manualmente na exibição.

Além disso, o JQuery e outras estruturas de cliente tentarão enganar o navegador para não usar a versão em cache de um recurso, adicionando informações ao URL, como um registro de data e hora ou GUID. Isso é eficaz para fazer o navegador solicitar o recurso novamente, mas não impede o armazenamento em cache.

Em uma nota final. Você deve estar ciente de que os resources também podem ser armazenados em cache entre o servidor e o cliente. ISPs, proxies e outros dispositivos de rede também armazenam resources em cache e geralmente usam regras internas sem examinar o recurso real. Não há muito o que fazer sobre isso. A boa notícia é que eles normalmente armazenam em cache por períodos de tempo mais curtos, como segundos ou minutos.

Tudo o que você precisa é:

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

ou, se você quiser desativá-lo para um controlador inteiro:

 [OutputCache(Duration=0)] public class MyController 

Apesar do debate nos comentários aqui, isso é suficiente para desabilitar o cache do navegador – isso faz com que o ASP.Net emita headers de resposta que informam ao navegador que o documento expira imediatamente:

Duração do OutputCache = 0 Cabeçalhos de Resposta: max-age = 0, s-maxage = 0

Na ação do controlador append ao header as seguintes linhas

  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. 

Aqui está o atributo NoCache proposto pelo mattytommo, simplificado usando as informações da resposta de Chris Moschini:

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

Para MVC6 ( DNX ), não há System.Web.OutputCacheAttribute

Nota: quando você define o parâmetro NoStore Duration, não é considerado. É possível definir uma duração inicial para o primeiro registro e replace isso por atributos personalizados.

Mas nós temos o Microsoft.AspNet.Mvc.Filters.ResponseCacheFilter

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

É possível replace o filtro inicial por um 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); } } 

Aqui está um caso de uso

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

Cache de Saída no MVC

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

 OU
 [OutputCache (NoStore = true, Duration = 0, VaryByParam = "Nenhum")]

Corrigir o valor do atributo para o Asp.Net MVC Core para impedir que o cache do navegador (incluindo o Internet Explorer 11 ) seja:

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

conforme descrito na documentação da Microsoft:

Cache de Resposta no ASP.NET Core – NoStore e Location.None