sosNiLa
sosNiLa

Reputation: 337

Angular POST and .NET Core WEB Api - 401 Unauthorized error / CORS

I have separate projects for front-end (Angular) and back-end (.NET Core WEB Api). I have been setup the CORS as well the windows AD authentification. All that is working well for GET calls, but I am having issues with the POST. I am getting following error.

OPTIONS http://localhost:50000/api/data/Update 401 (Unauthorized)
Access to XMLHttpRequest at 'http://localhost:50000/api/data/Update' 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.
Error: Http failure response for http://localhost:50000/api/data/Update: 0 Unknown Error

user.component.ts

update(data: NgForm) {
if (data.form.valid) {
  this.service.update(data.value)
    .subscribe(
      res => {
        console.log('Result: ' + res);
      },
      err => {
        console.log('Error: ' + err.message);
    });
  }
}

service.ts

headerOptions = new HttpHeaders({ 'Content-Type': 'application/x-www-form-urlencoded', 'Access- 
Control-Allow-Origin': '*' });

update(data: Form) {
  return this.http.post(this.apiUrl + '/data/Update', data, { headers: this.headerOptions });
}

Controller

[HttpPost("[action]")]
public string Update([FromForm] User data)
  {
    if (data != null)
  {
    return "Ok";
  }
    else
  {
    return "Data is null";
  }
}

CORS extension

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

I also have the interceptor inside Angular which is sending "withCredentials: true" for all calls.

Have in mind that all my GET calls are working without issues, I only have problems with the POST. If I change the method on Angular side from POST to GET, the Update method from back-end is getting called without issues...

Upvotes: 2

Views: 4175

Answers (2)

sosNiLa
sosNiLa

Reputation: 337

I was able to hit my controller and POST data after I did following changes:

  1. Changed controller attribute from "FromForm" to "FromBody" (thanks to Daniel note about it).
  2. Changed angular post method to the following

     headerOptions = new HttpHeaders({ 'Content-Type': 'application/json' 
     });
    
     update(data) {
     return this.http.post(this.apiUrl + '/data/Update', JSON.stringify(data), { 
     headers: this.headerOptions });
     }
    
  3. Set "anonymousAuthentication: true" inside my launchSettings.json.

  4. On this stage I had an issue because my user was null on application start, so I had to implement a new middleware found on this question ntlm anon in order to handle non-authenticated user on app start.

  5. Call middleware inside Configure (Startup.cs), just pay attention on the order. Here is mine:

    app.UseCors("CorsPolicy");
    app.UseAnonMiddleware();
    app.UseAdMiddleware();
    app.UseMvc();

And thats it.

Upvotes: 1

Dalorzo
Dalorzo

Reputation: 20014

Different ports are exactly the same as different applications, therefore your WebApi should allow CORS like

 [EnableCors(origins: "http://localhost:4200", headers: "*", methods: "*")]
    public class TestController : ApiController
    {
        // Controller methods not shown...
    }

However, if this is the same application and all you want is that all of the work through the same port then what I think you need to do is:

Add Microsoft.AspNetCore.SpaServices.Extensions nuget package.

And then configure in you Startup.cs the Angular Cli like:

app.UseStaticFiles();
app.UseSpaStaticFiles();

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

            app.UseSpa(spa =>
            {
                spa.Options.SourcePath = "ClientApp";

                if (env.IsDevelopment())
                {
                    spa.UseAngularCliServer(npmScript: "start");
                }
            });

Important:

To learn more about options for serving an Angular SPA from ASP.NET Core, see https://go.microsoft.com/fwlink/?linkid=864501

This allows you to have if you want angular running on separate port or the same port as your .net core app.

Upvotes: 0

Related Questions