enabling CORS in .net core webAPI - c#

I've installed NuGet package Microsoft.AspNetCore.Cors 2.2.0
then in my .net core webAPI Startup.cs I have done the following:
public void ConfigureServices(IServiceCollection services) {
......
services.AddCors();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseCors(options =>
options.WithOrigins("http://localhost:52556")
.AllowAnyMethod()
.AllowAnyHeader());
app.UseMvc();
}
Then when I send post request from my angular app in console I see this error:
Access to XMLHttpRequest at 'http://localhost:52556/api/PaymentDetail'
from origin 'http://localhost:4200' has been blocked by CORS policy:
Response to preflight request doesn't pass access control check: No
'Access-Control-Allow-Origin' header is present on the requested
resource.
I thought I've enabled CORS but it seems that something is blocking it. What can be done to solve this problem ?

Try this way. Ithink it's because you are allowing URLs with "http://localhost:52556" only. Using "*" will enable all URLs and if you can want you can limit it to any specific one.
public void ConfigureServices(IServiceCollection services)
{
.........................
services.AddCors(options =>
{
options.AddPolicy("NoRestrictions",
builder => builder.WithOrigins("*").AllowAnyHeader().AllowAnyMethod());
});;
...............
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, IOptions<AppServerSettings> appServerSettings)
{
..........
app.UseCors("NoRestrictions");
..........
}

You are setting Origin for you asp host.
Just replace this line
options.WithOrigins("http://localhost:52556")
with
options.WithOrigins("http://localhost:4200")

I solved same problem in C# by annotations/attributes,
[System.Web.Http.Cors.EnableCors(origins: "http://localhost:4200", headers: "*", methods: "*")]
public class StudentsController : ApiController{}
in MVC,
use,
// For Action,
[HttpGet]
[EnableCors("AllowSpecificOrigin")]
public IEnumerable<string> Get(){}
// For Controller,
[Route("api/[controller]")]
[EnableCors("AllowSpecificOrigin")]
public class ValuesController : ControllerBase{}
in your case, replace with this If specific to port number process 4200,
options.WithOrigins("http://localhost:4200");
or you can put No Restrictions,
app.UseCors("NoRestrictions");// To config
// To service
services.AddCors(options =>
{
options.AddPolicy("NoRestrictions",
builder => builder.WithOrigins("*").AllowAnyHeader().AllowAnyMethod());
});
Checks whats the origin,
1) checks port number (e.g. 8080 or 8888)
2) domain and sub domain (e.g. google.com or google.net)
3) schema (e.g. http or https)
register origin,
go inside Startup.ConfigureServices and call services.AddCors();
public void ConfigureServices(IServiceCollection services)
{
services.AddCors();
}
enable cors now,
go Startup.Configure and call app.UseCors(builder =>
builder.WithOrigins("http://google.com"));

Related

CORS stopping communication between Angular app and .NET CORE 3.0 API

