$ .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?


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);
    }
}

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 });
   });

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.


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")]

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");
    }

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ć)


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

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.