5
votes

SignalR works on localhost but doesn't work when is deployed in Azure

Asp.net Core 1.0.0 (.Net Framework 4.6.1)

SignalR.Core 2.2.1

public static void UseSignalR2(this IApplicationBuilder app)
    {
        app.UseAppBuilder(appBuilder => {
            appBuilder.MapSignalR(new HubConfiguration());
        });
        GlobalHost.HubPipeline.AddModule(new ErrorHandlingPipelineModule());
        GlobalHost.HubPipeline.AddModule(new LoggingPipelineModule());
    }

SignalR.js 2.2.1 with default settings

$.connection.hub.url = '/signalr';

Expected behavior

200 for url:

https://(name).azurewebsites.com/signalr/negotiate?clientProtocol=1.5&connectionData=%5B%7B%22name%22%3A%22productsimporthub%22%7D%5D&_=1472811629592

Actual behavior

/signalr/negotiate - on localhost returns 200 but for deployed app in azure returns 404

/signalr - works on both - Protocol error: Unknown transport.

/signalr/hubs - works on both - returns the SignalR js correctly

1
Did you ever find out what this was, I have a similar issue only when deployed to AzureJamie Pollard

1 Answers

1
votes

To find out the real cause of the issue you need to navigate to the negotiate url, and look for the response.

If the response tells you something about a 'CryptographicException: The data protection operation was unsuccessful...'. This is how to fix it.

1) Create a custom IDataProtectionProvider
2) Configure signalr

internal class MachineKeyProtectionProvider : IDataProtectionProvider
{
    public IDataProtector Create(params string[] purposes)
    {
        return new MachineKeyDataProtector(purposes);
    }
}

internal class MachineKeyDataProtector : IDataProtector
{
    private readonly string[] _purposes;

    public MachineKeyDataProtector(string[] purposes)
    {
        _purposes = purposes;
    }

    public byte[] Protect(byte[] userData)
    {
        //return MachineKey.Protect(userData, _purposes);
        return userData;
    }

    public byte[] Unprotect(byte[] protectedData)
    {
        //return System.Web.Security.MachineKey.Unprotect(protectedData, _purposes);
        return protectedData;
    }
}


I use katana extension methods to bridge the IAppBuilder to IApplicationBuilder. This allows your owin middleware to connect to asp.net core. It is important to use the RunSignalr method

app.UseAppBuilder(appBuilder =>
        {
            appBuilder.SetDataProtectionProvider(new MachineKeyProtectionProvider());

            appBuilder.Map("/signalr", map =>
            {
                var hubConfiguration = new HubConfiguration
                {
                    EnableDetailedErrors = true
                };

                map.RunSignalR(hubConfiguration);
            });


        });