CORS in .NET Core

C#WebCors.Net Core

C# Problem Overview


I am trying to enable CORS in .NET Core in this way:

    public IConfigurationRoot Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddCors(options => options.AddPolicy("AllowAll", p => p.AllowAnyOrigin()
                                                                    .AllowAnyMethod()
                                                                     .AllowAnyHeader()));     
        services.AddMvc();            
    }

    public void Configure(IApplicationBuilder app)
    {
        app.UseCors("AllowAll");
        
        app.UseMvc(routes =>
         {
             routes.MapRoute(
                 name: "default",
                 template: "{controller=Home}/{action=Index}/{id?}");
         });
        
    }
}

However, when I am sending a request to my app with Angular 2 I am getting the famous

> "No 'Access-Control-Allow-Origin' header is present on the requested > resource."

error message.

I am also using Windows Authentication + WebListener. If I am checking with postman the only response headers are:

> Content-Length →3533 > Content-Type →application/json; > charset=utf-8 > Date →Fri, 14 Oct 2016 12:17:57 > GMT Server →Microsoft-HTTPAPI/2.0

So there must be still something wrong configured. Any proposals?

If I remove the outcommented line it works, but I need Windows Authentication :-(

        var host = new WebHostBuilder()
            .UseWebListener()
            .UseContentRoot(Directory.GetCurrentDirectory())
            .UseIISIntegration()
            .UseStartup<Startup>()
            //.UseWebListener(options => options.Listener.AuthenticationManager.AuthenticationSchemes = AuthenticationSchemes.NTLM)
            .Build();

C# Solutions


Solution 1 - C#

Assume you have the answer, but for the benefit of searchers, I had the same problem with the standard tutorial on .NET Core Cors.

One of the many errors encountered:

> XMLHttpRequest cannot load localhost:64633/api/blogs. Response > to preflight request doesn't pass access control check: No > 'Access-Control-Allow-Origin' header is present on the requested > resource. Origin 'localhost:56573' is therefore not allowed > access. The response had HTTP status code 500.

After playing around, the following code worked. Full class posted below to aid understanding of what goes where.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Cors.Infrastructure;

namespace NetCoreWebApiTesting
{
	public class Startup
	{
		public Startup(IHostingEnvironment env)
		{
			var builder = new ConfigurationBuilder()
				.SetBasePath(env.ContentRootPath)
				.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
				.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true);

			if (env.IsEnvironment("Development"))
			{
				// This will push telemetry data through Application Insights pipeline faster, allowing you to view results immediately.
				builder.AddApplicationInsightsSettings(developerMode: true);
			}

			builder.AddEnvironmentVariables();
			Configuration = builder.Build();
		}

		public IConfigurationRoot Configuration { get; }

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

			services.AddMvc().AddJsonOptions(options => options.SerializerSettings.ReferenceLoopHandling =
															Newtonsoft.Json.ReferenceLoopHandling.Ignore);

			// ********************
			// Setup CORS
			// ********************
			var corsBuilder = new CorsPolicyBuilder();
			corsBuilder.AllowAnyHeader();
			corsBuilder.AllowAnyMethod();
			corsBuilder.AllowAnyOrigin(); // For anyone access.
			//corsBuilder.WithOrigins("http://localhost:56573"); // for a specific url. Don't add a forward slash on the end!
			corsBuilder.AllowCredentials();
			
			services.AddCors(options =>
			{
				options.AddPolicy("SiteCorsPolicy", corsBuilder.Build());
			});
		}

		// 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)
		{
			loggerFactory.AddConsole(Configuration.GetSection("Logging"));
			loggerFactory.AddDebug();

			app.UseApplicationInsightsRequestTelemetry();

			app.UseApplicationInsightsExceptionTelemetry();

			app.UseMvc();

			// ********************
			// USE CORS - might not be required.
			// ********************
			app.UseCors("SiteCorsPolicy");
		}
	}
}

To use it you can add the EnableCorsAttribute either on the controller or on the method. e.g.

[EnableCors("SiteCorsPolicy")]
[Route("api/[controller]")]
public class BlogsController : Controller
{
	
}

or

