简体   繁体   中英

CORS is not working with .NET Core API and Angular frontend

I have already read through the similar questions, tried a couple of the solutions mentioned in them but without any success - the problem is quite simple, I really don't know what the hell could be set wrong...

I have a very simple .NET Core API on which I want to set CORS.

I have tried this way (endpoint routing): https://learn.microsoft.com/en-us/as.net/core/security/cors?view=as.netcore-5.0#enable-cors-with-endpoint-routing

ConfigureServices() and Configure() methods in Startup.cs

It's exactly the default one which is generated by default, only added the CORS-related code from MSDN.

      public void ConfigureServices(IServiceCollection services)
      {
           services.AddCors(options =>
           {
               options.AddPolicy(name: "Policy1",
                    builder =>
                    {
                        // I read the site url from appsettings.json but for now I want to keep the example as simple as I can
                        // var lpSolverFrontendUrl = Configuration.GetValue<string>("Cors:AllowedSite");
                        builder.WithOrigins("http://localhost:4200").AllowAnyHeader().AllowAnyMethod();
                    });
            });
            services.AddControllers();
        }

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseHttpsRedirection();

            app.UseRouting();

            app.UseCors();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers().RequireCors("Policy1");
            });
        }

My controller class

    [Route("[controller]/[action]")]
    public class SimplexSolverController : Controller
    {
        public IActionResult Ping()
        {
            return Json(new { status = "OK" });
        }

        [HttpPost]
        public IActionResult Solve([FromBody] LPModelDto lpModelDto)
        {
            bool wrongFormat = false;
            string message = null;
            SimplexSolutionDto solution = null;
            //...
        }
        //...
   }

The other way I have already tried (with attributes): https://learn.microsoft.com/en-us/as.net/core/security/cors?view=as.netcore-5.0#enable-cors-with-attributes

Startup.cs this way

        public void ConfigureServices(IServiceCollection services)
        {
           services.AddCors(options =>
           {
               options.AddPolicy(name: "Policy1",
                    builder =>
                    {
                        // I read the site url from appsettings.json but I want to keep the example as simple as I can
                        // var lpSolverFrontendUrl = Configuration.GetValue<string>("Cors:AllowedSite");
                        builder.WithOrigins("http://localhost:4200").AllowAnyHeader().AllowAnyMethod();
                    });
            });
            services.AddControllers();
        }

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseHttpsRedirection();

            app.UseRouting();

            app.UseCors();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }

My controller class this way

I put the EnableCors attribute on the controller method to enable CORS on it.

    [Route("[controller]/[action]")]
    public class SimplexSolverController : Controller
    {
        public IActionResult Ping()
        {
            return Json(new { status = "OK" });
        }

        [EnableCors("Policy1")]
        [HttpPost]
        public IActionResult Solve([FromBody] LPModelDto lpModelDto)
        {
            bool wrongFormat = false;
            string message = null;
            SimplexSolutionDto solution = null;
             //...
        }
        //...
   }

No matter which way I choose I get an error in DevTools console, like: Access to XMLHttpRequest at 'http://localhost:4000/simplexsolver/solve' from origin 'http://localhost:4200' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

I exactly followed what the article said but without any result... I appreciate any help!

UPDATE

I succeeded to enable CORS finally. The sad thing is that I am not be able to set any kind of policy in ConfigureServices, because if I do so, the Access-Control-Allow-Origin header will have a "*" value (not the frontend's address) in the preflight request's response. The way I used is:

  • In the ConfigureServices() method only adding CORS without adding any policy
  • In Configure() I determine the allowance as parameter of the UseCors() method (No need for EnableCors attribute to be put on controller .nethod this way.)

Now my two methods in Startup.cs looks like this:

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddCors();
            services.AddControllers();
        }

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseCors(options => options.WithOrigins(Configuration.GetValue<string>("Cors:AllowedSite")).AllowAnyMethod().AllowAnyHeader().AllowCredentials());

            app.UseHttpsRedirection();

            app.UseRouting();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }

Thank you for all of the answers I got. I hope this will help someone in the future. But it is still strange to me what was wrong with using CORS with a policy.

Fix your code to this:


 app.UseCors("Policy1");

services.AddCors(options =>
           {
               options.AddPolicy("Policy1",
                    builder =>
                    {
                       
                       .builder.WithOrigins("http://localhost:4200")
                       .AllowAnyHeader()
                       .AllowAnyMethod();
                    });
            });

And remove

[EnableCors("Policy1")]

from controller actions.

I was able to allow CORS globally like this in .NET Core 3.1:

Startup.cs code:

public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllers();
        services.AddCors(options => 
        {
            options.AddPolicy(name: "AllowCORS", builder =>
            {
                builder.AllowAnyOrigin()
                       .AllowAnyMethod()
                       .AllowAnyHeader();
            });
        });
    }

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseCors("AllowCORS");

        app.UseHttpsRedirection();

        app.UseRouting();

        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
        });
    }

Use this:

public void ConfigureServices(IServiceCollection services)
        {
            services.AddCors(options =>
            {
                options.AddPolicy("AllowOrigin", builder => 
                        builder.AllowAnyOrigin()
                               .AllowAnyHeader()
                               .AllowAnyMethod());
            });
         
            //...
        }

If it does not work, set Mvc compatibility version to 3.0 using

services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_3_0);

like this:

public void ConfigureServices(IServiceCollection services)
        {
            services.AddCors(options =>
            {
                options.AddPolicy("AllowOrigin", builder => 
                        builder.AllowAnyOrigin()
                               .AllowAnyHeader()
                               .AllowAnyMethod());
            });
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_3_0);
            
            //...
        }

I needed to change order of the call the app.UseCors("CORS_POLICY") in configure.

Not works:

        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
                   
        app.ConfigureMetrics();
        app.UseRouting();
        app.UseAuthentication();
        app.UseAuthorization();
        app.UseUserContextClaimsInjector();
        app.UseGlobalExceptionHandlerMiddleware();
        app.UseResponseCompression();
        app.UseSwagger();
        app.UseSwaggerUI();
        app.UseStaticFiles();
        app.ConfigureHealthCheck();           
        app.UseResponseCompression();

        app.UseCors("CORS_POLICY");

Works:

        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        
        app.UseCors("CORS_POLICY");
        
        app.ConfigureMetrics();
        app.UseRouting();
        app.UseAuthentication();
        app.UseAuthorization();
        app.UseUserContextClaimsInjector();
        app.UseGlobalExceptionHandlerMiddleware();
        app.UseResponseCompression();
        app.UseSwagger();
        app.UseSwaggerUI();
        app.UseStaticFiles();
        app.ConfigureHealthCheck();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM