Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

asp.net core signalr error during websocket handshake

Sorry for my bad English. I'm trying connect to SignalR Hub from SPA-application (Vue.JS).

Code from client-side:

this.hubConnection = new HubConnectionBuilder()
    .withUrl('http://localhost:*****/testhub')
    .configureLogging(LogLevel.Information)
    .build()

I'm getting an error: Error: Failed to complete negotiation with the server: SyntaxError: Unexpected token < in JSON at position 0

Then I tried:

this.hubConnection = new HubConnectionBuilder()
    .withUrl('http://localhost:*****/testhub', {
      skipNegotiation: true,
      transport: HttpTransportType.WebSockets
    })
    .configureLogging(LogLevel.Information)
    .build()

Nothing was changed (But I get another error):

WebSocket connection to 'ws://localhost:50523/testhub' failed: Error during WebSocket handshake: Unexpected response code: 200

I checked UseWebsockets in Startup.cs. Also I tried to change SignalR version in client-side, but it can't to solve the problem. When I tried to connect SignalR in many-page applications, I don't see it. I have it at first time.

What I doing wrong?

Startup.cs

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.SpaServices.Webpack;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.AspNetCore.WebSockets;
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using Microsoft.AspNetCore.Authorization;
using Newtonsoft.Json;
using Vue2Spa.Models;
using Vue2Spa.Controllers.App;
using Vue2Spa.Hubs;

namespace Vue2Spa
{
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)
    {
        // Add framework services.
        services.AddMvc().AddJsonOptions(options => options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore)
            .SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
        var connection = @"Server=.\SQLEXPRESS;Database=****;Trusted_Connection=True;";
        services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(connection));

        services.AddIdentity<Account, IdentityRole>(options =>
        options.SignIn.RequireConfirmedEmail = true)
        .AddDefaultTokenProviders()
        .AddEntityFrameworkStores<ApplicationDbContext>();

        //JWT
        services.AddAuthentication(options =>
        {
            options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
            options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
        })
        .AddJwtBearer(options =>
            {
                options.RequireHttpsMetadata = false;
                options.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidateIssuer = true,
                    ValidIssuer = AuthOptions.ISSUER,
                    ValidateAudience = true,
                    ValidAudience = AuthOptions.AUDIENCE,
                    ValidateLifetime = true,
                    IssuerSigningKey = AuthOptions.GetSymmetricSecurityKey(),
                    ValidateIssuerSigningKey = true,
                };
            })


        services.AddAuthorization(options =>
        {

        });
        /*services.AddAuthorization(options =>
        {
            options.DefaultPolicy = new AuthorizationPolicyBuilder(JwtBearerDefaults.AuthenticationScheme)
                .RequireAuthenticatedUser()
                .Build();
        });*/

        // Simple example with dependency injection for a data provider.
        services.AddSingleton<Providers.IWeatherProvider, Providers.WeatherProviderFake>();

        //File's parameters
        services.Configure<FormOptions>(o => {
            o.ValueLengthLimit = int.MaxValue;
            o.MultipartBodyLengthLimit = int.MaxValue;
            o.MemoryBufferThreshold = int.MaxValue;
        });

        services.AddSignalR();

    }

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

            // Webpack initialization with hot-reload.
            app.UseWebpackDevMiddleware(new WebpackDevMiddlewareOptions
            {
                HotModuleReplacement = true,
            });
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
        }

        app.UseStaticFiles();

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

            routes.MapRoute(
                name: "default1",
                template: "{controller=Admin}/{action=Index}/{id?}");

            routes.MapSpaFallbackRoute(
                name: "spa-fallback",
                defaults: new { controller = "Home", action = "Index" });

            routes.MapSpaFallbackRoute(
                name: "spa-fallback1",
                defaults: new { controller = "Admin", action = "Index" });
        });
        app.UseAuthentication();
        app.Use(async (context, next) =>
        {
            context.Response.Headers.Add("X-Xss-Protection", "1");
            await next();
        }).UseSignalR(route =>
        {
            route.MapHub<ChatHub>("/chat");
        });
    }
}
}
like image 980
General2001 Avatar asked May 03 '19 08:05

General2001


2 Answers

The problem was solved. I moved UseSignalR above UseMvc.

like image 109
General2001 Avatar answered Oct 13 '22 10:10

General2001


In .NET Core 3 you can do this:

services.AddSignalR();

app.UseEndpoints( endpoints => {
    endpoints.MapControllers();
    endpoints.MapHub<ChatHub>( "/chatHub" );
} );
like image 43
Garrod Ran Avatar answered Oct 13 '22 12:10

Garrod Ran