some_randomer
some_randomer

Reputation: 333

CORS error from .NET Core web api even after successfully calling the api

So I have an angular cli app with Angular 4 talking to a new .NET Core API project. My environment is Windows 7 and the standard browser used in my organisation is IE 11 (so ultimately needs to work with this, however I want to develop in Chrome or FF as TypeScript / .map files don't work on Windows 7). It's an internal web application and we need to use Windows authentication. I created the .NET Core app with Visual Studio 2017 Community.

TL;DR My problem is that I continually get CORS errors in Chrome and FF, even after hitting the api and successfully returning data from the back end. The bizarre thing is that Chrome and FF successfully call the api when I don't enable CORS on the .NET side. When I try to enable CORS Chrome or FF don't hit the api at all. In either case the client code calls an error handler regardless of whether it can connect to the api or not.

So here's the .NET code I tried (although Chrome and FF both call the api without this). I created a CORS policy in Startup.cs\ConfigureSevices with AllowAnyOrigin and also tried the specific "http://localhost:4200" url (local server the app runs on). Also various combinations of AllowAnyMethod and AllowAnyHeader.

public void ConfigureServices(IServiceCollection services)
{
    services.AddCors(options =>
    {
        options.AddPolicy("MyPolicy",
            builder => 
            {
                builder.WithOrigins("http://localhost:4200")
                    .AllowAnyMethod()
                    .AllowAnyHeader()
                    .AllowCredentials();
            });
        });

    //...
}

I added the CORS policy globally in Startup.cs\Configure.

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    app.UseCors("MyPolicy");

    // ...
}

I also tried adding it to the Controller directly as an attribue using [EnableCors]

[Route("api/[controller]")]
[EnableCors("MyPolicy")]
public class CustomerController : Controller

Here's the method on the controller:

// GET: api/customer/id
//[Authorize]
//[EnableCors("MyPolicy")]
[HttpGet("{id}")]
public async Task<IActionResult> Get(int id)
{
    var customer = await _customerService.GetAsync(id);
    if (customer == null)
    {
        return NotFound();
    }

    string msJson = JsonConvert.SerializeObject(customer, 
        JsonCustomSettings.CustomJsonSettings);

    return Ok(msJson);
}

I also read that I need to add the withCredentials option to the api call in Angular - here's the Angular code:

getContent(Id: number): Promise<Client[]> {
    const headers = new Headers({'Content-Type': 'application/json'});
    const options = new RequestOptions({ headers: headers, withCredentials: true });
    console.debug('In getContent:' + id);

    return this.http.get("http://localhost:13751/api/customer/"+id, options)
        .toPromise()
        .then(res => this.extractData(res))
        .catch(this.handleError);
}

Results:

In Chrome and FF "this.handleError" always gets called. As I said Chrome and FF both call the api and return data successfully when I remove the CORS settings from the api.

When I add any of the CORS options on the .NET side in Startup.cs and / or on the controller and put a break point in the controller code:

When I disable all CORS settings on the api side:

====

Chrome error:

XMLHttpRequest cannot load http://localhost:13751/api/customer/2518. Response to preflight request doesn't pass access control check: A wildcard '*' cannot be used in the 'Access-Control-Allow-Origin' header when the credentials flag is true. Origin 'http://localhost:4200' is therefore not allowed access. The credentials mode of an XMLHttpRequest is controlled by the withCredentials attribute.

FF error:

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:13751/api/customer/2518. (Reason: CORS header 'Access-Control-Allow-Origin' missing) Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:13751/api/customer/2518. (Reason: CORS request failed).

====

So I really don't understand why I'm getting the CORS error in Chrome and FF when I can step through the code on the api side and data is returned to the client. (I also have the "Allow-Control-Allow-Origin" plugin for Chrome but this doesn't seem to make a difference).

Would be great if someone could shed some light on this.

Upvotes: 4

Views: 4263

Answers (2)

Marcus H&#246;glund
Marcus H&#246;glund

Reputation: 16801

Do you set the "Access-Control-Allow-Origin" header to the api response?

If not, here's a way of doing that:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    app.UseCors("MyPolicy");

    // ... add api and other stuff

    //Add a middleware which sets the header on the response
    app.Use(async (context, next) =>
    {
        // Add Header
        context.Response.Headers["Access-Control-Allow-Origin"] = "*";

        // Call next middleware
        await next.Invoke();
    });
}

Upvotes: 1

user6121334
user6121334

Reputation:

Cross origin requests are blocked by default because of the browser security policies. To allow CORS requests in Google Chrome install this plugin : https://chrome.google.com/webstore/detail/allow-control-allow-origi/nlfbmbojpeacfghkpbjhddihlkkiljbi?utm_source=chrome-ntp-icon

You will see an icon at top right corner of chrome. Turn on Cross origin resource sharing and then try it out.

Upvotes: 0

Related Questions