0

I am trying to POST a request from Angular 7 to an REST API in .NET Core 2.1 My interceptor is

import { Injectable } from '@angular/core';
import { HttpInterceptor, HttpRequest, HttpResponse, HttpHandler, HttpEvent, HttpErrorResponse } from '@angular/common/http';
import { Observable, throwError } from 'rxjs';
import { map, catchError } from 'rxjs/operators';

@Injectable()
export class HttpConfigInterceptor implements HttpInterceptor {
    constructor() { }
    intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        request = request.clone({
            withCredentials: true,
          });
        return next.handle(request).pipe(
            map((event: HttpEvent<any>) => {

                if (event instanceof HttpResponse) 
                {
                    localStorage.setItem('status','200');
                }
                return event;
            }),
            catchError((error: HttpErrorResponse) => {
                let data = {};
                data = {
                    reason: error && error.error && error.error.message ? error.error.message : '',
                    //status: error.status
                };
                if (data['reason'].length>0){
                alert("Error:"+ data['reason']);
                }
                else{
                    alert("Error :"+ error.message);
                }
                return throwError(error);
            }));
    }
}

My StartUp.cs's ConfigurationService and Configure methods are as follows

public void ConfigureServices(IServiceCollection services)
        {
            services.AddOptions();
            services.AddAuthentication(IISDefaults.AuthenticationScheme);
            //Get the configuration settings
            services.Configure<AppSettings>(Configuration.GetSection("URLSettings"));
            String[] origins = Configuration.GetSection("AllowedURLs").Get<AppSettings>().origins;

            //Add the services
            services.AddTransient<IClaimsTransformation, ClaimsTransformationService>();
            //Add Cors
            //services.AddCors();
            services.AddCors(options =>
            {
                options.AddPolicy("CorsPolicy",
                                    builder => builder
                                    .AllowAnyHeader()
                                    .AllowAnyMethod()
                                    .WithOrigins(origins)
                                    .AllowCredentials()
                                 );
            });

            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
        }

        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseHsts();
            }

            app.UseCors("CorsPolicy");
            //app.UseAuthentication();
            //app.UseHttpsRedirection();
            app.UseMvc();
        }

My POST method in Angular is

public GenerateCarModels(carIds: number[]) :any {
    const body = carIds;
    let httpOptions= { headers: new HttpHeaders({ 'Content-Type': 'application/json'})};
    const url = `${baseURL}${'/api/GenerateModels/GenerateCarModels'}`;
    return this.http.post(url,body,httpOptions);
  }

The GET Method works find and no issues with the interceptor or the APIs, but when I am trying to POST the values I get

Access to XMLHttpRequest at 'http://localhost:53499//api/reports/GenerateCarModels' 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. 
Failed to load resource: the server responded with a status of 401 (Unauthorized)

I am not sure what I am doing wrong here

My depencencies...

"dependencies": {
    "@angular/animations": "~7.2.0",
    "@angular/common": "~7.2.0",
    "@angular/compiler": "~7.2.0",
    "@angular/core": "~7.2.0",
    "@angular/forms": "~7.2.0",
    "@angular/platform-browser": "~7.2.0",
    "@angular/platform-browser-dynamic": "~7.2.0",
    "@angular/router": "~7.2.0",
....
....
....
}

Can you please help point what I am missing in headers or anything? I have allowed localhost:4200 in the origin and as I said other GET methods work finely. Thank you

EDIT: When I run Fiddler in the background capturing data it works.

Tony Ngo
  • 19,166
  • 4
  • 38
  • 60
Scorpy47
  • 87
  • 2
  • 13
  • can you show appsettings.json? – levent Oct 04 '19 at 06:11
  • Hi @levent { ' "Logging": { "LogLevel": { "Default": "Warning" } }, "AllowedHosts": "*", "AppSettings": { "origins": [ "http://localhost:4200"] } }' this is my appSettings.json – Scorpy47 Oct 07 '19 at 22:18
  • did u debug ConfigureServices method to check origins variable? your config key `"AllowedHosts"` but you trying read with `"AllowedURLs"`. – levent Oct 08 '19 at 05:31
  • @levent .. thank you for spotting it, but I was using the "origins" to drive along with "withOrigins", AllowedHosts.. can be removed. changed to Anonymous and included a "content type" for POST method.. I think you need atleast one of these in the headers and it worked. (unfortunately I wanted to post the answer but for some reason Stackoverflow does not allow me to post the answer, I have not answered anything before) – Scorpy47 Oct 08 '19 at 22:10

3 Answers3

1

Try this to see if it work

public void ConfigureServices(IServiceCollection services)
{
      services.AddCors();
      services.AddMvc();
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    app.UseCors(
        options => options.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader()
    );

    app.UseMvc();
}

Remember the middleware order is matter

Tony Ngo
  • 19,166
  • 4
  • 38
  • 60
  • Hi @Tony , I had to add ..AllowCredentials() as I am working withCredentials:true but sorry it did not work. I get the same error message as I have replied above. But the fact that it works when I am capturing the traffic using Fiddler tells that I am missing some header information or something obvious which I am not able to pick. – Scorpy47 Oct 04 '19 at 04:44
  • Hi All, After a while I found the solution in [link] https://www.codeproject.com/Answers/5162648/Currently-I-am-working-on-angular-and-web-API-NET#answer1 Thanks to the original author. I changed the launchSettings to what is mentioned in that and it worked. I did not have to use the middleware part mentioned there or any changes to the header on the Angular side. – Scorpy47 Oct 08 '19 at 01:18
0

Have you tried like this

changepassword(loginData: any): Observable<any> {
return this.http.post<any>('Usermaster/ChangePassword', loginData).pipe(
  tap(
    function (data) {
      return data;
    }
  )
);

}

Tis is sample which i am using

  • Hi @ShivShankar , Sorry it did not work. It always returns Unauthorised, Access to XMLHttpRequest at [link] (http://localhost:53499//api/GenerateModels/GenerateCarModels') 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. is thrown back – Scorpy47 Oct 04 '19 at 04:37
  • your origin and every think was correct there is some problem in your databinding or datamapping issue from your angular and from api both have same model class or the data which you are passing is exact and also check your url http://localhost:1233/api/Analytics you have double // and also check with postman first with sample data is your api is calling from there – ShivShankar Namdev Oct 04 '19 at 06:16
  • @shiwShankar `[HttpPost("GenerateCarModels")] public IActionResult GenerateCarModels([FromBody] int[] carIds) { return Ok(new { Message = "OK" }); }` this is the POST method in .NET CORE which receives the API call from angular (sorry abt formatting..) – Scorpy47 Oct 07 '19 at 22:21
0

Make sure in your cors configuration use something like options.WithOrigins("http://localhost:4200") instead of options.WithOrigins("http://localhost:4200/"), remove "/" at the end of url if you have.

Then try to integrate you solution with this link to enable OPTIONS header for CORS on .NET Core Web API

https://stackoverflow.com/a/42199758/10158551

Ryan
  • 19,118
  • 10
  • 37
  • 53