Как заставить $.post() использовать contentType=application/json?
Я заметил, что при использовании $.post() в jquery по умолчанию contentType является application/x-www-form-urlencoded - когда в моем коде mvc asp.net должен быть 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. Так что именно делает параметр "json", если он не меняет тип содержимого на json?
Если я попробую
$.ajaxSetup({
contentType: "application/json; charset=utf-8"
});
Это работает, но влияет на все мои $.get и $.post, которые у меня есть, и заставляет некоторые ломаться.
Так есть ли способ изменить поведение $.post() для отправки contentType=application/json?
15 ответов
Я думаю, что вам, возможно, придется
1. Измените источник так, чтобы $.post всегда использовал тип данных JSON, поскольку это просто ярлык для предварительно сконфигурированного $.ajax
вызов
Или же
2. Определите свою собственную служебную функцию, которая является ярлыком для $.ajax
Конфигурация, которую вы хотите использовать
Или же
3.Вы можете перезаписать $.post function
с вашей собственной реализацией через патч обезьяны.
Тип данных 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(){
//
}
});
В итоге я добавил следующий метод в 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!')
});
Это было сделано путем простого копирования кода "get" и "post" из исходных источников JQuery и жесткого кодирования нескольких параметров для принудительной отправки JSON POST.
Спасибо!
Использовать только
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 был совершенно прав!!
Начиная с версии 1.12.0 jQuery, мы можем сделать это:
$.post({
url: yourURL,
data: yourData,
contentType: 'application/json; charset=utf-8'
})
.done(function (response) {
//Do something on success response...
});
Я только что протестировал, и он работал!!
Это простое расширение jquery API (от: https://benjamin-schweizer.de/jquerypostjson.html) для $.postJSON() делает свое дело. Вы можете использовать postJSON (), как и любой другой нативный вызов jjery Ajax. Вы можете прикрепить обработчики событий и так далее.
$.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
});
};
Как и другие API Ajax (например, $http от AngularJS), он устанавливает правильный тип содержимого для 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");
});
Тип данных "json", который вы можете передать в качестве последнего параметра функции post (), указывает, какой тип данных ожидает функция в ответе сервера, а не какой тип она отправляет в запросе. В частности, он устанавливает заголовок "Принять".
Честно говоря, ваш лучший выбор - переключиться на вызов ajax(). Функция post () предназначена для удобства; упрощенная версия вызова ajax() для простой публикации формы. Вы нет.
Если вы действительно не хотите переключаться, вы можете создать свою собственную функцию, скажем, xpost (), и сделать так, чтобы она просто преобразовывала заданные параметры в параметры для вызова jQuery ajax() с установленным типом содержимого. Таким образом, вместо того, чтобы переписывать все эти функции post () в функции ajax(), вам просто нужно изменить их все с post на xpost (или как угодно).
В основе всего этого лежит тот факт, что 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
});
Я знаю, что это поздний ответ, у меня на самом деле есть ярлык, который я использую для публикации / чтения в / из служб на базе 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.parseAjax, который изменен из файла JS json.org, который добавляет обработку для дат "/Date(...)/" MS...
Измененный файл json2.js не включен, он использует синтаксический анализатор на основе сценариев в случае IE8, поскольку существуют случаи, когда собственный синтаксический анализатор ломается при расширении прототипа массива и / или объекта и т. Д.
Я собирался обновить этот код для реализации интерфейсов обещаний, но он мне очень помог.
В настоящее время документация показывает, что начиная с версии 3.0, $.post будет принимать объект настроек, что означает, что вы можете использовать опции $.ajax. 3.0 еще не выпущен, и в коммите, о котором они говорят, скрывают ссылку на него в документации, но ищите его в будущем!
У меня была похожая проблема со следующим кодом 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
Однако сервер начал возвращать то, что я ожидал.
По какой-то причине установка типа контента в запросе ajax, как предложил @Adrien, в моем случае не сработала. Однако вы можете изменить тип содержимого, используя $.post, выполнив это раньше:
$.ajaxSetup({
'beforeSend' : function(xhr) {
xhr.overrideMimeType('application/json; charset=utf-8');
},
});
Тогда сделай свой $.post
вызов:
$.post(url, data, function(), "json")
У меня были проблемы с jQuery + IIS, и это было единственное решение, которое помогло jQuery понять использование кодировки windows-1252 для запросов ajax.
$.post не работает, если у вас есть проблема CORS (Cross Origin Resource Sharing). Попробуйте использовать $.Ajax в следующем формате: "$.ajax({url: someurl, contentType: 'application/json', data: requestInJSONFormat, headers: {'Access-Control-Allow-Origin': '*'}, dataType: 'json', тип: 'POST', async: false, success: function (Data) {...} });"
Как насчет вашего собственного адаптера / оболочки?
//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... }
});
Мы можем изменить Content-type следующим образом в $.post
$.post (url, data, function (data, status, xhr) {xhr.setRequestHeader ("Content-type", "application / x-www-form-urlencoded; charset = utf-8");});
Вы не можете отправить application/json
напрямую - это должен быть параметр запроса GET/POST.
Так что-то вроде
$.post(url, {json: "...json..."}, function());