JQuery 停留在 CORS 预检和 IIS 幽灵响应

标签 jquery http asp.net-web-api cors

我被卡住了。 真的... - 已解决。继续阅读:)

场景:我想在这里做正确的事。我依赖 Thinktecture Identitymodel CORS DelegatingHandler 向我的 REST 服务 (ASP.NET Web-API) 添加了 CORS 功能。到目前为止一切顺利。

为了实际测试它是否有效,我执行了以下操作:

  1. 我设置了一个简单的 HTML 页面并将其发布在与其余服务不同的主机上 (xttp://otherhost/simplewebpage)。该页面使用 JQuery 发出示例请求。代码见下文。
  2. 接下来,我将我的休息服务设置为不使用 iis express,而是使用它在我的开发机器上运行的完全成熟的实例 (xttp://developmenthost/restservice)。
  3. 最后但同样重要的是,在我的开发机器上,我打开了 xttp://otherhost/simplewebpage 并触发了 Ajax 请求。执行错误回调告诉我 Chrome 中存在“传输错误”(IE9)或“”(空字符串)。我确保没有与代理相关的连接问题或类似问题。

所以我继续查看 Fiddler 跟踪和 IIS 日志。 Fiddler 说没有 GET/rest/hello 请求,而是一个 OPTIONS/rest/hello 请求——这完全可以预料!然而,对 OPTIONS 请求的响应相当有趣!

整个响应 header 如下所示:

HTTP/1.1 200 OK
Allow: OPTIONS, TRACE, GET, HEAD, POST
Server: Microsoft-IIS/7.5
Public: OPTIONS, TRACE, GET, HEAD, POST
Date: Fri, 15 Feb 2013 14:09:27 GMT
Content-Length: 0

这当然远未达到预期的响应。 有趣的是,请求甚至没有命中我的应用程序中的 Application_BeginRequest()。所以我的应用程序不可能对这个结果负责。我可以在我的 IIS 日志中看到该请求,并且 IIS 添加了 Powered-by-ASP.NET header 。因此它肯定会通过(正确的)IIS 站点。

触发ajax请求的JQuery代码:

    function Run()
    {
        $.ajax({
            type: 'GET',
            url: url,
            dataType: "json",
            beforeSend: function(jqXhr) {
                jqXhr.setRequestHeader("Authorization", "Basic " + getBasicHttpEncodedString(userName, password));
                jqXhr.setRequestHeader("Api-Key", "123");
            },
            success: successCallback,
            error: errorCallback,
            timeout: 180*1000
        });
    }

生成的 OPTIONS 请求如下所示:

OPTIONS http://services.dev13/Rest/Hello HTTP/1.1
Host: developmenthost
Connection: keep-alive
Access-Control-Request-Method: GET
Origin: http://otherhost/simplewebpage
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.57 Safari/537.17
Access-Control-Request-Headers: accept, origin, api-key, authorization
Accept: */*
DNT: 1
Referer: http://otherhost/simplewebpage
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3

...您已经看到了上面的回复。

知道谁准确地回答了我的 OPTIONS 请求吗?还是我的 JQuery 代码有缺陷? 如果我使用例如 Postman(Google Chrome 应用程序)或者如果我在 Fiddler 中伪造请求(这可能是因为他们不进行 CORS 协商 - 没有 OPTIONS 请求),REST 服务工作得很好。

更新 #1: 今天早些时候,我在某处读到禁用 WebDAV 是强制性的,因为它会干扰 OPTIONS 请求。我的 IIS 角色服务 View 告诉我 WebDAV Publishing 未安装

* 更新#2:* 问题解决了??我挖得更深。 IIS 中注册了一个模块,负责对 OPTIONS 请求的“不受欢迎的(?)”响应。它的名字是“OPTIONSVerbHandler”(处理程序:ProtocolSupportModule)。如果我禁用该模块,请求将传递到我的应用程序。创建了一个更有意义的响应,然后之后是实际的 GET 请求! YAY!

HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Expires: -1
Server: Microsoft-IIS/7.5
Access-Control-Allow-Origin: http://otherhost/simplewebpage
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: accept,origin,api-key,authorization
X-AspNet-Version: 4.0.30319
Date: Fri, 15 Feb 2013 15:09:25 GMT
Content-Length: 0

一旦您知道问题出在哪里,您当然会找到大量资源告诉您确保您的 web.config 看起来像这样:-/

<system.webServer>
    <validation validateIntegratedModeConfiguration="false" />
    <modules runAllManagedModulesForAllRequests="false">
      <remove name="WebDAVModule" />
    </modules>
    <handlers>
      <remove name="OPTIONSVerbHandler" />
      <remove name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" />
      <remove name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" />
      <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
      <add name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" />
      <add name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" />
      <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
    </handlers>
  </system.webServer>

虽然它在 IE9 中仍然不起作用(“错误:无传输”)。万一有人跟我走同一条路 -> 这是 IE9 的东西:https://stackoverflow.com/a/10232313/1407618

最佳答案

Create PreflightRequestsHandler class where you allow request headers(1) and enable cors before your class(2).

1. public class PreflightRequestsHandler : DelegatingHandler
    {
        protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
            if (request.Headers.Contains("Origin") && request.Method.Method.Equals("OPTIONS"))
            {
                var response = new HttpResponseMessage { StatusCode = HttpStatusCode.OK };
                // Define and add values to variables: origins, headers, methods (can be global)               
                response.Headers.Add("Access-Control-Allow-Origin", "*");
                response.Headers.Add("Access-Control-Allow-Headers", "content-type");
                response.Headers.Add("Access-Control-Allow-Methods", "*");
                var tsc = new TaskCompletionSource<HttpResponseMessage>();
                tsc.SetResult(response);
                return tsc.Task;
            }
            return base.SendAsync(request, cancellationToken);
        }

    }

2. [EnableCors(origins: "*", headers: "*", methods: "*", exposedHeaders: "X-Custom-Header")]

关于JQuery 停留在 CORS 预检和 IIS 幽灵响应,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14897247/

相关文章:

jquery - 选择最后一个直系子项

javascript - 使用 JQuery 按钮更改 URL #ID

http - 如何找到 Go http.Response 的远程 IP 地址?

javascript - 如何构建多部分 MIME 请求并使用 AngularJS 的 $http 方法发布它?

asp.net-web-api - MVC Web API 通过 x-www-form-encoded 发布整数数组

c# - 无法找到 System.Web.Services

javascript - 溢出-x :hidden; can still scroll when open at my phone

jquery - 在 jQuery 中更改 if 语句

angularjs - Angular - $scope 无法访问服务中的 $http 响应

asp.net-web-api - 如何更改.Net Core中 Controller 的OnActionExecuted方法中API的响应