我被困了。 严重...... - 已解决。请继续阅读:)
情景:我正在尝试做正确的事情。我依靠Thinktecture Identitymodel CORS DelegatingHandler将CORS功能添加到我的REST服务(ASP.NET Web-API)。到目前为止一切都很好。
要实际测试它是否正常工作,我会执行以下操作:
所以我出去看了一下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
这当然远不及预期的反应。 有趣的部分是,Request甚至没有在我的应用程序中点击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(谷歌Chrome应用程序)或者我在Fiddler伪造请求(这可能是因为他们没有进行CORS协商 - 没有OPTIONS请求),REST服务就可以正常工作。
更新#1: 今天早些时候,我在某处看到禁用WebDAV是强制性的,因为它会干扰OPTIONS请求。我的IIS角色服务视图告诉我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中仍然不起作用(“错误:没有传输”)。如果有人和我一样走了同一条路 - &gt;这是一个IE9的东西:https://stackoverflow.com/a/10232313/1407618
答案 0 :(得分:0)
你的答案在这里: https://gist.github.com/mathieucarbou/1114981
基本上,IE对于角色有一些非常具体的警告和陷阱。我开始自己写一次,但后来我找到了mathieucarbou的解决方案,并认为他的更好。
这可能比你想要的解决方案稍微重一点,但是对于跨浏览器的支持,我发现使用“自定义解决方案”尽可能地使用IE来接受IE是可以接受的。
答案 1 :(得分:0)
选中此set-access-control-allow-origin-in-web-api。这可能会对您有所帮助。
答案 2 :(得分:0)
创建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")]