The requested resource does not support http metho

2019-01-18 13:08发布

问题:

I am making the following request to an asp.net web api PUT method from my angular.js client:

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;
});

However getting the following errormsg (in fiddler):

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

This is a part of my asp.net web api web.config file:

 <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>

data controller 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);
}

This is my question: Why do I get the errormsg ( see above) when I make exactly the same request in fiddler ( works) as in the angularclient (does not work)??

回答1:

I know this is an old question, but I ran into the same problem and figured I could help others who are trying to figure out.

I solved it by removing 2 of the handler configurations in the 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>

I don't know exactly why it fixed the problem, but my working theory is that <remove name="OPTIONSVerbHandler" /> makes OPTIONS requests forbidden by default. When sending the request through angular, it sends an OPTIONS request first before the PUT request, so it never gets to the PUT request because the first OPTIONS request was denied as an invalid http method on the api.

In fiddler, I am assuming that it just sends only the PUT request (I observed the same behavior using the Postman web app sending requests manually). So it skips the forbidden OPTIONS request and succeeds.



回答2:

I also faced the same issue, after few research, I did following changes to web.config and Global.asax.cs files

<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>

Add the following code 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();
    }
}


回答3:

This is almost certainly a CORS problem. I'd first read up about it to make sure you understand what this is and why it is important. And I would guess that your server configuration is not correct.

Unfortunately, I don't know much about .net, but this CORS tutorial for .net describes what you should do quite clearly.

It looks like you are missing an EnableCors annotation. It looks like you need to add something like [EnableCors("*", "*", "*")] to your controller. Explicit handling of OPTIONS is not necessary. Of course, in producition, you don't want to use wildcards for your CORS handling. They should be more specific, but this is fine for testing.



回答4:

Andrew is correct, it is most probably a CORS issue. What you need is to add EnableCors attribute to your Controller class so that is looks something like this

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

The other way to do this is mentioned in this stack overflow post



回答5:

Apparently, in certain cases, an OPTIONS request is sent before the "real" request to determine whether the real request is safe to send due to CORS. See the following MS article at: http://www.asp.net/web-api/overview/security/enabling-cross-origin-requests-in-web-api and search for "Preflight Requests".

Some of the following Q&As might also help:

  • jQuery $.ajax(), $.post sending "OPTIONS" as REQUEST_METHOD in Firefox
  • AJAX in Chrome sending OPTIONS instead of GET/POST/PUT/DELETE?
  • Why does this jQuery AJAX PUT work in Chrome but not FF
  • How to support HTTP OPTIONS verb in ASP.NET MVC/WebAPI application


回答6:

Yep, an oldie but a goodie. I had the same problem and symptom but my resolution was self-inflicted. I'll share it anyway. The way our service configured the controller used in all of the MapHttpRoute calls at startup included the [DisableCors] attribute. As soon as I reconfigured my local machine startup to use a different controller, everything worked. So if you've done everything else listed here then check your controller and make sure you didn't do something stupid, like I did.