Jquery - Як змусити $ .post () використовувати contentType = application / json?


308

Я помітив, що при використанні $ .post () у jquery, що типовим 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. Отже, що саме робить парам "json", якщо він не змінює тип контенту на json?

Якщо я спробую

$.ajaxSetup({
  contentType: "application/json; charset=utf-8"
});

Це працює, але впливає на кожен $ .get і $ .post, який у мене є, і спричиняє зламати деякі.

То чи є спосіб змінити поведінку $ .post () для надсилання contentType = application / json?

Відповіді:


70

Я думаю, що вам, можливо, доведеться

1.Modify the source to make $ .post завжди використовує тип даних JSON, оскільки це насправді лише ярлик для попередньо налаштованого $.ajaxдзвінка

Або

2. Визначте власну функцію утиліти, яка є ярликом для $.ajaxконфігурації, яку ви хочете використовувати

Або

3.Ви можете перезаписати $.post functionсвою власну реалізацію за допомогою патч-мавпи.

Тип даних JSON у вашому прикладі відноситься до типу даних, поверненого з сервера, а не до формату, надісланого серверу.


5
+1, я б хотів визначити новий метод або jQuery.postметод перезапису , це дійсно проста функція ...
CMS

3
Це не погана ідея, просто створіть метод, який називається $ .mvcpost (), який робить те саме, що $ .post (копіюючи зв'язаний код), а також змінює тип контенту. Тоді для всіх $ .post (), які потрібно змінити, мені просто потрібно набрати 3 зайвих символи спереду. Це набагато швидше, ніж переписувати їх як $ .ajax ().
Ж.К.

9
@PavelRepin, мені довелося зателефонувати на JSON.stringify () на корисну нагрузку.
Устаман Сангат

2
@dragon - ось три рішення "чи є спосіб змінити поведінку $ .post () для надсилання contentType = application / json?". Яка частина - це не відповідь?
Russ Cam

2
Також важливо знати: $ .ajax і різні методи намагаються вгадати, яким має бути contentType (якщо він не вказаний) на основі даних, які ви їм надаєте. "mystring data"буде application/x-www-form-urlencoded;де об’єктом { anyKey: "anyvalue and type" }буде application/json. Багато серверів, які читають json, дозволять лише об’єкт або масив, а не рядок - тому jquery прогнозує речі таким чином. Якщо у вас є сервер, який читає рядки, цифри тощо, не загортаючись в об’єкт, ви повинні вказати тип вмісту, як у цій відповіді.
bzuillsmith

395
$.ajax({
  url:url,
  type:"POST",
  data:data,
  contentType:"application/json; charset=utf-8",
  dataType:"json",
  success: function(){
    ...
  }
})

Дивіться: jQuery.ajax ()


13
У початковому дописі запитується: "Так чи є спосіб змінити поведінку $ .post () для надсилання contentType = application / json?" Але це також говорить "Це працює, але впливає на кожен $ .get і $ .post, який я маю, і спричиняє деякі ламання". Я розумію питання як "як я можу досягти того ж самого, що і за допомогою $ .post, але надсилаючи правильний contentType, не порушуючи інших випадків $ .get та $ .post". Це неправильно?
Адріан

5
@ x1a4 явно не розуміє, що .ajax - це дзвінок, а не ajaxSetup
Walker

39
@Adrien, для чого це варто два роки пізніше, твоя - це відповідь, яку я шукав, коли це переглянув.
AwesomeTown

74
довелося використовувати JSON.stringify(data), оскільки сервер очікує, що рядок JSON і jQuery буде просто об'єднати парами ключ-значення, використовуючи амперсенди, кодовані формою.
дракон

3
Навіть через чотири роки ця відповідь вирішила мої години пошуку з менш ніж десяти рядками коду.
Пітер VDE

86

Нарешті я знайшов рішення, яке працює для мене:

jQuery.ajax ({
    url: myurl,
    type: "POST",
    data: JSON.stringify({data:"test"}),
    dataType: "json",
    contentType: "application/json; charset=utf-8",
    success: function(){
        //
    }
});

8
Не вдалося зрозуміти, чому я постійно отримував помилки, виявляється, ви повинні впорядкувати дані.
FriendlyGuy

5
Я знаю, що це працює, але ЧОМ о, ЧОМУ вам потрібно впорядкувати? Це помилка jQuery? Здається, це абсолютно раді серіалізувати ваш dataаргумент x-www-form-urlencoded, але якщо ви вказуєте, що тип вмісту запиту - JSON, він все ще наполягає на надсиланні dataу невідповідному форматі.
Павло Рєпін

Добре. Я її дуже не копав. Я був щасливий, що це працює. ;) Мій сервер вимагає JSON.
vvkatwss vvkatwss