I tried to avoid posting this question as there are so many others like, but after trying what seems like every combination none have solved my issue.
The Problem
My angular application CAN POST to my web API when it's running locally on IIS EXPRESS. But when the API is deployed to IIS my Angular app CANNOT POST to it. However it can successfully perform a GET request in both environments.
The Error
Access to XMLHttpRequest at 'https://mySite:1234/api/v1/postData' from origin 'https://mySite:1233' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
What I've tried/the code
Both applications run on different ports so I understand why I need to configure CORS and after quite a bit of reading I found that a pre-flight request is not made for GET requests (as covered in the Mozilla Docs), so that would explain why the GET request succeeds. The Mozilla docs lead me to believe that my POST does not come under the simple request category as it require authorisation, but that does not answer way it works on IIS EXPRESS and not on IIS (I assume express is a bit less strict?).
After following the official docs and NOT being able to get it to work then looking at various SO posts and trying various options, I've come to a dead-end and really hope someone can point out where I've gone wrong
Startup.cs
public class Startup
{
private const string ALLOWED_ORIGINS = "allowedOrigin";
...other stuff...
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options =>
{
options.AddPolicy(name: ALLOWED_ORIGINS,
builder =>
{
builder.WithOrigins("https://myLocalSite:1233", "https://myDeployedSite:1233")//these values are retrieve from config
.AllowAnyMethod()
.AllowAnyHeader();
});
});
services.AddControllers()
....other stuff...
services.AddMvc(o =>
{
var policy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
o.Filters.Add(new AuthorizeFilter(policy));
});
....other stuff...
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
...other stuff...
app.UseRouting();
app.UseCors(ALLOWED_ORIGINS);
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
...other stuff...
}
}
The controller
[ApiController]
[ApiVersion("1.0")]
[Route("api/v{version:apiVersion}/[controller]")]
public class PostDataController : ControllerBase
{
...other stuff...
[HttpPost]
public async Task<SomeResponse> Post(SomeRequest sr)
{
...other stuff...
}
}
Finally
I have not added any angular code as I believe that the issue is in my API set up. I will be happy to add the code if needed though
Try putting AddMvc BEFORE "AddCors".
Sanity checks: start with AllowAnyOrigin, and work your ways to more granular definition
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddCors();
}
public void Configure(IApplicationBuilder app)
{
app.UseCors(policy => policy.WithOrigins(ALLOWED_ORIGINS));
}
Looks like you have those (above).
Do you have (below) ?
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.Configure<CorsOptions>(options =>
{
options.AddPolicy(
"AllowAnySimpleRequest",
builder =>
{
builder.AllowAnyOrigin()
.WithMethods("GET", "POST", "HEAD");
});
Check out this file for a better "full context" code. https://csharp.hotexamples.com/site/file?hash=0x8b07b2262d54348025f4b69ad1c3a6e517321a0d14cca0e0bf05aed12f88424f&fullName=Startup.cs&project=psilon2000/LUV

Access-Control-Allow-Origin Problem in .NET Core Deployed at IIS Configured on Windows Server 2016

I have gone through several documentations at Enable Cross-Origin Requests and SO Answers here but I'm still not getting it right. Also followed Installed IIS CORS module
I have a .net core api 3.1 running on IIS at AWS EC2 Windows Server 2016 datacenter, with endpoint like https://6.13.21.111/api/user/authenticate. I have an angular 8 front end app running on AWS Amplify url like https://tests.d1nkxxfifp945dd.myapp.com Any time I make a request to the API I get the error below.
Access to XMLHttpRequest at 'https://6.13.21.111/api/user/authenticate' from origin 'https://tests.d1nkxxfifp945dd.myapp.com' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
zone.js:3372 POST https://6.13.21.111/api/users/authenticate net::ERR_FAILED
Also getting the same issue when I send request to endpoint from http://localhost:4200/
I have setup the following
Startup.cs
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
readonly string MyAllowSpecificOrigins = "_myAllowSpecificOrigins";
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options =>
{
options.AddPolicy(name: MyAllowSpecificOrigins,
builder =>
{
builder.AllowAnyOrigin()
.AllowAnyHeader()
.AllowAnyMethod();
});
});
services.AddControllers();
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_3_0);
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseCors(MyAllowSpecificOrigins);
app.UseAuthentication();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
User Controller
[Route("api/[controller]")]
[EnableCors("MyAllowSpecificOrigins")]
[ApiController]
public class UsersController : ControllerBase
{
private IUserService _userService;
public UsersController(IUserService userService)
{
_userService = userService;
}
[HttpPost("authenticate")]
public Task<ApiResponse> Authenticate([FromBody]UserRequest userRequest)
{
return _userService.Authenticate(userRequest);
}
}
Try changing "AllowAnyOrigin"to withOrigin("your amazon angular url") and see whether it will resolve the problem.

ASP.NET core Cors policy

I'm having problem setting up Cors policy in my ASP.NET core project.
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options =>
{
options.AddPolicy("AllowAll",
builder =>
{
builder
.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials();
});
});
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
services.AddMemoryCache();
}
I've tried adding app.UseCors("AllowAll"); in Configure(IApplicationBuilder app, IHostingEnvironment env), tried [EnableCors("AllowAll")]before controller declaration:
[Route("api/[controller]")]
[ApiController]
[EnableCors("AllowAll")]
public class TestController : ControllerBase
and before method declaration:
[HttpPost]
[EnableCors("AllowAll")]
public JsonResult Post([FromBody] dynamic request)
and no luck, I'm keep getting "Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at..."
Maybe someone can help me?
I know this is too late, but can help someone,
using CorsMiddleware in specified order is matters
app.UseRouting();
app.UseCors("AllowAll");
app.UseAuthorization();
app.UseResponseCaching();
The call to UseCors must be placed after UseRouting, but before
UseAuthorization.
When using Response Caching Middleware, call
UseCors before UseResponseCaching

