Desativando o cache do navegador para todos os navegadores do ASP.NET

87

Estou atrás de uma referência definitiva a qual código ASP.NET é necessário para que os navegadores desabilitem o cache da página. Existem muitas maneiras de afetar os cabeçalhos HTTP e metatags e tenho a impressão de que diferentes configurações são necessárias para fazer com que navegadores diferentes se comportem corretamente. Seria muito bom ter um pedaço de código de referência comentado para indicar o que funciona para todos os navegadores e o que é necessário para um navegador específico, incluindo versões.

Há uma grande quantidade de informações sobre esse problema, mas ainda não encontrei uma boa referência que descreva os benefícios de cada método e se uma técnica específica foi substituída por uma API de nível superior.

Estou particularmente interessado no ASP.NET 3.5 SP1, mas seria bom obter respostas para a versão anterior também.

Esta entrada do blog Duas diferenças importantes entre o cache do Firefox e do IE descreve algumas diferenças de comportamento do protocolo HTTP.

O código de exemplo a seguir ilustra o tipo de coisa em que estou interessado

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
fonte
5
Eu tentaria responder se não soubesse quão terrivelmente impossível é sua tarefa. Controlar o cache do cliente é como tentar usar pauzinhos de 3 metros para reorganizar os móveis.
Jeff Meatball Yang
Muitas respostas que cobrem apenas uma parte do problema ainda seriam muito valiosas. Por favor, jogue seu valor de 2 centavos.
Martin Hollingsworth

Respostas:

96

Isso é o que usamos no ASP.NET:

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

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

Ele para de armazenar em cache no Firefox e no IE, mas não experimentamos outros navegadores. Os seguintes cabeçalhos de resposta são adicionados por estas instruções:

Cache-Control: no-cache, no-store
Pragma: no-cache
HttpWatchSupport
fonte
5
+1 Isso está funcionando para mim no Chrome, muito obrigado. Também uso Response.Cache.SetAllowResponseInBrowserHistory (true); para evitar que o histórico armazene uma entrada para cada solicitação da mesma página.
daniloquio
12
Aparentemente, alguém descobriu que usar SetCacheability com NoCache também desativa o cache de saída ASP.NET (cache do lado do servidor). Eles sugerem usar a opção ServerAndNoCache em seu lugar. codeclimber.net.nz/archive/2007/04/01/…
md1337
1
Para esclarecer os comentários no snippet de código, o método principal é SetCacheability. SetNoStoreé uma solução alternativa para o IE6. Consulte Por que no-cache e no-store devem ser usados ​​na resposta HTTP? .
Edward Brey
3
FWIW ... Necessário adicionar SetNoStore para IE10
felickz
Para aqueles que estão lendo esta página que produzirão PDFs dinâmicos em https e definirão os cabeçalhos de cache como este, cuidado com o seguinte bug do IE8 e inferior: stackoverflow.com/questions/1038707/…
Paddy
41

Para valer a pena, eu apenas tive que lidar com isso em meu aplicativo ASP.NET MVC 3. Aqui está o bloco de código que usei no arquivo Global.asax para lidar com isso para todas as solicitações.

    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
fonte
Isso HttpContext.Current.Response.Cache.SetAllowResponseInBrowserHistory(false)fez a diferença para evitar o cache no IE e FireFox
Michael Kniskern
2
-1, a configuração em Application_BeginRequest () faz com que os cabeçalhos sem cache sejam enviados para itens que você provavelmente deseja armazenar em cache (arquivos JavaScript, imagens, etc). Eu não tentei ainda, mas a localização do OP (configuração dos cabeçalhos na própria página ASP) é provavelmente melhor.
Evan Haas
Eu esperava que essa resposta funcionasse, pois é a maneira mais simples de configurá-la em glabal.asax, mas ainda não há alegria
lawphotog
5
@Evan, Application_BeginRequest só será chamado para solicitações enviadas do IIS para o ASP.NET. Muitas vezes, arquivos estáticos como CSS, JS, imagens, fontes, etc. são extensões consideradas arquivos estáticos do IIS e não são enviados para o ASP.NET Runtime. Se o IIS estiver configurado para enviar todas as solicitações ao tempo de execução do ASP.NET, então sim, isso se aplicaria a todas as solicitações, mesmo se os arquivos forem estáticos e devam ser armazenados em cache.
Adam Carr
@Adam, faz sentido. Eu desfaria meu -1, mas SO diz que meu voto está bloqueado em :-(
Evan Haas
2

Eu tentei várias combinações e eles falharam no FireFox. Já faz um tempo que a resposta acima pode funcionar bem ou posso ter esquecido alguma coisa.

O que sempre funcionou para mim é adicionar o seguinte ao cabeçalho de cada página, ou o modelo (Master Page in .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>

Isso desabilitou todo o cache em todos os navegadores para mim sem falhar.

Steve
fonte
7
Não tenho certeza do que isso deve fazer, mas parece um grande hack que está fadado a falhar na próxima atualização de qualquer um desses navegadores.
md1337
É explicado em, por exemplo, web.archive.org/web/20160112095216/http://www.hunlock.com/blogs/… - em resumo, o evento onbeforeunload foi implementado para ser usado por bancos e evita que a página seja armazenada em cache.
ChrisW
1

Existem duas abordagens que conheço. A primeira é dizer ao navegador para não armazenar a página em cache. Definir a resposta para nenhum cache cuida disso, no entanto, como você suspeita, o navegador frequentemente ignorará essa diretiva. A outra abordagem é definir a data e hora de sua resposta para um ponto no futuro. Acredito que todos os navegadores irão corrigir isso para a hora atual quando adicionarem a página ao cache, mas irá mostrar a página como mais recente quando a comparação for feita. Acredito que pode haver alguns casos em que uma comparação não é feita. Não tenho certeza dos detalhes e eles mudam a cada novo lançamento do navegador. Nota final Tive mais sorte com páginas que se "atualizam" (outra diretiva de resposta). A atualização parece menos provável de vir do cache.

Espero que ajude.

Pato
fonte
0

Vou testar a adição da tag no-store ao nosso site para ver se isso faz diferença no cache do navegador (o Chrome às vezes tem feito o cache das páginas). Eu também achei este artigo muito útil na documentação sobre como e por que o armazenamento em cache funciona e irei dar uma olhada nas ETags a seguir se o no-store não for confiável:

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

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

O codificador
fonte