Jquery - Cách tạo $ .post () sử dụng contentType = application / json?


309

Tôi đã nhận thấy rằng khi sử dụng $ .post () trong jquery rằng contentType mặc định là application / x-www-form-urlencoding - khi mã mvc asp.net của tôi cần phải có contentType = application / json

(Xem câu hỏi này để biết tại sao tôi phải sử dụng application / json: ASPNET MVC - Tại sao ModelState.IsValid sai "Trường x là bắt buộc" khi trường đó có giá trị? )

Làm cách nào tôi có thể tạo $ .post () gửi contentType = application / json? Tôi đã có một số lượng lớn các hàm $ .post (), vì vậy tôi không muốn đổi thành $ .ajax () vì sẽ mất quá nhiều thời gian

Nếu tôi cố gắng

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

Nó vẫn có contentType = application / x-www-form-urlencoding. Vậy chính xác thì "json" param sẽ làm gì nếu nó không thay đổi nội dung thành json?

Nếu tôi cố gắng

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

Điều đó hoạt động nhưng ảnh hưởng đến mỗi $ .get và $ .post mà tôi có và khiến một số bị hỏng.

Vậy có cách nào để tôi có thể thay đổi hành vi của $ .post () để gửi contentType = application / json không?

Câu trả lời:


71

Tôi nghĩ bạn có thể phải

1.Modify nguồn để tạo $ .post luôn sử dụng kiểu dữ liệu JSON vì nó thực sự chỉ là một lối tắt cho một $.ajaxcuộc gọi được cấu hình trước

Hoặc là

2. Xác định chức năng tiện ích của riêng bạn là lối tắt cho $.ajaxcấu hình bạn muốn sử dụng

Hoặc là

3. Bạn có thể ghi đè lên $.post functionvới việc thực hiện của riêng bạn thông qua việc vá khỉ.

Kiểu dữ liệu JSON trong ví dụ của bạn đề cập đến kiểu dữ liệu được trả về từ máy chủ chứ không phải định dạng được gửi đến máy chủ.


5
+1, tôi sẽ định nghĩa một phương thức mới hoặc jQuery.postphương thức ghi đè , đó là một chức năng thực sự đơn giản ...
CMS

3
Đó không phải là một ý tưởng tồi, chỉ cần tạo một phương thức gọi là $ .mvcpost () giống như $ .post (bằng cách sao chép mã được liên kết) cộng với thay đổi kiểu nội dung. Sau đó, đối với tất cả các $ .post () cần thay đổi, tôi chỉ cần nhập thêm 3 ký tự phía trước. Nó nhanh hơn nhiều so với việc viết lại chúng thành $ .ajax ().
JK.

9
@PavelRepin, tôi đã phải gọi JSON.opesify () trên tải trọng.
Ustaman Sangat

2
@dragon - đây là 3 giải pháp cho "có cách nào để tôi có thể thay đổi hành vi của $ .post () để gửi contentType = application / json không?". Phần nào không phải là một câu trả lời?
Nga Cam

2
Một điều cũng quan trọng cần biết: $ .ajax và các phương thức khác nhau sẽ cố gắng đoán nội dung nên là gì (trừ khi được chỉ định) dựa trên dữ liệu bạn cung cấp. "mystring data"sẽ là application/x-www-form-urlencoded;nơi như một đối tượng { anyKey: "anyvalue and type" }sẽ được application/json. Nhiều máy chủ đọc json, sẽ chỉ cho phép một đối tượng hoặc mảng, không phải là một chuỗi - do đó tại sao jquery dự đoán mọi thứ theo cách này. Nếu bạn có một máy chủ đọc các chuỗi, số, v.v. mà không được bọc trong một đối tượng, bạn phải chỉ định loại nội dung như trong câu trả lời này.
bzuillsmith

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

Xem: jQuery.ajax ()