Missing method in EnableCorsAttribute

I want to enable CORS from my controller into asp.net core 2 application, so into controller I add attribute like:
[EnableCors(origins: "*", headers: "accept,content-type,origin,x-my-header", methods: "*")]
But I get error on origins:
The best overload for 'EnableCorsAttribute' does not have a parameter
named 'origins'
So I access to EnableCorsAttribute from meta data and I found this methods:
namespace Microsoft.AspNetCore.Cors
{
public class EnableCorsAttribute : Attribute, IEnableCorsAttribute
{
public EnableCorsAttribute(string policyName);
public string PolicyName { get; set; }
}
}
But is supposly it be a method like this:
public EnableCorsAttribute(string origins, string headers, string methods);
Why I don't have it? I need to install something? I'm new in Asp.Net Core and I don't understand why that method isn't in my api. Regards
There's no such attribute like EnableCorsAttribute(string origins, string headers, string methods) in Microsoft.AspNetCore.Cors package.
In Your scenario and based on Enable Cross-Origin Requests (CORS) in ASP.NET Core:
If provided cors configuration is for whole app then in Your ConfigureServices method add cors services:
public void ConfigureServices(IServiceCollection services)
{
services.AddCors();
}
and then global cors middleware in Configure method:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
app.UseCors(builder => builder
.WithOrigins("https://my.web.com", "http://localhost:5001")
.AllowAnyMethod()
.AllowCredentials()
.WithHeaders("Accept", "Content-Type", "Origin", "X-My-Header"));
//code omitted
}
Replace ("https://my.web.com", "http://localhost:5001") with your origin(s).
In case You would like to have more than one cors configuration then in ConfigureServices method:
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options =>
{
options.AddPolicy("MyCorsPolicy", builder => builder
.WithOrigins("https://my.web.com", "http://localhost:5001")
.AllowAnyMethod()
.AllowCredentials()
.WithHeaders("Accept", "Content-Type", "Origin", "X-My-Header"));
});
}
in Configure method:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
app.UseCors("MyCorsPolicy");
//code omitted
}
and finally in controller:
[EnableCors("MyCorsPolicy")]
public class MyController : Controller
{ ... }

How to enable CORS in ASP.net Core WebAPI

