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: 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
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