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

后端 未结 7 747
天命终不由人
天命终不由人 2020-12-01 16:04

I\'ve searched thoroughly but cannot find a solution to this issue in my particular circumstance.

Cross-domain service calls using Fiddler (POST) execute correctly a

相关标签:
7条回答
  • 2020-12-01 16:26

    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>
    
    0 讨论(0)
  • 2020-12-01 16:28

    For those using .NET Core 3.1, here is a COMPLETE solution (front-end to back-end):

    My problem: When I enabled the windows authentication on my web API, I could not do fetch calls from my react app to my .NET Core 3.1 web API, CORS was freaking out. With Anonymous authentication it worked, but not when windows authentication is enabled.

    1.launchSettings.json

    this will be used only for your dev environnment, make sure windows auth is also enabled in IIS on your prod server.

    {
      "iisSettings": {
        "windowsAuthentication": true,
        "anonymousAuthentication": false,
        "iisExpress": {
          "applicationUrl": "http://localhost:58747",
          "sslPort": 0
        }
      },
     {... more settings if any}
    }
    

    2.Startup.cs:

    CORS policy is enabled here. The order of methods is important here. Also, you don't need to set those in a web.config

    public void ConfigureServices(IServiceCollection services)
        {
            services.AddCors(options =>
            {
                options.AddPolicy("CorsPolicy", //give it the name you want
                               builder =>
                               {
                                   builder.WithOrigins( "http://localhost:3000", //dev site
                                                        "production web site"
                                                       .AllowAnyHeader()
                                                       .AllowAnyMethod()
                                                       .AllowCredentials();
                               });
            });
    
            //database services here
    
            services.AddControllers();
        }
    
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
    
            app.UseRouting();
    
            // global policy same name as in the ConfigureServices()
            app.UseCors("CorsPolicy");
    
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }
    

    3.Controller(s):

    using Microsoft.AspNetCore.Cors;
    ... your other usings
    
    namespace ProjectTest.Controllers
    {
        [ApiController]
        [EnableCors("CorsPolicy")] //THIS HERE needs to be the same name as set in your startup.cs
        [Route("[controller]")]
        public class FooController:Controller
        {
            [HttpGet("getTest")]
            public JsonResult GetTest()
            {
                return Json("bar");
            }
        }
    }
    

    4.React Component fetch call example:

    The "credential: 'include'" is the secret

        await fetch('http://localhost:3000/Foo/getTest', {
            method: 'GET',
            credentials: 'include'
        }).then(resp => resp.json());
    
    0 讨论(0)
  • 2020-12-01 16:29

    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();
            }
        }
    
    0 讨论(0)
  • 2020-12-01 16:29

    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.

    0 讨论(0)
  • 2020-12-01 16:35

    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.

    0 讨论(0)
  • 2020-12-01 16:44

    This helped me too, I had CORS configured in web.config already

    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();
        }
    }
    
    0 讨论(0)
提交回复
热议问题