13
Bài đăng gốc hỏi: "Vậy có cách nào để tôi có thể thay đổi hành vi của $ .post () để gửi contentType = application / json không?" NHƯNG nó cũng ghi "Điều đó hoạt động nhưng ảnh hưởng đến từng $ .get và $ .post mà tôi có và khiến một số bị hỏng." Tôi hiểu câu hỏi là "làm thế nào tôi có thể đạt được điều tương tự như khi sử dụng $ .post nhưng gửi đúng nội dungType mà không phá vỡ các lần xuất hiện khác của $ .get và $ .post". Điều đó có sai không?
Adrien

5
@ x1a4 rõ ràng không hiểu rằng .ajax là cuộc gọi, không phải là ajaxSetup
Walker

39
@Adrien, vì những gì đáng giá hai năm sau, câu trả lời của bạn là câu trả lời mà tôi đang tìm kiếm khi tôi tìm hiểu điều này.
AwesomeTown

74
phải sử dụng JSON.stringify(data), vì máy chủ mong đợi một chuỗi JSON và jQuery chỉ đơn giản là ghép các cặp khóa-giá trị bằng cách sử dụng ký hiệu, mã hóa mẫu.
rồng

3
Thậm chí bốn năm sau, câu trả lời này đã giải quyết được hàng giờ tìm kiếm của tôi với ít hơn mười dòng mã.
Pieter VDE

86

Cuối cùng tôi đã tìm ra giải pháp, nó hiệu quả với tôi:

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

8
Không thể hiểu tại sao tôi cứ bị lỗi, hóa ra bạn phải xâu chuỗi dữ liệu.
zastrowm

5
Tôi biết điều này hoạt động, nhưng TẠI SAO oh TẠI SAO bạn cần phải xâu chuỗi? Đây có phải là một lỗi của jQuery không? Có vẻ như hoàn toàn vui mừng khi tuần tự hóa datađối số của bạn x-www-form-urlencoded, nhưng nếu bạn chỉ ra rằng loại nội dung yêu cầu là JSON, thì nó vẫn khăng khăng gửi datatheo định dạng không khớp.
Pavel Repin

Tốt. Tôi đã không đào nó nhiều. Tôi rất vui vì nó đã làm việc. ;) Máy chủ của tôi yêu cầu JSON.
vvkatwss vvkatwss

Tương tự ở đây. Nếu không có JSON.opesify thì nó không hoạt động, tôi tự hỏi tại sao.
John Simoes

42

Tôi đã kết thúc việc thêm phương thức sau vào jQuery trong tập lệnh của mình:

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

Và để sử dụng nó

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

Điều này được thực hiện bằng cách sao chép mã "get" và "post" từ các nguồn JQuery ban đầu và mã hóa một vài tham số để buộc JSON POST.

Cảm ơn!


2
Như thường lệ - câu trả lời hay nhất xuất hiện cuối cùng trong bữa tiệc và có ít lượt
upvote

Câu trả lời tuyệt vời - phải mất một thời gian để nhận ra rằng $ .post không làm điều này "ngoài luồng".
markp3rry 28/03 '

21

chỉ sử dụng

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

CẬP NHẬT @JK: Nếu bạn viết trong câu hỏi của mình chỉ một ví dụ mã với $ .post, bạn sẽ tìm thấy một ví dụ tương ứng trong câu trả lời. Tôi không muốn lặp lại cùng một thông tin mà bạn đã nghiên cứu cho đến khi biết: $ .post và $ .get là các dạng ngắn của $ .ajax. Vì vậy, chỉ cần sử dụng $ .ajax và bạn có thể sử dụng bộ đầy đủ các tham số của nó mà không phải thay đổi bất kỳ cài đặt chung nào.

