我被困住了。 说真的... -解决了。继续阅读:)
场景:我正在尝试在这里做正确的事情。我依靠 Thinktecture Identitymodel CORS DelegatingHandler 将 CORS 功能添加到了我的 REST 服务 (ASP.NET Web-API)。到目前为止,一切都很好。
为了实际测试它是否有效,我做了以下操作:
- 我设置了一个简单的 HTML 页面并将其发布在与其他服务不同的主机上(xttp://otherhost/simplewebpage)。该页面使用 JQuery 发出示例请求。代码见下文。
- 接下来,我将我的 rest 服务设置为不使用 iis express,而是使用它在我的开发机器上运行的完全成熟的实例(xttp://developmenthost/restservice)。
- 最后但同样重要的是,在我的开发机器上,我打开 xttp://otherhost/simplewebpage 并触发 Ajax 请求。执行错误回调,告诉我 Chrome 中存在“传输错误”(IE9)或“”(空字符串)。我确保没有与代理相关的连接问题或类似问题。
所以我开始查看 Fiddler 跟踪和 IIS 日志。Fiddler 说没有 GET /rest/hello 请求,而是一个 OPTIONS /rest/hello 请求——这完全没问题,也是意料之中的!然而,对 OPTIONS 请求的响应相当有趣!
整个响应标头如下所示:
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 标头。所以它肯定会通过(正确的)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 角色服务视图告诉我 WebDAV Publishing is Not installed。
* 更新 #2:*问题解决了??我挖得更深了。在 IIS 中注册了一个模块,该模块负责对 OPTIONS 请求的“不想要的(?)”响应。它的名字是“OPTIONSVerbHandler”(处理程序:ProtocolSupportModule)。如果我禁用该模块,请求将传递到我的应用程序。创建了一个更有意义的响应,然后是实际的 GET 请求! 耶!
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