A quick post to give an insight on a non expected problem most likely you will stumble across when you start creating a little web app using your favorite web app framework and and ASP.NET Core web service running in your localhost. It also seemed to be a common question on the internet, but I could not find the exact answer.
Setup
1 2 3 4 5 6 7 8 9 |
// NOTE: // Below code it was tested from a plain js file and React component // I tried to pass the following options with no luck // var options = { mode: 'no-cors', method: 'GET', credentials: 'omit', headers : {'Content-Type': 'application/json'} }; fetch('http://localhost:5000/api/values') .then(response => response.json()) .then(data => console.log('DATA:' + data)) .catch(err => console.log('ERR:' + err)); |
Symptom
I the error message in Chrome is:
1 |
Failed to load http://localhost:5000/api/values: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled. |
FireFox is:
1 |
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:5000/api/values. (Reason: CORS header 'Access-Control-Allow-Origin' missing). |
And in Edge is:
1 |
SEC7120: Origin http://localhost:3000 not found in Access-Control-Allow-Origin header. |
Solution
Solution lies at the server side. My rest api is built using ASP.NET Core 2.1. So the server needs to know how to handle requests from differnet origins. Probably my lack of knowledge with CORS in practise is the reason of finding a lot of misleading answers on the web.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; namespace WebService { 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.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1); //Add CORS support services.AddCors(o => o.AddPolicy("AllowAll", builder => { builder .AllowAnyOrigin() .AllowAnyMethod() .AllowAnyHeader() .AllowCredentials(); })); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) app.UseDeveloperExceptionPage(); else app.UseHsts(); //app.UseHttpsRedirection(); // Uncomment it for production // Apply to every Controller app.UseCors("AllowAll"); app.UseMvc(); } } } |
Extras
During development there is a workaround by disabling CORS on the web browser itslef. If you use Google Chrome run it with the command line argument “–disable-web-security”, or if you debug you develop your JS application with VS Code add it to launch.json:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
{ // Use IntelliSense to learn about possible attributes. // Hover to view descriptions of existing attributes. // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ { "type": "chrome", "request": "launch", "name": "Launch Chrome against localhost", "url": "http://localhost:3000", "webRoot": "${workspaceFolder}", "runtimeArgs": ["--disable-web-security"] } ] } |