$ .getJSON zwraca dane z pamięci podręcznej w IE8

102

W tej chwili bawię się ASP.net MVC i JQuery. Natknąłem się na zachowanie, które wydaje się nie mieć sensu.

Wzywam $.getJSONfunkcję JQuery do zapełnienia niektórych elementów div. Zdarzenie jest wywoływane w $(document).readyzdarzeniu. To działa doskonale.

Jest mały, AJAX.BeginFormktóry dodaje inną wartość do użycia podczas wypełniania elementów div. Wywołuje funkcję zdalną poprawnie, a po pomyślnym zakończeniu wywołuje oryginalną funkcję javascript, aby ponownie zapełnić elementy div.

Oto dziwna część: w FireFox i Chrome - wszystko działa. ALE W IE8 (Beta) to drugie wywołanie skryptu wypełniającego (który wywołuje funkcję $ .getJSON) pobiera dane z pamięci podręcznej i nie pyta o serwer!

Mam nadzieję, że to pytanie ma sens: w pigułce - dlaczego $.getJSONdane są buforowane? I dlaczego wpływa tylko na IE8?

Andrew Harry
źródło
O dziwo, widzę ten błąd nie tylko w IE, ale także w Firefoksie. Pomogło mi wyłączenie buforowania Ajax w jquery.
Josef Sábl

Odpowiedzi:

67

Abyś wiedział, Firefox i Chrome traktują wszystkie żądania Ajax jako niebuforowalne. IE (wszystkie wersje) traktują wywołanie Ajax tak samo, jak inne żądania sieciowe. Dlatego widzisz takie zachowanie.
Jak zmusić IE do pobierania danych przy każdym żądaniu:

  • Jak powiedziałeś, użyj opcji „cache” lub „nocache” w JQuery
  • Dodaj losowy parametr do żądania (brzydki, ale działa :))
  • Po stronie serwera ustaw cachability (na przykład używając atrybutu, patrz poniżej)

Kod:

public class NoCacheAttribute : ActionFilterAttribute
{
    public override void OnActionExecuted(ActionExecutedContext context)
    {
        context.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache);
    }
}
Nico
źródło
1
To rozwiązanie do mnie przemawia. Naprawdę podoba mi się elegancja stosowania atrybutu w MVC
Andrew Harry
1
Obecnie istnieje OutputCacheAttribute OOTB.
bzlm
1
@bzlm, ale to jest łatwiejsze do wyszukania
Simon_Weaver
sprawdź formatinternet.wordpress.com/2010/01/14/… aby znaleźć rozwiązanie po stronie klienta
Ivo
1
Właściwie jest na odwrót, ale zgadzam się, że programista IE wymaga cierpliwości :)
Nico
107

Tak to u mnie zadziałało ...

$.ajaxSetup({ cache: false });
$.getJSON("/MyQueryUrl",function(data,item) {
     // do stuff with callback data
     $.ajaxSetup({ cache: true });
   });
Jitesh Patil
źródło
Walczyłem z tym problemem, a Twoje rozwiązanie dało szybki sposób na jego rozwiązanie. :) Mam pytanie, czy wiesz, jakich opcji można użyć do $ .ajaxSetup? Dokumentacja jQuery niestety nie podaje szczegółów ...
Achimnol
1
Dostępne opcje są identyczne z $ .ajax Zobacz docs.jquery.com/Ajax/jQuery.ajax#options, aby uzyskać więcej informacji
Dan Esparza,
12
Małe ostrzeżenie dla powyższego kodu - zawiera stan wyścigu. Ponieważ wywołanie i jego odpowiedź są asynchroniczne, należy wywołać $.ajaxSetup({ cache: true });zaraz po, getJSON()a nie w wywołaniu zwrotnym.
saksofon
16

Dziękuję Kent za odpowiedź. Używając $ .ajax ('{cache: no}'); działał idealnie. [edytować]

A przynajmniej tak mi się wydawało. Wygląda na to, że jquery $ .getJSON nie odczytuje żadnych zmian wprowadzonych do obiektu $ .ajax.

Rozwiązaniem, które ostatecznie zadziałało, było ręczne dodanie nowego parametru

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

rozdzielczość daty jest tylko do minuty; co skutecznie oznacza, że ​​to rozwiązanie nadal buforuje przez maksymalnie jedną minutę. Jest to do przyjęcia dla moich celów.

Andrew Harry
źródło
9
var noCache = new Date (). getTime (); // przekaże ci ms
scunliffe
dzięki Scunliffe! - Jestem całkiem nowy w javascript, ASP MVC otworzył mi nowe horyzonty
Andrew Harry,
Możesz także spróbować czegoś takiego jak Math.Random ().
Falkayn
@Falkayn - Math.Random()można użyć ciężkiego , jego wyniki będą nieznane i możesz otrzymać tę samą liczbę dwa razy z rzędu (lub więcej). użycie new Date().getTime()zapewni, że nigdy się to nie powtórzy. (chyba że jesteś w stanie cofnąć się w czasie;))
Dementic
11

Rozwiązałem ten sam problem, umieszczając następujący atrybut w akcji w kontrolerze:

[OutputCache(Duration = 0, VaryByParam = "None")]
Chłopak
źródło
Wspaniale! Świetnie jest mieć alternatywy (wybrałem tę). Dziękujemy wszystkim współpracownikom!
Anders Juul
Działa dobrze z Asp.Net MVC 4.0
Mayank
4

Jeśli używasz ASP.net MVC, rozważ dodanie metody rozszerzenia, aby łatwo zaimplementować brak buforowania:

    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
źródło
Niezły pomysł - więc wywołujesz tę metodę rozszerzenia na serwerze podczas wywołania zwrotnego, prawda?
Guy
2

Może być konieczne wysłanie wyłącznika pamięci podręcznej.

Zalecałbym użycie $ .ajax ({cache: no}) na wszelki wypadek (dodaje losowy sufiks do żądania get)

(Obecnie zwykle używam $ .ajax wszędzie, lepiej dostrajać)

Kent Fredric
źródło
Dziękuję za odpowiedź! ... jeszcze tego nie wypróbowałem. Wkrótce dostarczy informację zwrotną
Andrew Harry