无法在 jQuery.ajax 中将内容类型设置为“应用程序/json”

Posted

技术标签:

【中文标题】无法在 jQuery.ajax 中将内容类型设置为“应用程序/json”【英文标题】:Cannot set content-type to 'application/json' in jQuery.ajax 【发布时间】:2012-04-03 00:42:00 【问题描述】:

当我有这个代码时

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

这是为什么呢?应该在那里发布的选项是什么?我的内容类型在哪里设置为 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

它没有帮助,我有 Method not allowed 来自服务器的错误。

这是我的提琴手说的

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

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

【问题讨论】:

你应该试试 JSON.stringfy() 方法 看这里。这对我很有效:***.com/questions/9754767/… 我遇到了完全相同的问题,但我正在使用 NodeJS 作为后端,我还将所有 OPTION 请求设置为不仅被接受,而且强制对所有 OPTION 请求做出 200 响应,所以其余的请愿书按预期工作,但没有任何回应...... 嗨@VitaliiKorsakov。你的问题解决了吗?我遇到了同样的问题,即无法修改 contentType。 我遇到了同样的问题,只是让它工作..解决方案在此页面上的答案中:***.com/questions/20295080/… ..总结起来:“使用 contentType 时:'application/json'您将无法依赖 $_POST 被填充。$_POST 仅针对表单编码的内容类型填充。因此,您需要从 php 原始输入中读取数据“..我现在看到您没有使用 php服务器端,但希望这些信息在某种程度上有所帮助。 【参考方案1】:

似乎从 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);
  
);​

参考资料:

http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html http://enable-cors.org/ https://developer.mozilla.org/en/http_access_control

【讨论】:

我想松散客户端和服务器之间的耦合。服务器是 RESTful 服务,该服务的所有客户端都应该知道它的 url。 您能否在您的帖子中提供有关此问题场景的更多详细信息?如果您的客户将在不同的域上,您可能会遇到同源问题。 我已经发布了有关服务器端的其他信息。现在服务器和客户端都在本地主机上,但端口不同。以后他们很可能会在不同的域上。 您遇到的问题似乎与同源策略有关,除了这些链接之外,可能值得查看 jsonp 和我在答案中链接的问题 - related question。 jquery cross domain guide - 我对跨域请求没有太多经验,但希望这些链接对你有用。 我不认为这是一个问题,因为当我不传递任何参数并且内容类型为 application/x-www-form-urlencoded 时一切正常。但是如果我不能传递任何参数,我就不需要 POST 请求。【参考方案2】:

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

  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 @VitaliiKorsakov 我走了,你的问题解决了吗。 感谢您的回答!我不敢相信这不是在其他地方拼写出来的。当您指定的类型为“json”时,JQuery 似乎会发布 json,但我想不会...... @JasonGoemaat jQuery 中的 dataType 参数仅用于解析返回的响应体。如果您阅读文档,您会发现它甚至不需要。 dataType 的默认值是智能猜测。您的问题是 jquery 中的 data 属性不可配置。你不知道 jquery 应该如何解析数据对象。这就是为什么你必须先序列化json。因为jquery只序列化为url-form-encode【参考方案3】:

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

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

作为您发布请求的字段,它会起作用。

【讨论】:

api.jquery.com/jquery.ajax 如果您查看文档,它会说没有指定它默认为 'application/x-www-form-urlencoded; charset=UTF-8' (这就是发生这种情况的原因。我想知道为什么只设置 contentType 不起作用。您可能需要检查您拥有的 jQuery 版本,如果您使用的是旧版本,请更新)。 这不起作用。即使我有type: "POST",它也在发送OPTIONS【参考方案4】:

我认出了这些屏幕,我正在使用 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)  
  
)

【讨论】:

遗憾的是我的正确答案。省略 contentType 并仅使用 dataType 绕过许多服务无法正确实现的 CORS OPTIONS 垃圾。太烦人了。【参考方案6】:

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

工作正常。谢谢安德烈·佩德罗索。 :-)

【讨论】:

【参考方案7】:

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

Firefox 会预先调用您的服务器/rest url 以检查哪些选项是允许的。那是您的服务器没有相应回复的“选项”请求。如果此 OPTIONS 调用被正确回复,则执行第二次调用,这是带有 json 内容的实际“POST”请求。

这仅在执行跨域调用时发生。在您的情况下,调用 'http://localhost:16329/Hello' 而不是调用同一域下的 url 路径 '/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")

【讨论】:

【参考方案8】:

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

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

希望这可以为其他人节省大量时间!

【讨论】:

【参考方案9】:

我得到了通过 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。 希望这会对某些人有所帮助。

【讨论】:

它并没有真正转换为 OPTION,它发送 CORS 预检请求以检查是否允许 POST。如果返回不正确,则 POST 不会发生。【参考方案10】:

嗨,这两行对我有用。

contentType:"application/json; charset=utf-8", 数据类型:“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);
            

谢谢, 普拉尚特

【讨论】:

以上是关于无法在 jQuery.ajax 中将内容类型设置为“应用程序/json”的主要内容,如果未能解决你的问题,请参考以下文章

JQuery中$.ajax()方法参数详解 ASP.NET jquery ajax传递参数

jquery ajax如何判断正在进行

JQuery $.ajax(); 异步访问完整参数

jQuery Ajax Post - 无法使用回调函数设置全局变量?

jquery - ajax 请求使用

jQuery AJAX POST 到 ASMX Web 服务导致“无法将 System.String 类型的对象转换为 System.Collections.Generic.IDictionary”