jQuery AJAX 在不应该生成 304 响应的情况下生成 304 响应

发布于 2024-10-27 21:46:27 字数 3973 浏览 5 评论 0原文

这实在是让我摸不着头脑。也就是说,因为它只发生在 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 在控制器中调用一个方法,但问题在我们做到这一点之前就出现了,所以除非有人认为它很重要,否则我不会发布该代码。所发生的情况通常是出于无法解释的原因,调用 PC/DeleteAssociation 的第一次 ajax 突发会返回 304(未修改)响应。我知道当没有任何变化需要刷新时,就会发生这种情况。但这不是一个 get,它应该被视为一个 post,而且我的印象是 jquery.ajax 的设计目的是,除非另有说明,否则不会生成 304 响应。我显然在这里遗漏了一些东西,而且我自己盯着它看得太久了,无法捕捉到它。有人看到我错过了什么吗?谢谢。

This really has me scratching my head. Namely because it only happens in IE, not Firefox, and I was under the impression that jQuery was effectively browser neutral. I've been cracking at this thing for the past few hours and have nailed down, at least, what is happening.

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

Filled by this function:

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

Which is cleanly populated from the model. This is not the issue. The issue arises when using the delete functionality, which is formatted back in the controller like so:

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

and calls this function

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 is an internal function that creates a particularly formatted blockUI)

The ajax calls a method back in the controller, but the issue arises before we make it that far, so unless someone thinks it important, I'm not going to post that code. What happens is, often for inexplicable reasons, the first burst of ajax that calls PC/DeleteAssociation is coming back with a 304 (not modified) response. I know that happens on a get when nothing has changed that needs to be refreshed. But this isn't a get, it should be treated as a post, and I was under the impression that jquery.ajax was designed to, unless otherwise instructed, not generate 304 responses. I'm obviously missing something here and have been staring at it far too long to catch it myself. Anyone see what I missed? Thank you.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

甜心 2024-11-03 21:46:27

我看不到,您将 ajax 请求指定为 POST。所以基本上添加:

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

如果仍然失败(由于某些浏览器 AJAX 怪异),您可以尝试设置 cache: false

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

顺便说一句,所有 cache: false 都会向请求 URL 添加一些随机内容。

编辑1:

关于

...我的印象是
jquery.ajax 的设计目的是,除非
另有说明,不生成 304
回应

jQuery 不会在这里生成任何响应。 304 标头只是一个 HTTP 标头。 HTTP AJAX 请求是普通的 HTTP 请求,可以返回任何有效的标头。如果服务器响应 304,XHR 对象将简单地提供来自服务器的本地缓存响应。不过,它对用户来说是完全透明的。

EDIT2:

删除了有关防止缓存的建议。对我来说就像巫毒。

EDIT3:

再次添加该位,因为它显然是必要的。环顾网络,IE 似乎在某种程度上非法缓存了 AJAX POST。

I cannot see, you specifying the ajax request as a POST. So basically add:

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

and if that still fails (due to some browser AJAX weirdness), you could try setting cache: false:

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

Btw, all cache: false does, is adding some random stuff to the request URL.

EDIT1:

Regarding the

... and I was under the impression that
jquery.ajax was designed to, unless
otherwise instructed, not generate 304
responses

jQuery istn't generating any responses here. And the 304-header is just an HTTP header. HTTP AJAX requests are ordinary HTTP requests and may return any valid header. If the server responds with 304, the XHR object will simply serve up the locally cached response from the server. It's completely transparent for the user, though.

EDIT2:

Removed the advice about preventing caching. Seems like Voodoo to me.

EDIT3:

Added that bit in again because it apparently was necessary. Looking around the web, IE seems to be illegally caching AJAX POSTs to some extent.

夏夜暖风 2024-11-03 21:46:27
  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. Always use POST for calls to methods that modify state, not GET. This should be enough in this instance to prevent IE caching the request.
  2. IE aggressively caches ajax requests (see http://www.dashbay.com/2011/05/internet-explorer-caches-ajax/ and https://blog.httpwatch.com/2009/08/07/ajax-caching-two-important-facts/). To prevent this, you can:
    1. Add a cache busting parameter ($.ajaxSetup({ cache: false }); does this automatically.
    2. Always use POST requests (probably not appropriate in most cases).
    3. Turn on cache headers for AJAX requests server side. The first link demonstrates how to do this using in groovy. Similar methods should apply to any framework.
梨涡 2024-11-03 21:46:27

缓存清除就是解决方案!

在我的例子中,应用程序使用带有自定义标头的单个服务调用作为代理,将浏览器桥接到服务器的私有部分(每个调用都转到相同的 URL,但使用自定义标头来告诉代理服务要使用哪个服务)将其传递给)。 Chrome 和 FF 上一切正常,但 IE 不断返回页面上第一次调用的数据。 jQuery.ajax 中的 cache=false 选项是修复方法,因为 IE 只是查看被调用的相同 url,甚至不去查看是否使用了任何自定义标头,或者是否在正文中传递了不同的数据,并且只是说“哦,我知道这个,在这里……”并回复了第一个电话的响应。使用缓存清除技术,该 url 看起来与 IE 不同,因此它发送了它。

Cache busting is the solution!

In my case the application used a single service call with a custom header as a proxy to bridge the browser to the private part of the server (every call went to the same url, but used a custom header to tell the proxy service which service to pass it onto). Everything worked fine on Chrome and FF but IE kept returning data from the first call made on the page. cache=false option in jQuery.ajax was the fix since IE just looked at the same url being called, didn't even bother looking at whether any custom headers were used, or whether different data was even being passed in the body, and just said "oh, I know this one, here.." and gave back the response of the first call. With the cache busting technique the url looks different to IE so it sent it through.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文