Jquery - Bagaimana cara membuat $ .post () menggunakan contentType = application / json?

309

Saya perhatikan ketika menggunakan $ .post () di jquery bahwa contentType default adalah application / x-www-form-urlencoded - ketika kode mvc asp.net saya perlu memiliki contentType = application / json

(Lihat pertanyaan ini mengapa saya harus menggunakan aplikasi / json: ASPNET MVC - Mengapa ModelState.IsValid false "Bidang x diperlukan" ketika bidang itu memang memiliki nilai? )

Bagaimana saya dapat menghasilkan $ .post () mengirim contentType = application / json? Saya sudah memiliki banyak fungsi $ .post (), jadi saya tidak ingin mengubah ke $ .ajax () karena itu akan memakan terlalu banyak waktu

Jika saya mencoba

$.post(url, data, function(), "json") 

Itu masih memiliki contentType = application / x-www-form-urlencoded. Jadi apa sebenarnya yang dilakukan param "json" jika tidak mengubah contenttype menjadi json?

Jika saya mencoba

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

Itu bekerja tetapi mempengaruhi setiap $. Get dan $ .post yang saya miliki dan menyebabkan beberapa rusak.

Jadi apakah ada cara agar saya dapat mengubah perilaku $ .post () untuk mengirim contentType = application / json?

JK.
sumber

Jawaban:

71

Saya pikir Anda mungkin harus melakukannya

1.Modifikasi sumber untuk membuat $ .post selalu menggunakan tipe data JSON karena ini hanyalah jalan pintas untuk $.ajaxpanggilan pra-konfigurasi

Atau

2. Tentukan fungsi utilitas Anda sendiri yang merupakan jalan pintas untuk $.ajaxkonfigurasi yang ingin Anda gunakan

Atau

3. Anda dapat menimpa $.post functiondengan implementasi Anda sendiri melalui patch monyet.

Tipe data JSON dalam contoh Anda mengacu pada tipe data yang dikembalikan dari server dan bukan format yang dikirim ke server.

Russ Cam
sumber
5
+1, saya akan mendefinisikan metode baru, atau jQuery.postmetode menimpa , ini adalah fungsi yang sangat sederhana ...
CMS
3
Ini bukan ide yang buruk, cukup buat metode yang disebut $ .mvcpost () yang melakukan hal yang sama dengan $ .post (dengan menyalin kode tertaut) ditambah mengubah tipe konten. Kemudian untuk semua $ .post () yang perlu diubah, saya hanya perlu mengetik 3 karakter tambahan di depan. Jauh lebih cepat daripada menulis ulang mereka sebagai $ .ajax ().
JK.
9
@ PavelRepin, saya harus menelepon JSON.stringify () di payload.
Ustaman Sangat
2
@dragon - di sini ada 3 solusi untuk "apakah ada cara agar saya dapat mengubah perilaku $ .post () untuk mengirim contentType = application / json?". Bagian mana yang bukan jawaban?
Russ Cam
2
Penting juga untuk diketahui: $ .ajax dan beragam metode akan mencoba menerka apa seharusnya contentType (kecuali ditentukan) berdasarkan data yang Anda berikan. "mystring data"akan application/x-www-form-urlencoded;di mana sebagai objek { anyKey: "anyvalue and type" }akan application/json. Banyak server yang membaca json, hanya akan mengizinkan objek atau array, bukan string - jadi mengapa jquery memprediksi hal-hal seperti ini. Jika Anda memiliki server yang membaca string, angka, dll tanpa dibungkus objek, Anda harus menentukan tipe konten seperti dalam jawaban ini.
bzuillsmith
395
$.ajax({
  url:url,
  type:"POST",
  data:data,
  contentType:"application/json; charset=utf-8",
  dataType:"json",
  success: function(){
    ...
  }
})

Lihat: jQuery.ajax ()

