Response to preflight: “No 'Access-Control-Allowed-Origin'” despite CORS-enabled
Asked Answered
L

3

8

I am having trouble figuring out an issue with an angular 4 preflight request not passing a CORS access-control check: “No 'Access-Control-Allowed-Origin'”. I am able to successfully get data from the db but not able to post/save data. I am using VS code for my front end to access my visual studio 2015 back end. My Web Api controller has an attribute of:

[EnableCors(origins: "*", headers: "*", methods: "*")]

    [HttpPost]
    public async Task<IHttpActionResult> Post([FromBody]Employee employee)
    {
        _repo.Create(employee);
        return Ok();
    }

…but when request is made, I'm getting an error of:

XMLHttpRequest cannot load http://localhost:54429/api/createEmployee/. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:4200' is therefore not allowed access

In my vs code, my service looks like this:

postEmployeeForm(employee: Employee): Observable<any>{

    let body = JSON.stringify(employee); 
    let headers = new Headers();
    headers.append('Content-Type', 'application/json');
    let options       = new RequestOptions({ headers: headers });

    console.log('posting employee ' , employee);

    return this.http.post("http://localhost:54429/api/employees/", body, options)
                    .map(this.extractData)
                    .catch(this.handleError)


}

enter image description here

405 Response after removing the body and options from the post.

enter image description here

Not sure what I am missing.

web config

<configuration>
  <configSections>
    <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
  </configSections>
  <connectionStrings>
    <add name="DefaultConnection" connectionString="Data Source=(LocalDb)\MSSQLLocalDB;AttachDbFilename=|DataDirectory|\aspnet-TBryant.WebAPI-20170303082842.mdf;Initial Catalog=aspnet-TBryant.WebAPI-20170303082842;Integrated Security=True" providerName="System.Data.SqlClient" />
    <!--<add name="SampleEntities" connectionString="metadata=res://*/MyModels.csdl|res://*/MyModels.ssdl|res://*/MyModels.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=(localdb)\MSSQLLocalDB;initial catalog=Sample;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework&quot;" providerName="System.Data.EntityClient" />-->
    <add name="northwindEntities" connectionString="metadata=res://*/NorthwindModel.csdl|res://*/NorthwindModel.ssdl|res://*/NorthwindModel.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=(localdb)\MSSQLLocalDB;initial catalog=northwind;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework&quot;" providerName="System.Data.EntityClient" />
    <add name="SampleEntities1" connectionString="metadata=res://*/EmployeeDataModel.csdl|res://*/EmployeeDataModel.ssdl|res://*/EmployeeDataModel.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=(localdb)\MSSQLLocalDB;initial catalog=Sample;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework&quot;" providerName="System.Data.EntityClient" />
  </connectionStrings>
  <appSettings></appSettings>
  <system.web>
    <authentication mode="None" />
    <compilation debug="true" targetFramework="4.6.1" />
    <httpRuntime targetFramework="4.6.1" />
  </system.web>
  <system.webServer>
    <!--<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,PUT,DELTE,OPTIONS"/>
      </customHeaders>
    </httpProtocol>-->
    <modules>
      <remove name="FormsAuthentication" />
    </modules>
    <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>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="Microsoft.Owin.Security" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="Microsoft.Owin.Security.OAuth" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="Microsoft.Owin.Security.Cookies" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="Newtonsoft.Json" culture="neutral" publicKeyToken="30ad4fe6b2a6aeed" />
        <bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Web.Optimization" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="1.0.0.0-1.1.0.0" newVersion="1.1.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="WebGrease" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="0.0.0.0-1.5.2.14234" newVersion="1.5.2.14234" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="1.0.0.0-5.2.3.0" newVersion="5.2.3.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Web.Cors" publicKeyToken="31bf3856ad364e35" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-5.2.3.0" newVersion="5.2.3.0" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
  <entityFramework>
    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" />
    <providers>
      <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
    </providers>
  </entityFramework>
  <system.codedom>
    <compilers>
      <compiler language="c#;cs;csharp" extension=".cs" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:6 /nowarn:1659;1699;1701" />
      <compiler language="vb;vbs;visualbasic;vbscript" extension=".vb" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.VBCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:14 /nowarn:41008 /define:_MYTYPE=\&quot;Web\&quot; /optionInfer+" />
    </compilers>
  </system.codedom>
