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

标签: json jquery content-type wcf-rest


【解决方案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);
  }
});​

参考资料:

【讨论】:

  • 我想松散客户端和服务器之间的耦合。服务器是 RESTful 服务,该服务的所有客户端都应该知道它的 url。
  • 您能否在您的帖子中提供有关此问题场景的更多详细信息?如果您的客户将在不同的域上,您可能会遇到同源问题。
  • 我已经发布了有关服务器端的其他信息。现在服务器和客户端都在本地主机上,但端口不同。以后他们很可能会在不同的域上。
  • 您遇到的问题似乎与同源策略有关,除了这些链接之外,可能值得查看 jsonp 和我在答案中链接的问题 - related questionjquery 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);
                      }
          

          谢谢, 普拉尚特

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2016-12-24
            • 2011-08-12
            • 2015-10-09
            • 2017-10-08
            • 1970-01-01
            • 2023-03-06
            相关资源
            最近更新 更多