我被卡住了 说真的-已解决。读取时间:)
场景:我正在努力做正确的事情。我依靠ThinktectureIdentitymodelCORSDelegatingHandler将CORS功能添加到我的REST服务(ASP.NETWeb-API)中。到目前为止还不错。
为了实际测试它是否工作,我做了以下操作:
- 我建立了一个简单的HTML页面,并将其发布在与rest服务不同的主机上(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发布未安装。
*更新#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.NETFrameworkv4.0.30319aspnet_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.NETFramework64v4.0.30319aspnet_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
创建PreflightRequestsHandler类,在其中允许请求头(1),并在类(2)之前启用cors。
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")]
您的答案如下:https://gist.github.com/mathieucarbou/1114981
基本上,IE对cors有一些非常具体的警告和陷阱。我曾经自己写过一篇,但后来我找到了马蒂厄卡布的解决方案,并认为他的解决方案更好。
这可能是一个比你想要的更重的解决方案,但对于跨浏览器支持,我发现用"自定义解决方案"来打击IE是可以接受的。
检查这个set-access-control-allow-origin-in-web-api。这可能会对你有所帮助。