2

We are trying to use a standalone SignalR server and have a couple of hubs built that we are utilizing. They are working correctly, but I have been unable to get SignalR to utilize the WebSockets transport.

In general, I've had trouble finding current information on the requirements for getting SignalR to negotiate using WebSockets. Can someone help us figure out why WebSockets are not being used?

A little bit about our configuration:

  • SignalR Server:
    • "Microsoft.AspNet.SignalR": "2.2.1"
    • Framework: net462
  • Hosting:
    • Azure App Services
      • Web sockets: On
      • CORS: Allowed Origins: *
      • Pricing Tier: Basic: 1 Small
      • .NET Framework version v4.6
      • SSL certificate

We're using the most recent versions of Chrome and Edge as a JS client.

Here is some of our SignalR server configuration:

Startup.cs

app.UseOwinAppBuilder(map =>
{
    map.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
    HubConfiguration hubConfiguration = new HubConfiguration
    {
        EnableDetailedErrors = hubConfig.EnableDetailedErrors.Value,
    };
    map.MapSignalR("/signalr", hubConfiguration);
});


public static IApplicationBuilder UseOwinAppBuilder(this IApplicationBuilder app, Action<IAppBuilder> configuration)
{
    if (app == null)
    {
        throw new ArgumentNullException(nameof(app));
    }

    if (configuration == null)
    {
        throw new ArgumentNullException(nameof(configuration));
    }

    return app.UseOwin(setup => setup(next =>
    {
        AppBuilder builder = new AppBuilder();
        IApplicationLifetime lifetime = (IApplicationLifetime)app.ApplicationServices.GetService(typeof(IApplicationLifetime));
        IServiceProvider serviceProvider = (IServiceProvider)app.ApplicationServices.GetService(typeof(IServiceProvider));
        IHostingEnvironment hostingEnv = (IHostingEnvironment)app.ApplicationServices.GetService(typeof(IHostingEnvironment));

        AppProperties properties = new AppProperties(builder.Properties);
        properties.AppName = hostingEnv.ApplicationName;
        properties.OnAppDisposing = lifetime.ApplicationStopping;
        properties.DefaultApp = next;

        configuration(builder);

        return builder.Build<Func<IDictionary<string, object>, Task>>();
    }));
}

Negotiate response from SignalR server:

https: //customdomain/signalr/negotiate?clientProtocol=1.5&connectionData=[{"name":"hubname"}]

{
    "Url": "/signalr",
    "ConnectionToken": "MTY5ODlmZmItMDUxNC00ZmJhLTgzZjMtOTcyOGM5ZTUxY2IwOg==",
    "ConnectionId": "16989ffb-0514-4fba-83f3-9728c9e51cb0",
    "KeepAliveTimeout": 20,
    "DisconnectTimeout": 30,
    "ConnectionTimeout": 110,
    "TryWebSockets": false,
    "ProtocolVersion": "1.5",
    "TransportConnectTimeout": 5,
    "LongPollDelay": 0
}

JS client initilization:

$.connection.hub.logging = true;
$.connection.hub.start({ 
    transport: ['webSockets', 'longPolling'],
    withCredentials: false
});

Full Web.config:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <system.web>
        <httpRuntime targetFramework="4.6"/>
        <compilation targetFramework="4.6" strict="true">           
        </compilation>
    </system.web>
    <system.webServer>
        <handlers>
            <add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified"/>
        </handlers>
        <aspNetCore processPath="%LAUNCHER_PATH%" arguments="%LAUNCHER_ARGS%" stdoutLogEnabled="true" stdoutLogFile=".\logs\stdout" forwardWindowsAuthToken="false"/>
    </system.webServer>
</configuration>

Chrome Tools console messages:

