jQuery AJAX 不应该产生 304 响应
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5502002/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
jQuery AJAX producing 304 responses when it shouldn't
提问by guildsbounty
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.
这真的让我摸不着头脑。即因为它只发生在 IE 中,而不是 Firefox,我的印象是 jQuery 是有效的浏览器中立的。在过去的几个小时里,我一直在努力解决这个问题,并且至少确定了正在发生的事情。
This jqGrid:
这个 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)
(showGlobalMessage 是一个内部函数,它创建了一个特别格式化的 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.
ajax 调用回控制器中的一个方法,但问题在我们实现之前就出现了,所以除非有人认为它很重要,否则我不会发布该代码。发生的情况是,通常出于莫名其妙的原因,第一次调用 PC/DeleteAssociation 的 ajax 返回 304(未修改)响应。我知道当没有任何变化需要刷新时会发生这种情况。但这不是获取,它应该被视为帖子,我的印象是 jquery.ajax 的设计目的是,除非另有说明,否则不会生成 304 响应。我显然在这里遗漏了一些东西,并且盯着它看得太久了,无法自己捕捉到它。有人看到我错过了什么吗?谢谢你。
回答by skarmats
I cannot see, you specifying the ajax request as a POST. So basically add:
我看不到,您将 ajax 请求指定为 POST。所以基本上添加:
$.ajax({ type: 'POST' });
and if that still fails (due to some browser AJAX weirdness), you could try setting cache: false
:
如果仍然失败(由于某些浏览器 AJAX 奇怪),您可以尝试设置cache: false
:
$.ajax({ type: 'POST', cache: false });
Btw, all cache: false does, is adding some random stuff to the request URL.
顺便说一句,所有 cache: false 都会向请求 URL 添加一些随机内容。
EDIT1:
编辑1:
Regarding the
关于
... and I was under the impression that jquery.ajax was designed to, unless otherwise instructed, not generate 304 responses
...我的印象是 jquery.ajax 的设计目的是,除非另有说明,否则不会生成 304 响应
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.
jQuery 不会在这里生成任何响应。而 304 标头只是一个 HTTP 标头。HTTP AJAX 请求是普通的 HTTP 请求,可能返回任何有效的标头。如果服务器以 304 响应,则 XHR 对象将简单地提供来自服务器的本地缓存响应。不过,它对用户来说是完全透明的。
EDIT2:
编辑2:
Removed the advice about preventing caching. Seems like Voodoo to me.
删除了关于防止缓存的建议。对我来说就像巫毒教。
EDIT3:
编辑3:
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.
再次添加该位,因为它显然是必要的。环顾网络,IE 似乎在某种程度上非法缓存了 AJAX POST。
回答by Joshka
- 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.
- 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:
- Add a cache busting parameter
($.ajaxSetup({ cache: false });
does this automatically. - Always use POST requests (probably not appropriate in most cases).
- 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.
- Add a cache busting parameter
- 始终使用 POST 来调用修改状态的方法,而不是 GET。在这种情况下,这应该足以防止 IE 缓存请求。
- IE 积极缓存 ajax 请求(参见http://www.dashbay.com/2011/05/internet-explorer-caches-ajax/和https://blog.httpwatch.com/2009/08/07/ajax-caching-两个重要的事实/)。为了防止这种情况,您可以:
- 添加缓存破坏参数
($.ajaxSetup({ cache: false });
会自动执行此操作。 - 始终使用 POST 请求(在大多数情况下可能不合适)。
- 为 AJAX 请求服务器端打开缓存头。第一个链接演示了如何在 groovy 中执行此操作。类似的方法应该适用于任何框架。
- 添加缓存破坏参数
回答by Ali
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.
在我的例子中,应用程序使用带有自定义标头的单个服务调用作为代理将浏览器桥接到服务器的私有部分(每次调用都转到相同的 url,但使用自定义标头告诉代理服务要使用哪个服务)传递给)。在 Chrome 和 FF 上一切正常,但 IE 一直从页面上的第一次调用中返回数据。jQuery.ajax 中的 cache=false 选项是修复,因为 IE 只是查看被调用的同一个 url,甚至没有费心查看是否使用了任何自定义标头,或者是否甚至在正文中传递了不同的数据,而只是说“哦,我知道这个,在这里..”并回复了第一个电话的回应。使用缓存破坏技术,url 看起来与 IE 不同,所以它发送了它。