2
votes

I have web API and Angular app for him.

I enabled cors policy on web api side:

services.AddCors(options =>
            {
                options.AddPolicy("CorsPolicy", b =>
                    {
                        b.AllowAnyOrigin()
                            .AllowAnyMethod()
                            .AllowAnyHeader()
                            .AllowCredentials();
                    }
                );
            });

app.UseCors("CorsPolicy");

I send get request from Angular like this:

this._httpClient.get(`WebApi link`);

but catch error:

Error during WebSocket handshake: Unexpected response code 400

What am I doing wrong?

This link perfect work in PostMan and I'm getting the result.

Web API uses win auth.

UPD

Web API side has this setting in Startup.cs:

public class Startup
{
    private readonly ILoggerFactory _loggerFactory;  
    public Startup(IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        AutomapperConfig.Init();

        _loggerFactory = loggerFactory;
        var builder = new ConfigurationBuilder()
            .SetBasePath(env.ContentRootPath)
            .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
            .AddEnvironmentVariables();
        Configuration = builder.Build();
    }   
    public IConfigurationRoot Configuration { get; }

    /// <summary>
    /// This method gets called by the runtime. Use this method to add services to the container.
    /// </summary>
    /// <param name="services"></param>
    /// <returns></returns>
    public IServiceProvider ConfigureServices(IServiceCollection services)
    {
        services.AddResponseCompression();
        services.AddMvc();
        services.AddAuthentication(HttpSysDefaults.AuthenticationScheme);
        services.AddAuthorization(options =>
        {
            foreach (var action in Action.All)
                options.AddPolicy(action.Name, policy =>
                    policy.Requirements.Add(new AssemblyStorageRequirement(action)));
        });
        services.AddSingleton<IAuthorizationHandler, AssemblyStorageRequirementHandler>();

        services.AddCors(options =>
        {
            options.AddPolicy("CorsPolicy", b =>
                {
                    b.AllowAnyOrigin()
                        .AllowAnyMethod()
                        .AllowAnyHeader()
                        .AllowCredentials();
                }
            );
        });

        services.AddSwaggerGen(c =>
        {
            c.SwaggerDoc("v1", new Info { Title = "My API", Version = "v1" });
            var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
            var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
            c.IncludeXmlComments(xmlPath);
        });
        services.AddOptions();   
        services.AddSingleton(Configuration);   // IConfigurationRoot
        services.AddSingleton<IConfiguration>(Configuration);       // IConfiguration explicitly                          
        return services.AddDiConfig(Configuration);
    }

    /// <summary>
    /// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    /// </summary>
    /// <param name="app"></param>
    /// <param name="env"></param>
    /// <param name="loggerFactory"></param>
    /// <param name="appLifetime"></param>
    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, IApplicationLifetime appLifetime)
    {
        loggerFactory.AddConsole(Configuration.GetSection("Logging"));
        loggerFactory.AddDebug();
        loggerFactory.AddLog4Net();
        app.UseSwagger();
        app.UseSwaggerUI(c =>
        {
            c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
        });
        app.UseAuthentication();
        app.UseResponseCompression();
        app.UseCors("CorsPolicy");
        app.UseMvc();

        app.UseForwardedHeaders(new ForwardedHeadersOptions
        {
            ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
        });   
        appLifetime.ApplicationStopped.Register(DiConfig.DisposeContainer);
    }
}

The Angular side has this setting in Startup.cs:

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);

        // In production, the Angular files will be served from this directory
        services.AddSpaStaticFiles(configuration =>
        {
            configuration.RootPath = "ClientApp/dist";
        });
        services.AddCors(options =>
        {
            options.AddPolicy("CorsPolicy", b =>
                {
                    b.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.UseExceptionHandler("/Error");
            app.UseHsts();
        }
        app.UseCors("CorsPolicy");
        app.UseHttpsRedirection();
        app.UseStaticFiles();
        app.UseSpaStaticFiles();

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

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

            spa.Options.SourcePath = "ClientApp";

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

Request Headers: GET wss://localhost:44391/sockjs-node/616/kjiu00aa/websocket HTTP/1.1 Host: localhost:44391 Connection: Upgrade Pragma: no-cache Cache-Control: no-cache Upgrade: websocket Origin: https://localhost:44391 Sec-WebSocket-Version: 13 User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36 Accept-Encoding: gzip, deflate, br Accept-Language: ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7 Sec-WebSocket-Key: Ia0VO1G8+d52FJG74UvsQw== Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits

Response Headers:

HTTP/1.1 400 Bad Request Transfer-Encoding: chunked Vary: Origin Server: Kestrel Access-Control-Allow-Credentials: true Access-Control-Allow-Origin: https://localhost:44391 X-SourceFiles: =?UTF-8?B?RTpcUHJvamVjdHNcVEZTXE9jdG9wdXNTZXJ2aWNlc1xBc3NlbWJseVN0b3JhZ2VcQXNzZW1ibHlTdG9yYWdlV2ViU2l0ZVxBc3NlbWJseVN0b3JhZ2VXZWJTaXRlXHNvY2tqcy1ub2RlXDYxNlxraml1MDBhYVx3ZWJzb2NrZXQ=?= X-Powered-By: ASP.NET Date: Fri, 15 Mar 2019 08:03:32 GMT

General:

Request URL: wss://localhost:44391/sockjs-node/616/kjiu00aa/websocket Request Method: GET Status Code: 400 Bad Request

UPD

If I comment out the only place in the code where HttpClient is used, then the error still show...

So the problem is not in WebApi

2
@KirkLarkin,Ok a little later. Maybe I should pass a request to get something else? - iluxa1810
I tried to add {withCredentials:true} but did not help - iluxa1810
Can you provide more information about the error as it looks in your browser's developer tools? The request that fails with a 400 should be visible in the network tab there and could help diagnose this. - Kirk Larkin
The error message suggests the issue isn't related to the API endpoint you've mentioned in your question. wss://localhost:44391/sockjs-node/... is a web-socket connection back to the SPA server being hosted via the Angular CLI, so at this stage this is difficult to diagnose. The next step would be to look at the server logs and see what exactly is happening when processing that request. - Kirk Larkin
@KirkLarkin, This project created from default Visual Studio Template with Angular and with my little change after. Maybe i should install someone? - iluxa1810

2 Answers

0
votes

Can you try this way.

    services.AddCors(options =>
    {
        options.AddPolicy("CorsPolicy",
            builder => builder.AllowAnyOrigin()
              .AllowAnyMethod()
              .AllowAnyHeader()
              .AllowCredentials()
        .Build());
    });
0
votes

Everything was simple...

This error was useless, at least for me.

I did not know that the observer was lazy thus and so the request did not pass

UPD:

After updated from 5 to 7 Version of Angular this error dont show.