Desabilitar o cache do navegador para todo o site ASP.NET

199

Estou procurando um método para desativar o cache do navegador de um site inteiro do ASP.NET MVC

Encontrei o seguinte método:

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

E também um método de meta tag (não funcionará para mim, pois algumas ações do MVC enviam HTML / JSON parcial através do Ajax, sem cabeçalho, meta tag).

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

Mas estou procurando um método simples para desativar o cache do navegador de um site inteiro.

Palani
fonte

Respostas:

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 as solicitações são roteadas através do default.aspx primeiro - portanto, supondo que você possa apenas inserir o código por trás dele.

Squiggs.
fonte
17
Eu o colocaria em Global.asax.cs em Application_BeginRequest (). Eu não confio nessa coisa default.aspx ... Outra pergunta: isso tem precedência sobre os atributos [OutputCache]?
Chris166
5
Eu gosto da idéia de simplesmente criar um filtro de ação global e colocar essas coisas dessa maneira. Nega a necessidade de se preocupar com Default.aspx e Global.asax.
21411 Keith Adler
13
Colocar isso em Application_BeingRequest pode causar alguns problemas. Se suas imagens forem roteadas pelo tempo de execução .net (o que pode acontecer se você estiver usando o mapeamento curinga para obter bons URLs), nenhuma imagem será armazenada em cache no navegador. Isso pode REALMENTE diminuir o tempo de carregamento da página, pois cada solicitação de página baixará novamente todas as imagens.
herbrandson
4
Usar qualquer coisa programaticamente sempre substituirá qualquer Atributo declarado. Em outras palavras, o uso do código do OP substituirá qualquer atributo [OutputCache] declarado.
Dave Black
Alguma idéia de como testar o fumo e verificar se a desativação do cache está realmente funcionando?
paaone
366

Crie uma classe que herda 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);
    }
}

Em seguida, coloque atributos onde necessário ...

[NoCache]
[HandleError]
public class AccountController : Controller
{
    [NoCache]
    [Authorize]
    public ActionResult ChangePassword()
    {
        return View();
    }
}
JKG
fonte
19
Em vez de HttpContext.Current.Response, você provavelmente deve usar filterContext.HttpContext.Response, pois HttpContext.Current retorna o objeto HttpContext pré-MVC e o filterContext.HttpContext retorna o HttpContextBase pós-MVC. Aumenta a testabilidade e consistência.
Mckobbs
5
IActionFilter já está implementado no ActionFilterAttribute, portanto, você não precisa repeti-lo.
Andrew Davey
104
Nas versões atuais do ASP.NET MVC, você pode simplesmente usar OutputCacheAttribute para impedir o armazenamento em cache: [OutputCache (NoStore = true, Duração = 0, VaryByParam = "None")]
Ashley Tate
9
Gostaria de ressaltar que passei vários dias usando todas as soluções "coloque isso no seu código para interromper o cache" sob o sol para o ASP.NET MVC, incluindo a resposta aceita a essa pergunta, sem sucesso. Esta resposta - o atributo - funcionou. + 1M Rep se eu pudesse ...
Tom Kidd
5
Você pode adicionar if (filterContext.IsChildAction) return;na parte superior - isso impedirá que a ação externa seja 'sem cache' se chamar uma ação filho decorada com NoCacheatributo. Em outras palavras, o NoCacheatributo não vazará para outras ações se eles executarem ações filho. Além disso, o nome da classe deve estar NoCacheAttributeem conformidade com a convenção de nomenclatura geralmente aceita para atributos.
Jakub Konecki
132

Em vez de criar o seu próprio, basta usar o que é fornecido para você.

Como mencionado anteriormente, não desative o cache para tudo. Por exemplo, os scripts jQuery usados ​​muito no ASP.NET MVC devem ser armazenados em cache. Na verdade, idealmente, você deveria usar uma CDN para eles, mas meu argumento é que algum conteúdo deve ser armazenado em cache.

O que eu acho que funciona melhor aqui, em vez de espalhar o [OutputCache] em todos os lugares, é usar uma classe:

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

Todos os seus controladores para os quais você deseja desativar o cache herdarão deste controlador.

