ไม่สามารถตั้งค่าชนิดเนื้อหาเป็น 'application / json' ใน jQuery.ajax


106

เมื่อฉันมีรหัสนี้

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

ใน Fiddler ฉันเห็นตามคำขอดิบ

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

แต่สิ่งที่ฉันพยายามคือการกำหนดประเภทเนื้อหาจากแอพลิเคชัน / x-www ฟอร์ม urlencodedจะapplication / JSON แต่รหัสนี้

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

สร้างคำขอแปลก ๆ (ซึ่งฉันเห็นใน 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

ทำไมถึงเป็นเช่นนั้น? OPTIONS คืออะไรเมื่อควรโพสต์ที่นั่น? และประเภทเนื้อหาของฉันถูกตั้งค่าเป็น application / json ที่ไหน และพารามิเตอร์การร้องขอหายไปด้วยเหตุผลบางประการ

อัปเดต 1

ในฝั่งเซิร์ฟเวอร์ฉันมีบริการ RESTful ที่เรียบง่ายจริงๆ

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

แต่ด้วยเหตุผลบางประการฉันไม่สามารถเรียกวิธีนี้ด้วยพารามิเตอร์ได้

อัปเดต 2

ขออภัยที่ไม่ได้ตอบนาน

ฉันได้เพิ่มส่วนหัวเหล่านี้ในการตอบกลับของเซิร์ฟเวอร์แล้ว

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

ไม่ได้ช่วยฉันมีข้อผิดพลาดวิธีที่ไม่อนุญาตจากเซิร์ฟเวอร์

นี่คือสิ่งที่นักเล่นซอของฉันพูด

ใส่คำอธิบายภาพที่นี่

ดังนั้นตอนนี้ฉันมั่นใจได้ว่าเซิร์ฟเวอร์ของฉันยอมรับPOST, GET, OPTIONS (หากส่วนหัวการตอบกลับทำงานอย่างที่ฉันคาดหวัง) แต่ทำไม "วิธีการไม่อนุญาต"?

ในการตอบสนอง WebView จากเซิร์ฟเวอร์ (คุณสามารถดูการตอบสนองแบบRawในภาพด้านบน) จะมีลักษณะดังนี้

ใส่คำอธิบายภาพที่นี่


2
คุณควรลองใช้วิธี JSON.stringfy ()
Amritpal Singh

ดูนี่. สิ่งนี้ได้ผลดีสำหรับฉัน: stackoverflow.com/questions/9754767/…
Fanda

ฉันมีปัญหาเดียวกันแน่นอน แต่ฉันกำลังทำงานกับ NodeJS เป็นแบ็กเอนด์และฉันยังตั้งค่าคำขอ OPTION ทั้งหมดไม่เพียง แต่จะได้รับการยอมรับ แต่ยังบังคับให้ตอบกลับ 200 คำขอสำหรับคำขอ OPTION ทั้งหมดเพื่อให้คำร้องที่เหลือทำงานตามที่คาดไว้ โดยไม่มีการตอบสนอง ...
HeberLZ

1
สวัสดี @VitaliiKorsakov คุณแก้ปัญหาของคุณแล้วหรือยัง? ฉันพบปัญหาเดียวกันคือไม่สามารถแก้ไข contentType
worldterminator

1
ฉันมีปัญหาเดียวกันและใช้งานได้ .. วิธีแก้ปัญหาอยู่ในคำตอบในหน้านี้: stackoverflow.com/questions/20295080/… ..สรุปได้ว่า: "เมื่อใช้ contentType: 'application / json' คุณจะ ไม่สามารถพึ่งพาการเติม $ _POST ได้ $ _POST จะถูกเติมสำหรับประเภทเนื้อหาที่เข้ารหัสแบบฟอร์มเท่านั้นดังนั้นคุณต้องอ่านข้อมูลของคุณจากอินพุตดิบของ PHP ".. ฉันเห็นว่าตอนนี้คุณไม่ได้ใช้ php บนเซิร์ฟเวอร์ ด้านข้าง แต่หวังว่าข้อมูลนี้จะช่วยได้บ้าง
Sarah

คำตอบ:


91

ดูเหมือนว่าการลบออกhttp://จากตัวเลือก url จะช่วยให้แน่ใจว่ามีการส่งส่วนหัว HTTP POST ที่ถูกต้อง

ฉันไม่คิดว่าคุณต้องมีคุณสมบัติครบถ้วนในชื่อโฮสต์เพียงแค่ใช้ URL สัมพัทธ์ดังต่อไปนี้

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

ตัวอย่างของฉันที่ใช้งานได้:

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

อาจเกี่ยวข้อง: jQuery $ .ajax (), $ .post ส่ง "OPTIONS" เป็น REQUEST_METHOD ใน Firefox

แก้ไข: หลังจากการค้นคว้าเพิ่มเติมฉันพบว่าส่วนหัว OPTIONS ถูกใช้เพื่อค้นหาว่าคำขอจากโดเมนต้นทางได้รับอนุญาตหรือไม่ เมื่อใช้ fiddler ฉันได้เพิ่มสิ่งต่อไปนี้ในส่วนหัวการตอบกลับจากเซิร์ฟเวอร์ของฉัน

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

เมื่อเบราว์เซอร์ได้รับการตอบกลับนี้ระบบจะส่งคำขอ POST ที่ถูกต้องพร้อมข้อมูล json ดูเหมือนว่าประเภทเนื้อหาที่เข้ารหัสแบบฟอร์มเริ่มต้นจะถือว่าปลอดภัยและไม่ได้รับการตรวจสอบข้ามโดเมนเพิ่มเติม

ดูเหมือนว่าคุณจะต้องเพิ่มส่วนหัวที่กล่าวถึงก่อนหน้านี้ให้กับเซิร์ฟเวอร์ของคุณเพื่อตอบสนองต่อคำขอ OPTIONS แน่นอนคุณควรกำหนดค่าให้อนุญาตคำขอจากโดเมนเฉพาะแทนที่จะเป็นทั้งหมด

ฉันใช้ jQuery ต่อไปนี้เพื่อทดสอบสิ่งนี้

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

อ้างอิง:


ฉันต้องการเชื่อมต่อระหว่างไคลเอนต์และเซิร์ฟเวอร์อย่างหลวม ๆ เซิร์ฟเวอร์เป็นบริการ RESTful และไคลเอนต์ทั้งหมดของบริการนี้ควรทราบ url ของมัน
Vitalii Korsakov

คุณสามารถให้รายละเอียดเพิ่มเติมในโพสต์ของคุณเกี่ยวกับสถานการณ์ของคำถามนี้ได้หรือไม่ หากลูกค้าของคุณอยู่ในโดเมนที่แตกต่างกันคุณอาจพบปัญหาที่มาเดียวกัน
Mike Wade

ฉันได้โพสต์ข้อมูลเพิ่มเติมเกี่ยวกับฝั่งเซิร์ฟเวอร์ ตอนนี้เซิร์ฟเวอร์และไคลเอนต์ทั้งบน localhost แต่แตกต่างกันในพอร์ต ในภายหลังพวกเขามักจะอยู่ในโดเมนที่แตกต่างกัน
Vitalii Korsakov

ดูเหมือนว่าปัญหาที่คุณกำลังประสบคือจะทำอย่างไรกับนโยบายกำเนิดเดียวกันก็อาจจะมีมูลค่าการมองหาที่ jsonp และคำถามที่ฉันเชื่อมโยงกับในคำตอบของฉันนอกเหนือไปจากการเชื่อมโยงเหล่านี้ - คำถามที่เกี่ยวข้อง jquery cross domain guide - ฉันไม่มีประสบการณ์กับคำขอข้ามโดเมนมากนัก แต่หวังว่าลิงก์เหล่านั้นจะเป็นประโยชน์สำหรับคุณ
Mike Wade

ฉันไม่คิดว่านี่เป็นปัญหาเพราะทุกอย่างทำงานได้ดีเมื่อฉันไม่ผ่านพารามิเตอร์ใด ๆ และ content-type คือ application / x-www-form-urlencoded แต่ฉันไม่ต้องการคำขอ POST หากฉันไม่สามารถส่งผ่านพารามิเตอร์ใด ๆ
Vitalii Korsakov

41

ฉันสามารถแสดงให้คุณเห็นว่าฉันใช้มันอย่างไร

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

เช่นเดียวกับในคำตอบถัดไป ฉันไม่สามารถระบุ url ไปยังเซิร์ฟเวอร์ที่โฮสต์ฟังก์ชันบริการทั้งหมด
Vitalii Korsakov

@VitaliiKorsakov ฉันไปแล้วคุณจัดการปัญหาของคุณได้ไหม
Amritpal Singh

ขอบคุณสำหรับคำตอบ! ไม่อยากจะเชื่อเลยว่านี่ไม่ได้สะกดที่อื่น ดูเหมือนว่า JQuery จะโพสต์ json เมื่อประเภทที่คุณระบุคือ 'json' แต่ฉันเดาว่าไม่ใช่ ...
Jason Goemaat

1
@JasonGoemaat พารามิเตอร์ dataType ใน jQuery ใช้เพื่อแยกวิเคราะห์เนื้อหาการตอบกลับที่ส่งคืนเท่านั้น หากคุณอ่านเอกสารคุณจะเห็นว่ามันไม่จำเป็นด้วยซ้ำ ค่าเริ่มต้นสำหรับ dataType คือการคาดเดาอย่างชาญฉลาด ปัญหาของคุณคือแอตทริบิวต์ข้อมูลใน jquery ไม่สามารถกำหนดค่าได้ คุณไม่สามารถบอกได้ว่า jquery ควรแยกวิเคราะห์วัตถุข้อมูลอย่างไร นั่นเป็นเหตุผลที่คุณต้องซีเรียลไลซ์ json ก่อน เนื่องจาก jquery ทำให้อนุกรมกับการเข้ารหัส url-form-encode เท่านั้น
Loïc Faure-Lacroix

12

ดังนั้นสิ่งที่คุณต้องทำเพื่อให้ได้ผลคือเพิ่ม:

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

เป็นช่องสำหรับคำขอโพสต์ของคุณและจะใช้งานได้


api.jquery.com/jquery.ajax หากคุณดูในเอกสารระบุว่าโดยไม่ได้ระบุค่าเริ่มต้นเป็น 'application / x-www-form-urlencoded; charset = UTF-8 '(ซึ่งเป็นสาเหตุที่เกิดขึ้น Idk ทำไมการตั้งค่า contentType ถึงใช้ไม่ได้คุณอาจต้องการตรวจสอบว่าคุณมี jQuery เวอร์ชันใดและอัปเดตหากคุณใช้เวอร์ชันเก่า)
Cody Jacques

สิ่งนี้ไม่ทำงาน แม้ว่าฉันมีก็จะส่งtype: "POST" OPTIONS
user9645

5

ฉันจำหน้าจอเหล่านั้นได้ฉันใช้ CodeFluentEntities และฉันก็มีวิธีแก้ปัญหาที่เหมาะกับฉันเช่นกัน

ฉันใช้โครงสร้างนั้น:

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

อย่างที่คุณเห็นถ้าฉันใช้

contentType: "",

หรือ

contentType: "text/plain", //chrome

ทุกอย่างใช้งานได้ดี

ฉันไม่แน่ใจ 100% ว่าทุกอย่างที่คุณต้องการเพราะฉันเปลี่ยนส่วนหัวด้วย


5

หากคุณใช้สิ่งนี้:

contentType: "application/json"

AJAX จะไม่ส่งพารามิเตอร์ GET หรือ POST ไปยังเซิร์ฟเวอร์ .... ไม่รู้ว่าทำไม

ฉันใช้เวลาหลายชั่วโมงในการเรียนรู้วันนี้

เพียงใช้:

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

1
น่าเศร้าที่คำตอบที่ถูกต้องสำหรับฉัน ละเว้น contentType และใช้ dataType เพื่อหลีกเลี่ยงขยะ CORS OPTIONS ที่บริการจำนวนมากไม่สามารถใช้งานได้อย่างถูกต้อง น่ารำคาญมาก.
Umopepisdn

2

ผมพบว่าวิธีการแก้ปัญหานี้ที่นี่ อย่าลืมอนุญาตคำกริยา OPTIONS บนตัวจัดการบริการแอป IIS

ใช้งานได้ดี ขอบคุณAndré Pedroso :-)


