首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何在ASP.NET MVC/WebAPI应用程序中支持HTTP谓词

如何在ASP.NET MVC/WebAPI应用程序中支持HTTP谓词
EN

Stack Overflow用户
提问于 2013-09-30 21:41:13
回答 11查看 129.1K关注 0票数 80

我已经从一个MVC4/ web API模板开始设置了一个ASP.NET Web应用程序。看起来一切都很顺利--据我所知没有任何问题。我已经用Chrome和Firefox浏览了这个网站。我使用Fiddler进行了测试,所有的反应似乎都是在金钱上。

因此,现在我继续编写一个简单的Test.aspx来使用这个新的Web API。脚本的相关部分:

代码语言:javascript
复制
<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>

这将生成一个请求头:

代码语言:javascript
复制
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方法。

代码语言:javascript
复制
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>

我知道默认情况下,选项动词并没有连接到Web API控制器中……因此,我在我的UserController.cs中放置了以下代码:

代码语言:javascript
复制
// OPTIONS HTTP-verb handler
public HttpResponseMessage OptionsUser()
{
    var response = new HttpResponseMessage();
    response.StatusCode = HttpStatusCode.OK;
    return response;
}

...and这消除了405方法不允许的错误,但响应完全为空-不返回任何数据:

代码语言:javascript
复制
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站点在火狐或Chrome浏览器上能正常响应,而上面的.ajax调用却出错了。如何处理.ajax代码中的“印前检查”?也许我应该在客户端的.ajax逻辑上解决这个问题?或者,如果这是服务器端由于未处理OPTIONS谓词而出现的问题。

有人能帮上忙吗?这肯定是一个非常常见的问题,如果这里有人回答了,我很抱歉。我搜索了一下,但没有找到任何有用的答案。

更新 IMHO,这是一个客户端问题,与上面的Ajax JQuery代码有关。我这么说是因为当我从web浏览器访问mywebapidomain/api/user时,Fiddler不会显示任何405错误标头。我唯一可以重现这个问题的地方是JQuery .ajax()调用。此外,当在服务器(相同的域)上运行时,上面相同的Ajax调用也可以很好地工作。

我发现了另一个帖子:Prototype AJAX request being sent as OPTIONS rather than GET; results in 501 error,这似乎是相关的,但我已经修补了他们的建议,但没有成功。显然,JQuery的编码方式是这样的:如果Ajax请求是跨域的(我的就是跨域的),它会添加几个头,以某种方式触发OPTIONS头。

代码语言:javascript
复制
'X-Requested-With': 'XMLHttpRequest',
'X-Prototype-Version': Prototype.Version,

似乎应该有一个比在JQuery中修改核心代码更好的解决方案……

下面提供的答案假设这是一个服务器端问题。也许吧,我猜,但我倾向于客户,而打电话给托管提供商是没有帮助的。

EN

回答 11

Stack Overflow用户

回答已采纳

发布于 2013-10-01 02:02:54

正如Daniel A.怀特在他的评论中所说,OPTIONS请求很可能是由客户端创建的,作为跨域JavaScript请求的一部分。这由兼容跨域资源共享(CORS)的浏览器自动完成。该请求是初步的或飞行前请求,在实际的AJAX请求之前发出,以确定CORS支持哪些请求谓词和头部。服务器可以选择不支持、全部支持或部分支持HTTP动词。

为了完成图片,AJAX请求有一个额外的"Origin“头,它标识托管JavaScript的原始页面是从哪里提供的。服务器可以选择支持来自任何来源的请求,或者仅支持一组已知的、可信来源的请求。允许任何来源都是一个安全风险,因为is会增加跨站点请求伪造(CSRF)的风险。

因此,您需要启用CORS。

以下链接解释了如何在ASP.Net Web API中执行此操作

http://www.asp.net/web-api/overview/security/enabling-cross-origin-requests-in-web-api#enable-cors

这里描述的实现允许您指定,尤其是

  • CORS在每个操作、每个控制器或全局基础上的支持
  • supported origins
  • 启用CORS控制器或全局级别时,支持的HTTP verbs
  • 服务器是否支持使用跨域请求发送凭据

一般来说,这很好用,但您需要确保您知道安全风险,特别是当您允许来自任何域的跨域请求时。在允许这样做之前,请仔细考虑。

关于哪些浏览器支持CORS,Wikipedia表示以下引擎支持它:

  • Gecko 1.9.1 (FireFox 3.5)
  • WebKit (Safari 4,Chrome Chrome 6 (IE10),部分支持IE8和9
  • Presto (FireFox 12)

http://en.wikipedia.org/wiki/Cross-origin_resource_sharing#Browser_support

票数 52
EN

Stack Overflow用户

发布于 2014-01-30 22:14:30

Mike Goodwin的回答很棒,但当我尝试它时,它似乎是针对MVC5/WebApi 2.1的。在我的MVC4项目中,Microsoft.AspNet.WebApi.Cors的依赖性不能很好地发挥作用。

使用MVC4在WebApi上启用CORS的最简单方法如下。

请注意,我已经允许了所有,我建议您将Origin限制为您希望API服务的客户端。允许一切都是安全风险。

Web.config:

代码语言:javascript
复制
<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>

BaseApiController.cs:

我们这样做是为了允许选项http谓词

代码语言:javascript
复制
 public class BaseApiController : ApiController
  {
    public HttpResponseMessage Options()
    {
      return new HttpResponseMessage { StatusCode = HttpStatusCode.OK };
    }
  }
票数 94
EN

Stack Overflow用户

发布于 2015-10-29 15:45:46

只需将此代码添加到您的Application_OnBeginRequest方法(这将为您的应用程序全局启用CORS支持)并“处理”印前检查请求:

代码语言:javascript
复制
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();
}

*安全性:请注意,这将允许从任何地方到您的服务器的ajax请求(如果您愿意,只能允许以逗号分隔的源/urls列表)。

我使用当前客户端源而不是*,因为这将允许凭据=>将Access-Control-Allow-Credentials设置为true将启用跨浏览器会话管理

此外,您还需要在您的webconfigsystem.webServer中启用delete和put、patch和options动词,否则IIS将阻止它们:

代码语言:javascript
复制
<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>

希望这能有所帮助

票数 24
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19095777

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档