Se você precisar substituir os padrões na classe NoCacheController, basta especificar as configurações de cache no seu método de ação e as configurações no seu método Action terão precedência.

[HttpGet]
[OutputCache(NoStore = true, Duration = 60, VaryByParam = "*")]
public ViewResult Index()
{
  ...
}
Adam Tuliper - MSFT
fonte
4
@Ozziepeeps, seu comentário não está correto. Os documentos do msdn discutem o cache do navegador e um teste simples mostra que este atributo altera o cabeçalho de resposta do controle de cache para "Controle de cache: público, sem armazenamento, idade máxima = 0" de "Controle de cache: privado" sem usando o atributo
Adam Tuliper - MSFT
2
também fyi - você pode controlar todos os três locais (servidor, proxy, cliente) com esse atributo para que possa absolutamente controlar além do cache do servidor. Veja asp.net/mvc/tutorials/… para mais detalhes.
Adam Tuliper - MSFT
1
+1 "Se você precisar substituir os padrões na classe NoCacheController, basta especificar as configurações de cache no seu método de ação e as configurações no seu método Action terão precedência."
Korayem
2
Observe que, se você usa [System.Web.Mvc.OutputCache(NoStore = true, Duration = 0, VaryByParam = "*")]no nível da turma, não pode ter PartialViews na sua turma.
Vivian rio
1
O método OutputCache não impediu o armazenamento em cache do IE quando duas condições estavam presentes: 1) a ação não tomou parâmetros e 2) a ação retornou apenas texto via Content (someText). Quando eu retorno JSON e tomo um parâmetro, o cache do IE é derrotado corretamente.
Kasey Speakman
10

Convém desativar o cache do navegador para todas as páginas renderizadas pelos controladores (ou seja, páginas HTML), mas mantenha o cache no local para recursos como scripts, folhas de estilo e imagens . Se você estiver usando o pacote MVC4 + e a minificação, manterá as durações padrão do cache para scripts e folhas de estilo (durações muito longas, pois o cache é invalidado com base em uma alteração em um URL exclusivo, não no tempo).

No MVC4 +, para desativar o cache do navegador em todos os controladores, mas retê-lo para qualquer coisa que não seja atendida por um controlador, adicione isto a FilterConfig.RegisterGlobalFilters:

filters.Add(new DisableCache());

Defina da DisableCacheseguinte maneira:

class DisableCache : ActionFilterAttribute
{
    public override void OnResultExecuting(ResultExecutingContext filterContext)
    {
        filterContext.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache);
    }
}
Edward Brey
fonte
Infelizmente, isso não parece funcionar, pois pressionar o botão Voltar após o logout exibe a página.
ᴍᴀᴛᴛ ʙᴀᴋᴇʀ
6

Sei que esta resposta não está 100% relacionada à pergunta, mas pode ajudar alguém.

Se você deseja desabilitar o cache do navegador para todo o site ASP.NET MVC , mas deseja fazer isso TEMPORARIAMENTE, é melhor desabilitar o cache no navegador.

Aqui está uma captura de tela no Chrome

Carlos Martinez T
fonte
Isso é exatamente o que eu estava procurando ... durante o desenvolvimento, se eu alterar um arquivo .js, será uma grande dor fazer com que isso aconteça imediatamente quando tiver problemas para solucionar pequenos ciclos de atualização / atualização / teste. Isso é perfeito, obrigado! Apenas fez a minha vida a depuração do lado do cliente muito mais fácil
jleach
2

Eu implementei todas as respostas anteriores e ainda tinha uma visão que não funcionava corretamente.

Descobriu-se que o nome da visualização com a qual eu estava tendo o problema foi chamado de 'Recente'. Aparentemente, isso confundiu o navegador Internet Explorer.

Depois de alterar o nome da exibição (no controlador) para um nome diferente (eu escolhi 'Recente5'), as soluções acima começaram a funcionar.

DrHooverCraft
fonte
0

Você pode tentar o código abaixo no arquivo Global.asax.

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

UI

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

fundo

Context.Response.Cache.SetCacheability(HttpCacheability.NoCache); 
Response.Expires = -1;          
Response.Cache.SetNoStore();
Alfa
fonte
1
precisa prosa explicativo, mesmo que seja tecnicamente correta
rmalayter