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()に変更したくはありません。
試してみると
$.post(url, data, function(), "json")
まだcontentType = application/x-www-form-urlencodedがあります。では、contenttypeがjsonに変更されない場合、 "json"パラメータは正確には何をするのでしょうか。
試してみると
$.ajaxSetup({
contentType: "application/json; charset=utf-8"
});
これは機能しますが、私が持っているすべての$ .getと$ .postに影響し、いくつかを壊します。
では、contentType = application/jsonを送信するように$ .post()の動作を変更できる方法はありますか?
私はあなたがする必要があるかもしれないと思います
1.ソースを変更して$ .postが常にJSONデータ型を使用するようにします。これは実際には事前設定された$.ajax
呼び出しのショートカットにすぎないためです。
または
2。使用したい$.ajax
設定へのショートカットである独自のユーティリティ関数を定義します
または
3.モンキーパッチを使って、$.post function
を自分の実装で上書きすることができます。
この例のJSONデータ型は、fromサーバーから返されたデータ型を指し、はサーバーに送信の形式ではありません。 。
$.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(){
//
}
});
スクリプトの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を強制するためにいくつかのパラメーターをハードコーディングすることによって行われました。
ありがとうございます。
ただ使う
jQuery.ajax ({
url: myurl,
type: "POST",
data: mydata,
dataType: "json",
contentType: "application/json; charset=utf-8",
success: function(){
//
}
});
UPDATED @JK:質問のみを書く場合1つのコード例 $ .postを使用すると、答えに対応する例が1つ見つかります。私が知っているまであなたがすでに勉強した同じ情報を繰り返したくありません:$ .postと$ .getは$ .ajaxの短い形式です。したがって、$。ajaxを使用するだけで、グローバル設定を変更することなく、パラメーターの完全なセットを使用できます。
ところで、標準の$ .postを上書きすることはお勧めしません。それは私の個人的な意見ですが、私にとっては、プログラムが機能するだけでなく、あなたのプログラムを読んだすべての人がそれを同じ方法で理解することも重要です。標準メソッドの上書き非常に重要な理由はないは、プログラムコードの読み取りの誤解に従うことができます。したがって、もう一度推奨事項を繰り返します。jQuery.get
およびjQuery.post
の代わりにjQuery形式の元の$ .ajaxを使用するだけで、完全に機能するだけでなく、誤解のない人々が読むことができるプログラムを受け取ります。 。
Post()の最後のパラメータとして渡すことができる "json"データ型は、関数がリクエストで送信するデータ型ではなく、関数がサーバの応答に期待するデータ型を示します。具体的には "Accept"ヘッダーを設定します。
正直なところあなたの最善の策はajax()呼び出しに切り替えることです。 post()関数は便宜上のものです。 ajax()の単純化されたバージョンは、単純なフォーム投稿をしているときに呼び出します。あなたは違います。
本当に切り替えたくない場合は、xpost()などの独自の関数を作成し、content-typeを設定して、指定されたパラメーターをjQuery ajax()呼び出しのパラメーターに変換するだけで済みます。そうすれば、それらのpost()関数すべてをajax()関数に書き換えるのではなく、それらすべてをpostからxpost(またはその他)に変更するだけで済みます。
私はこれが遅い答えであることを知っています、私は実際に私がMSベースのサービスへの投稿/からの読み取りのために使用するショートカットメソッドを持っています..それはASMXなどMVCで動作します...
つかいます:
$.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にはgetJSONが存在し、正しいことをしている間はpostJSONメソッドがないということです。
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
});
$ .postJSON()のためのこの簡単なjquery APIの拡張(from: 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オブジェクト)を渡すことができます。返される予定のdataTypeはJSONに設定されています。約束のためにjqueryのデフォルトのイベントハンドラをつけることができます。例えば:
$.postJSON(apiURL, jsonData)
.fail(function(res) {
console.error(res.responseText);
})
.always(function() {
console.log("FINISHED ajax post, hide the loading throbber");
});
私は次の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; charset=UTF-8
{"value":"5","maxValue":"5"}
その結果、私のサーバーはオブジェクトをサーバーサイド型にマッピングできませんでした。
最後の行をこれに変更した後:
$.post(url, rating, showSavedNotification);
フィドラーで私はまだ見ることができました:
Content-Type: application/x-www-form-urlencoded; charset=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がajaxリクエストにwindows-1252エンコーディングを使うことを理解するのを助けた唯一の解決策でした。