Nhân tiện, tôi không khuyên bạn nên ghi đè $ .post tiêu chuẩn. Đó là ý kiến ​​cá nhân của tôi , nhưng đối với tôi, điều quan trọng là, không chỉ chương trình hoạt động mà còn tất cả những ai đọc chương trình của bạn đều hiểu nó theo cùng một cách. Ghi đè các phương thức tiêu chuẩn mà không có một lý do rất quan trọng có thể dẫn đến sự hiểu lầm trong việc đọc mã chương trình. Vì vậy, tôi lặp lại đề nghị thêm một lần nữa tôi: chỉ cần sử dụng $ .ajax gốc hình thành jQuery thay vì jQuery.getjQuery.postvà bạn nhận được các chương trình mà không chỉ làm việc một cách hoàn hảo, nhưng có thể được đọc bởi những người không có bất kỳ sự hiểu lầm.


1
Lời giải thích và hướng dẫn tuyệt vời
Ved Prakash

8

Kiểu dữ liệu "json" mà bạn có thể chuyển làm tham số cuối cùng để đăng () cho biết loại dữ liệu mà hàm đang mong đợi trong phản hồi của máy chủ, chứ không phải loại nào được gửi trong yêu cầu. Cụ thể, nó đặt tiêu đề "Chấp nhận".

Thành thật mà nói, cách tốt nhất của bạn là chuyển sang một cuộc gọi ajax (). Hàm post () có nghĩa là tiện lợi; một phiên bản đơn giản của lệnh gọi ajax () khi bạn chỉ thực hiện một bài đăng đơn giản. Bạn không.

Nếu bạn thực sự không muốn chuyển đổi, bạn có thể tạo hàm riêng của mình được gọi là xpost () và chỉ cần chuyển đổi các tham số đã cho thành tham số cho lệnh gọi jQuery ajax (), với bộ kiểu nội dung. Bằng cách đó, thay vì viết lại tất cả các hàm post () đó thành các hàm ajax (), bạn chỉ cần thay đổi tất cả chúng từ bài đăng sang xpost (hoặc bất cứ điều gì).


Chỉ có các phương thức $ .post () gọi phương thức điều khiển mvc asp.net cần thay đổi. Các jquery thuần nên không thay đổi (tự động hoàn thành, diaplog, jqgrid, v.v.) Tôi đã hy vọng sẽ có một thay đổi đơn giản mà tôi có thể thực hiện đối với $ .post (). Nhưng có vẻ như tôi cần chuyển đổi chúng thành $ .ajax (). Đây là một ứng dụng lớn và rất nặng ajax, vì vậy có rất nhiều trong số họ phải thay đổi.
JK.

6

