Jquery - How to make $.post() use contentType=application/json?
我注意到在jquery中使用$ .post()时默认的contentType是application / x-www-form-urlencoded - 当我的asp.net mvc代码需要有contentType = application / json
(请参阅此问题,为什么我必须使用application / json:ASPNET MVC - 为什么ModelState.IsValid为false"当该字段确实有值时,x字段是必需的?)
如何使$ .post()发送contentType = application / json? 我已经有了大量的$ .post()函数,所以我不想改成$ .ajax(),因为它需要花费太多时间
如果我试试
1 | $.post(url, data, function(),"json") |
它仍然有contentType = application / x-www-form-urlencoded。 那么如果"json"参数没有将contenttype更改为json,那究竟该做什么呢?
如果我试试
1 2 3 | $.ajaxSetup({ contentType:"application/json; charset=utf-8" }); |
这有效但影响我拥有的每一个$ .get和$ .post并导致一些破坏。
那么有什么方法可以改变$ .post()的行为来发送contentType = application / json?
1 2 3 4 5 6 7 8 9 10 | $.ajax({ url:url, type:"POST", data:data, contentType:"application/json; charset=utf-8", dataType:"json", success: function(){ ... } }) |
请参阅:jQuery.ajax()
最后我找到了适合我的解决方案:
1 2 3 4 5 6 7 8 9 10 | jQuery.ajax ({ url: myurl, type:"POST", data: JSON.stringify({data:"test"}), dataType:"json", contentType:"application/json; charset=utf-8", success: function(){ // } }); |
我想你可能不得不这样做
1.修改源以使$ .post始终使用JSON数据类型,因为它实际上只是预先配置的
要么
2.定义您自己的实用程序功能,它是您要使用的
要么
3.你可以通过猴子补丁用你自己的实现覆盖
示例中的JSON数据类型是指从服务器返回的数据类型,而不是发送到服务器的格式。
我最终在我的脚本中将以下方法添加到jQuery:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 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 }); }; |
并使用它
1 2 3 | $.postJSON('http://url', {data: 'goes', here: 'yey'}, function (data, status, xhr) { alert('Nailed it!') }); |
这是通过简单地从原始JQuery源复制"get"和"post"的代码并硬编码一些参数来强制执行JSON POST来完成的。
谢谢!
使用只是
1 2 3 4 5 6 7 8 9 10 | jQuery.ajax ({ url: myurl, type:"POST", data: mydata, dataType:"json", contentType:"application/json; charset=utf-8", success: function(){ // } }); |
UPDATED @JK:如果你在问题中只用一个代码示例写一个$ .post,你会在答案中找到一个相应的例子。我不想重复你已经研究过的相同信息,直到知道:$ .post和$ .get是$ .ajax的缩写形式。因此,只需使用$ .ajax即可使用其完整的参数集,而无需更改任何全局设置。
顺便说一下,我不建议覆盖标准的$ .post。这是我个人的意见,但对我而言,重要的是,不仅程序有效,而且所有阅读程序的人都以同样的方式理解它。在没有非常重要原因的情况下覆盖标准方法可能会导致在阅读程序代码时出现误解。所以我再一次重复我的建议:只使用原始的$ .ajax形式jQuery而不是
您可以作为post()的最后一个参数传递的"json"数据类型指示函数在服务器响应中期望的数据类型,而不是它在请求中发送的类型。具体来说,它设置"接受"标题。
老实说,你最好的选择是切换到ajax()调用。 post()函数意味着方便;当你刚刚做一个简单的表单发布时,ajax()调用的简化版本。你不是。
如果你真的不想切换,你可以创建自己的函数,比如xpost(),并让它简单地将给定的参数转换为jQuery ajax()调用的参数,并设置内容类型。这样,你不必将所有post()函数重写为ajax()函数,而只需将它们全部从post更改为xpost(或其他)。
我知道这是一个迟到的答案,我实际上有一个快捷方法,我用它来发布/读取基于MS的服务..它适用于MVC以及ASMX等...
使用:
1 2 3 4 5 6 7 8 9 10 | $.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. } ); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 | //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.parseAjax方法,该方法是从json.org的JS文件修改的,它为MS"/Date(...)/"日期添加了处理...
修改后的json2.js文件不包含在内,它在IE8的情况下使用基于脚本的解析器,因为在扩展数组和/或对象的原型等时存在本机解析器中断的实例。
我一直在考虑修改这个代码来实现promises接口,但它对我来说非常好用。
问题的核心在于,JQuery在撰写本文时没有postJSON方法,而getJSON存在并做正确的事情。
postJSON方法将执行以下操作:
1 2 3 | postJSON = function(url,data){ return $.ajax({url:url,data:JSON.stringify(data),type:'POST', contentType:'application/json'}); }; |
并可以像这样使用:
1 2 3 4 5 6 7 8 9 10 11 12 | 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 }); |
对于$ .postJSON(),这个简单的jquery API扩展(来自:https://benjamin-schweizer.de/jquerypostjson.html)可以解决问题。您可以像所有其他本机jquery Ajax调用一样使用postJSON()。您可以附加事件处理程序等。
1 2 3 4 5 6 7 8 9 10 | $.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对象),因为它在此处进行了字符串化。
预期返回的dataType设置为JSON。
您可以为promises附加jquery的默认事件处理程序,例如:
1 2 3 4 5 6 7 | $.postJSON(apiURL, jsonData) .fail(function(res) { console.error(res.responseText); }) .always(function() { console.log("FINISHED ajax post, hide the loading throbber"); }); |
文档目前显示,从3.0开始,$ .post将接受设置对象,这意味着您可以使用$ .ajax选项。 3.0尚未发布,在提交时他们正在讨论在文档中隐藏对它的引用,但将来会查找它!
我在以下JavaScript代码中遇到了类似的问题:
1 2 3 4 5 6 7 8 | 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; charset=UTF-8 -
身体:
{"value":"5","maxValue":"5"}
因此,我的服务器无法将对象映射到服务器端类型。
将最后一行更改为此行后:
1 | $.post(url, rating, showSavedNotification); |
在小提琴手中我仍然可以看到:
-
标题:
Content-Type: application/x-www-form-urlencoded; charset=UTF-8 -
身体:
value=5&maxValue=10
但是,服务器开始返回我的预期。
你自己的适配器/包装器怎么样?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | //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; } } })(); |
非常简单的用法:
1 2 3 4 5 6 7 8 | 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更改内容类型,方法是:
1 2 3 4 5 | $.ajaxSetup({ 'beforeSend' : function(xhr) { xhr.overrideMimeType('application/json; charset=utf-8'); }, }); |
然后拨打
1 | $.post(url, data, function(),"json") |
我遇到了jQuery + IIS的问题,这是帮助jQuery理解为ajax请求使用windows-1252编码的唯一解决方案。
如果您有CORS(跨源资源共享)问题,$ .post不起作用。尝试使用以下格式的$ .Ajax:
"$ .ajax({
url:someurl,
contentType:'application / json',
data:requestInJSONFormat,
标题:{'Access-Control-Allow-Origin':'*'},
dataType:'json',
类型:'POST',
async:false,
成功:功能(数据){...}
});"
我们可以在$ .post中更改内容类型
$ .post(url,data,function(data,status,xhr){
xhr.setRequestHeader("Content-type","application / x-www-form-urlencoded; charset = utf-8");});
您无法直接发送
所以像
1 | $.post(url, {json:"...json..."}, function()); |