定义Content-Type时跨域jQueryAJAX失败

Cross-domain jQuery AJAX fails when defining Content-Type

我有一个 ASP.NET WebAPI 客户端,它具有以下配置,允许任何跨域 POSTGET 调用:

public static void Register(HttpConfiguration config)
{
    config.EnableCors(new EnableCorsAttribute("*", "*", "GET,POST"));

    // other unrelated configurations
}

我对我的 WebAPI 应用程序进行了 AJAX 次调用,但所有调用均失败,并在控制台中显示 CORS 预防消息。

以下 AJAX 请求失败:

$.ajax({
    url: "myserver:8081/User/Get",
    data: {
        "Id": 12
    },
    type: "POST",
    dataType: "json",
    contentType: "application/json; encoding=utf-8"
});

为什么会出现这种情况,如何解决?

我花了很多时间 "fighting" 使用 WebAPI CORS,突然我明白问题出在 AJAX 调用中。此请求执行成功:

$.ajax({
    url: "myserver:8081/User/Get",
    data: {
        "Id": 12
    },
    type: "POST",
    dataType: "json",
    // contentType: "application/json; encoding=utf-8"
});

根据jQuery.ajax() documentation,

For cross-domain requests, setting the content type to anything other than application/x-www-form-urlencoded, multipart/form-data, or text/plain will trigger the browser to send a preflight OPTIONS request to the server.

浏览器正在预检请求以查找 CORS headers 并发现服务器是否允许 cross-domain 请求并发出真正的请求是安全的。如果请求可以接受,它将发送真正的请求。

浏览器发送预检请求是:

  • HTTP 方法不是 GETPOSTHEAD
  • 或者如果 Content-Type 不是 application/x-www-form-urlencodedmultipart/form-datatext/plain
  • 或者如果设置了任何自定义 HTTP headers。

所以,Chrome发送OPTIONS"preflight"请求。就我在服务器上仅允许 POSTGET 请求而言,浏览器认为这是 CORS 违规并拒绝请求。

This Whosebug question 与这个问题直接相关,并解释了什么是 "preflight" 请求以及为什么浏览器需要发送它。

解决方案与问题原因一样简单 - 不要在 cross-domain AJAX 调用中指定 Content-Type。

如果您需要为您的请求指定自定义 headers 或 Content-Type,您可以实施一个允许预检请求的特殊处理程序。 This Whosebug article 描述了如何做到这一点。

我希望它能帮助别人节省时间。