无法在jQuery.ajax中将content-type设置为'application / json'

时间:2012-03-17 23:39:34

标签: json jquery content-type wcf-rest

当我有这段代码时

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

但我正在尝试将内容类型从 application / x-www-form-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什么时候应该在那里POST?我的content-type设置为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

没有帮助,我从服务器方法不允许错误。

这是我的小提琴手所说的

enter image description here

所以,现在我可以确定我的服务器接受 POST,GET,OPTIONS (如果响应头像我期望的那样工作)。但为什么“方法不允许”?

来自服务器的WebView响应(您可以在上面的图片中看到 Raw 响应)看起来像这样

enter image description here

10 个答案:

答案 0 :(得分:81)

似乎从url选项中删除http://可确保发送正确的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 sending "OPTIONS" as REQUEST_METHOD in Firefox

修改 经过一些研究后,我发现OPTIONS标头用于查明是否允许来自原始域的请求。使用fiddler,我将以下内容添加到服务器的响应头中。

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

一旦浏览器收到此响应,它就会用json数据发送正确的POST请求。似乎默认的form-urlencoded内容类型被认为是安全的,因此不会进行额外的跨域检查。

看起来您需要将以前提到的标头添加到服务器响应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);
  }
});​

参考文献:

答案 1 :(得分:33)

我可以告诉你我是如何使用它的

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

答案 2 :(得分:9)

所以你需要做的就是添加:

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

作为您的帖子请求的字段,它将起作用。

答案 3 :(得分:4)

我认识到那些屏幕,我使用CodeFluentEntities,而且我也有解决方案对我有用。

我正在使用这种结构:

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

如你所见,如果我使用

contentType: "",

contentType: "text/plain", //chrome

一切正常。

我并非100%确定您需要的一切,因为我也改变了标题。

答案 4 :(得分:2)

我找到了解决此问题的方法here。不要忘记在IIS应用服务处理程序上允许动词OPTIONS。

工作正常。谢谢AndréPedroso。 : - )

答案 5 :(得分:1)

我有同样的问题。我在jboss服务器上运行java rest应用程序。但我认为解决方案在ASP .NET webapp上类似。

Firefox会对您的服务器/其他网址进行预调用,以检查允许的选项。这是您的服务器不会相应回复的“OPTIONS”请求。如果正确回答此OPTIONS调用,则执行第二次调用,这是具有json内容的实际“POST”请求。

这仅在执行跨域调用时发生。在您的情况下,调用“http://localhost:16329/Hello”而不是在同一域名下调用网址路径'/ Hello'

如果您打算进行跨域调用,则必须使用带注释的方法增强其余服务类,并支持“OPTIONS”http请求。这是相应的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")

答案 6 :(得分:1)

如果您使用此:

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

答案 7 :(得分:0)

我得到了通过jquery ajax通过POST请求发送JSON数据的解决方案。我使用下面的代码

    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。 希望这对一些人有所帮助。

答案 8 :(得分: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

答案 9 :(得分:0)

我正在解决同样的问题,这是由于缺少 JSON.stringfy() 引起的,即

data: JSON.stringfy({ name: 'norm' }),

希望这可以为其他人节省很多时间!