Search code examples
c#.netazureasp.net-coreasp.net-core-signalr

Error: Server returned handshake error: Handshake was canceled


I'm developing a webapp on Azure that creates an application with signalr.

Localhost I can communicate normally, but when I publish to Azure, I receive a Handshake error.

I have no idea what it could be. Error Messages

Error: Connection disconnected with error

'Error: Server returned handshake error: Handshake was canceled.'

I added the redis backplane to see if this was the problem, but the problem persisted

I have this code on backend:

public static IServiceCollection AddSignalRWebApi(this IServiceCollection services, IConfiguration configuration)
{
    var redisConnectionString = configuration.GetConnectionString("Redis");
    const string channelName = "CustomerPosition";

    if (redisConnectionString is null) throw new ArgumentNullException(nameof(redisConnectionString));

    services
        .AddSignalR(options =>
        {
            options.EnableDetailedErrors = true;
            options.AddFilter<CustomerInformationFilter>();
            options.HandshakeTimeout = TimeSpan.FromSeconds(60);
        })
        .AddStackExchangeRedis(options =>
        {
            options.ConnectionFactory = async writer =>
            {
                var config = ConfigurationOptions.Parse(redisConnectionString);
                config.ChannelPrefix = channelName;

                var connection = await ConnectionMultiplexer.ConnectAsync(config, writer);
                connection.ConnectionFailed += async (_, _) =>
                {
                    await RedisBackplaneDisconnectHandler.ReleaseConnections();
                };
                return connection;
            };
        });

    services.AddSingleton<IConnectionsManager, ConnectionsManager>();
    services.AddSingleton<CustomerInformationFilter>();
    return services;
}



public static IEndpointRouteBuilder UseSignalR(this IEndpointRouteBuilder endpoints, IApplicationBuilder app)
{
    endpoints.MapHub<CustomerPatrimonyHub>("/sse/customer/patrimony",
        options => { options.Transports = HttpTransportType.ServerSentEvents; });

    RedisBackplaneDisconnectHandler.Configure(app.ApplicationServices.GetRequiredService<IConnectionsManager>());

    return endpoints;
}

And my front-end looks like this

const setupConnection = (bearerToken) => {
return new Promise(resolve => {

    connection = new signalR.HubConnectionBuilder()
        .withUrl(`https://UrlToApplicationInAzure`, {
            accessTokenFactory: (() => {
                return bearerToken;
            }),
            skipNegotiation: true
        })
        .configureLogging(signalR.LogLevel.Debug)
        .build();

    connection.on("CustomerPatrimonyChanged", (data) => {
        const customerCodeValueDiv = document.getElementById("customerCodeValue");
        customerCodeValueDiv.innerHTML = data.customerCode;

        const patrimonyValueValueDiv = document.getElementById("patrimonyValue");
        patrimonyValueValueDiv.innerHTML = data.patrimony;

    });

    connection.on("Finished", () => {
        connection.stop();
    });

    connection.start()
        .then(() => resolve(connection))
        .catch(err => console.error('Start: ', err.toString()));

    connection.onclose(() => {
        console.log('OnClose - Disconnected: ', connection.state === signalR.HubConnectionState.Disconnected);
    });
})
  };

 const handler = e => {
  e.preventDefault();

const bearerTokenElement = document.getElementById("bearerToken");

setupConnection(bearerTokenElement.value)
    .then(conn => {
        conn.invoke("LoadCustomerPatrimony")
            .catch(err => console.error('Get Customer Patrimony Update: ', err.toString()));
    });

}; document.getElementById("submit").addEventListener("click", handler);


I tried to activate websockets on Azure, but the option doesn't appear for me: Azure Print


Solution

  • I finally found the problem! In my case, the problem was in the application's DNS security policies. And I also needed to configure Sticky Sessions on my load balancer