Không thể đặt loại nội dung thành 'application / json' trong jQuery.ajax


106

Khi tôi có mã này

$.ajax({
    type: 'POST',
    //contentType: "application/json",
    url: 'http://localhost:16329/Hello',
    data: { name: 'norm' },
    dataType: 'json'
});

trong Fiddler, tôi có thể thấy yêu cầu thô sau đây

POST http://localhost:16329/Hello HTTP/1.1
Host: localhost:16329
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:10.0.2) Gecko/20100101 Firefox/10.0.2
Accept: application/json, text/javascript, */*; q=0.01
Accept-Language: ru-ru,ru;q=0.8,en-us;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Referer: http://localhost:14693/WebSite1/index.html
Content-Length: 9
Origin: http://localhost:14693
Pragma: no-cache
Cache-Control: no-cache

name=norm

Nhưng những gì tôi đang cố gắng là đặt loại nội dung từ application / x-www-form-urlencoded thành application / json . Nhưng mã này

$.ajax({
    type: "POST",
    contentType: "application/json",
    url: 'http://localhost:16329/Hello',
    data: { name: 'norm' },
    dataType: "json"
});

Tạo yêu cầu lạ (tôi có thể thấy trong Fiddler)

OPTIONS http://localhost:16329/Hello HTTP/1.1
Host: localhost:16329
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:10.0.2) Gecko/20100101 Firefox/10.0.2
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: ru-ru,ru;q=0.8,en-us;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Connection: keep-alive
Origin: http://localhost:14693
Access-Control-Request-Method: POST
Access-Control-Request-Headers: content-type
Pragma: no-cache
Cache-Control: no-cache

Tại sao vậy? OPTIONS là gì khi nó nên được ĐĂNG ở đó? Và loại nội dung của tôi được đặt thành application / json ở đâu? Và các tham số yêu cầu đã biến mất vì một số lý do.

CẬP NHẬT 1

Về phía máy chủ, tôi có dịch vụ RESTful thực sự đơn giản.

[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class RestfulService : IRestfulService
{
    [WebInvoke(
        Method = "POST",
        UriTemplate = "Hello",
        ResponseFormat = WebMessageFormat.Json)]
    public string HelloWorld(string name)
    {
        return "hello, " + name;
    }
}

Nhưng vì một số lý do mà tôi không thể gọi phương thức này với các tham số.

CẬP NHẬT 2

Xin lỗi vì đã không trả lời quá lâu.

Tôi đã thêm các tiêu đề này vào phản hồi máy chủ của mình

 Access-Control-Allow-Origin: *
 Access-Control-Allow-Headers: Content-Type
 Access-Control-Allow-Methods: POST, GET, OPTIONS

Nó không giúp được gì, tôi gặp lỗi Phương pháp không được phép từ máy chủ.

Đây là những gì người chơi của tôi nói

nhập mô tả hình ảnh ở đây

Vì vậy, bây giờ tôi có thể chắc chắn rằng máy chủ của mình chấp nhận POST, GET, OPTIONS (nếu tiêu đề phản hồi hoạt động như tôi mong đợi). Nhưng tại sao "Phương pháp không được phép"?

Trong phản hồi WebView từ máy chủ (bạn có thể thấy phản hồi thô trên hình trên) trông như thế này

nhập mô tả hình ảnh ở đây


2
bạn nên thử phương thức JSON.stringfy ()
Amritpal Singh

Nhìn đây. Này hoạt động đối với tôi rất tốt: stackoverflow.com/questions/9754767/...
Fanda

Tôi đang gặp vấn đề chính xác, nhưng tôi đang làm việc với NodeJS làm chương trình phụ trợ, tôi cũng đặt tất cả các yêu cầu TÙY CHỌN không chỉ để được chấp nhận mà còn buộc 200 phản hồi cho tất cả các yêu cầu TÙY CHỌN để phần còn lại của các kiến ​​nghị hoạt động như mong đợi không có phản hồi ...
HeberLZ

1
Xin chào @VitaliiKorsakov. Bạn đã giải quyết được vấn đề của mình chưa? Tôi gặp vấn đề tương tự, tức là không thể sửa đổi contentType.
worldterminator 12/1214

1
Tôi đã gặp vấn đề tương tự và nó đang hoạt động .. giải pháp nằm trong câu trả lời trên trang này: stackoverflow.com/questions/20295080/… ..để tóm tắt lại: "Khi sử dụng contentType: 'application / json', bạn sẽ không thể dựa vào $ _POST đang được điền. $ _POST chỉ được điền cho các loại nội dung được mã hóa biểu mẫu. Do đó, bạn cần đọc dữ liệu của mình từ đầu vào thô PHP ".. Tôi thấy hiện tại bạn không sử dụng php trên máy chủ nhưng hy vọng thông tin này sẽ giúp ích một cách nào đó.
Sarah

Câu trả lời:


91

Có vẻ như việc xóa http://khỏi tùy chọn url sẽ đảm bảo gửi đúng tiêu đề HTTP POST.

Tôi không nghĩ rằng bạn cần phải đủ điều kiện tên của máy chủ, chỉ cần sử dụng một URL tương đối như bên dưới.

   $.ajax({
      type: "POST",
      contentType: "application/json",
      url: '/Hello',
      data: { name: 'norm' },
      dataType: "json"
   });

Một ví dụ của tôi hoạt động:

        $.ajax({
            type: "POST",
            url: siteRoot + "api/SpaceGame/AddPlayer",
            async: false,
            data: JSON.stringify({ Name: playersShip.name, Credits: playersShip.credits }),
            contentType: "application/json",
            complete: function (data) {
            console.log(data);
            wait = false;
        }
    });

Có thể liên quan: jQuery $ .ajax (), $ .post gửi "OPTIONS" dưới dạng REQUEST_METHOD trong Firefox

Chỉnh sửa: Sau khi nghiên cứu thêm, tôi phát hiện ra tiêu đề OPTIONS được sử dụng để tìm hiểu xem yêu cầu từ miền gốc có được phép hay không. Sử dụng fiddler, tôi đã thêm phần sau vào tiêu đề phản hồi từ máy chủ của mình.

 Access-Control-Allow-Origin: *
 Access-Control-Allow-Headers: Content-Type
 Access-Control-Allow-Methods: POST, GET, OPTIONS

Khi trình duyệt nhận được phản hồi này, nó sẽ gửi yêu cầu POST chính xác với dữ liệu json. Có vẻ như loại nội dung được mã hóa theo biểu mẫu mặc định được coi là an toàn và do đó không trải qua kiểm tra tên miền chéo bổ sung.

Có vẻ như bạn sẽ cần thêm các tiêu đề đã đề cập trước đó vào phản hồi của máy chủ đối với yêu cầu TÙY CHỌN. Tất nhiên, bạn nên định cấu hình chúng để cho phép các yêu cầu từ các miền cụ thể thay vì tất cả.

Tôi đã sử dụng jQuery sau để kiểm tra điều này.

$.ajax({
   type: "POST",
   url: "http://myDomain.com/path/AddPlayer",
   data: JSON.stringify({
      Name: "Test",
       Credits: 0
   }),
   //contentType: "application/json",
   dataType: 'json',
   complete: function(data) {
       $("content").html(data);
  }
});​

Người giới thiệu:


Tôi muốn kết nối lỏng lẻo giữa máy khách và máy chủ. Máy chủ là dịch vụ RESTful và tất cả các máy khách của dịch vụ này phải biết url của nó.
Vitalii Korsakov

Bạn có thể cung cấp thêm một số chi tiết trong bài đăng của bạn về kịch bản của câu hỏi này không? Nếu khách hàng của bạn sử dụng các miền khác nhau, bạn có thể gặp phải các vấn đề về nguồn gốc giống nhau.
Mike Wade

Tôi đã đăng thông tin bổ sung về phía máy chủ. Ngay bây giờ máy chủ và máy khách đều trên localhost nhưng khác nhau về cổng. Sau này rất có thể chúng sẽ ở trên các miền khác nhau.
Vitalii Korsakov

Có vẻ như vấn đề bạn đang gặp phải là làm với cùng một chính sách xuất xứ, có thể đáng xem xét jsonp và câu hỏi tôi đã liên kết trong câu trả lời của mình ngoài các liên kết này - câu hỏi liên quan . Hướng dẫn về tên miền chéo jquery - Tôi không có nhiều kinh nghiệm với các yêu cầu tên miền chéo nhưng hy vọng những liên kết đó sẽ hữu ích cho bạn.
Mike Wade

Tôi không nghĩ rằng đây là một vấn đề vì mọi thứ hoạt động tốt khi tôi không chuyển bất kỳ tham số nào và loại nội dung là application / x-www-form-urlencoded. Nhưng tôi không cần yêu cầu ĐĂNG nếu tôi không thể chuyển bất kỳ tham số nào.
Vitalii Korsakov

41

Tôi có thể chỉ cho bạn cách tôi đã sử dụng nó

  function GetDenierValue() {
        var denierid = $("#productDenierid").val() == '' ? 0 : $("#productDenierid").val();
        var param = { 'productDenierid': denierid };
        $.ajax({
            url: "/Admin/ProductComposition/GetDenierValue",
            dataType: "json",
            contentType: "application/json;charset=utf-8",
            type: "POST",
            data: JSON.stringify(param),
            success: function (msg) {
                if (msg != null) {
                    return msg.URL;
                }
            }
        });
    }

Điều tương tự như trong câu trả lời tiếp theo. Tôi không thể không để xác định url đến máy chủ mà tất cả các chức năng dịch vụ được lưu trữ
Vitalii Korsakov

@VitaliiKorsakov Tôi đã đi rồi, bạn đã giải quyết vấn đề của mình chưa.
Amritpal Singh

Cảm ơn vì câu trả lời! Tôi không thể tin rằng điều này không được viết ở nơi khác Nó chắc chắn có vẻ như JQuery sẽ gửi json khi loại bạn chỉ định là 'json', nhưng tôi đoán không ...
Jason Goemaat

1
@JasonGoemaat tham số dataType trong jQuery chỉ được sử dụng để phân tích cú pháp phần thân phản hồi được trả về. Nếu bạn đọc tài liệu, bạn sẽ thấy rằng nó thậm chí không cần thiết. Giá trị mặc định cho dataType là đoán thông minh. Vấn đề của bạn là thuộc tính dữ liệu trong jquery không thể định cấu hình. Bạn không thể biết cách jquery nên phân tích cú pháp đối tượng dữ liệu. Đó là lý do tại sao bạn phải serialize json trước. Bởi vì jquery chỉ tuần tự hóa thành url-form-encode
Loïc Faure-Lacroix

12

Vì vậy, tất cả những gì bạn cần làm để điều này hoạt động là thêm:

headers: {
    'Accept': 'application/json',
    'Content-Type': 'application/json'
}

như một trường cho yêu cầu bài đăng của bạn và nó sẽ hoạt động.


api.jquery.com/jquery.ajax Nếu bạn xem trong tài liệu, nó nói rằng không chỉ định nó sẽ mặc định là 'application / x-www-form-urlencoded; charset = UTF-8 '(đó là lý do tại sao điều đó lại xảy ra. Idk tại sao chỉ thiết lập contentType lại không hoạt động. Bạn có thể muốn kiểm tra phiên bản jQuery mình có và cập nhật nếu bạn đang sử dụng phiên bản cũ).
Cody Jacques

Đây không phải là làm việc. Mặc dù tôi có type: "POST", nó đang gửi OPTIONS.
user9645,

5

Tôi đã nhận ra những màn hình đó, tôi đang sử dụng CodeFluentEntities và tôi cũng có giải pháp phù hợp với mình.

Tôi đang sử dụng cấu trúc đó:

$.ajax({
   url: path,
   type: "POST",
   contentType: "text/plain",
   data: {"some":"some"}
}

như bạn thấy, nếu tôi sử dụng

contentType: "",

hoặc là

contentType: "text/plain", //chrome

Mọi thứ đều hoạt động tốt.

Tôi không chắc chắn 100% rằng đó là tất cả những gì bạn cần, vì tôi cũng đã thay đổi tiêu đề.


5

Nếu bạn sử dụng cái này:

contentType: "application/json"

AJAX sẽ không gửi thông số GET hoặc POST tới máy chủ .... không biết tại sao.

Tôi đã mất hàng giờ để học nó ngày hôm nay.

Chỉ dùng:

$.ajax(
  { url : 'http://blabla.com/wsGetReport.php',
    data : myFormData, type : 'POST', dataType : 'json', 
    // contentType: "application/json", 
    success : function(wsQuery) { }
  }
)

1
đáng buồn là câu trả lời chính xác cho tôi. Bỏ qua contentType và chỉ sử dụng dataType để bỏ qua rác CORS OPTIONS mà nhiều dịch vụ không triển khai đúng cách. Rất khó chịu.
Umopepisdn

2

Tôi đã tìm thấy giải pháp cho vấn đề này ở đây . Đừng quên cho phép OPTIONS động từ trên trình xử lý dịch vụ ứng dụng IIS.

Hoạt động tốt. Cảm ơn André Pedroso. :-)


1

Tôi gặp vấn đề tương tự. Tôi đang chạy ứng dụng java rest trên máy chủ jboss. Nhưng tôi nghĩ rằng giải pháp tương tự trên ứng dụng web ASP .NET.

Firefox thực hiện cuộc gọi trước đến máy chủ / url nghỉ ngơi của bạn để kiểm tra tùy chọn nào được phép. Đó là yêu cầu "TÙY CHỌN" mà máy chủ của bạn không trả lời tương ứng. Nếu cuộc gọi OPTIONS này được trả lời chính xác, cuộc gọi thứ hai được thực hiện, đó là yêu cầu "ĐĂNG" thực tế với nội dung json.

Điều này chỉ xảy ra khi thực hiện cuộc gọi giữa nhiều miền. Trong trường hợp của bạn, hãy gọi ' http://localhost:16329/Hello' thay vì gọi một đường dẫn url trong cùng một miền '/ Xin chào'

Nếu bạn định thực hiện cuộc gọi tên miền chéo, bạn phải nâng cao lớp dịch vụ nghỉ ngơi của mình bằng một phương thức có chú thích hỗ trợ yêu cầu http "TÙY CHỌN". Đây là cách triển khai java theo:

@Path("/rest")
public class RestfulService {

    @POST
    @Path("/Hello")
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.TEXT_PLAIN)
    public string HelloWorld(string name)
    {
        return "hello, " + name;
    }

//THIS NEEDS TO BE ADDED ADDITIONALLY IF MAKING CROSS-DOMAIN CALLS

    @OPTIONS
    @Path("/Hello")
    @Produces(MediaType.TEXT_PLAIN+ ";charset=utf-8")
    public Response checkOptions(){
        return Response.status(200)
        .header("Access-Control-Allow-Origin", "*")
        .header("Access-Control-Allow-Headers", "Content-Type")
        .header("Access-Control-Allow-Methods", "POST, OPTIONS") //CAN BE ENHANCED WITH OTHER HTTP CALL METHODS 
        .build();
    }
}

Vì vậy, tôi đoán trong .NET bạn phải thêm một phương thức bổ sung được chú thích bằng

[WebInvoke(
        Method = "OPTIONS",
        UriTemplate = "Hello",
        ResponseFormat = WebMessageFormat.)]

nơi các tiêu đề sau được đặt

.header("Access-Control-Allow-Origin", "*")
        .header("Access-Control-Allow-Headers", "Content-Type")
        .header("Access-Control-Allow-Methods", "POST, OPTIONS")

0

Tôi có giải pháp để gửi dữ liệu JSON theo yêu cầu POST thông qua jquery ajax. Tôi đã sử dụng mã dưới đây

    var data = new Object();
    data.p_clientId = 4;
    data =  JSON.stringify(data);

    $.ajax({
      method: "POST",
      url: "http://192.168.1.141:8090/api/Client_Add",
      data: data,
      headers: {
        'Accept': 'application/json',
        'Content-Type': 'text/plain'
    }
    })
      .done(function( msg ) {
        alert( "Data Saved: " + msg );
      });


        });
    });

Tôi đã sử dụng 'Content-Type': 'text/plain'trong tiêu đề để gửi dữ liệu json thô.
Bởi vì nếu chúng ta sử dụng Content-Type: 'application/json'các phương thức yêu cầu được chuyển đổi thành TÙY CHỌN, nhưng sử dụng Content-Type: 'test/plain'phương thức này không được chuyển đổi và vẫn ở dạng POST. Hy vọng rằng điều này sẽ giúp một số người.


3
Nó không thực sự chuyển đổi thành OPTION, nó đang gửi một yêu cầu khởi hành trước CORS để kiểm tra xem liệu POST có được phép hay không. Khi điều này không trở lại đúng, POST sẽ không xảy ra.
Umopepisdn

0

Xin chào Hai dòng này làm việc cho tôi.

contentType: "application / json; charset = utf-8", dataType: "json"

 $.ajax({
            type: "POST",
            url: "/v1/candidates",
            data: obj,
            **contentType:"application/json; charset=utf-8",
            dataType:"json",**
            success: function (data) {
                table.row.add([
                    data.name, data.title
                ]).draw(false);
            }

Cảm ơn, Prashant

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.