I have a simple Angular App running locally on 4200 i am testing with a web api running locally on 5000 using .net core. My startup.cs has CORS configured correctly to allow everything i believe.
In the ConfigureServices section i have:
services.AddCors();
In the Configure section i have:
app.UseCors(options => options.AllowAnyHeader().AllowAnyMethod().AllowAnyOrigin());
However when i try and hit my webapi i still get this in the browser.
from origin 'http://localhost:4200' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: Redirect is not allowed for a preflight request.
I have looked at the other answers and they all seem to have this or similar variations that i have tried with no change. Not sure what else i need to do?
using Microsoft.Net.Http.Headers; var builder = WebApplication.CreateBuilder(args); builder.Services.AddCors(options => { options.AddPolicy("MyAllowAllHeadersPolicy", policy => { policy.WithOrigins("https://*.example.com") .AllowAnyHeader(); }); }); builder.Services.AddControllers(); var app = builder.Build();
startup.cs.Configure()
method, does app.UseCors()
precede app.useMVC()
? (/)
?Firefox requires a certificate to be installed for your API in order to send Http Request utilizing the HTTPS protocol.
Test your API with Postman and your browser Developer Tool. Notice 2 Http requests. The Http 200 is a “pre-flight” to see what CORS options are available.
HTTP 500 (Internal Server Error)
, it will return a developer exception page and Postman will display a “no ‘Access-Control-Allow-Origin’ header is present on the requested resource”
message - this is mis-leading.AllowAnyOrigin()
is not recommended in production unless you intend to allow anyone to utilize your API AND you will not implement credentials.EnableCors
attribute when utilizing multiple CORS policies. ASP.NET Core 2.2 does not permit allowing credentials with AllowAnyOrigin()
Enable Cross-Origin Requests (CORS) in ASP.NET Core
(/)
.Create Visual Studio Solution
md c:\s\a cd c:\s\a c:\s\a>dotnet new sln -n solutionName
Create ASP.NET Core Project
c:\s\a>md s c:\s\a>cd s c:\s\a\s>dotnet new webapi -o api -n api
API Launch Settings and CORS Configuration
launchSettings.json
Clone Development Profile to Staging Profile
{
"$schema": "http://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iis": {
"applicationUrl": "http://localhost:myIISApiPortNumber",
"sslPort": myIISApiSSLPortNumber
},
"iisExpress": {
"applicationUrl": "http://localhost:myIISExpressApiPortNumber",
"sslPort": myIISExpressApiSSLPortNumber
}
},
"profiles": {
"Development (IIS Express)": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "api/values",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"Staging (IIS Express)": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "api/values",
"applicationUrl": "https://localhost:myIISExpressApiSSLPortNumber;http://localhost:myIISExpressApiPortNumber",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Staging"
}
},
"Production (IIS)": {
"commandName": "IIS",
"launchBrowser": true,
"launchUrl": "api/values",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Production"
},
"applicationUrl": "https:localhost:myIISApiSSLPortNumber;http://localhost:myIISApiPortNumber"
}
}
}
startup.cs
Add CORS Configuration
public class Startup
{
public IConfiguration Configuration { get; }
public IServiceCollection _services { get; private set; }
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public void ConfigureServices(IServiceCollection services)
{
_services = services;
RegisterCorsPolicies();
services.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseCors("DevelopmentCorsPolicy");
app.UseDeveloperExceptionPage();
}
else if (env.IsStaging())
{
app.UseCors("StagingCorsPolicy");
}
else
{
app.UseCors("ProductionCorsPolicy");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseMvc(); // CORS middleware must precede any defined endpoints
}
private void RegisterCorsPolicies()
{
string[] localHostOrigins = new string[] {
"http://localhost:4200", "http://localhost:3200"};
string[] stagingHostOrigins= new string[] {
"http://localhost:4200"};
string[] productionHostOrigins = new string[] {
"http://yourdomain.net", "http://www.yourdomain.net",
"https://yourdomain.net", "https://www.yourdomain.net"};
_services.AddCors(options => // CORS middleware must precede any defined endpoints
{
options.AddPolicy("DevelopmentCorsPolicy", builder =>
{
builder.WithOrigins(localHostOrigins)
.AllowAnyHeader().AllowAnyMethod();
});
options.AddPolicy("StagingCorsPolicy", builder =>
{
builder.WithOrigins(stagingHostOrigins)
.AllowAnyHeader().AllowAnyMethod();
});
options.AddPolicy("ProductionCorsPolicy", builder =>
{
builder.WithOrigins(productionHostOrigins)
.AllowAnyHeader().AllowAnyMethod();
});
//options.AddPolicy("AllowAllOrigins",
// builder =>
// {
// WARNING: ASP.NET Core 2.2 does not permit allowing credentials with AllowAnyOrigin()
// cref: https://docs.microsoft.com/en-us/aspnet/core/migration/21-to-22?view=aspnetcore-2.2&tabs=visual-studio
// builder.AllowAnyOrigin()
// .AllowAnyHeader().AllowAnyMethod();
// });
//options.AddPolicy("AllowSpecificMethods",
// builder =>
// {
// builder.WithOrigins(productionHostOrigins)
// .WithMethods("GET", "POST", "HEAD");
// });
//options.AddPolicy("AllowSpecificHeaders",
// builder =>
// {
// builder.WithOrigins(productionHostOrigins)
// .WithHeaders("accept", "content-type", "origin", "x-custom-header");
// });
//options.AddPolicy("ExposeResponseHeaders",
// builder =>
// {
// builder.WithOrigins(productionHostOrigins)
// .WithExposedHeaders("x-custom-header");
// });
//options.AddPolicy("AllowCredentials",
// WARNING: ASP.NET Core 2.2 does not permit allowing credentials with AllowAnyOrigin() cref: https://docs.microsoft.com/en-us/aspnet/core/migration/21-to-22?view=aspnetcore-2.2&tabs=visual-studio
// builder =>
// {
// builder.WithOrigins(productionHostOrigins)
// .AllowCredentials();
// });
//options.AddPolicy("SetPreflightExpiration",
// builder =>
// {
// builder.WithOrigins(productionHostOrigins)
// .SetPreflightMaxAge(TimeSpan.FromSeconds(2520));
// });
});
}
}
Set breakpoint on ValuesController.Get()
Test API with Postman:
https://localhost:myApiPortNumber/api/values
Create Angular application
c:\s\a\s>ng new Spa1 --routing (will automatically create Spa folder)
Start Spa1 application
c:\s\a\s>cd Spa1 c:\s\a\s\Spa1>Ng serve
Browse to http://localhost:4200/
Implement CORs in Spa1
app.module.ts
- Import HttpClientModule
import { HttpClientModule } from '@angular/common/http';
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
@NgModule({
declarations: [
AppComponent
],
imports: [
HttpClientModule,
BrowserModule,
AppRoutingModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
app.component.ts
Import HttpClient
Add
getValues()
method with CORS Request
import { Component, OnInit } from '@angular/core';
import { HttpClient } from '@angular/common/http';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit {
title = 'Spa1';
values: any;
apiUrl: string = environment.apiUrl;
valuesUrl = this.apiUrl + "values";
constructor(private http: HttpClient) { }
ngOnInit() {
this.getValues();
}
getValues() {
this.http.get(this.valuesUrl).subscribe(response => {
this.values = response;
}, error => {
console.log(error);
});
}
}
app.component.html
<div style="text-align:center">
<h1>
Welcome to {{ title }}!
</h1>
</div>
<h2>Values</h2>
<p *ngFor="let value of values">
{{value}}
</p>
<router-outlet></router-outlet>
environment.ts
export const environment = {
production: false,
apiUrl: 'https://localhost:myApiPortNumber/api/'
};
Start Spa1 application
c:\s\a\s\Spa1>Ng serve
Browse to http://localhost:4200/
One way of remediating the Firefox block:
FireFox | Options | Privacy & Security | Security | Certificates | [View Certificates] :
Certificate Manager | [Add Exception]:
add localhost
Clone Spa1
c:\s\a\s>xcopy /s /i Spa1 Spa2
Refactor title of Spa2
app.component.ts
export class AppComponent implements OnInit {
title = 'Spa2';
}
Start Spa2 application on port 3200
c:\s\a\s\Spa2>ng serve --port 3200
Browse to http://localhost:3200/
Stop Debugging API with Development (IIS Express) profile
Start Debugging API with Staging (IIS Express) profile
Browse to http://localhost:4200/
Browse to http://localhost:3200/
inspect Http Response with Developer Tools:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With