Подтвердить что ты не робот

JQuery AJAX производит 304 ответа, когда это не должно

Это действительно заставляет меня почесывать голову. А именно потому, что это происходит только в IE, а не в Firefox, и у меня создалось впечатление, что jQuery был фактически нейтральным браузером. Я пробовал эту штуку в течение последних нескольких часов и прибил, по крайней мере, то, что происходит.

Этот jqGrid:

$("#DocumentListByPartRecordsGrid").jqGrid(
          {
            datatype: 'local',            
            colNames: ['<b>Id</b>', '<b>Document Name</b>', '<b>Document Type</b>', '<b>Effective Date</b>', '<b>Expiration Date</b>', '<b>Delete</b>'],
            colModel: [
                  { name: 'ASSOCIATION_ID', Index: 'ASSOCIATION_ID', resizable: true, align: 'left', hidden: true, sortable: false },
                  { name: 'FILE_NAME', Index: 'FILE_NAME', resizable: true, align: 'left', sortable: false, width:'20%' },
                  { name: 'DOCUMENT_TYPE', Index: 'DOCUMENT_TYPE', resizable: true, align: 'left', sortable: false, width:'20%' },
                  { name: 'EFFECTIVE_DATE', Index: 'EFFECTIVE_DATE', resizable: true, align: 'left', sortable: false, width:'20%' },
                  { name: 'EXPIRATION_DATE', Index: 'EXPIRATION_DATE', resizable: true, align: 'left', sortable: false, width:'20%' },
                  { name: 'Delete', Index: 'Delete',resizable: true, align: 'center', sortable: false, width:'20%' },
                  ],            
            rowNum: 15,
            rowList: [15, 50, 100],
            imgpath: '/Drm/Content/jqGrid/steel/images',
            viewrecords: true,            
            height: 162,           
            loadui: 'block',
            forceFit: true
        });

Заполняется этой функцией:

var mydata = '';    
<% if(!string.IsNullOrEmpty(Model.PCAssociatedDocuments)) { %>        
   var mydata = <%= Model.PCAssociatedDocuments %>;
<% } %>

for (var i = 0; i <= mydata.length; i++){
        jQuery("#DocumentListByPartRecordsGrid").addRowData(i, mydata[i], "last");
        }

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

<a class='deleteAttachment' style='cursor: pointer;' href='#' onclick='javascript:PCDocumentDelete(" + s.AssociationId.ToString() + ", " + pcId + ");'>Delete</a>

и вызывает эту функцию

function PCDocumentDelete(id, pcid) {
if (confirm("Are you sure you want to delete this document?")) {
    $.blockUI({
        message: "Working...",
        css: {
            background: '#e7f2f7',
            padding: 10
        }
    });
    $.ajax(
        {
            url: '/DRM/Pc/DeleteAssociation?associationId=' + id + '&pcid=' + pcid,
            async: true,
            dataType: "json",
            success: function(result) {
                if (result.Success == true) {
                    //Reload grid                       
                    $.ajax({ async: false });
                    $("#DocumentListByPartRecordsGrid").setGridParam({ url: "/Drm/Pc/DeAssociatePartRecordsWithDocument?pcid=" + pcid, datatype: 'json', myType: 'GET', page: 1 });
                    $("#DocumentListByPartRecordsGrid").trigger("reloadGrid");
                    $.unblockUI();
                    $.showGlobalMessage('Specified document has been successfully disassociated from this part record.');
                }
                else {
                    $.unblockUI();
                    $.showGlobalMessage('An error occurred deleting the attachment.');
                }
            },
            error: function(res, stat) {
                alert(res.toString());
                alert(stat.toString());
            }
        });
    return false;
}
else {
    return false;
}

}

(showGlobalMessage - это внутренняя функция, которая создает особенно форматированный блокUI)

Ajax вызывает метод обратно в контроллере, но проблема возникает, прежде чем мы сделаем это так далеко, поэтому, если кто-то не считает это важным, я не буду публиковать этот код. Случается, что по необъяснимым причинам первый всплеск ajax, вызывающий PC/DeleteAssociation, возвращается с 304 (не измененным) ответом. Я знаю, что это происходит, когда ничего не изменилось, что нужно обновить. Но это не получается, его следует рассматривать как сообщение, и у меня создалось впечатление, что jquery.ajax был разработан, если не указано иное, не генерирует 304 ответа. Я, очевидно, что-то пропустил здесь и смотрел на него слишком долго, чтобы поймать его сам. Кто-нибудь видит, что я пропустил? Спасибо.

4b9b3361

Ответ 1

Я не вижу, вы указываете запрос ajax как POST. Поэтому в основном добавьте:

$.ajax({ type: 'POST' });

и если это все еще не удается (из-за какой-то странности браузера AJAX), вы можете попробовать установить cache: false:

$.ajax({ type: 'POST', cache: false });

Btw, весь кеш: false делает, добавляет некоторые случайные вещи в URL-адрес запроса.

EDIT1:

Что касается

... и у меня сложилось впечатление, что jquery.ajax был разработан, если только в противном случае указывается, а не генерировать 304 Ответы

jQuery не генерирует никаких ответов здесь. И заголовок 304 - это просто HTTP-заголовок. Запросы HTTP AJAX являются обычными HTTP-запросами и могут возвращать любой допустимый заголовок. Если сервер отвечает 304, объект XHR будет просто обслуживать локально кэшированный ответ с сервера. Это полностью прозрачно для пользователя.

EDIT2:

Удален совет о предотвращении кэширования. Мне кажется Voodoo.

EDIT3:

Добавил этот бит снова, потому что он, по-видимому, был необходим. Оглядываясь на Интернет, IE, похоже, в некоторой степени незаконно кэширует AJAX POST.

Ответ 2

  • Всегда используйте POST для вызовов методов, которые изменяют состояние, а не GET. Этого должно быть достаточно в этом случае, чтобы предотвратить кеширование IE запроса.
  • IE агрессивно кэширует запросы ajax (см. http://www.dashbay.com/2011/05/internet-explorer-caches-ajax/ и https://blog.httpwatch.com/2009/08/07/ajax-caching-two-important-facts/). Чтобы предотвратить это, вы можете:
    • Добавить параметр busting для кеша ($.ajaxSetup({ cache: false }); делает это автоматически.
    • Всегда используйте POST-запросы (вероятно, не соответствующие в большинстве случаев).
    • Включите заголовки кеша для AJAX-запросов на стороне сервера. Первая ссылка демонстрирует, как это сделать, используя groovy. Подобные методы должны применяться к любой инфраструктуре.

Ответ 3

Вызов кэша - это решение!

В моем случае приложение использовало один служебный вызов с настраиваемым заголовком в качестве прокси-сервера для подключения браузера к частной части сервера (каждый вызов переходил на тот же URL-адрес, но использовался пользовательский заголовок, чтобы сообщить службе прокси-сервера какая служба должна передать его). Все отлично работало в Chrome и FF, но IE продолжал возвращать данные с первого вызова, сделанного на странице. cache = false в jQuery.ajax было исправление, так как IE просто смотрел на тот же url, который вызывался, даже не потрудился посмотреть, были ли использованы пользовательские заголовки или были ли переданы разные данные в теле, и просто сказал: "О, я знаю этот, здесь..." и ответил ответ первого звонка. С помощью метода перебора кэша URL-адрес выглядит по-разному для IE, поэтому он отправил его.