// POST api/value
[EnableCors("SiteCorsPolicy")]
[HttpPost]
public HttpResponseMessage Post([FromBody]Blog value)
{
	// Do something with the blog here....

	var msg = new HttpResponseMessage(System.Net.HttpStatusCode.OK);
	return msg;

}

When I called this using the following code (using standard js/jQuery for easy of copy and paste), the communication stopped being rejected.

function HandleClick() {

	var entityData = {
		"blogId": 2,
		"url": "http://blog.com/blog1",
		"posts": [
		{
			"postId": 3,
			"title": "Post 1-1",
			"content": "This is post 1 for blog 1",
			"blogId": 2
		},
		{
			"postId": 4,
			"title": "Post 1-2",
			"content": "This is post 2 for blog 1",
			"blogId": 2
		}
		]
	};

	$.ajax({
		type: "POST",
		url: "http://localhost:64633/api/blogs",
		async: true,
		cache: false,
		crossDomain: true,
		data: JSON.stringify(entityData),
		contentType: "application/json; charset=utf-8",
		dataType: "json",
		success: function (responseData, textStatus, jqXHR) {
			var value = responseData;
		},
		error: function (responseData, textStatus, errorThrown) {
			alert('POST failed.');
		}
	});
}

Solution 2 - C#

This way works normally, just tried it on angular2 with .net core. The issue the OP is having is that this doesnt work with windows authentication. I am assuming the middleware for windows authentication is happening before a request comes through, in which case its breaking. Best bet would be to see if there is a way to enable the windows auth middleware after the cors middleware has processed in Configure.

Then the order would be

App.UseCors()

App.UseWindowsAuth()

App.UseMVC()

They must happen in this order for it to work.

public void ConfigureServices(IServiceCollection services)
    {
        services.AddCors(options => options.AddPolicy("AllowAll", p => p.AllowAnyOrigin()
                                                                    .AllowAnyMethod()
                                                                     .AllowAnyHeader()));     
        services.AddMvc();            
    }

    public void Configure(IApplicationBuilder app)
    {
        app.UseCors("AllowAll");

        app.UseMvc(routes =>
         {
             routes.MapRoute(
                 name: "default",
                 template: "{controller=Home}/{action=Index}/{id?}");
         });

    }

Solution 3 - C#

What the documentation misses, is the importance of .AllowAnyMethod(). If not present, the dreaded No 'Access-Control-Allow-Origin' will keep bugging you. In your code it's there, so I guess you missed setting the right header in jour client side application.

I Personally got it to work by allowing all:

app.UseCors(b => b.AllowAnyHeader().AllowAnyMethod().AllowAnyOrigin().AllowCredentials());

And my Angular post function like:

post(model) {

    let headers = new Headers({
      'Content-Type':'application/json; charset=utf-8;' 
      ,'Accept':'*/*'
    });


    let options = new RequestOptions({ headers: headers });
    let body = JSON.stringify(model);

    return this.http.post(
      'http://localhost:58847/api/TestPost', body, options)
      .map((response: Response) => {
        let res = response.json();
        return res;
      }
    );
}

After that, you gradually work your way up by specifying origins etc.

Solution 4 - C#

In ASPNET CORE 2.0, The following works for me

   public void ConfigureServices(IServiceCollection services)
    {
        
        services.Configure<MvcOptions>(options =>
        {
            options.Filters.Add(new CorsAuthorizationFilterFactory("AllowSpecificOrigin"));
        });
        services.AddCors(options =>
        {
            options.AddPolicy("AllowSpecificOrigin",
                builder => builder.WithOrigins("http://localhost:5000").AllowAnyHeader()
                .AllowAnyMethod());
        });

        services.AddMvc()
    }

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

        loggerFactory.AddConsole();
        loggerFactory.AddDebug(LogLevel.Information);

        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        
        // Shows UseCors with named policy.
        app.UseCors("AllowSpecificOrigin");

        app.UseStaticFiles();
        app.UseAuthentication();
        

        app.UseMvcWithDefaultRoute();
    }
}

Solution 5 - C#

Add this section in appsettings.json

"App": {
  "CorsOrigins": "http://yourdomain"
}

and

