Click here to Skip to main content
15,886,095 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I am facing a CORS policy problem and I do not know how to fix it. I tried many approaches but what makes me crazy is that the service works fine on some devices and I can utilize all its resources and works a little bit on others and does not work at others while the whole devices having the same configuration equally set. To be more clear I am having a Web application based entirely and only on AngularJS 2 and a Web API that exposes a few actions. I installed the IIS and hosted the Web API on the default Web Site, which means it can be called from port 80 for simplicity, and I hosted the Web application using port 4200. Now let's give more detail about my Web API application structure.

EMG.WebApi.Core -> this project is the core project in which I put the controller classes and the web configuration class
EMG.WebApi.WebHost -> this project is used merely for hosting and it contains a reference to the EMG.WebApi.Core project and is the one that contains the Global.asax and within its Application_Start I am calling the Register method of Configuration class of the WebApi.Core and give it as a parameter the GlobalConfiguration object to register my handlers, tracers etc.

C#
using EMG.ElectrometerWS.WebApi.Core;
using System;
using System.Web.Http;
using EMG.ElectrometerWS.WebApi.Core.Configuration;

namespace EMG.ElectrometerWS.WebApi.WebHost
{
    public class Global : System.Web.HttpApplication
    {
        protected void Application_Start(object sender, EventArgs e)
        {
            WebApiConfig.Register(GlobalConfiguration.Configuration);
            GlobalConfiguration.Configuration.EnsureInitialized();
        }
    }
}


C#
using EMG.ElectrometerWS.WebApi.Core.Handlers;
using EMG.ElectrometerWS.WebApi.Core.Tracer;
using System;
using System.Configuration;
using System.Web.Http;
using System.Web.Http.Cors;
using System.Web.Http.Tracing;

namespace EMG.ElectrometerWS.WebApi.Core.Configuration
{
    public static class WebApiConfig
    {
        ...

        public static string CorsOrigin
        {
            get
            {
                string result = ConfigurationManager.AppSettings.Get("CorsOrigin");
                if (!string.IsNullOrEmpty(result))
                {
                    return result;
                }
                throw new Exception("AppSetting CorsOrigin not found in web.config file.");
            }
        }
        public static void Register(HttpConfiguration config)
        {

            // Web API configuration and services
            EnableCorsAttribute enableCors =
               new EnableCorsAttribute(CorsOrigin, "*", "*");
            config.EnableCors(enableCors);
            // Web API routes
            config.MapHttpAttributeRoutes();            
            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );
            //config.Routes.MapHttpRoute(
            //    name: "Secret Api",
            //    routeTemplate: "secretapi/{controller}/{id}",
            //    defaults: new { id = RouteParameter.Optional },
            //    constraints: null,
            //    handler: new ApiKeyProtectionMessageHandler() {
            //        InnerHandler = new HttpControllerDispatcher(config)
            //    });

            // Enable ASP.NET Web API tracing
            //config.EnableSystemDiagnosticsTracing();
            //config.Services.Replace(typeof(ITraceWriter), new EntryExitTracer());
            //config.Services.Replace(typeof(ITraceWriter), new WebApiTracer());
            

            //config.MessageHandlers.Add(new EmptyPostBodyMessageHandler());
            // Message handler to check the performance in production environment ONLY
            config.MessageHandlers.Add(new TracingHandler());
            //config.MessageHandlers.Add(new XHttpMethodOverrideHandler());
            config.MessageHandlers.Add(new JwtHandler());
        }
    }
}


EMG.ElectrometerWS.WebApi.WebHost Web.Cofig

XML
<appSettings>
   ....
   <add key="CorsOrigin" value="http://localhost:4200"/>
 </appSettings>


What makes me crazy is that everything works fine on my colleague laptop and he can use all the actions. On mine I cannot call some of PUT methods while I can for others on other colleague/testers they can only call GET methods!!! And increases my surprises is that after clearing the browser history/cookies one of those laptops that have only GET methods being called have all things works fine.

What I have tried:

I tried a lot of approaches

C#
EnableCorsAttribute enableCors =
               new EnableCorsAttribute(CorsOrigin, "*", "*");
            config.EnableCors(enableCors);


Creating the following handler and registered it as the first handler before other handlers

C#
public class CorsPreflightHandler : DelegatingHandler
{
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request,
CancellationToken cancellationToken)
{
if (request.Headers.Contains("Origin") && request.Method == HttpMethod.Options)
{
var response = new HttpResponseMessage(HttpStatusCode.OK);
response.Headers.Add("Access-Control-Allow-Origin", "*");
response.Headers.Add("Access-Control-Allow-Methods", "*");

return response;
}
return await base.SendAsync(request, cancellationToken);
}
}


Removing the previous code and configured the CORS using the Web.config file of the WebHost project

XML
<system.webServer>
     <httpProtocol>
         <customHeaders>
            <add name="Access-Control-Allow-Origin" value="http:localhost:4200" />
            <add name="Access-Control-Allow-Methods" value="*" />
            <add name="Access-Control-Allow-Headers" value="*" />
         </customHeaders>
     </httpProtocol>
</system.webServer>


Finally removing the web config tags and enabled if on each controller class

C#
[EnableCors(origins: "http://localhost:4200", headers: "*", methods: "*")]
    public class XXXController : ApiController
    {
       Public string Get(int id)
       {
           return "value";
       }
    }
Posted
Updated 12-Jan-18 11:47am
v2
Comments
j snooze 12-Jan-18 18:00pm    
don't know if this will help you but I using .net core, I have this. in my startup.cs


// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{

services.AddCors();
services.AddMvc();
services.Configure<iisoptions>(options => { options.ForwardWindowsAuthentication = true; });
var appSettings = Configuration.GetSection("AppSettings");
services.Configure<wtsprinters.models.appsettings>(appSettings);
}

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{

// Shows UseCors with named policy.
app.UseCors(builder => builder.WithOrigins("*")
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials());

app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "api/{controller}/{action}/{id?}");
});
}
}
j snooze 12-Jan-18 18:01pm    
I do feel your pain though, I fought the preflight for hours. Fun times.
Amr Mohammad Rashad 13-Jan-18 6:42am    
Unfortunately I am not using Core framework :(. I saw a lot of solution and I have tried almost all of them but I got lots of wired working/not working situations. Also I've added my own json web token handler and I am not using OWIN type of token authentication as I do not know anything about OWIN and I do not have time to investigate as we should present some demo to the client or we are going to loss the tender :(.
Amr Mohammad Rashad 13-Jan-18 6:40am    
Is my question is a mystery or there can be a solution?
j snooze 15-Jan-18 17:33pm    
I don't know. Most of my issues were I was just learning about cors from an angular2/.net core perspective. I had my angular2 passing the the credentials, but ended up having to allow anonymous authentication for the preflight to make it through. This was only an intranet application and I used windows authentication for the actual call, but still had to enable anonymous for the preflight. Probably not your situation, but that was my dilemma.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900