[19:05:22 GMT-0400 (Eastern Daylight Time)] SignalR: Fired ajax abort async = false.
[19:05:22 GMT-0400 (Eastern Daylight Time)] SignalR: Auto detected cross domain url.
[19:05:22 GMT-0400 (Eastern Daylight Time)] SignalR: Client subscribed to hub 'concurrentaccesshub'.
[19:05:22 GMT-0400 (Eastern Daylight Time)] SignalR: Negotiating with 'https: //customdomain/signalr/negotiate?clientProtocol=1.5&connectionData=%5B%7B%22name%22%3A%22concurrentaccesshub%22%7D%5D'.
[19:05:22 GMT-0400 (Eastern Daylight Time)] SignalR: longPolling transport starting.
[19:05:23 GMT-0400 (Eastern Daylight Time)] SignalR: Opening long polling request to 'https: //customdomain/signalr/connect?transport=longP…Og%3D%3D&connectionData=%5B%7B%22name%22%3A%22concurrentaccesshub%22%7D%5D'.
[19:05:23 GMT-0400 (Eastern Daylight Time)] SignalR: Long poll complete.
[19:05:23 GMT-0400 (Eastern Daylight Time)] SignalR: LongPolling connected.
[19:05:23 GMT-0400 (Eastern Daylight Time)] SignalR: longPolling transport connected. Initiating start request.

Edit 4/26/2017

Per suggestion, I explicitly set the transport to be only webSockets transport:

$.connection.hub.logging = true;
$.connection.hub.start({ 
    transport: ['webSockets'],
    withCredentials: false
});

Here are the error messages:

SignalR: Auto detected cross domain url.
SignalR: Client subscribed to hub 'concurrentaccesshub'.
SignalR: Negotiating with 'http: //localhost:56637/signalr/negotiate?clientProtocol=1.5&connectionData=%5B%7B%22name%22%3A%22concurrentaccesshub%22%7D%5D'.
SignalR: No transports supported by the server were selected.
SignalR: Stopping connection.
Steve B
  • 161
  • 2
  • 13

1 Answers1

0

I can't reproduce the issue on my side based on your description. I can use Websocket Transport with ASPNET 4.6 on Azure Web App.

"TryWebSockets": false,

This response means that the webSocket is disabled on server side. webSocket also could be disabled in web.config. Please check whether your web configuration file contains following section.

<system.webServer>
  <webSocket enabled="false"/>
</system.webServer>

Updated 5/2/2017

Since you are using OWIN, please check whether you have added following code to Startup.Configure method to use web sock.

public void Configure(IApplicationBuilder app)
{
    app.UseWebSockets();
    app.UseSignalR();
}
Amor
  • 8,325
  • 2
  • 19
  • 21
  • I do not have `` in my web.config, but I will try to explicitly set this to true. I am also going to ammend my initial question to have my full web.config – Steve B Apr 24 '17 at 13:46
  • Running locally with IIS Express (Windows 10 host), I am unable to add `` or `` to see if I have any behavior changes. I actually receive a 500.19 error on the WebSocketModule b/c this is already defined as true in the applicationHost.config. I've also updated my post with my full web.config file. – Steve B Apr 24 '17 at 16:03
  • Please change the value of transport as ['webSockets'] in JS code to explicit use webSockets. Please check whether a error is happened and provide the detail error message. – Amor Apr 25 '17 at 09:44
  • I changed the transport to be only webSockets `transport: ['webSockets']` and appended the error messages to my post. – Steve B Apr 26 '17 at 18:11
  • I also had an opportunity to add a websocket test to my project outside of SignalR using an example from ZBrad's Blog http://zbrad.github.io/tools/wscore/ . This example is working fine and successfully establishes a webSocket. I am wondering if the issue I'm experiencing with SignalR is related to the UseOwinAppBuilder call I have in my post that converts the IApplicationBuilder (Owin) to an IAppBuilder that SignalR utilizes? – Steve B Apr 26 '17 at 18:18
  • I do have `app.UseWebSockets();` in my Startup, but the extension method for `app.UseSignalR();` is not available. I am using `"Microsoft.AspNet.SignalR": "2.2.1"`. – Steve B May 03 '17 at 23:59