我有一个Web API 2项目,需要从单独的域访问。 GET请求工作正常,但POST失败并带有预先飞行请求。我无法让OPTIONS请求正确返回。
我已将NuGet包Microsoft.AspNet.WebApi.Cors添加到项目中。
在WebApiConfig.cs中,我打电话给:
public static void Register(HttpConfiguration config)
{
config.EnableCors();
我的Web.config包含以下值:
<system.webServer>
<modules>
<remove name="FormsAuthentication" />
</modules>
<handlers>
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<remove name="OPTIONSVerbHandler" />
<remove name="TRACEVerbHandler" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Methods" value="GET,PUT,POST,DELETE,OPTIONS" />
<add name="Access-Control-Allow-Headers" value="Content-Type" />
</customHeaders>
</httpProtocol>
</system.webServer>
在global.asax.cs中我添加了:
protected void Application_BeginRequest(object sender, EventArgs e)
{
if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
{
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*");
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "*");
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept");
HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "1728000");
HttpContext.Current.Response.End();
}
}
在Fiddler中,我看到了
的请求OPTIONS / api / app / controller HTTP / 1.1
但回复是
HTTP / 1.1 504 Fiddler - 接收失败
当AngularJS发出请求时,它有以下标题:
Connection: keep-alive
Access-Control-Request-Method: POST
Origin: http://localhost:4104
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36
Access-Control-Request-Headers: accept, content-type
Accept: */*
Referer: http://localhost:4104/index.html
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-GB,en-US;q=0.8,en;q=0.6
如果我使用具有相同标头的高级REST客户端的Chrome插件,它也会失败。但是,如果我删除标题Access-Control-Request-Method: POST
,我会从OPTIONS请求中返回200响应。
更新
将Global.asax.cs代码更改为
protected void Application_BeginRequest(object sender, EventArgs e)
{
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*");
if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
{
HttpContext.Current.Response.AddHeader("Cache-Control", "no-cache");
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "OPTIONS, GET, POST");
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept");
HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "1728000");
HttpContext.Current.Response.Flush();
HttpContext.Current.Response.SuppressContent = true;
HttpContext.Current.ApplicationInstance.CompleteRequest();
}
}
从Chrome Advanced REST客户端发出请求时,我收到了200响应代码。但是,我仍然从调用web api的角度代码中看到完全相同的超时。
这是AngularJs代码:
$http({
method: 'POST',
url: 'http://www.test.com/api/app/controller',
data: postdata,
headers: {
'Content-Type': 'application/json'
}
})
.then(function(response) {
// Do stuff
}, function() {
// Show error
})
.finally(function() {
// Cancel loading indicator
});
我已更改Application_BeginRequest
的第一行以包含日志记录:
protected void Application_BeginRequest(object sender, EventArgs e)
{
log.Debug("Application_BeginRequest " + HttpContext.Current.Request.HttpMethod);
对于GET
请求,请记录Application_BeginRequest GET
。从AngularJS发出OPTIONS
请求时,不会记录任何内容。看起来似乎永远无法访问代码Application_BeginRequest
。当我使用Chrome Advanced REST API从同一台计算机拨打电话时,它会记录(并且可以正常工作)。
答案 0 :(得分:2)
使用Global.asax
中的Application_BeginRequest手动添加标头 protected void Application_BeginRequest(object sender, EventArgs e)
{
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*");
if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
{
HttpContext.Current.Response.AddHeader("Cache-Control", "no-cache");
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST");
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept");
HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "1728000");
HttpContext.Current.Response.End();
}
}