</configuration>
Loiseloiter answered 16/9, 2017 at 3:33 Comment(6)
try to declare specific headers and methods not wildcards (*).Omor
@JesusCarrasco Originally thats what I had the specific local host url but that wasnt working so i opened it up to wild cardsLoiseloiter
@TroyBryant, try to remove webDAV module, if it is added in your site or server and your response simply define that server only support get, post request. ref -link: weblog.west-wind.com/posts/2015/apr/09/…Urceolate
Can you include how do you setup the CORS ? Are you using owin ? Link to sample solution with just the controller & setup would be ideal.Sorcha
@OndrejSvejdar here is a git hub link to the projects github.com/troyb408Loiseloiter
Is this a web server configuration issue? In the web.config the OPTIONS verb seems to be removed in the handlers section and you need that for the preflight. This is how I added specific verbs to make it work in IIS: https://mcmap.net/q/76714/-iis-7-5-enable-put-and-delete-for-restful-service-extensionlessMoonseed
R
5

I have managed to reproduce your problem. The solution that worked for me is to replace part of Web.config. Under system.webServer, either add or replace the existing <handlers> block with the following:

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

If you already have that exact content in place, try removing it, running the server, stopping the server, re-adding the content and then running the server again. I know that sounds odd but I think it's what ended up fixing it for me. Good luck.

UPDATE #1

Now that we have something happening on the server side of things, try removing the Content-Type header and JSON.stringify stuff in your Angular code. i.e.:

postEmployeeForm(employee: Employee): Observable<any>{
    console.log('posting employee ' , employee);

    return this.http.post("http://localhost:54429/api/employees/", employee)
        .map(this.extractData)
        .catch(this.handleError)
}

UPDATE #2

I think your IIS Express configuration may be overriding some of the changes we've made. Close Visual Studio, delete the .vs/config folder at the root of the solution in Windows Explorer and then try re-running the project. This should reset your IIS Express settings. If you're not completely comfortable with deleting the folder, just rename it and follow the same process.

UPDATE #3

I've managed to get your example project running. It demonstrates a problem with CORS, but this was fixed by using my initial suggestion of adding config.EnableCors:

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        // Web API configuration and services
        config.EnableCors();

        // Web API routes
        config.MapHttpAttributeRoutes();

        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );
    }
}
Richart answered 19/9, 2017 at 7:39 Comment(9)
Originally I had this commented out. I did see an article that said uncomment that section. Now my error is Response for preflight has invalid HTTP status code 405.Loiseloiter
405 response method not allowed added the image aboveLoiseloiter
I put the api and angular code in separate repositories but here you go....github.com/troyb408Loiseloiter
ok then i must be missing something some where else because i have enabled cors in the webapiconfig and rebuilt and refreshed and still have the same errorLoiseloiter
It seems so. At this point I suggest you clean out the project directory (remove .vs, bin, etc) and then copy it to another folder. Something must be screwed up in your IIS Express. Try changing the port too.Richart
Any other suggestions I tried moving bin to another folder. Same issue then I just created a whole new web api same issue. enabled cors in the webapiconfig. what would i be looking to check in IIS that could be causing this issue?Loiseloiter
Try some of the suggestions here: #22495740.Richart
Hi @TroyBryant , you should add an API endpoint in your server to support OPTIONS requests, and respond to them with the access-control-allow-origin header. See my answer bellow.Salon
if you are using Owin based application then follow the link: #22495740Vibrate
S
3

The problem seems to be on the server side.

Before any non-simple CORS request, the browser sends an OPTIONS preflight request to make sure that this server allows non-simple CORS requests. (POST requests with application/json are not considered simple)

In your case, as the error implies, only if the response to the preflight OPTIONS request contains the access-control-allow-origin header with the value 'http://localhost:4200' your original POST request will be sent. (The response in your screenshot doesn't contain this header)

You didn't write much about your server implementation, but if you're using asp.net-web-api here is a simple (a bit hacky) solution on how to make it respond to these preflight OPTIONS requests - link (Also see the comment there by Marcus Cunningham)

Salon answered 19/9, 2017 at 1:16 Comment(0)
P
0

this is all about server side configuration. for your development side testing you can use Google chrome and its plugin.

https://chrome.google.com/webstore/detail/allow-control-allow-origi/nlfbmbojpeacfghkpbjhddihlkkiljbi?hl=en

hope this helpful.

Pithecanthropus answered 25/9, 2017 at 10:13 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.