我注意到在 jquery 中使用 $.post() 时,默认 contentType 是 application/x-www-form-urlencoded - 当我的 asp.net mvc 代码需要 contentType=application/json
(请参阅此问题了解为什么我必须使用 application/json:ASPNET MVC - Why is ModelState.IsValid false "The x field is required" when that field does have a value?)
如何让 $.post() 发送 contentType=application/json?我已经有大量的 $.post() 函数,所以我不想更改为 $.ajax() 因为它会花费太多时间
如果我尝试
$.post(url, data, function(), "json")
它仍然有 contentType=application/x-www-form-urlencoded。那么,如果“json”参数不将内容类型更改为 json,它究竟做了什么?
如果我尝试
$.ajaxSetup({
contentType: "application/json; charset=utf-8"
});
这有效,但会影响我拥有的每一个 $.get 和 $.post 并导致一些中断。
那么有什么方法可以改变 $.post() 的行为来发送 contentType=application/json 吗?
$.ajax({
url:url,
type:"POST",
data:data,
contentType:"application/json; charset=utf-8",
dataType:"json",
success: function(){
...
}
})
请参阅:jQuery.ajax()
最后我找到了适合我的解决方案:
jQuery.ajax ({
url: myurl,
type: "POST",
data: JSON.stringify({data:"test"}),
dataType: "json",
contentType: "application/json; charset=utf-8",
success: function(){
//
}
});
data
参数序列化为 x-www-form-urlencoded
似乎非常高兴,但如果您指出请求内容类型是 JSON,它仍然坚持以不匹配的格式发送 data
。
JSON.stringify()
救了我。 +1
我想你可能不得不
1.修改源以使 $.post 始终使用 JSON 数据类型,因为它实际上只是预配置 $.ajax
调用的快捷方式
或者
2.Define your own utility function that is a shortcut for the $.ajax
configuration you want to use
或者
3.您可以通过猴子修补用您自己的实现覆盖 $.post function
。
您示例中的 JSON 数据类型是指从服务器返回的数据类型,而不是发送到服务器的格式。
jQuery.post
方法,它是一个 really simple function...
"mystring data"
将是 application/x-www-form-urlencoded;
,而对象 { anyKey: "anyvalue and type" }
将是 application/json
。许多读取 json 的服务器只允许一个对象或数组,而不是一个字符串——这就是 jquery 以这种方式预测事物的原因。如果您有一个读取字符串、数字等而不被包装在对象中的服务器,则必须在此答案中指定内容类型。
我最终在我的脚本中向 jQuery 添加了以下方法:
jQuery["postJSON"] = function( url, data, callback ) {
// shift arguments if data argument was omitted
if ( jQuery.isFunction( data ) ) {
callback = data;
data = undefined;
}
return jQuery.ajax({
url: url,
type: "POST",
contentType:"application/json; charset=utf-8",
dataType: "json",
data: data,
success: callback
});
};
并使用它
$.postJSON('http://url', {data: 'goes', here: 'yey'}, function (data, status, xhr) {
alert('Nailed it!')
});
这是通过简单地从原始 JQuery 源中复制“get”和“post”的代码并硬编码一些参数来强制 JSON POST 来完成的。
谢谢!
JSON.stringify
周围的数据。
只用
jQuery.ajax ({
url: myurl,
type: "POST",
data: mydata,
dataType: "json",
contentType: "application/json; charset=utf-8",
success: function(){
//
}
});
更新的@JK:如果您在问题中仅使用 $.post 编写一个代码示例,您会在答案中找到一个相应的示例。我不想重复你已经研究过的相同信息:$.post 和 $.get 是 $.ajax 的缩写形式。因此,只需使用 $.ajax,您就可以使用它的完整参数集,而无需更改任何全局设置。
顺便说一句,我不建议覆盖标准的 $.post。这是我的个人意见,但对我来说,重要的是,不仅程序有效,而且所有阅读您的程序的人都以同样的方式理解它。 在没有非常重要的原因的情况下重写标准方法可能会导致在阅读程序代码时出现误解。所以我再重复一次我的建议:只需使用原始的 $.ajax 形式的 jQuery 而不是 jQuery.get
和 jQuery.post
,您就会收到不仅完美运行,而且人们可以毫无误解地阅读的程序。
你猜怎么着? @BenCreasy 完全正确!!
从 jQuery 的 1.12.0 版本开始,我们可以这样做:
$.post({
url: yourURL,
data: yourData,
contentType: 'application/json; charset=utf-8'
})
.done(function (response) {
//Do something on success response...
});
我刚刚测试了它并且它有效!
这个用于 $.postJSON() 的简单 jquery API 扩展(来自:https://benjamin-schweizer.de/jquerypostjson.html)可以解决问题。您可以像使用其他所有原生 jquery Ajax 调用一样使用 postJSON()。您可以附加事件处理程序等。
$.postJSON = function(url, data, callback) {
return jQuery.ajax({
'type': 'POST',
'url': url,
'contentType': 'application/json; charset=utf-8',
'data': JSON.stringify(data),
'dataType': 'json',
'success': callback
});
};
与其他 Ajax API(如来自 AngularJS 的 $http)一样,它将正确的 contentType 设置为 application/json。您可以直接传递您的 json 数据(javascript 对象),因为它在此处被字符串化。预期返回的数据类型设置为 JSON。您可以为承诺附加 jquery 的默认事件处理程序,例如:
$.postJSON(apiURL, jsonData)
.fail(function(res) {
console.error(res.responseText);
})
.always(function() {
console.log("FINISHED ajax post, hide the loading throbber");
});
您可以作为最后一个参数传递给 post() 的“json”数据类型表示函数在服务器响应中期望的数据类型,而不是它在请求中发送的数据类型。具体来说,它设置“接受”标题。
老实说,您最好的选择是切换到 ajax() 调用。 post() 函数是为了方便;当您只是做一个简单的表单发布时,ajax() 调用的简化版本。你不是。
如果您真的不想切换,您可以创建自己的函数,例如 xpost(),并让它简单地将给定参数转换为 jQuery ajax() 调用的参数,并设置内容类型。这样,您不必将所有这些 post() 函数重写为 ajax() 函数,只需将它们全部从 post 更改为 xpost(或其他)。
我知道这是一个迟到的答案,我实际上有一个快捷方法,用于发布/读取基于 MS 的服务。它适用于 MVC 以及 ASMX 等。
利用:
$.msajax(
'/services/someservice.asmx/SomeMethod'
,{} /*empty object for nothing, or object to send as Application/JSON */
,function(data,jqXHR) {
//use the data from the response.
}
,function(err,jqXHR) {
//additional error handling.
}
);
//sends a json request to an ASMX or WCF service configured to reply to JSON requests.
(function ($) {
var tries = 0; //IE9 seems to error out the first ajax call sometimes... will retry up to 5 times
$.msajax = function (url, data, onSuccess, onError) {
return $.ajax({
'type': "POST"
, 'url': url
, 'contentType': "application/json"
, 'dataType': "json"
, 'data': typeof data == "string" ? data : JSON.stringify(data || {})
,beforeSend: function(jqXHR) {
jqXHR.setRequestHeader("X-MicrosoftAjax","Delta=true");
}
, 'complete': function(jqXHR, textStatus) {
handleResponse(jqXHR, textStatus, onSuccess, onError, function(){
setTimeout(function(){
$.msajax(url, data, onSuccess, onError);
}, 100 * tries); //try again
});
}
});
}
$.msajax.defaultErrorMessage = "Error retreiving data.";
function logError(err, errorHandler, jqXHR) {
tries = 0; //reset counter - handling error response
//normalize error message
if (typeof err == "string") err = { 'Message': err };
if (console && console.debug && console.dir) {
console.debug("ERROR processing jQuery.msajax request.");
console.dir({ 'details': { 'error': err, 'jqXHR':jqXHR } });
}
try {
errorHandler(err, jqXHR);
} catch (e) {}
return;
}
function handleResponse(jqXHR, textStatus, onSuccess, onError, onRetry) {
var ret = null;
var reterr = null;
try {
//error from jqXHR
if (textStatus == "error") {
var errmsg = $.msajax.defaultErrorMessage || "Error retreiving data.";
//check for error response from the server
if (jqXHR.status >= 300 && jqXHR.status < 600) {
return logError( jqXHR.statusText || msg, onError, jqXHR);
}
if (tries++ < 5) return onRetry();
return logError( msg, onError, jqXHR);
}
//not an error response, reset try counter
tries = 0;
//check for a redirect from server (usually authentication token expiration).
if (jqXHR.responseText.indexOf("|pageRedirect||") > 0) {
location.href = decodeURIComponent(jqXHR.responseText.split("|pageRedirect||")[1].split("|")[0]).split('?')[0];
return;
}
//parse response using ajax enabled parser (if available)
ret = ((JSON && JSON.parseAjax) || $.parseJSON)(jqXHR.responseText);
//invalid response
if (!ret) throw jqXHR.responseText;
// d property wrap as of .Net 3.5
if (ret.d) ret = ret.d;
//has an error
reterr = (ret && (ret.error || ret.Error)) || null; //specifically returned an "error"
if (ret && ret.ExceptionType) { //Microsoft Webservice Exception Response
reterr = ret
}
} catch (err) {
reterr = {
'Message': $.msajax.defaultErrorMessage || "Error retreiving data."
,'debug': err
}
}
//perform final logic outside try/catch, was catching error in onSuccess/onError callbacks
if (reterr) {
logError(reterr, onError, jqXHR);
return;
}
onSuccess(ret, jqXHR);
}
} (jQuery));
注意:我还有一个从 json.org 的 JS 文件修改的 JSON.parseAjax 方法,它添加了对 MS "/Date(...)/" 日期的处理......
不包含修改后的 json2.js 文件,它在 IE8 的情况下使用基于脚本的解析器,因为当您扩展数组和/或对象等的原型时,本机解析器会中断。
我一直在考虑修改这段代码来实现 Promise 接口,但它对我来说效果很好。
问题的核心是 JQuery 在撰写本文时没有 postJSON 方法,而 getJSON 存在并且做正确的事情。
postJSON 方法将执行以下操作:
postJSON = function(url,data){
return $.ajax({url:url,data:JSON.stringify(data),type:'POST', contentType:'application/json'});
};
并且可以像这样使用:
postJSON( 'path/to/server', my_JS_Object_or_Array )
.done(function (data) {
//do something useful with server returned data
console.log(data);
})
.fail(function (response, status) {
//handle error response
})
.always(function(){
//do something useful in either case
//like remove the spinner
});
getJSON
仅以 JSON 格式返回数据,但这并不意味着它以相同格式发送数据。当然,它在 ASP.Net MVC 和 ASP.Net API 中按预期工作,但尝试在 WebMethod
(ASP.Net WebForms) 中使用它[ScriptMethod(UseHttpGet = true)]
属性,你会感到惊讶
documentation 当前显示,从 3.0 开始,$.post 将接受设置对象,这意味着您可以使用 $.ajax 选项。 3.0 尚未发布,on the commit 他们正在谈论在文档中隐藏对它的引用,但在未来寻找它!
我对以下 JavaScript 代码有类似的问题:
var url = 'http://my-host-name.com/api/Rating';
var rating = {
value: 5,
maxValue: 10
};
$.post(url, JSON.stringify(rating), showSavedNotification);
在 Fiddler 中我可以看到请求的位置:
标头:Content-Type:application/x-www-form-urlencoded;字符集=UTF-8
正文:{"value":"5","maxValue":"5"}
结果,我的服务器无法将对象映射到服务器端类型。
将最后一行更改为这一行后:
$.post(url, rating, showSavedNotification);
在提琴手我仍然可以看到:
标头:Content-Type:application/x-www-form-urlencoded;字符集=UTF-8
正文:value=5&maxValue=10
但是,服务器开始返回我所期望的。
你自己的适配器/包装器怎么样?
//adapter.js
var adapter = (function() {
return {
post: function (url, params) {
adapter.ajax(url, "post", params);
},
get: function (url, params) {
adapter.ajax(url, "get", params);
},
put: function (url, params) {
adapter.ajax(url, "put", params);
},
delete: function (url, params) {
adapter.ajax(url, "delete", params);
},
ajax: function (url, type, params) {
var ajaxOptions = {
type: type.toUpperCase(),
url: url,
success: function (data, status) {
var msgType = "";
// checkStatus here if you haven't include data.success = true in your
// response object
if ((params.checkStatus && status) ||
(data.success && data.success == true)) {
msgType = "success";
params.onSuccess && params.onSuccess(data);
} else {
msgType = "danger";
params.onError && params.onError(data);
}
},
error: function (xhr) {
params.onXHRError && params.onXHRError();
//api.showNotificationWindow(xhr.statusText, "danger");
}
};
if (params.data) ajaxOptions.data = params.data;
if (api.isJSON(params.data)) {
ajaxOptions.contentType = "application/json; charset=utf-8";
ajaxOptions.dataType = "json";
}
$.ajax($.extend(ajaxOptions, params.options));
}
})();
//api.js
var api = {
return {
isJSON: function (json) {
try {
var o = JSON.parse(json);
if (o && typeof o === "object" && o !== null) return true;
} catch (e) {}
return false;
}
}
})();
并且非常简单的用法:
adapter.post("where/to/go", {
data: JSON.stringify(params),
onSuccess: function (data) {
//on success response...
}
//, onError: function(data) { //on error response... }
//, onXHRError: function(xhr) { //on XHR error response... }
});
出于某种原因,在我的情况下,按照@Adrien 的建议设置 ajax 请求的内容类型不起作用。但是,您实际上可以使用 $.post 更改内容类型,方法是在此之前执行以下操作:
$.ajaxSetup({
'beforeSend' : function(xhr) {
xhr.overrideMimeType('application/json; charset=utf-8');
},
});
然后拨打 $.post
:
$.post(url, data, function(), "json")
我在使用 jQuery + IIS 时遇到了问题,这是唯一帮助 jQuery 理解将 windows-1252 编码用于 ajax 请求的解决方案。
如果您遇到 CORS(跨源资源共享)问题,$.post
将不起作用。尝试按以下格式使用 $.ajax
:
$.ajax({
url: someurl,
contentType: 'application/json',
data: requestInJSONFormat,
headers: { 'Access-Control-Allow-Origin': '*' },
dataType: 'json',
type: 'POST',
async: false,
success: function (Data) {...}
});
我们可以在 $.post 中像这样更改 Content-type
$.post(url,data, function (data, status, xhr) {
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded; charset=utf-8");});
$.ajaxSetup({ contentType: "application/json; charset=utf-8" });
您不能直接发送 application/json
- 它必须是 GET/POST 请求的参数。
所以像
$.post(url, {json: "...json..."}, function());
JSON.stringify(data)
,因为服务器需要一个 JSON 字符串,而 jQuery 将简单地使用与符号连接键值对,form-urlencoded。