问题描述
我已经从 MVC 4/Web API 模板开始设置了一个 ASP.NET Web 应用程序.似乎一切都运行良好 - 我没有意识到任何问题.我使用 Chrome 和 Firefox 浏览了该网站.我已经使用 Fiddler 进行了测试,所有的反应似乎都在金钱上.
I've set up an ASP.NET web application starting with an MVC 4/Web API template. It seems as though things are working really well - no problems that I'm aware of. I've used Chrome and Firefox to go through the site. I've tested using Fiddler and all of the responses seem to be on the money.
所以现在我继续编写一个简单的 Test.aspx 来使用这个新的 Web API.脚本的相关部分:
So now I proceed to write a simple Test.aspx to consume this new Web API. The relevant parts of the script:
<script type="text/javascript">
$(function () {
$.ajax({
url: "http://mywebapidomain.com/api/user",
type: "GET",
contentType: "json",
success: function (data) {
$.each(data, function (index, item) {
....
});
}
);
},
failure: function (result) {
alert(result.d);
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
alert("An error occurred, please try again. " + textStatus);
}
});
});
</script>
这会生成一个请求头:
OPTIONS http://host.mywebapidomain.com/api/user HTTP/1.1
Host: host.mywebapidomain.com
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:24.0) Gecko/20100101 Firefox/24.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Origin: http://mywebapidomain.com
Access-Control-Request-Method: GET
Access-Control-Request-Headers: content-type
Connection: keep-alive
按原样,Web API 返回 405 Method Not Allowed.
As is, Web API returns a 405 Method Not Allowed.
HTTP/1.1 405 Method Not Allowed
Cache-Control: no-cache
Pragma: no-cache
Content-Type: application/xml; charset=utf-8
Expires: -1
Server: Microsoft-IIS/8.0
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Mon, 30 Sep 2013 13:28:12 GMT
Content-Length: 96
<Error><Message>The requested resource does not support http method 'OPTIONS'.</Message></Error>
我知道默认情况下 OPTIONS 动词未连接到 Web API 控制器中...因此,我将以下代码放在我的 UserController.cs 中:
I understand that the OPTIONS verb is not wired up in Web API controllers by default... So, I placed the following code in my UserController.cs:
// OPTIONS HTTP-verb handler
public HttpResponseMessage OptionsUser()
{
var response = new HttpResponseMessage();
response.StatusCode = HttpStatusCode.OK;
return response;
}
...这消除了 405 Method Not Allowed 错误,但响应完全为空 - 没有数据返回:
...and this eliminated the 405 Method Not Allowed error, but the response is completely empty - no data is returned:
HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Expires: -1
Server: Microsoft-IIS/8.0
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Mon, 30 Sep 2013 12:56:21 GMT
Content-Length: 0
必须有额外的逻辑......我不知道如何正确编码 Options 方法,或者控制器是否甚至是放置代码的正确位置.奇怪(对我而言)Web API 站点在从 Firefox 或 Chrome 查看时正确响应,但上面的 .ajax 调用出错了.我如何处理预检"?检查 .ajax 代码?也许我应该在客户端的 .ajax 逻辑上解决这个问题?或者,如果由于未处理 OPTIONS 动词而导致服务器端出现问题.
There must be additional logic... I don't know how to properly code the Options method or if the controller is even the proper place to put the code. Weird (to me) that the Web API site responds properly when viewed from Firefox or Chrome, yet the .ajax call above errors out. How do I handle the "preflight" check in the .ajax code? Maybe I should be addressing this issue on the client side's .ajax logic? Or, if this is an issue on the server side due to not handling the OPTIONS verb.
有人可以帮忙吗?这一定是一个非常普遍的问题,如果在这里得到解答,我深表歉意.我进行了搜索,但没有找到任何有用的答案.
Can anyone help? This must be a very common issue and I apologize if it's been answered here. I searched but didn't find any answers that helped.
更新恕我直言,这是一个客户端问题,与上面的 Ajax JQuery 代码有关.我这样说是因为当我从 Web 浏览器访问 mywebapidomain/api/user 时,Fiddler 没有显示任何 405 错误标头.我可以复制这个问题的唯一地方是来自 JQuery .ajax() 调用.此外,上述相同的 Ajax 调用在服务器(同一域)上运行时也能正常工作.
UPDATEIMHO, this is a client-side issue and has to do with the Ajax JQuery code above. I say this because Fiddler doesn't show any 405 error headers when I access mywebapidomain/api/user from a web browser. The only place I can duplicate this problem is from the JQuery .ajax() call. Also, the identical Ajax call above works fine when run on the server (same domain).
我发现了另一个帖子:原型 AJAX 请求作为 OPTIONS 而不是 GET 发送;导致 501 错误,这似乎是相关的,但我修改了他们的建议但没有成功.显然,JQuery 是这样编码的,如果 Ajax 请求是跨域的(我的是),它会添加几个以某种方式触发 OPTIONS 标头的标头.
I found another post: Prototype AJAX request being sent as OPTIONS rather than GET; results in 501 error that seems to be related, but I've tinkered with their suggestions with no success. Apparently, JQuery is coded so that if an Ajax request is cross-domain (which mine is) it adds a couple of headers that trigger the OPTIONS header somehow.
'X-Requested-With': 'XMLHttpRequest',
'X-Prototype-Version': Prototype.Version,
似乎应该有比修改 JQuery 中的核心代码更好的解决方案......
It just seems that there should be a better solution available than modifying core code in JQuery...
下面提供的答案假定这是服务器端问题.也许吧,我猜,但我倾向于客户,打电话给托管服务提供商也无济于事.
The answer provided below assumes this is a server-side issue. Maybe, I guess, but I lean toward clients, and calling a hosting provider isn't going to help.
推荐答案
正如 Daniel A. White 在他的评论中所说,OPTIONS 请求很可能是由客户端创建的,作为跨域 JavaScript 请求的一部分.这是由跨源资源共享 (CORS) 兼容浏览器自动完成的.该请求是初步或飞行前请求,在实际 AJAX 请求之前发出,以确定 CORS 支持哪些请求动词和标头.服务器可以选择不支持、全部或部分 HTTP 动词.
As Daniel A. White said in his comment, the OPTIONS request is most likely created by the client as part of a cross domain JavaScript request. This is done automatically by Cross Origin Resource Sharing (CORS) compliant browsers. The request is a preliminary or pre-flight request, made before the actual AJAX request to determine which request verbs and headers are supported for CORS. The server can elect to support it for none, all or some of the HTTP verbs.
为了完成图片,AJAX 请求有一个额外的Origin"标头,它标识了托管 JavaScript 的原始页面是从哪里提供的.服务器可以选择支持来自任何来源的请求,或者只支持一组已知的、可信的来源.允许任何来源都存在安全风险,因为这会增加跨站请求伪造 (CSRF) 的风险.
To complete the picture, the AJAX request has an additional "Origin" header, which identified where the original page which is hosting the JavaScript was served from. The server can elect to support request from any origin, or just for a set of known, trusted origins. Allowing any origin is a security risk since is can increase the risk of Cross site Request Forgery (CSRF).
因此,您需要启用 CORS.
So, you need to enable CORS.
这是一个解释如何在 ASP.Net Web API 中执行此操作的链接
Here is a link that explains how to do this in ASP.Net Web API
http://www.asp.net/web-api/overview/security/enabling-cross-origin-requests-in-web-api#enable-cors
那里描述的实现允许您指定,其中包括
The implementation described there allows you to specify, amongst other things
- 基于每个操作、每个控制器或全局的 CORS 支持
- 支持的来源
- 在控制器或全局级别启用 CORS 时,支持的 HTTP 动词
- 服务器是否支持通过跨域请求发送凭据
一般来说,这工作正常,但您需要确保您了解安全风险,尤其是当您允许来自任何域的跨源请求时.在您允许这样做之前,请务必仔细考虑.
In general, this works fine, but you need to make sure you are aware of the security risks, especially if you allow cross origin requests from any domain. Think very carefully before you allow this.
就哪些浏览器支持 CORS 而言,维基百科表示以下引擎支持它:
In terms of which browsers support CORS, Wikipedia says the following engines support it:
- 壁虎 1.9.1 (FireFox 3.5)
- WebKit(Safari 4、Chrome 3)
- MSHTML/Trident 6 (IE10) 部分支持 IE8 和 9
- Presto (Opera 12)
http://en.wikipedia.org/wiki/Cross-origin_resource_sharing#Browser_support
这篇关于如何在 ASP.NET MVC/WebAPI 应用程序中支持 HTTP OPTIONS 动词的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!