Adrien
sumber
13
Posting asli bertanya: "Jadi apakah ada cara agar saya dapat mengubah perilaku $ .post () untuk mengirim contentType = application / json?" TAPI itu juga menyatakan "Itu bekerja tetapi mempengaruhi setiap $. Get dan $ .post yang saya miliki dan menyebabkan beberapa rusak.". Saya memahami pertanyaan sebagai "bagaimana saya bisa mencapai hal yang sama seperti menggunakan $ .post tetapi mengirimkan contentType yang tepat tanpa merusak kejadian lainnya dari $ .get dan $ .post". Apakah itu salah?
Adrien
5
@ x1a4 jelas tidak mengerti bahwa .ajax adalah panggilannya, bukan ajaxSetup
Walker
39
@ Adrien, untuk apa nilainya dua tahun kemudian, jawaban Anda adalah yang saya cari ketika saya mencari di Google.
AwesomeTown
74
harus digunakan JSON.stringify(data), karena server mengharapkan string JSON dan jQuery hanya akan menggabungkan pasangan nilai kunci menggunakan ampersand, bentuk-urlencoded.
naga
3
Bahkan empat tahun kemudian, jawaban ini telah memecahkan jam saya mencari dengan kurang dari sepuluh baris kode.
Pieter VDE
86

Akhirnya saya menemukan solusinya, yang bekerja untuk saya:

jQuery.ajax ({
    url: myurl,
    type: "POST",
    data: JSON.stringify({data:"test"}),
    dataType: "json",
    contentType: "application/json; charset=utf-8",
    success: function(){
        //
    }
});
vvkatwss vvkatwss
sumber
8
Tidak dapat mengetahui mengapa saya terus mendapatkan kesalahan, ternyata Anda harus merangkai data.
zastrowm
5
Saya tahu ini bekerja, tapi MENGAPA oh MENGAPA Anda perlu merumuskan? Apakah ini bug jQuery? Tampaknya sangat senang untuk membuat serialisasi dataargumen Anda x-www-form-urlencoded, tetapi jika Anda menunjukkan bahwa tipe konten permintaan adalah JSON, itu tetap bersikeras mengirim datadalam format yang tidak cocok.
Pavel Repin
Baik. Saya tidak menggali terlalu banyak. Saya senang itu berhasil. ;) Server saya membutuhkan JSON.
vvkatwss vvkatwss
Sama disini. Tanpa JSON.stringify tidak bekerja, saya bertanya-tanya mengapa.
John Simoes
42

Saya akhirnya menambahkan metode berikut ke jQuery di skrip saya:

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

Dan untuk menggunakannya

$.postJSON('http://url', {data: 'goes', here: 'yey'}, function (data, status, xhr) {
    alert('Nailed it!')
});

Ini dilakukan dengan hanya menyalin kode "get" dan "post" dari sumber JQuery asli dan meng-hardcoding beberapa parameter untuk memaksa JSON POST.

Terima kasih!

