$ .getJSON возвращает кешированные данные в IE8

102

В данный момент я играю с ASP.net MVC и JQuery. Я встречал поведение, которое, кажется, не имеет смысла.

Я вызываю $.getJSONфункцию JQuery для заполнения некоторых div. Событие запускается по $(document).readyсобытию. Это прекрасно работает.

Есть небольшой, AJAX.BeginFormкоторый добавляет еще одно значение, которое будет использоваться при заполнении div. Он правильно вызывает удаленную функцию и в случае успеха вызывает исходную функцию javascript для повторного заполнения div.

Вот что странно: в FireFox и Chrome - все работает. НО В IE8 (бета) этот второй вызов сценария заполнения Div (который вызывает функцию $ .getJSON) получает кэшированные данные и не запрашивает сервер!

Надеюсь, этот вопрос имеет смысл: В общем, зачем $.getJSONнужны кэшированные данные? И почему это влияет только на IE8?

Эндрю Гарри
источник
Как ни странно, я вижу эту ошибку не только в IE, но и в Firefox. Мне помогло отключение кеширования ajax в jquery.
Josef Sábl

Ответы:

67

Просто чтобы вы знали, Firefox и Chrome считают все запросы Ajax некэшируемыми. IE (все версии) обрабатывает вызов Ajax так же, как и другие веб-запросы. Вот почему вы видите такое поведение.
Как заставить IE скачивать данные при каждом запросе:

  • Как вы сказали, используйте опцию 'cache' или 'nocache' в JQuery
  • Добавить в запрос случайный параметр (некрасиво, но работает :))
  • На стороне сервера установите кэшируемость (например, используя атрибут, см. Ниже)

Код:

public class NoCacheAttribute : ActionFilterAttribute
{
    public override void OnActionExecuted(ActionExecutedContext context)
    {
        context.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache);
    }
}
Нико
источник
1
Мне это решение нравится. Мне очень нравится элегантность применения атрибута в MVC
Эндрю Гарри
1
В настоящее время существует OOTB OutputCacheAttribute.
bzlm
1
@bzlm, но это легче найти
Simon_Weaver,
проверить formatinternet.wordpress.com/2010/01/14/... на стороне клиента решения
Ivo
1
На самом деле, это наоборот, но я согласен, как разработчик IE требует терпения :)
Нико
107

Вот как это сработало для меня ...

$.ajaxSetup({ cache: false });
$.getJSON("/MyQueryUrl",function(data,item) {
     // do stuff with callback data
     $.ajaxSetup({ cache: true });
   });
Джитеш Патил
источник
Я боролся с этой проблемой, и ваше решение позволило быстро ее решить. :) У меня вопрос, знаете ли вы, какие параметры можно использовать для $ .ajaxSetup? Документация jQuery, к сожалению, не содержит подробностей ...
Ахимнол,
1
Доступные параметры идентичны $ .ajax См. Docs.jquery.com/Ajax/jQuery.ajax#options для получения дополнительной информации
Дэн Эспарза,
12
Небольшое предупреждение для приведенного выше кода - он содержит состояние гонки. Поскольку вызов и ответ на него асинхронны, вы должны вызывать $.ajaxSetup({ cache: true });сразу после, getJSON()а не в обратном вызове .
sax
16

Спасибо, Кент, за твой ответ. Использование $ .ajax ('{cache: no}'); работал отлично. [редактировать]

По крайней мере, я так думал. Похоже, jquery $ .getJSON не читает никаких изменений, внесенных в объект $ .ajax.

Решение, которое в итоге сработало, заключалось в добавлении нового параметра вручную.

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

разрешение даты только с точностью до минуты; что фактически означает, что это решение все еще кэшируется до одной минуты. Это приемлемо для моих целей.

Эндрю Гарри
источник
9
var noCache = новая дата (). getTime (); // передам вам мс
scunliffe
спасибо, Сканлифф! - Я новичок в javascript, ASP MVC открыл для меня новые горизонты
Эндрю Гарри
Вы также можете попробовать что-нибудь вроде Math.Random ().
Falkayn
@Falkayn - Math.Random()можно использовать жесткий , его результаты будут неизвестны, и вы можете получить одно и то же число дважды подряд (или больше). использование new Date().getTime()гарантирует, что это никогда не повторится. (если вы не можете вернуться в прошлое;))
Рафаэль Херскович
11

Я решил эту же проблему, поместив следующий атрибут в действие в контроллере:

[OutputCache(Duration = 0, VaryByParam = "None")]
Парень
источник
Чудесно! Замечательно иметь альтернативу (я выбрал эту). Спасибо всем участникам!
Андерс Юул,
Прекрасно работает с Asp.Net MVC 4.0
Mayank
4

Если вы используете ASP.net MVC, рассмотрите возможность добавления метода расширения, чтобы легко реализовать отсутствие кеширования, например:

    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");
    }
Джош
источник
Хорошая идея - значит, вы вызываете этот метод расширения на сервере во время обратного вызова, верно?
Guy
2

Возможно, вам потребуется отправить кеш-прерыватель.

Я бы рекомендовал на всякий случай использовать $ .ajax ({cache: no}) (добавляет случайный суффикс к запросу на получение)

(В наши дни я обычно использую $ .ajax везде, более настраиваемый)

Кент Фредрик
источник
Спасибо за ответ! ... я еще не пробовал. В ближайшее время предоставлю обратную связь
Эндрю Гарри