What I am trying to do
I have a backend ASP.Net Core Web API hosted on an Azure Free Plan (Source Code: https://github.com/killerrin/Portfolio-Backend).
I also have a Client Website which I want to make consume that API. The Client Application will not be hosted on Azure, but rather will be hosted on Github Pages or on another Web Hosting Service that I have access to. Because of this the domain names won't line up.
Looking into this, I need to enable CORS on the Web API side, however I have tried just about everything for several hours now and it is refusing to work.
How I have the Client Setup
Its just a simple client written in React.js. I'm calling the APIs through AJAX in Jquery. The React site works so I know its not that. The Jquery API call works as I confirmed in Attempt 1. Here is how I make the calls
var apiUrl = "http://andrewgodfroyportfolioapi.azurewebsites.net/api/Authentication";
//alert(username + "|" + password + "|" + apiUrl);
$.ajax({
url: apiUrl,
type: "POST",
data: {
username: username,
password: password
},
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (response) {
var authenticatedUser = JSON.parse(response);
//alert("Data Loaded: " + authenticatedUser);
if (onComplete != null) {
onComplete(authenticatedUser);
}
},
error: function (xhr, status, error) {
//alert(xhr.responseText);
if (onComplete != null) {
onComplete(xhr.responseText);
}
}
});
What I have tried
Attempt 1 - The 'proper' way
https://learn.microsoft.com/en-us/aspnet/core/security/cors
I have followed this tutorial on the Microsoft Website to a T, trying all 3 options of enabling it Globally in the Startup.cs, Setting it up on every controller and Trying it on every Action.
Following this method, the Cross Domain works, but only on a single Action on a single controller (POST to the AccountController). For everything else, the Microsoft.AspNetCore.Cors middleware refuses to set the headers.
I installed Microsoft.AspNetCore.Cors through NUGET and the version is 1.1.2
Here is how I have it setup in Startup.cs
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
// Add Cors
services.AddCors(o => o.AddPolicy("MyPolicy", builder =>
{
builder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader();
}));
// Add framework services.
services.AddMvc();
services.Configure<MvcOptions>(options =>
{
options.Filters.Add(new CorsAuthorizationFilterFactory("MyPolicy"));
});
...
...
...
}
// 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();
// Enable Cors
app.UseCors("MyPolicy");
//app.UseMvcWithDefaultRoute();
app.UseMvc();
...
...
...
}
As you can see, I am doing everything as told. I add Cors before MVC both times, and when that didn't work I attempted putting [EnableCors("MyPolicy")] on every controller as so
[Route("api/[controller]")]
[EnableCors("MyPolicy")]
public class AdminController : Controller
Attempt 2 - Brute Forcing it
https://andrewlock.net/adding-default-security-headers-in-asp-net-core/
After several hours of trying on the previous attempt, I figured I would try to bruteforce it by trying to set the headers manually, forcing them to run on every response. I did this following this tutorial on how to manually add headers to every response.
These are the headers I added
.AddCustomHeader("Access-Control-Allow-Origin", "*")
.AddCustomHeader("Access-Control-Allow-Methods", "*")
.AddCustomHeader("Access-Control-Allow-Headers", "*")
.AddCustomHeader("Access-Control-Max-Age", "86400")
These are other headers I tried which failed
.AddCustomHeader("Access-Control-Allow-Methods", "GET, POST, PUT, PATCH, DELETE")
.AddCustomHeader("Access-Control-Allow-Headers", "content-type, accept, X-PINGOTHER")
.AddCustomHeader("Access-Control-Allow-Headers", "X-PINGOTHER, Host, User-Agent, Accept, Accept: application/json, application/json, Accept-Language, Accept-Encoding, Access-Control-Request-Method, Access-Control-Request-Headers, Origin, Connection, Content-Type, Content-Type: application/json, Authorization, Connection, Origin, Referer")
With this method, the Cross Site headers are being properly applied and they show up in my developer console and in Postman. The problem however is that while it passes the Access-Control-Allow-Origin check, the webbrowser throws a hissy fit on (I believe) Access-Control-Allow-Headers stating 415 (Unsupported Media Type)
So the brute force method doesn't work either
Finally
Has anyone gotten this to work and could lend a hand, or just be able to point me in the right direction?
EDIT
So to get the API calls to go through, I had to stop using JQuery and switch to a Pure Javascript XMLHttpRequest format.
Attempt 1
I managed to get the Microsoft.AspNetCore.Cors to work by following MindingData's answer, except within the Configure Method putting the app.UseCors before app.UseMvc.
In addition, when mixed with the Javascript API Solution options.AllowAnyOrigin() for wildcard support began to work as well.
Attempt 2
So I have managed to get Attempt 2 (brute forcing it) to work... with the only exception that the Wildcard for Access-Control-Allow-Origin doesn't work and as such I have to manually set the domains that have access to it.
Its obviously not ideal since I just want this WebAPI to be wide opened to everyone, but it atleast works for me on a separate site, which means it's a start
app.UseSecurityHeadersMiddleware(new SecurityHeadersBuilder()
.AddDefaultSecurePolicy()
.AddCustomHeader("Access-Control-Allow-Origin", "http://localhost:3000")
.AddCustomHeader("Access-Control-Allow-Methods", "OPTIONS, GET, POST, PUT, PATCH, DELETE")
.AddCustomHeader("Access-Control-Allow-Headers", "X-PINGOTHER, Content-Type, Authorization"));
Because you have a very simple CORS policy (Allow all requests from XXX domain), you don't need to make it so complicated. Try doing the following first (A very basic implementation of CORS).
If you haven't already, install the CORS nuget package.
Install-Package Microsoft.AspNetCore.Cors
In the ConfigureServices method of your startup.cs, add the CORS services.
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(); // Make sure you call this previous to AddMvc
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}
Then in your Configure method of your startup.cs, add the following :
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
// Make sure you call this before calling app.UseMvc()
app.UseCors(
options => options.WithOrigins("http://example.com").AllowAnyMethod()
);
app.UseMvc();
}
Now give it a go. Policies are for when you want different policies for different actions (e.g. different hosts or different headers). For your simple example you really don't need it. Start with this simple example and tweak as you need to from there.
Further reading : http://dotnetcoretutorials.com/2017/01/03/enabling-cors-asp-net-core/
In ConfigureServices add services.AddCors(); BEFORE services.AddMvc();
Add UseCors in Configure
app.UseCors(builder => builder
.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader());
app.UseMvc();
Main point is that add app.UseCors, before app.UseMvc().
Make sure you declare the CORS functionality before MVC so the middleware fires before the MVC pipeline gets control and terminates the request.
After the above method works you can change it configure a specific ORIGIN to accept api calls and avoid leaving your API so open to anyone
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options => options.AddPolicy("ApiCorsPolicy", builder =>
{
builder.WithOrigins("http://localhost:4200").AllowAnyMethod().AllowAnyHeader();
}));
services.AddMvc();
}
In the configure method tell CORS to use the policy you just created:
app.UseCors("ApiCorsPolicy");
app.UseMvc();
I just found this compact article on the subject -
https://dzone.com/articles/cors-in-net-core-net-core-security-part-vi
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseCors(builder => builder
.AllowAnyHeader()
.AllowAnyMethod()
.SetIsOriginAllowed((host) => true)
.AllowCredentials()
);
}
public void ConfigureServices(IServiceCollection services)
{
services.AddCors();
}
I created my own middleware class that worked for me, i think there is something wrong with .net core middleware class
public class CorsMiddleware
{
private readonly RequestDelegate _next;
public CorsMiddleware(RequestDelegate next)
{
_next = next;
}
public Task Invoke(HttpContext httpContext)
{
httpContext.Response.Headers.Add("Access-Control-Allow-Origin", "*");
httpContext.Response.Headers.Add("Access-Control-Allow-Credentials", "true");
httpContext.Response.Headers.Add("Access-Control-Allow-Headers", "Content-Type, X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Date, X-Api-Version, X-File-Name");
httpContext.Response.Headers.Add("Access-Control-Allow-Methods", "POST,GET,PUT,PATCH,DELETE,OPTIONS");
return _next(httpContext);
}
}
// Extension method used to add the middleware to the HTTP request pipeline.
public static class CorsMiddlewareExtensions
{
public static IApplicationBuilder UseCorsMiddleware(this IApplicationBuilder builder)
{
return builder.UseMiddleware<CorsMiddleware>();
}
}
and used it this way in the startup.cs
app.UseCorsMiddleware();
I was struggling with this for DAYS.
I finally got it to work by moving app.UseCors(CORS_POLICY); to the TOP of Configure().
https://weblog.west-wind.com/posts/2016/sep/26/aspnet-core-and-cors-gotchas
Make sure you declare the CORS functionality before > MVC as the
headers have to be applied before MVC completes the request.
<= Even though my app didn't call UseMVC(), moving UseCors() to the top fixed the problem
Also:
Microsoft.AspNetCore.Cors used to be a required NuGet package in .Net Core 2 and lower; it's now automatically a part of Microsoft.AspNetCore in .Net Core 3 and higher.
builder.AllowAnyOrigin() and .AllowCredentials() CORS options are now mutually exclusive in .Net Core 3 and higher
CORS policy seems to require Angular call the server with https. An http URL seemed to give a CORS error regardless of the .Net Core server's CORS configuration. For example, http://localhost:52774/api/Contacts would give a CORS error; simply changing the URL to https://localhost:44333/api/Contacts worked.
Additional note:
In my case, CORS wouldn't work until I moved app.UseCors() above app.UseEndpoints(endpoints => endpoints.MapControllers()).
In my case only get request works well according to MindingData's answer. For other types of request you need to write:
app.UseCors(corsPolicyBuilder =>
corsPolicyBuilder.WithOrigins("http://localhost:3000")
.AllowAnyMethod()
.AllowAnyHeader()
);
Don't forget to add .AllowAnyHeader()
For .NET CORE 3.1
In my case, I was using https redirection just before adding cors middleware and able to fix the issue by changing order of them
What i mean is:
change this:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
...
app.UseHttpsRedirection();
app.UseCors(x => x
.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader());
...
}
to this:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
...
app.UseCors(x => x
.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader());
app.UseHttpsRedirection();
...
}
By the way, allowing requests from any origins and methods may not be a good idea for production stage, you should write your own cors policies at production.
To expand on user8266077's answer, I found that I still needed to supply OPTIONS response for preflight requests in .NET Core 2.1-preview for my use case:
// https://stackoverflow.com/a/45844400
public class CorsMiddleware
{
private readonly RequestDelegate _next;
public CorsMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext context)
{
context.Response.Headers.Add("Access-Control-Allow-Origin", "*");
context.Response.Headers.Add("Access-Control-Allow-Credentials", "true");
// Added "Accept-Encoding" to this list
context.Response.Headers.Add("Access-Control-Allow-Headers", "Content-Type, X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Accept-Encoding, Content-Length, Content-MD5, Date, X-Api-Version, X-File-Name");
context.Response.Headers.Add("Access-Control-Allow-Methods", "POST,GET,PUT,PATCH,DELETE,OPTIONS");
// New Code Starts here
if (context.Request.Method == "OPTIONS")
{
context.Response.StatusCode = (int)HttpStatusCode.OK;
await context.Response.WriteAsync(string.Empty);
}
// New Code Ends here
await _next(context);
}
}
and then enabled the middleware like so in Startup.cs
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseMiddleware(typeof(CorsMiddleware));
// ... other middleware inclusion such as ErrorHandling, Caching, etc
app.UseMvc();
}
for ASP.NET Core 3.1 this soleved my Problem
https://jasonwatmore.com/post/2020/05/20/aspnet-core-api-allow-cors-requests-from-any-origin-and-with-credentials
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddCors();
services.AddControllers();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseRouting();
// global cors policy
app.UseCors(x => x
.AllowAnyMethod()
.AllowAnyHeader()
.SetIsOriginAllowed(origin => true) // allow any origin
.AllowCredentials()); // allow credentials
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(x => x.MapControllers());
}
}
For .Net Core 6
var builder = WebApplication.CreateBuilder(args);
var apiCorsPolicy = "ApiCorsPolicy";
builder.Services.AddCors(options =>
{
options.AddPolicy(name: apiCorsPolicy,
builder =>
{
builder.WithOrigins("http://localhost:4200", "https://localhost:4200")
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials();
//.WithMethods("OPTIONS", "GET");
});
});
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
var app = builder.Build();
app.UseHttpsRedirection();
app.UseCors(apiCorsPolicy);
app.UseAuthorization();
app.MapControllers();
app.Run();
here more examples
None of the above procedures helped and I then read article which solved the issue.
Below is the code.
public void ConfigureServices(IServiceCollection services)
{
// Add service and create Policy with options
services.AddCors(options =>
{
options.AddPolicy("CorsPolicy",
builder => builder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials() );
});
services.AddMvc();
}
and
public void Configure(IApplicationBuilder app)
{
// ...
// global policy - assign here or on each controller
app.UseCors("CorsPolicy");
and on the top of my actionmethod
[EnableCors("CorsPolicy")]
Simplest solution is add
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseHsts();
}
app.UseCors(options => options.AllowAnyOrigin());
app.UseHttpsRedirection();
app.UseMvc();
}
to Startup.cs.
try adding jQuery.support.cors = true; before the Ajax call
It could also be that the data your sending to the API is wonky,
try adding the following JSON function
var JSON = JSON || {};
// implement JSON.stringify serialization
JSON.stringify = JSON.stringify || function (obj) {
var t = typeof (obj);
if (t != "object" || obj === null) {
// simple data type
if (t == "string") obj = '"' + obj + '"';
return String(obj);
}
else {
// recurse array or object
var n, v, json = [], arr = (obj && obj.constructor == Array);
for (n in obj) {
v = obj[n]; t = typeof (v);
if (t == "string") v = '"' + v + '"';
else if (t == "object" && v !== null) v = JSON.stringify(v);
json.push((arr ? "" : '"' + n + '":') + String(v));
}
return (arr ? "[" : "{") + String(json) + (arr ? "]" : "}");
}
};
// implement JSON.parse de-serialization
JSON.parse = JSON.parse || function (str) {
if (str === "") str = '""';
eval("var p=" + str + ";");
return p;
};
then in your data: object change it to
data: JSON.stringify({
username: username,
password: password
}),
I think if you use your own CORS middleware you need to make sure it is really CORS request by checking origin header.
public class CorsMiddleware
{
private readonly RequestDelegate _next;
private readonly IMemoryCache _cache;
private readonly ILogger<CorsMiddleware> _logger;
public CorsMiddleware(RequestDelegate next, IMemoryCache cache, ILogger<CorsMiddleware> logger)
{
_next = next;
_cache = cache;
_logger = logger;
}
public async Task InvokeAsync(HttpContext context, IAdministrationApi adminApi)
{
if (context.Request.Headers.ContainsKey(CorsConstants.Origin) || context.Request.Headers.ContainsKey("origin"))
{
if (!context.Request.Headers.TryGetValue(CorsConstants.Origin, out var origin))
{
context.Request.Headers.TryGetValue("origin", out origin);
}
bool isAllowed;
// Getting origin from DB to check with one from request and save it in cache
var result = _cache.GetOrCreateAsync(origin, async cacheEntry => await adminApi.DoesExistAsync(origin));
isAllowed = result.Result.Result;
if (isAllowed)
{
context.Response.Headers.Add(CorsConstants.AccessControlAllowOrigin, origin);
context.Response.Headers.Add(
CorsConstants.AccessControlAllowHeaders,
$"{HeaderNames.Authorization}, {HeaderNames.ContentType}, {HeaderNames.AcceptLanguage}, {HeaderNames.Accept}");
context.Response.Headers.Add(CorsConstants.AccessControlAllowMethods, "POST, GET, PUT, PATCH, DELETE, OPTIONS");
if (context.Request.Method == "OPTIONS")
{
_logger.LogInformation("CORS with origin {Origin} was handled successfully", origin);
context.Response.StatusCode = (int)HttpStatusCode.NoContent;
return;
}
await _next(context);
}
else
{
if (context.Request.Method == "OPTIONS")
{
_logger.LogInformation("Preflight CORS request with origin {Origin} was declined", origin);
context.Response.StatusCode = (int)HttpStatusCode.NoContent;
return;
}
_logger.LogInformation("Simple CORS request with origin {Origin} was declined", origin);
context.Response.StatusCode = (int)HttpStatusCode.Forbidden;
return;
}
}
await _next(context);
}
For me, it had nothing to do with the code that I was using. For Azure we had to go into the settings of the App Service, on the side menu the entry "CORS". There I had to add the domain that I was requesting stuff from. Once I had that in, everything was magic.
For me the solution was to correct the order:
app.UseCors();
app.UseAuthentication();
app.UseAuthorization();
Here's a .NET 6 example of a Program.cs file using top-level statements to configure CORS. As can be seen, builder.Services.AddCors and app.UseCors are the required statements. The two commented UseCors statements also work and were included to show other options. I made no changes to my ASP.NET API controllers.
For reference, my development Angular app is running on localhost:4200 and is connecting to the development ASP.NET API server using https://localhost:7262.
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddCors();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthorization();
//app.UseCors(options => options.WithOrigins("http://localhost:4200").AllowAnyMethod());
//app.UseCors(options => options.WithOrigins("http://localhost:4200").WithMethods(new string[] {"POST", "PUT"}));
app.UseCors(options => options.AllowAnyOrigin().AllowAnyMethod());
app.MapControllers();
app.Run();
In launchSettings.json, under iisSettings, set anonymousAuthentication to true:
"iisSettings": {
"windowsAuthentication": true,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:4200/",
"sslPort": 0
}
}
Then, in Startup.cs, under ConfigureServices, before services.AddMvc, add:
services.AddCors(options => options.AddPolicy("ApiCorsPolicy", builder =>
{
builder
.AllowAnyOrigin()
.WithHeaders(HeaderNames.AccessControlAllowHeaders, "Content-Type")
.AllowAnyMethod()
.AllowCredentials();
}));
and then, in configure method, before app.UseMvc() add:
app.UseCors("ApiCorsPolicy");
.NET Core 3.1
Worked for me and how the docs say to do it:
in Startup class:
readonly string MyAllowSpecificOrigins = "_myAllowSpecificOrigins";
In ConfigureServices() method:
services.AddCors(options =>
{
options.AddPolicy(MyAllowSpecificOrigins,
builder =>
{
builder.WithOrigins("http://example.com",
"http://www.contoso.com");
});
});
In Configure() method:
app.UseCors(MyAllowSpecificOrigins);
https://learn.microsoft.com/en-us/aspnet/core/security/cors?view=aspnetcore-3.1
Based on your comment in MindingData's answer, it has nothing to do with your CORS, it's working fine.
Your Controller action is returning the wrong data. HttpCode 415 means, "Unsupported Media type". This happens when you either pass the wrong format to the controller (i.e. XML to a controller which only accepts json) or when you return a wrong type (return Xml in a controller which is declared to only return xml).
For later one check existence of [Produces("...")]attribute on your action
I'm using .Net CORE 3.1 and I spent ages banging my head against a wall with this one when I realised that my code has started actually working but my debugging environment was broken, so here's 2 hints if you're trying to troubleshoot the problem:
If you're trying to log response headers using ASP.NET middleware, the "Access-Control-Allow-Origin" header will never show up even if it's there. I don't know how but it seems to be added outside the pipeline (in the end I had to use wireshark to see it).
.NET CORE won't send the "Access-Control-Allow-Origin" in the response unless you have an "Origin" header in your request. Postman won't set this automatically so you'll need to add it yourself.
Here is my code : )
app.Use((ctx, next) =>
{
ctx.Response.Headers.Add("Access-Control-Allow-Origin", ctx.Request.Headers["Origin"]);
ctx.Response.Headers.Add("Access-Control-Allow-Methods", "*");
ctx.Response.Headers.Add("Access-Control-Allow-Credentials", "true");
ctx.Response.Headers.Add("Access-Control-Allow-Headers", "AccessToken,Content-Type");
ctx.Response.Headers.Add("Access-Control-Expose-Headers", "*");
if (ctx.Request.Method.ToLower() == "options")
{
ctx.Response.StatusCode = 204;
return Task.CompletedTask;
}
return next();
});
In my case I fixed with UseCors before UserRouting..
Simple and easy way to do it.
Install package
Install-Package Microsoft.AspNetCore.Cors
Put this below code in startup.cs file
app.UseCors(options => options.AllowAnyOrigin());
Use a custom Action/Controller Attribute to set the CORS headers.
Example:
public class AllowMyRequestsAttribute : ControllerAttribute, IActionFilter
{
public void OnActionExecuted(ActionExecutedContext context)
{
// check origin
var origin = context.HttpContext.Request.Headers["origin"].FirstOrDefault();
if (origin == someValidOrigin)
{
context.HttpContext.Response.Headers.Add("Access-Control-Allow-Origin", origin);
context.HttpContext.Response.Headers.Add("Access-Control-Allow-Credentials", "true");
context.HttpContext.Response.Headers.Add("Access-Control-Allow-Headers", "*");
context.HttpContext.Response.Headers.Add("Access-Control-Allow-Methods", "*");
// Add whatever CORS Headers you need.
}
}
public void OnActionExecuting(ActionExecutingContext context)
{
// empty
}
}
Then on the Web API Controller / Action:
[ApiController]
[AllowMyRequests]
public class MyController : ApiController
{
[HttpGet]
public ActionResult<string> Get()
{
return "Hello World";
}
}
In my case character / at the end of my origin name was causing an issue.
Solution that worked out for me in .NET Core 3.1:
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(c => c.AddPolicy("PolicyName", policy => {
policy.WithOrigins("http://localhost:3000")
.AllowAnyMethod()
.AllowAnyHeader();
}));
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseCors("PolicyName");
}
The solution that worked for me in ASP.NET Core 3.1:
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options =>
{
options.AddPolicy("CorsPolicy",
builder => builder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader());
});
services.AddControllersWithViews();
}
and then change the following:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseCors("CorsPolicy");
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
}
Then program worked and error was solved.
I got MindingData's answer above to work, but I had to use Microsoft.AspNet.Cors instead of Microsoft.AspNetCore.Cors. I am using .NetCore Web Application API project in Visual Studio 2019
The
Microsoft.AspNetCore.Cors
will allow you to do CORS with built-in features, but it does not handle OPTIONS request.
The best workaround so far is creating a new Middleware as suggested in a previous post. Check the answer marked as correct in the following post:
Enable OPTIONS header for CORS on .NET Core Web API
Here is how I did this.
I see that in some answers they are setting app.UserCors("xxxPloicy") and putting [EnableCors("xxxPloicy")] in controllers. You do not need to do both.
Here are the steps.
In Startup.cs inside the ConfigureServices add the following code.
services.AddCors(c=>c.AddPolicy("xxxPolicy",builder => {
builder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader();
}));
If you want to apply all over the project then add the following code in Configure method in Startup.cs
app.UseCors("xxxPolicy");
Or
If you want to add it to the specific controllers then add enable cors code as shown below.
[EnableCors("xxxPolicy")]
[Route("api/[controller]")]
[ApiController]
public class TutorialController : ControllerBase {}
For more info: see this

Categories

Resources