Те ж саме. Без JSON.stringify це не працює, мені цікаво чому.
Джон Сімос

42

Я в кінцевому підсумку додав наступний метод до 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 та жорсткого кодування декількох параметрів, щоб змусити JSON POST.

Дякую!


2
Як завжди - найкраща відповідь приходить останньою на вечірку та має найменше відгуків; (
nikib3ro

Чудова відповідь - потрібен час, щоб зрозуміти, що $ .post не робить цього "поза коробкою".
markp3rry

21

використовувати просто

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і ви отримаєте програми , які не тільки відмінно працювати, але можуть бути прочитані людьми без будь - яких непорозумінь.


1
Чудове пояснення та настанова
Вед Пракаш

8

Тип даних "json", який ви можете передати як останній параметр для публікації (), вказує, який тип даних функція очікує у відповіді сервера, а не тип, який він надсилає у запиті. Зокрема, він встановлює заголовок "Прийняти".

Чесно кажучи, ваш найкращий варіант - перейти на виклик Ajax (). Функція post () розуміється як зручність; спрощена версія виклику ajax (), коли ви просто робите просту форму публікації. Ви не є.

Якщо ви дійсно не хочете перемикатися, ви можете зробити власну функцію, яку називають, скажімо, xpost (), і дозволити їй просто перетворити задані параметри в параметри для виклику jQuery ajax () з набором типу вмісту. Таким чином, замість того, щоб переписувати всі ці функції post () в функції ajax (), ви просто повинні змінити їх усі з поста на xpost (або що завгодно).


Єдиний метод $ .post (), який викликає метод контролера asp.net mvc, який потрібно змінити. Чисті jquery повинні бути незмінними (автозаповнення, діалог, jqgrid тощо). Я сподівався, що відбудеться проста зміна, яку я можу внести у відповідні $ .post () s. Але схоже, мені потрібно конвертувати їх у $ .ajax (). Це великий і дуже ajax важкий додаток, тому їх можна багато змінити.
Ж.К.

5

Я знаю, що це пізня відповідь, у мене фактично є метод швидкого доступу, який я використовую для публікації / читання до / від служб, що базуються на 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, який додає обробку для MS "/Date(...)/" дат ...

Змінений файл json2.js не включений, він використовує аналізатор на основі скрипту у випадку IE8, оскільки є випадки, коли нативний парсер розривається, коли ви розширюєте прототип масиву та / або об'єкта тощо.

Я розглядав можливість оновлення цього коду для реалізації інтерфейсів обіцянок, але він працював дуже добре для мене.


5

Це просте розширення API jquery (від: https://benjamin-schweizer.de/jquerypostjson.html ) для $ .postJSON () робить трюк. Ви можете використовувати postJSON (), як і будь-який інший вихідний jquery 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), він встановлює правильний 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");
 });

4

В основі цього питання той факт, що в 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
    });

1

Документації в даний час показує , що за станом на 3,0, $ .post буде приймати об'єкт налаштування, а це означає , що ви можете використовувати опції $ .ajax. 3.0 ще не випущено, і на комітеті вони говорять про приховування посилання на нього в документах, але шукайте це в майбутньому!


1

У мене була подібна проблема із таким кодом 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);

У Fiddler я ще міг бачити:

  • Заголовок: Content-Type: application/x-www-form-urlencoded; charset=UTF-8
  • Тіло: value=5&maxValue=10

Однак сервер почав повертати те, що я очікував.


0

Як щодо власного адаптера / обгортки?

//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... }
});

Спробував, але все ж не отримав очікуваних результатів. у мене є Spring Bost Rest API.
Suraj Shingade

0

Чомусь встановлення типу вмісту на запит 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.


0

ми можемо змінити такий тип вмісту в $ .post

$ .post (url, data, function (data, status, xhr) {xhr.setRequestHeader ("Тип вмісту", "application / x-www-form-urlencoded; charset = utf-8");});


-1

$ .post не працює, якщо у вас є проблема CORS (Cross Origin Resource Sharing). Спробуйте використовувати $ .Ajax у такому форматі: "$ .ajax ({url: someurl, contentType: 'application / json', дані: requestInJSONFormat, заголовки: {'Access-Control-Allow-Origin': '*'}, dataType: 'json', введіть: 'POST', async: false, success: function (Data) {...}}); "


-19

Ви не можете надсилати application/jsonбезпосередньо - це повинен бути параметр запиту GET / POST.

Так щось на кшталт

$.post(url, {json: "...json..."}, function());

Ця відповідь може бути неправильною, але вона низької якості, і це спроба відповісти на питання. З огляду .
Вай Ха Лі
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.