1

ฉันมีปัญหาเดียวกัน ฉันใช้งานแอป java rest บนเซิร์ฟเวอร์ jboss แต่ฉันคิดว่าวิธีแก้ปัญหานั้นคล้ายกันบนเว็บแอป ASP .NET

Firefox ทำการโทรล่วงหน้าไปยังเซิร์ฟเวอร์ / URL ที่เหลือของคุณเพื่อตรวจสอบว่าตัวเลือกใดได้รับอนุญาต นั่นคือคำขอ "OPTIONS" ซึ่งเซิร์ฟเวอร์ของคุณไม่ตอบกลับตามนั้น หากการเรียก OPTIONS นี้ได้รับการตอบกลับอย่างถูกต้องจะมีการเรียกครั้งที่สองซึ่งเป็นคำขอ "POST" จริงที่มีเนื้อหา json

สิ่งนี้จะเกิดขึ้นเมื่อทำการโทรข้ามโดเมนเท่านั้น ในกรณีของคุณเรียก " http://localhost:16329/Hello" แทนที่จะเรียกเส้นทาง url ภายใต้โดเมนเดียวกัน "/ Hello"

หากคุณตั้งใจจะโทรข้ามโดเมนคุณต้องปรับปรุงคลาสบริการส่วนที่เหลือของคุณด้วยวิธีการที่มีคำอธิบายประกอบจะสนับสนุนคำขอ http "OPTIONS" นี่คือการใช้งาน Java ตาม:

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

