rwk*_*iii 77 asp.net ajax asp.net-web-api
我已经设置了一个ASP.NET Web应用程序,从MVC 4/Web API模板开始.看起来好像工作得很好 - 我没有发现任何问题.我使用Chrome和Firefox浏览网站.我已经使用Fiddler进行了测试,所有的回复似乎都在钱上.
所以现在我继续编写一个简单的Test.aspx来使用这个新的Web API.脚本的相关部分:
<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>
Run Code Online (Sandbox Code Playgroud)
这会生成一个REQUEST标头:
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
Run Code Online (Sandbox Code Playgroud)
因此,Web API返回405方法不允许.
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>
Run Code Online (Sandbox Code Playgroud)
据我所知,默认情况下OPTIONS动词没有在Web API控制器中连接...所以,我将以下代码放在我的UserController.cs中:
// OPTIONS http-verb handler
public HttpResponseMessage OptionsUser()
{
var response = new HttpResponseMessage();
response.StatusCode = HttpStatusCode.OK;
return response;
}
Run Code Online (Sandbox Code Playgroud)
...这消除了405 Method Not Allowed错误,但响应完全为空 - 没有返回数据:
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
Run Code Online (Sandbox Code Playgroud)
必须有额外的逻辑......我不知道如何正确编码Options方法,或者控制器是否是放置代码的适当位置.奇怪(对我而言)从Firefox或Chrome查看时,Web API站点响应正常,但上面的.ajax调用错误.如何处理.ajax代码中的"预检"检查?也许我应该在客户端的.ajax逻辑上解决这个问题?或者,如果由于不处理OPTIONS动词而在服务器端出现问题.
有人可以帮忙吗?这一定是一个非常普遍的问题,如果在这里得到解答我会道歉.我搜索但没有找到任何帮助的答案.
更新 恕我直言,这是一个客户端问题,与上面的Ajax JQuery代码有关.我这样说是因为当我从Web浏览器访问mywebapidomain/api/user时,Fiddler没有显示任何405错误标题.我可以复制此问题的唯一地方是来自JQuery .ajax()调用.此外,上面相同的Ajax调用在服务器(同一域)上运行时工作正常.
我找到了另一篇文章:Prototype AJAX请求作为OPTIONS而不是GET发送; 导致501错误似乎与此有关,但我对他们的建议进行了修改但没有成功.显然,JQuery是编码的,如果一个Ajax请求是跨域的(我的是),它会添加一些标题,以某种方式触发OPTIONS标题.
'X-Requested-With': 'XMLHttpRequest',
'X-Prototype-Version': Prototype.Version,
Run Code Online (Sandbox Code Playgroud)
似乎应该有一个比在JQuery中修改核心代码更好的解决方案...
下面提供的答案假设这是服务器端问题.也许,我猜,但我倾向于客户并致电托管服务提供商并不会有所帮助.
Oli*_*ver 89
Mike Goodwin的答案很棒但是当我尝试它的时候,似乎是针对MVC5/WebApi 2.1.Microsoft.AspNet.WebApi.Cors的依赖项与我的MVC4项目不能很好地兼容.
使用MVC4在WebApi上启用CORS的最简单方法如下.
请注意,我允许所有,我建议您将Origin限制为您希望API提供服务的客户.允许一切都存在安全风险.
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Methods" value="GET, PUT, POST, DELETE, HEAD" />
<add name="Access-Control-Allow-Headers" value="Origin, X-Requested-With, Content-Type, Accept" />
</customHeaders>
</httpProtocol>
</system.webServer>
Run Code Online (Sandbox Code Playgroud)
我们这样做是为了允许OPTIONS http动词
public class BaseApiController : ApiController
{
public HttpResponseMessage Options()
{
return new HttpResponseMessage { StatusCode = HttpStatusCode.OK };
}
}
Run Code Online (Sandbox Code Playgroud)
Mik*_*win 50
正如Daniel A. White在评论中所说,OPTIONS请求很可能是由客户端创建的,作为跨域JavaScript请求的一部分.这是由符合跨域资源共享(CORS)的浏览器自动完成的.请求是初步或飞行前请求,在实际的AJAX请求之前做出,以确定CORS支持哪些请求动词和标头.服务器可以选择支持无,全部或部分HTTP动词.
为了完成图片,AJAX请求有一个额外的"Origin"标题,它标识了托管JavaScript的原始页面所在的位置.服务器可以选择支持来自任何来源的请求,或仅支持一组已知的可信来源.允许任何来源是一种安全风险,因为这会增加跨站点请求伪造(CSRF)的风险.
因此,您需要启用CORS.
这是一个解释如何在ASP.Net Web API中执行此操作的链接
http://www.asp.net/web-api/overview/security/enabling-cross-origin-requests-in-web-api#enable-cors
这里描述的实现允许您指定其中的内容
通常,这样可以正常工作,但您需要确保知道安全风险,特别是如果您允许来自任何域的跨源请求.在允许之前要仔细考虑.
关于哪些浏览器支持CORS,维基百科说以下引擎支持它:
http://en.wikipedia.org/wiki/Cross-origin_resource_sharing#Browser_support
Cht*_*lek 22
只需将此添加到您的Application_OnBeginRequest方法(这将为您的应用程序全局启用CORS支持)并"处理"预检请求:
var res = HttpContext.Current.Response;
var req = HttpContext.Current.Request;
res.AppendHeader("Access-Control-Allow-Origin", req.Headers["Origin"]);
res.AppendHeader("Access-Control-Allow-Credentials", "true");
res.AppendHeader("Access-Control-Allow-Headers", "Content-Type, X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Date, X-Api-Version, X-File-Name");
res.AppendHeader("Access-Control-Allow-Methods", "POST,GET,PUT,PATCH,DELETE,OPTIONS");
// ==== Respond to the OPTIONS verb =====
if (req.HttpMethod == "OPTIONS")
{
res.StatusCode = 200;
res.End();
}
Run Code Online (Sandbox Code Playgroud)
*安全性:请注意,这将从您的服务器的任何位置启用ajax请求(如果您愿意,您可以只允许以逗号分隔的Origins/url列表).
我使用当前客户端来源而不是*因为这将允许凭证=>设置Access-Control-Allow-Credentials为true将启用跨浏览器会话管理
你还需要在你的webconfig部分中启用delete和put,patch和options动词system.webServer,否则IIS会阻止它们:
<handlers>
<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>
Run Code Online (Sandbox Code Playgroud)
希望这可以帮助
def*_*nes 16
在Web API 2项目中遇到相同的问题(并且由于不值得进入的原因而无法使用标准CORS包)之后,我能够通过实现自定义DelagatingHandler来解决这个问题:
public class AllowOptionsHandler : DelegatingHandler
{
protected override async Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request, CancellationToken cancellationToken)
{
var response = await base.SendAsync(request, cancellationToken);
if (request.Method == HttpMethod.Options &&
response.StatusCode == HttpStatusCode.MethodNotAllowed)
{
response = new HttpResponseMessage(HttpStatusCode.OK);
}
return response;
}
}
Run Code Online (Sandbox Code Playgroud)
对于Web API配置:
config.MessageHandlers.Add(new AllowOptionsHandler());
Run Code Online (Sandbox Code Playgroud)
请注意,我还在Web.config中启用了CORS标头,类似于此处发布的其他一些答案:
<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
<remove name="WebDAVModule" />
</modules>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Headers" value="accept, cache-control, content-type, authorization" />
<add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, OPTIONS" />
</customHeaders>
</httpProtocol>
<handlers>
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<remove name="TRACEVerbHandler" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
</system.webServer>
Run Code Online (Sandbox Code Playgroud)
请注意,我的项目不包括MVC,只包括Web API 2.
小智 9
我已设法仅在Global.asax中的自定义代码来克服扔在飞行前阿贾克斯选项请求405和404错误
protected void Application_BeginRequest()
{
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*");
if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
{
//These headers are handling the "pre-flight" OPTIONS call sent by the browser
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, OPTIONS");
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept");
HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "1728000");
HttpContext.Current.Response.End();
}
}
Run Code Online (Sandbox Code Playgroud)
PS:在允许所有内容时考虑安全问题*.
我必须禁用CORS,因为它返回'Access-Control-Allow-Origin'标头包含多个值.
在web.config中也需要这个:
<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>
Run Code Online (Sandbox Code Playgroud)
并且app.pool需要设置为集成模式.
我有同样的问题.对我来说,修复是从jQuery AJAX调用中删除自定义内容类型.自定义内容类型会触发转机前请求.我找到了这个:
如果满足以下条件,浏览器可以跳过预检请求:
所述请求的方法是
GET,HEAD,或POST,和该应用程序不设置比其他任何请求头
Accept,Accept-Language,Content-Language,Content-Type,或Last-Event-ID,和所述
Content-Type标头(如果设置)是下述之一:
application/x-www-form-urlencodedmultipart/form-datatext/plain
从此页面:http://www.asp.net/web-api/overview/security/enabling-cross-origin-requests-in-web-api (在"预检请求"下)
| 归档时间: |
|
| 查看次数: |
114295 次 |
| 最近记录: |