$ .getJSON retornando dados em cache no IE8

102

Estou brincando com ASP.net MVC e JQuery no momento. Eu encontrei um comportamento que não parece fazer sentido.

Estou chamando a $.getJSONfunção JQuery para preencher alguns div's. O evento é acionado no $(document).readyevento. Isso funciona perfeitamente.

Há um pequeno AJAX.BeginFormque adiciona outro valor a ser usado ao preencher os divs. Ele chama a função remota corretamente e, em caso de sucesso, chama a função javascript original para preencher novamente os divs.

Aqui está a parte estranha: no FireFox e no Chrome - tudo funciona. MAS No IE8 (Beta), esta segunda chamada para o script popular Div (que chama a função $ .getJSON) obtém dados em cache e não pergunta ao servidor!

Espero que esta pergunta faça sentido: Em poucas palavras - Por que está $.getJSONobtendo dados em cache? E por que está afetando apenas o IE8?

Andrew Harry
fonte
Estranhamente, vejo esse bug não apenas no IE, mas também no Firefox. Desativar o cache de ajax no jquery me ajudou.
Josef Sábl de

Respostas:

67

Apenas para informá-lo, o Firefox e o Chrome consideram todas as solicitações Ajax como não armazenáveis ​​em cache. O IE (todas as versões) trata a chamada Ajax apenas como outra solicitação da web. É por isso que você vê esse comportamento.
Como forçar o IE a baixar dados em cada solicitação:

  • Como você disse, use a opção 'cache' ou 'nocache' no JQuery
  • Adicione um parâmetro aleatório à solicitação (feio, mas funciona :))
  • No lado do servidor, defina cachability (por exemplo, usando um atributo, veja abaixo)

Código:

public class NoCacheAttribute : ActionFilterAttribute
{
    public override void OnActionExecuted(ActionExecutedContext context)
    {
        context.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache);
    }
}
Nico
fonte
1
Esta solução me agrada. Eu realmente gosto da elegância de aplicar um atributo em MVC
Andrew Harry
1
Existe um OutputCacheAttribute OOTB hoje em dia.
bzlm
1
@bzlm mas isso é mais fácil de pesquisar
Simon_Weaver
confira formatinternet.wordpress.com/2010/01/14/… para uma solução do lado do cliente
Ivo
1
Na verdade, é o contrário, mas concordo, como um desenvolvedor, o IE requer paciência :)
Nico
107

É assim que funcionou para mim ...

$.ajaxSetup({ cache: false });
$.getJSON("/MyQueryUrl",function(data,item) {
     // do stuff with callback data
     $.ajaxSetup({ cache: true });
   });
Jitesh Patil
fonte
Eu estava lutando com esse problema e sua solução me deu uma maneira rápida de resolvê-lo. :) Eu tenho uma pergunta, você sabe quais opções podem ser usadas para $ .ajaxSetup? A documentação do jQuery não fornece detalhes, infelizmente ...
Achimnol
1
As opções disponíveis são idênticas a $ .ajax Consulte docs.jquery.com/Ajax/jQuery.ajax#options para obter mais informações
Dan Esparza
12
Um pequeno aviso para o código acima - contém condição de corrida. Como a chamada e sua resposta são assíncronas, você deve chamar $.ajaxSetup({ cache: true });logo depois de getJSON()e não no retorno de chamada.
sax
16

Obrigado Kent pela sua resposta. Usando $ .ajax ('{cache: no}'); funcionou perfeitamente. [editar]

Ou pelo menos eu pensei que sim. Parece que o jquery $ .getJSON não está lendo nenhuma alteração feita no objeto $ .ajax.

A solução que acabou dando certo foi adicionar um novo parâmetro manualmente

var noCache = Date();
$.getJSON("/somepage/someaction", { "noCache": noCache }, Callback);

a resolução de data é minuciosa; o que efetivamente significa que essa solução ainda armazena em cache por até um minuto. Isso é aceitável para meus propósitos.

Andrew Harry
fonte
9
var noCache = new Date (). getTime (); // lhe dará o ms
scunliffe
obrigado Scunliffe! - eu sou muito novo em javascript, ASP MVC abriu novos horizontes para mim
Andrew Harry
Você também pode tentar algo como Math.Random ().
Falkayn,
@Falkayn - tough Math.Random()pode ser usado, seus resultados serão desconhecidos e você pode obter o mesmo número duas vezes seguidas (ou mais). o uso new Date().getTime()garantirá que nunca seja repetido. (a menos que você seja capaz de voltar no tempo;))
Demência
11

Resolvi esse mesmo problema colocando o seguinte atributo na Ação no Controlador:

[OutputCache(Duration = 0, VaryByParam = "None")]
Cara
fonte
Maravilhoso! Ótimo ter alternativas (eu escolhi esta). Obrigado a todos os contribuidores!
Anders Juul
Funciona bem com Asp.Net MVC 4.0
Mayank
4

Se você estiver usando ASP.net MVC, considere adicionar um método de extensão para implementar facilmente nenhum armazenamento em cache, como:

    public static void NoCache(this HttpResponse Response)
    {
        Response.Cache.SetNoStore();
        Response.Cache.SetExpires(DateTime.MinValue);
        Response.Cache.SetCacheability(HttpCacheability.NoCache);
        Response.Cache.SetValidUntilExpires(false);

        Response.Expires = -1;
        Response.ExpiresAbsolute = DateTime.MinValue;
        Response.AddHeader("Cache-Control", "no-cache");
        Response.AddHeader("Pragma", "no-cache");
    }
Josh
fonte
Boa ideia - então você chama esse método de extensão no servidor durante o retorno de chamada, certo?
Guy
2

Pode ser necessário enviar um quebrador de cache.

Eu recomendaria usar $ .ajax ({cache: no}) apenas no caso (adiciona um sufixo aleatório à solicitação get)

(Eu costumo usar $ .ajax em todos os lugares hoje em dia, mais ajustável)

Kent Fredric
fonte
Obrigado pela sua resposta! ... ainda não experimentei. Fornecerá feedback em breve
Andrew Harry