ดังนั้นฉันเดาว่าใน. NET คุณต้องเพิ่มวิธีการเพิ่มเติมที่มีคำอธิบายประกอบ

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

ที่ตั้งค่าส่วนหัวต่อไปนี้

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

0

ฉันได้รับโซลูชันในการส่งข้อมูล JSON โดยคำขอ POST ผ่าน jquery ajax ฉันใช้รหัสด้านล่าง

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


        });
    });

ฉันใช้'Content-Type': 'text/plain'ในส่วนหัวเพื่อส่งข้อมูลดิบ json
เพราะถ้าเราใช้Content-Type: 'application/json'วิธีการร้องขอที่แปลงเป็น OPTION แต่การใช้Content-Type: 'test/plain'วิธีนี้ไม่ได้รับการแปลงและยังคงเป็น POST หวังว่านี่จะช่วยได้บ้าง


3
ไม่ได้แปลงเป็น OPTION จริง ๆ แต่จะส่งคำขอ CORS preflight เพื่อตรวจสอบว่าอนุญาตให้ POST หรือไม่ เมื่อสิ่งนี้ไม่กลับมาถูกต้อง POST จะไม่เกิดขึ้น
Umopepisdn

0

สวัสดีสองบรรทัดนี้ใช้ได้ผลสำหรับฉัน

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

ขอบคุณ Prashant

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.