所请求的资源不支持HTTP方法“OPTIONS”。

16
我正在从我的Angular.js客户端向ASP.NET Web API PUT方法发出以下请求:

我正在从我的Angular.js客户端向ASP.NET Web API PUT方法发出以下请求:

var org = {
                  OrgId: 111,
                  name: 'testing testing'
          };
$http.put("http://localhost:54822/api/data/putorganisation/1/", org).then(function(status) {
         console.log("success PUT");
         return status.data;
});

然而在 Fiddler 中出现以下错误消息:

{"message":"The requested resource does not support http method 'OPTIONS'."}

这是我的 asp.net web api web.config 文件的一部分:

 <system.webServer>
    <httpProtocol>
      <customHeaders>
        <add name="Access-Control-Allow-Origin" value="*" />
        <add name="Access-Control-Allow-Headers" value="Content-Type,x-xsrf-token,X-Requested-With" />
        <add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, OPTIONS" />
      </customHeaders>
    </httpProtocol>
    <validation validateIntegratedModeConfiguration="false" />
    <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" />
      <remove name="WebDAV" />
    </handlers>
    <modules runAllManagedModulesForAllRequests="true">
      <remove name="WebDAVModule" />
    </modules>
  </system.webServer>

数据控制器 Web API:

public HttpResponseMessage Options()
{
            var response = new HttpResponseMessage();
            response.StatusCode = HttpStatusCode.OK;
            return response;
}

public HttpResponseMessage PutOrganisation(int id, [FromBody]Organisation org)
{
  var opStatus = _Repository.UpdateOrganisation(org);
  if (opStatus.Status)
  {
     return Request.CreateResponse<Organisation>(HttpStatusCode.Accepted, org);
  }

return Request.CreateErrorResponse(HttpStatusCode.NotModified, opStatus.ExceptionMessage);
}
这是我的问题:当我在 Fiddler 中发出完全相同的请求(可行)和在 Angular 客户端中发出请求时为什么会收到错误消息(如上所示)?
这是我的问题:当我在 Fiddler 中发出完全相同的请求(可行)和在 Angular 客户端中发出请求时为什么会收到错误消息(如上所示)?
6个回答

39

我知道这是一个老问题,但我遇到了同样的问题,想帮助其他人解决。

我通过在Web.config中删除2个处理程序配置来解决了它:

<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>
我不确定为什么这样做可以解决问题,但我的工作理论是,<remove name="OPTIONSVerbHandler" />会默认禁止OPTIONS请求。当从浏览器发送请求时,它会先发送一个OPTIONS请求,然后才是PUT请求,因此它永远无法达到PUT请求,因为第一个 OPTIONS请求被API拒绝了,认为它是一种无效的HTTP方法。

在Fiddler中,我假设它只发送PUT请求(我观察到使用Postman Web应用程序手动发送请求也会有同样的行为)。因此,它跳过了被禁止的OPTIONS请求并成功执行了PUT请求。


非常感谢,你救了我的一天! 我一直在试图解决CORS的问题。 微软真的需要更新文档和项目模板,我只需更改web.config就可以解决问题。 <customHeaders> <add name="Access-Control-Allow-Credentials" value="true"/> <add name="Access-Control-Allow-Origin" value="http://appdomain.com" /> <add name="Access-Control-Allow-Methods" value="GET, PUT, POST, DELETE, OPTIONS" /> <add name="Access-Control-Allow-Headers" value="Content-Type" /> </customHeaders> - Shawn
4
删除这部分内容后,我得到的是 404 错误而不是 400。 - Rosdi Kasim
根据您的工作理论,通过删除OPTIONSVerbHandler,我们删除了处理OPTIONS动词的处理程序,因此我只需从我的web.config文件中删除该行即可。之后它就可以正常工作了。您有什么理论可以解释为什么还需要删除<add />吗? - Morvael
非常感谢!不过我有一个小提示:对于我的情况,如果我删除/注释掉OPTIONSVerbHandlerExtensionlessUrlHandler-Integrated-4.0,那么我会得到现有请求的404错误。但是当我只注释掉OPTIONSVerbHandler时,问题就解决了。 - Arsen Khachaturyan
1
只注释掉 <!--<remove name="OPTIONSVerbHandler" />--> 就可以了。 - Aji
1
@NathanHanna 你是最棒的,我已经为此苦苦挣扎了几周,而这解决了我的问题。谢谢你。 - Gonzalo

11

我也遇到了相同的问题,在进行了一些研究后,我对 web.config 和 Global.asax.cs 文件做出了以下更改

<configuration>

  <system.webServer>
    <directoryBrowse enabled="true" />
    <validation validateIntegratedModeConfiguration="false" />
    <httpProtocol>
      <customHeaders>
        <add name="Access-Control-Allow-Origin" value="*" />
        <add name="Access-Control-Allow-Methods" value="GET, POST, PUT, PATCH, DELETE, OPTIONS" />
        <add name="Access-Control-Allow-Headers" value="Origin, X-Requested-With, Content-Type, Accept" />

      </customHeaders>
    </httpProtocol>
    <handlers>
      <remove name="WebDAV" />
      <remove name="OPTIONSVerbHandler"/>
      <remove name="TRACEVerbHandler" />
      <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="C:\windows\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="C:\windows\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>
    <modules runAllManagedModulesForAllRequests="true">
      <remove name="WebDAVModule" />
      <remove name="ApplicationInsightsWebTracking" />
      <add name="ApplicationInsightsWebTracking" type="Microsoft.ApplicationInsights.Web.ApplicationInsightsHttpModule, Microsoft.AI.Web" preCondition="managedHandler" />
    </modules>
  </system.webServer>

</configuration>
在global.ascx.cs文件中添加以下代码。
protected void Application_BeginRequest()
{
    if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
    {
        HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST, PUT, PATCH, DELETE, OPTIONS");
        HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
        HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "1728000");
        HttpContext.Current.Response.End();
    }
}

1
这几乎肯定是CORS问题。我建议你先了解一下,确保你理解它的含义和重要性。我猜测你的服务器配置不正确。
不幸的是,我对.net不太了解,但是这个CORS教程 for .net非常清晰地描述了你应该做什么。
看起来你缺少一个EnableCors注释。似乎你需要在控制器中添加像[EnableCors("*", "*", "*")]这样的东西。不需要显式处理OPTIONS。当然,在生产环境中,你不应该使用通配符来处理CORS。它们应该更加具体,但是在测试中使用这个是可以的。

1

没错,这是一个老问题但是很好解决。我曾经遇到过同样的问题和症状,但是我的解决方案是自己制造的。无论如何,我还是会分享我的经验。我们服务配置的控制器在启动时使用了所有MapHttpRoute调用中包含的[DisableCors]属性。只要我重新配置本地机器的启动以使用不同的控制器,一切都能正常工作。所以如果你已经尝试了所有其他方法,请检查你的控制器,并确保你没有像我一样做了什么愚蠢的事情。


1

安德鲁说得对,这很可能是CORS问题。您需要在控制器类中添加EnableCors属性,使其看起来像这样:

 [EnableCors(origins: "https://example.com,http://example.org", headers: "*", methods: "*")]
    public class  TestController : ApiController
    {
         // your code 

另一种方法在这个stack overflow帖子中提到。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接