kontinuitas
sumber
2
Seperti biasa - jawaban terbaik datang terakhir ke pesta dan memiliki paling sedikit upvotes; (
nikib3ro
Jawaban yang bagus - perlu beberapa saat untuk menyadari bahwa $ .post tidak melakukan ini "di luar kotak".
markp3rry
21

gunakan saja

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

UPDATED @JK: Jika Anda menulis dalam pertanyaan Anda hanya satu contoh kode dengan $ .post Anda menemukan satu contoh yang sesuai dalam jawabannya. Saya tidak ingin mengulangi informasi yang sama yang sudah Anda pelajari sampai Anda tahu: $ .post dan $. Get adalah bentuk singkat dari $ .ajax. Jadi gunakan saja $ .ajax dan Anda dapat menggunakan set lengkap parameternya tanpa harus mengubah pengaturan global apa pun.

Ngomong-ngomong, saya tidak akan merekomendasikan menimpa pos $ standar. Ini pendapat pribadi saya , tetapi bagi saya ini penting, tidak hanya programnya bekerja, tetapi juga semua orang yang membaca program Anda memahaminya dengan cara yang sama. Menimpa metode standar tanpa alasan yang sangat penting dapat menyebabkan kesalahpahaman dalam membaca kode program. Jadi saya ulangi rekomendasi saya sekali lagi: cukup gunakan $ .ajax form asli jQuery daripada jQuery.getdan jQuery.postdan Anda menerima program yang tidak hanya berfungsi dengan baik, tetapi dapat dibaca oleh orang-orang tanpa kesalahpahaman.

Oleg
sumber
1
Penjelasan dan pedoman hebat
Ved Prakash
8

Tipe data "json" yang dapat Anda lewati sebagai parameter terakhir yang dikirim () menunjukkan tipe data apa yang diharapkan fungsi dalam respons server, bukan tipe apa yang dikirim dalam permintaan. Khususnya itu mengatur header "Terima".

Jujur taruhan terbaik Anda adalah beralih ke panggilan ajax (). Fungsi post () dimaksudkan sebagai kenyamanan; versi sederhana dari panggilan ajax () ketika Anda hanya melakukan postingan formulir sederhana. Kamu tidak.

Jika Anda benar-benar tidak ingin beralih, Anda bisa membuat fungsi Anda sendiri bernama, katakanlah, xpost (), dan minta saja mengubah parameter yang diberikan menjadi parameter untuk panggilan jQuery ajax (), dengan set tipe-konten. Dengan begitu, alih-alih menulis ulang semua fungsi post () menjadi fungsi ajax (), Anda hanya perlu mengubah semuanya dari postingan menjadi xpost (atau apa pun).

Jacob Mattison
sumber
Hanya metode $ .post () yang memanggil metode pengontrol asp.net mvc yang perlu diubah. Yang murni jquery harus tidak berubah (autocomplete, diaplog, jqgrid dll). Saya berharap akan ada perubahan sederhana yang bisa saya lakukan untuk $ .post () s yang relevan. Tapi sepertinya saya perlu mengubahnya menjadi $ .ajax (). Ini aplikasi besar dan sangat ajax, jadi ada banyak dari mereka yang berubah.
JK.
6

Perpanjangan API jquery sederhana ini (dari: https://benjamin-schweizer.de/jquerypostjson.html ) untuk $ .postJSON () berhasil. Anda dapat menggunakan postJSON () seperti setiap panggilan Ajax jquery asli lainnya. Anda dapat melampirkan penangan acara dan sebagainya.

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

Seperti API Ajax lainnya (seperti $ http dari AngularJS) ia menetapkan contentType yang benar ke application / json. Anda dapat mengirimkan data json Anda (objek javascript) secara langsung, karena data tersebut akan diikat di sini. DataType yang dikembalikan diharapkan diatur ke JSON. Anda dapat melampirkan event handler jquery untuk janji, misalnya:

$.postJSON(apiURL, jsonData)
 .fail(function(res) {
   console.error(res.responseText);
 })
 .always(function() {
   console.log("FINISHED ajax post, hide the loading throbber");
 });
Ruwen
sumber
5

Saya tahu ini adalah jawaban yang terlambat, saya sebenarnya memiliki metode pintas yang saya gunakan untuk posting / membaca ke / dari layanan berbasis MS .. ia bekerja dengan MVC serta ASMX dll ...

Menggunakan:

$.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));

CATATAN: Saya juga memiliki metode JSON.parseAjax yang dimodifikasi dari file JS json.org, yang menambahkan penanganan untuk tanggal MS "/ Tanggal (... )/" ...

File json2.js yang dimodifikasi tidak termasuk, ia menggunakan parser berbasis skrip dalam kasus IE8, karena ada contoh di mana parser asli rusak ketika Anda memperpanjang prototipe array dan / atau objek, dll.

Saya telah mempertimbangkan pembenahan kode ini untuk mengimplementasikan antarmuka yang dijanjikan, tetapi itu bekerja dengan sangat baik bagi saya.

Pelacak1
sumber
4

