Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"The requested resource does not support http method 'OPTIONS'" when using EnableCors

I want to enable CORS on one specific action in an Asp.net Web Api. Here's how I'm trying to do it:

[Route("api/mycontroller/myaction")]
[HttpPost]
[EnableCors("https://example.com", "*", "post")]
public async Task<IHttpActionResult> MyAction()
{
    ...
}

But when I send an OPTIONS request to the route, I get back an error: "The requested resource does not support http method 'OPTIONS'." I also tried removing the [HttpPost] annotation to no avail. What am I missing?

like image 470
SZH Avatar asked Aug 10 '17 19:08

SZH


3 Answers

For me, I added the following headers to the request by adding the following code to the Application_BeginRequest function of the Global.asax.cs file:

protected void Application_BeginRequest()
{
    if (Request.Headers.AllKeys.Contains("Origin", StringComparer.CurrentCultureIgnoreCase)
        && Request.HttpMethod == "OPTIONS")
    {
        Response.AddHeader("Access-Control-Allow-Headers", "content-type", "accept", "pragma", "cache-control", "authorization");
        Response.End();
    }
}

I have little idea why this works. Out of curiosity, I tried adding all headers by using an asterisk but then Web API complained that the Authorization header was missing.

like image 194
Ciaran Gallagher Avatar answered Nov 06 '22 10:11

Ciaran Gallagher


You've probably missed the higher level call to HttpConfiguration.EnableCors, as described here: https://enable-cors.org/server_aspnet.html.

Add this code to your configuration:

public static void Register(HttpConfiguration config)
{
    // New code
    config.EnableCors();
}
like image 5
Kirk Larkin Avatar answered Nov 06 '22 08:11

Kirk Larkin


To ensure the OPTIONS request gets handled by your application code and not some other part of the system before it reaches your app code, you may try adding the following to your web.config:

<system.webServer>
  <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>
</system.webServer>

You might also need to include:

<add name="OPTIONSVerbHandler" path="*" verb="OPTIONS"
  modules="IsapiModule" requireAccess="None"
  scriptProcessor="C:\Windows\System32\inetsrv\asp.dll"
  resourceType="Unspecified" />

See the answer at IIS hijacks CORS Preflight OPTIONS request.

Or maybe even just this:

 <add name="OPTIONSVerbHandler" path="*" verb="OPTIONS"
   modules="ProtocolSupportModule" requireAccess="None" />

If none of that on its own works, then in your global.asax or other code you might try:

if (filterContext.HttpContext.Request.HttpMethod == "OPTIONS")
{
    filterContext.HttpContext.Response.Flush();
}

…or some other variation on that, for example:

if (Request.Headers.AllKeys.Contains("Origin", StringComparer.OridinalIgnoreCase)
    && Request.HttpMethod == "OPTIONS") {
    Response.Flush();
}

Regardless of what specific code you use to do it, the point is to:

  • make sure OPTIONS requests are actually getting caught/handled by your application code—not caught/handled by some other part of the system before ever reaching your app code
  • make sure you have explicit handling for OPTIONS requests in your application code
  • make the OPTIONS handling in your application code just do Response.Flush()

Or another approach I’m not sure is relevant to your situation as coded but I’ll mention just in case:

public HttpResponseMessage Options()
{
    var response = new HttpResponseMessage
    {
        StatusCode = HttpStatusCode.OK
    };
    return response;
}
like image 5
2 revs Avatar answered Nov 06 '22 10:11

2 revs