Phần mở rộng API jquery đơn giản này (từ: https://benjamin-schweizer.de/jquerypostjson.html ) cho $ .postJSON () thực hiện thủ thuật. Bạn có thể sử dụng postJSON () như mọi cuộc gọi Ajax jquery bản địa khác. Bạn có thể đính kèm xử lý sự kiện và như vậy.

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

Giống như các API Ajax khác (như $ http từ AngularJS), nó đặt nội dung chính xác cho application / json. Bạn có thể truyền trực tiếp dữ liệu json của mình (đối tượng javascript) vì nó được xâu chuỗi ở đây. DataType được trả về dự kiến ​​được đặt thành JSON. Bạn có thể đính kèm các trình xử lý sự kiện mặc định của jquery cho các lời hứa, ví dụ:

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

5

Tôi biết đây là một câu trả lời muộn, tôi thực sự có một phương pháp phím tắt mà tôi sử dụng để đăng / đọc đến / từ các dịch vụ dựa trên MS .. nó hoạt động với MVC cũng như ASMX, v.v ...

Sử dụng:

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

LƯU Ý: Tôi cũng có một phương thức JSON.parseAjax được sửa đổi từ tệp JS của json.org, để thêm xử lý cho ngày MS "/Date(...)/" ...

Tệp json2.js đã sửa đổi không được bao gồm, nó sử dụng trình phân tích cú pháp dựa trên tập lệnh trong trường hợp IE8, vì có những trường hợp trình phân tích cú pháp riêng bị hỏng khi bạn mở rộng nguyên mẫu của mảng và / hoặc đối tượng, v.v.

Tôi đã xem xét việc cải tiến mã này để thực hiện các giao diện hứa hẹn, nhưng nó thực sự hiệu quả với tôi.


4

Trọng tâm của vấn đề là thực tế là JQuery tại thời điểm viết bài không có phương thức postJSON trong khi getJSON tồn tại và thực hiện đúng.

một phương thức postJSON sẽ làm như sau:

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

và có thể được sử dụng như thế này:

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

Các tài liệu hiện cho thấy tính đến 3.0, $ .post sẽ chấp nhận các thiết lập đối tượng, nghĩa là bạn có thể sử dụng các tùy chọn $ .ajax. 3.0 chưa được phát hành và trên cam kết họ đang nói về việc giấu tham chiếu đến nó trong các tài liệu, nhưng hãy tìm nó trong tương lai!


1

Tôi gặp vấn đề tương tự với mã JavaScript sau:

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

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

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

Ở đâu trong Fiddler tôi có thể thấy yêu cầu với:

  • Tiêu đề: Content-Type: application/x-www-form-urlencoded; charset=UTF-8
  • Thân hình: {"value":"5","maxValue":"5"}

Do đó, máy chủ của tôi không thể ánh xạ một đối tượng sang loại phía máy chủ.

Sau khi thay đổi dòng cuối cùng thành dòng này:

$.post(url, rating, showSavedNotification);

Trong Fiddler tôi vẫn có thể thấy:

  • Tiêu đề: Content-Type: application/x-www-form-urlencoded; charset=UTF-8
  • Thân hình: value=5&maxValue=10

Tuy nhiên, máy chủ bắt đầu trả lại những gì tôi mong đợi.


0

Làm thế nào về bộ chuyển đổi / bọc của riêng bạn?

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

Và cách sử dụng cực kỳ đơn giản:

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

Đã thử nhưng vẫn không nhận được kết quả như mong đợi. Tôi có API khởi động mùa xuân.
Suraj Shingade

0

Vì một số lý do, việc đặt loại nội dung theo yêu cầu ajax như @Adrien đề xuất không hoạt động trong trường hợp của tôi. Tuy nhiên, bạn thực sự có thể thay đổi loại nội dung bằng cách sử dụng $ .post bằng cách thực hiện việc này trước:

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

Sau đó thực hiện $.postcuộc gọi của bạn :

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

Tôi gặp sự cố với jQuery + IIS và đây là giải pháp duy nhất giúp jQuery hiểu cách sử dụng mã hóa windows-1252 cho các yêu cầu ajax.


0

chúng ta có thể thay đổi Kiểu nội dung như thế này trong $ .post

$ .post (url, dữ liệu, chức năng (dữ liệu, trạng thái, xhr) {xhr.setRequestHeader ("Kiểu nội dung", "application / x-www-form-urlencoding; charset = utf-8");});


-1

$ .post không hoạt động nếu bạn gặp sự cố CORS (Chia sẻ tài nguyên nguồn gốc chéo). Hãy thử sử dụng $ .Ajax theo định dạng sau: "$ .ajax ({url: someurl, contentType: 'application / json', data: requestInJSONFormat, headers: {'Access-Control-allow-Origin': '*'}, dataType: 'json', gõ: 'POST', async: false, thành công: function (Dữ liệu) {...}}); "


-19

Bạn không thể gửi application/jsontrực tiếp - đó phải là một tham số của yêu cầu GET / POST.

Vì vậy, một cái gì đó như

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

Câu trả lời này có thể không chính xác, nhưng nó không phải là chất lượng thấp và đó là một nỗ lực để trả lời câu hỏi. Từ đánh giá .
Wai Ha Lee
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.