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

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.


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

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