21
votes

I have a problem with my ASP.NET core API and my Angular Client. I want to implement SignalR to have a connection between API and Angular. The cors policy are already activated on our client and the API because we can already retrieve data from the API with our client. But the problem now is when I try to use SignalR I receive an error with CORS POLICY:

Access to XMLHttpRequest at 'http://localhost:50501/CoordinatorHub/negotiate' 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.

But there's already cors policy inside the Startup.cs on our API and it's like that:

In the ConfigureServices method :

services.AddCors(options =>
{
    options.AddPolicy("AllowSpecificOrigin",
        builder => 
        builder.WithOrigins("http://localhost:4200/")
            .AllowCredentials()
            //.AllowAnyOrigin()
            .AllowAnyMethod()
            .AllowAnyHeader()
            .SetIsOriginAllowedToAllowWildcardSubdomains());
});

And inside the Configure method :

app.UseCors("AllowSpecificOrigin");

In our Client we just want to try to make a connection between the API and the client and it's like that:

this.hubConnection.start({withCredentials: false}).then(() => 
     this.hubConnection.invoke('send', 'Hello'));
7
I had the same problem, and i was not able to solve it. - Ghyath Serhal
Same issue, have you figured it out? Best help I found was this, which is what you already have in ConfigureServices: github.com/aspnet/SignalR/issues/2095 - MDave
could you please post the your Configure method - BRAHIM Kamel

7 Answers

7
votes

Note this can be applied to .net core 3.1

As it's stated on microsoft docs it seems doesn't work docs

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    // Preceding code ommitted.
    app.UseRouting();

    app.UseCors();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
    });

    // Following code ommited.
}

Warning

With endpoint routing, the CORS middleware must be configured to execute between the calls to UseRouting and UseEndpoints. Incorrect configuration will cause the middleware to stop functioning correctly.

But if you move your UseCors() in the first place your application will work as expected so the working code will be

 public void ConfigureServices(IServiceCollection services)
        {
            services.AddCors(options =>
                options.AddDefaultPolicy(builder => builder.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod()));
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
//place your useCors here 
    app.UseCors();
    app.UseRouting();


    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
    });

    // Following code ommited.
}
8
votes

The accepted answer did not work for me so I decided to put down here what worked for me. In case someone stumbles across the same issue.

I was facing same issue in my local testing while playing around with signalR on Angular 9.

I solved it by switching my Asp NET Core (3.1) app URL from https to http. if you are using Visual Studio,

  1. just right click on project properties -> Debug.
  2. Uncheck Enable SSL

Asp Net core Project

Also do not forget to change the port on your URL in angular App. So basically URL in angular app will be something like this

this.hubConnection = new signalR.HubConnectionBuilder()
      .withUrl("http://localhost:50782/hub").build();

whereas the relevant code in Configure method is something like this

app.UseHttpsRedirection();
app.UseStaticFiles();

   
app.UseRouting();
app.UseCors("_myAllowSpecificOrigins");

app.UseAuthorization();

app.UseEndpoints(endpoints =>
{
    endpoints.MapRazorPages();
    endpoints.MapHub<ChatHub>("/hub");
});

and in your configureServices method I had following

    services.AddRazorPages();

    services.AddCors(options =>
        {
            options.AddPolicy("_myAllowSpecificOrigins",
                builder =>
                {
                    builder.WithOrigins("https://localhost:4200")
                           .AllowAnyHeader()
                           .AllowAnyMethod()
                           .SetIsOriginAllowed((x) => true)
                           .AllowCredentials();
                });
        });
    
   services.AddSignalR();

Hope this helps !

UPDATE

if you are just playing around with samples on your local machine you can also try to run chrome in security mode as mentioned here

on my mac I just simply ran command from terminal

open -n -a /Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --args --user-data-dir="/tmp/chrome_dev_test" --disable-web-security

With this you should be able to run your sample without CORS bothering

6
votes

I solved my problem according to this link

Add this block code to service

services.AddCors(options => options.AddPolicy("CorsPolicy",
        builder =>
        {
            builder.AllowAnyHeader()
                   .AllowAnyMethod()
                   .SetIsOriginAllowed((host) => true)
                   .AllowCredentials();
        }));

and add this block code in configuring app

app.UseCors("CorsPolicy");
app.UseSignalR(routes =>
        {
            routes.MapHub<General>("/hubs/general");
        });
2
votes

try something like this in your startup configuration class:

app.Map("/CoordinatorHub/negotiate", map =>
{
    map.UseCors(CorsOptions.AllowAll);
    var hubConfiguration = new HubConfiguration 
    {
        // You can enable JSONP by uncommenting line below.
    // EnableDetailedErrors = true,
        // EnableJSONP = true

    };
    map.RunSignalR(hubConfiguration);
});
1
votes

I had a similar problem that I struggled with for 6 hours.

It turned out that I had a slash at the end of my Origins.

So instead of:

.WithOrigins("https://aaa.azurewebsites.net/")

use:

.WithOrigins("https://aaa.azurewebsites.net")

Why the final slash isn't just stripped is beyond my understanding.

0
votes

Recently i have face the same issue for .Net Core 3.1, Issue start when i deploy in Azure App service and lastly able to solve the issue use the following code.

I use the following code in ConfigureServices function on Startup.cs file

services.AddCors(options =>
        {
            var corsUrls = Configuration.GetSection("App:CorsOrigins").Value.ToString()
                      .Split(",", StringSplitOptions.RemoveEmptyEntries)
                             .Select(o => o.Trim('/'))
                             .ToArray();
            options.AddPolicy("CorsPolicy",
            builder =>
            {
                builder.WithOrigins(corsUrls)
                       .AllowAnyHeader()
                       .AllowAnyMethod()
                       .AllowCredentials();
            });
        });

Then add the following code in Configure function

app.UseCors("CorsPolicy");
app.UseEndpoints(endpoints =>
  {
    endpoints.MapControllers();
    endpoints.MapHub<WebhookHub>("/Webhook");
  });

Don't forgot to add the following section in appsetting.json file

"App": {
"CorsOrigins": "https://myservice.com" }
0
votes

Tested on signalR in .Net Core 3.1+ and Angular 8+ versions and android 19+ api level and working on iOS devices too

.Net core code

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


            services.AddRazorPages();
            services.AddAccessTokenService();
            services.AddSignalR()
                 .AddHubOptions<ChatHub>(options => options.EnableDetailedErrors = true)
                 .AddJsonProtocol(options =>
                 {
                     options.PayloadSerializerOptions.PropertyNamingPolicy = null;
                  }); ;
            services.AddSingleton<IUserIdProvider, NameUserIdProvider>();

        }



public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Error");
                app.UseHsts();
            }

            app.UseHttpsRedirection();
            app.UseStaticFiles();

            app.UseRouting();
            app.UseCors("CorsPolicy");

            app.UseAuthentication();
            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
                endpoints.MapRazorPages();
                endpoints.MapHub<ChatHub>("/chathub");
            });

        }

--Angular code replace url and token(optional part) with and it's working--

public startConnection = () => {
  this.hubConnection = new signalR.HubConnectionBuilder()
                          .withUrl(this.url,{ accessTokenFactory: () => this.token},)
                          .build();

  this.hubConnection
    .start()
    .then(() => console.log('Connection started'))
    .catch(err => console.log('Error while starting connection: ' + err))
}

   ngOnInit(): void {
      this.startConnection();

  }