JQuery AJAX производит 304 ответа, когда это не должно - PullRequest
28 голосов
/ 31 марта 2011

Это действительно заставляет меня чесать голову. А именно потому, что это происходит только в 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 - внутренняя функция, которая создает особо отформатированный blockUI)

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

Ответы [ 3 ]

44 голосов
/ 31 марта 2011

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

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

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

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

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

EDIT1:

Относительно

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

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

EDIT2:

Удален совет по предотвращению кеширования. Мне кажется, Вуду.

EDIT3:

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

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

Очистка кеша - это решение!

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

...