CORS enabled but response for preflight has invalid HTTP status code 404 when POSTing JSON

Thanks but getting 405 error,after the above config changes.

Finally it works after adding below code in web api Global.asax file

protected void Application_BeginRequest(Object sender, EventArgs e)
    {
        //HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*");
        if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
        {
            HttpContext.Current.Response.AddHeader("Cache-Control", "no-cache");
            HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST");
            HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept");
            HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "1728000");
            HttpContext.Current.Response.End();
        }
    }

I finally got this to work.

This article 'WebAPI with CORS – IIS Intercepts OPTIONS Verb' informed my thinking. An image showed where, in IIS, the OPTIONS handler mapping appeared and why, within the web.config we needed to remove it to ensure IIS did not intercept.

When I took a look at IIS that handler WAS NOT there. I then took a look at the linked article 'Can't set HttpHandler order using Web.Config unless a «clear» tag exists' and saw that, in this article, after removing the OPTION handler, it was then explicitly added within the web.config.

As I could not see the OPTION handler in IIS, I too added it to the web.config file and all suddenly worked. It appeared that this addition is what was needed.

The final web.config handlers section looks as follows (notice I decided to keep the initial 'remove' just in case this caused problems if I migrated to a different web server in the future).

<system.webServer>
    <handlers>
      <remove name="WebDAV"/>
      <remove name="OPTIONSVerbHandler"/>
      <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" />
      <add name="OPTIONSVerbHandler" path="*" verb="OPTIONS" modules="ProtocolSupportModule" requireAccess="None" responseBufferLimit="4194304" />
    </handlers>
    <httpProtocol>
      <customHeaders>
        <add name="Access-Control-Allow-Origin" value="*" />
        <add name="Access-Control-Allow-Headers" value="Content-Type" />
        <add name="Access-Control-Allow-Methods" value="GET, POST, OPTIONS" />
      </customHeaders>
    </httpProtocol>
</system.webServer>

This worked for me.

In Global.asax

protected void Application_BeginRequest(Object sender, EventArgs e)
{
    //HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*");
    if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
    {
        HttpContext.Current.Response.AddHeader("Cache-Control", "no-cache");
        HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST");
        HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept");
        HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "1728000");
        HttpContext.Current.Response.End();
    }
}

In Web.config

    <httpProtocol>
        <customHeaders>

    <add name="Access-Control-Allow-Origin" value="*"/>
    <add name="Access-Control-Allow-Methods" value="GET,PUT,POST,DELETE,OPTIONS"/>
    <add name="Access-Control-Allow-Headers" value="Content-Type"/>
        </customHeaders>
    </httpProtocol>

rebuild and hey presto.


I have a similar setup that was showing 404 errors and 500 errors as I was attempting to get CORS running on my web service. My fix basically used Hussain's solution, but as I cleaned up my fix, I noted that only one Response line was needed, and I was able to keep the original web handlers in the web.config, and did NOT need to move all of the response handlers into code.

Basically, my fix includes this ONE MAJOR FIX in my ApplicationOnBeginRequest handler:

    private void ApplicationOnBeginRequest( object sender, EventArgs eventArgs )
        {
...
            if ( context.Request.HttpMethod == "OPTIONS" )
                response.End();
        }

and these handlers in my web.config:

<system.webServer>
    <!--Other handlers/modules ...-->
    <httpProtocol>
        <customHeaders>
            <clear />
            <add name="Access-Control-Allow-Origin" value="*" />
            <add name="Access-Control-Allow-Credentials" value="true" />
            <add name="Access-Control-Allow-Headers" value="Content-Type,Accept" />
            <add name="Access-Control-Allow-Methods" value="GET,POST,PUT,DELETE,OPTIONS" />
        </customHeaders>
    </httpProtocol>
   </system.webServer>

Sorry I couldn't send this note as a comment to Hussain's answer.