services.AddCors(options => {
  options.AddPolicy(DefaultCorsPolicyName, builder => {
   
   builder.WithOrigins(
     _appConfiguration["App:CorsOrigins"]
       .Split(",", StringSplitOptions.RemoveEmptyEntries)
       .Select(o => o.RemovePostFix("/"))
       .ToArray()
   ).SetIsOriginAllowedToAllowWildcardSubdomains()
    .AllowAnyHeader()
    .AllowAnyMethod()
    .AllowCredentials();
  });
});

Note: App:CorsOrigins in appsettings.json can contain more than one address with splitted by comma.

Solution 6 - C#

You just need to add this in ConfigureService Method of StartUp Class

services.AddCors ();

and this in Configure Method of Startup Class and it will work fine then

app.UseCors (builder => builder
                 .AllowAnyOrigin ()
                 .AllowAnyHeader ()
                 .AllowAnyMethod ());

There is nothing more to add to enable CORS in .Net Core

Solution 7 - C#

I just fixed my problem with Cors in Core 3.1. I was following almost every example and documentation out there. Unfortunately nothing worked until I did .Build() for the builder inside the AddPolicy portion.

        services.AddCors(options => {
            options.AddPolicy(
                name: OrginPolicyKey, 
                builder => builder.WithOrigins("http://localhost:3000")
                    .AllowAnyHeader()
                    .AllowAnyMethod()
                    .Build() // <--- This right here
            );
        });

Also, other people were mentioning about calling the UseCors(OrginPolicyKey) before the rest of your routing and UseMvc stuff. That is correct and I saw that Putting UseCors after the route part broke it. Below is how mine is setup.

        app.UseCors(OrginPolicyKey); // <--- First

        // Then routing stuff..
        app.UseRouting();
        app.UseEndpoints(endpoints =>
        {
            endpoints
                .MapControllerRoute(
                    name: "default",
                    pattern: "{controller=Home}/{action=Index}/{id?}"
                );
        });

Who knew a builder needs to be built ;D

Solution 8 - C#

The answer of @HockeyJ is right, but you can do something more concise if wanted.

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();

    //Or if you want to chose what to include
    services.AddMvcCore()
            .AddCors()
            (...)
}


public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    //Cors
    app.UseCors(builder =>
    {
        builder.AllowAnyHeader();
        builder.AllowAnyMethod();
        builder.AllowCredentials();
        builder.AllowAnyOrigin(); // For anyone access.
        //corsBuilder.WithOrigins("http://localhost:56573"); // for a specific url.
     });
}

Solution 9 - C#

I encountered CORS issues in my application. I felt that I properly implemented the logic but was still getting presented with Access-Control-Allow-Origin 403 Error. I tried every setting mentioned above but nothing worked.

I later discovered that my issue wasn't CORS related. I implemented a custom attribute

[Route("v1/[Controller]")]
[ServiceFilter(typeof(MyCustomFilterAttribute))]
public class MySpecialListsController 

Calls made to the controller were properly making it to the method OnActionExecuting

public override void OnActionExecuting(ActionExecutingContext context)

The logic within the filter was throwing an exception and was presented as a CORS 403 error.

Solution 10 - C#

this is actually is a bug in dotnet core.

try to add cors policy right in the "Configure" method.

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        app.UseRouting();
        app.UseCors(option =>
            option.AllowAnyOrigin()
                .AllowAnyMethod()
                .AllowAnyHeader()
                );
    }

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionDavidView Question on Stackoverflow
Solution 1 - C#JsAndDotNetView Answer on Stackoverflow
Solution 2 - C#seanView Answer on Stackoverflow
Solution 3 - C#Stefan de GrootView Answer on Stackoverflow
Solution 4 - C#Tanver HasanView Answer on Stackoverflow
Solution 5 - C#mostafa kazemiView Answer on Stackoverflow
Solution 6 - C#Rameshwar TrivediView Answer on Stackoverflow
Solution 7 - C#Alex EhlertView Answer on Stackoverflow
Solution 8 - C#GerfautView Answer on Stackoverflow
Solution 9 - C#BDarleyView Answer on Stackoverflow
Solution 10 - C#Pourya TagharrobView Answer on Stackoverflow