Inti masalahnya adalah kenyataan bahwa JQuery pada saat penulisan tidak memiliki metode postJSON sementara getJSON ada dan melakukan hal yang benar.

metode postJSON akan melakukan hal berikut:

postJSON = function(url,data){
    return $.ajax({url:url,data:JSON.stringify(data),type:'POST', contentType:'application/json'});
};

dan bisa digunakan seperti ini:

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
    });
dbrin
sumber
1

The dokumentasi saat ini menunjukkan bahwa pada 3,0, $ .post akan menerima pengaturan objek, yang berarti bahwa Anda dapat menggunakan $ ajax pilihan. 3.0 belum dirilis dan di komit mereka berbicara tentang menyembunyikan referensi untuk itu di dokumen, tetapi mencarinya di masa depan!

Ben Creasy
sumber
1

Saya memiliki masalah serupa dengan kode JavaScript berikut:

var url = 'http://my-host-name.com/api/Rating';

var rating = { 
  value: 5,
  maxValue: 10
};

$.post(url, JSON.stringify(rating), showSavedNotification);

Di mana di Fiddler saya bisa melihat permintaan dengan:

  • Tajuk: Content-Type: application/x-www-form-urlencoded; charset=UTF-8
  • Tubuh: {"value":"5","maxValue":"5"}

Akibatnya, server saya tidak dapat memetakan objek ke jenis sisi server.

Setelah mengubah baris terakhir ke yang ini:

$.post(url, rating, showSavedNotification);

Di Fiddler saya masih bisa melihat:

  • Tajuk: Content-Type: application/x-www-form-urlencoded; charset=UTF-8
  • Tubuh: value=5&maxValue=10

Namun, server mulai mengembalikan apa yang saya harapkan.

Oleg Burov
sumber
0

Bagaimana dengan adaptor / pembungkus Anda sendiri?

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

Dan penggunaan yang sangat sederhana:

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... }
});
Menghitam
sumber
Sudah mencoba tetapi masih belum mendapatkan hasil yang diharapkan. saya punya Spring Boot Rest API.
Suraj Shingade
0

Untuk beberapa alasan, mengatur jenis konten pada permintaan ajax seperti yang disarankan @Adrien tidak berfungsi dalam kasus saya. Namun, Anda sebenarnya dapat mengubah jenis konten menggunakan $ .post dengan melakukan ini sebelumnya:

$.ajaxSetup({
    'beforeSend' : function(xhr) {
        xhr.overrideMimeType('application/json; charset=utf-8');
    },
});

Kemudian lakukan $.postpanggilan:

$.post(url, data, function(), "json")

Saya mengalami masalah dengan jQuery + IIS, dan ini adalah satu-satunya solusi yang membantu jQuery memahami untuk menggunakan pengkodean windows-1252 untuk permintaan ajax.

Johannes
sumber
0

kita dapat mengubah tipe-konten seperti ini di $ .post

$ .post (url, data, fungsi (data, status, xhr) {xhr.setRequestHeader ("Tipe konten", "application / x-www-form-urlencoded; charset = utf-8");});

Snziv Gupta
sumber
-1

$ .post tidak berfungsi jika Anda memiliki masalah CORS (Cross Origin Resource Sharing). Coba gunakan $ .Ajax dalam format berikut: "$ .ajax ({url: someurl, contentType: 'application / json', data: requestInJSONFormat, header: {'Access-Control-Allow-Origin': '*'}, dataType: 'json', ketik: 'POST', async: false, success: function (Data) {...}}); "

Soma Sarkar
sumber
-19

Anda tidak dapat mengirim application/jsonsecara langsung - itu harus menjadi parameter permintaan GET / POST.

Jadi sesuatu seperti itu

$.post(url, {json: "...json..."}, function());
Amy B
sumber
Jawaban ini mungkin salah, tetapi kualitasnya tidak rendah, dan ini merupakan upaya untuk menjawab pertanyaan itu. Dari Ulasan .
Wai Ha Lee