定义 Content-Type 时跨域 jQuery AJAX 失败

Yel*_*yev 3 ajax jquery cross-domain cors asp.net-web-api2

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

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

    // other unrelated configurations
}
Run Code Online (Sandbox Code Playgroud)

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

以下 AJAX 请求失败:

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

为什么会发生这种情况以及如何解决这个问题?

Yel*_*yev 6

当我突然明白问题出在 AJAX 调用中时,我花了很多时间与 WebAPI CORS 进行“斗争”。此请求执行成功:

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

根据jQuery.ajax() documentation

对于跨域请求,将内容类型设置为application/x-www-form-urlencodedmultipart/form-data、 或以外的任何内容text/plain将触发浏览器向服务器发送预检选项请求。

浏览器正在预检请求以查找 CORS 标头并发现服务器是否允许跨域请求并发出真实请求是安全的。如果请求是可以接受的,它就会发送真正的请求。

浏览器发送的预检请求是:

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

因此,Chrome 会发送OPTIONS“预检”请求。就我在服务器上只允许POSTGET请求而言,浏览器认为这是 CORS 违规并拒绝请求。

这个 StackOverflow 问题与这个问题直接相关,并解释了什么是“预检”请求以及为什么浏览器需要发送它。

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

如果您需要指定自定义标头或Content-Type为您的请求指定,您可以实现一个允许预检请求的特殊处理程序。这篇 StackOverflow 文章描述了如何做到这一点。

我希望它会帮助某人节省时间。