Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SignalR CORS error on request to Hub method

Tags:

signalr

I'm just trying to get SignalR setup to run owin hosted and I want to connect via the JavaScript client. Should be easy right? I was able to quickly get the SignalR server set up and running and the client connecting to the server. However, when the done callback is called on the client I try to make a call to the hubs Send method and I get the following error in the console:

XMLHttpRequest cannot load http://localhost:8199/signalr/signalr/send?transport=serverSentEvents&clien…AxBg6iaFwlK50s2DnurE&connectionData=%5B%7B%22name%22%3A%22testhub%22%7D%5D. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost' is therefore not allowed access. The response had HTTP status code 500.

Here is my server Side code:

    public static IAppBuilder UseService(this IAppBuilder app)
    {
        log4net.Config.XmlConfigurator.Configure();
        app.UseService(NinjectConfig.CreateKernel);
        app.UseLogging();
        app.UseSignalr();
        return app;
    }
    internal static IAppBuilder UseSignalr(this IAppBuilder app)
    {
        app.Map("/signalr", map =>
            {
               map.UseCors(CorsOptions.AllowAll);

                var hubConfig = new HubConfiguration {EnableDetailedErrors = true};
                map.RunSignalR(hubConfig);
            }
        );
        return app;
    }

Here is the client side:

    var connection = $.hubConnection('http://localhost:8199/signalr');
    var testHub = connection.createHubProxy('testHub');

    testHub.on('addMessage', function(name){
        console.log(name);
    });

    connection.start().done(function () {
            testHub.invoke('send', 'testName');
        }).fail(function (e) {
            console.log('Failed to connect');
        });
        connection.error(function(error){
        console.log(error);
    });

Why is the CORS request working for the start call and not the subsequent hub method call?

Update: In the network tab i can see there is a call to: http://localhost8199/signalr/negotiate - this call works and the CORS headers are riding the response as expected

There is then a call to: http://localhost:8199/signalr/connect and that call also has the correct CORS headers and works.

Then there is a call to: http://localhost:8199/signalr/start Same good things happen here.

Finally there is a call to: http://localhost:8199/signalr/send and this is the call that fails and there are zero CORS headers per the failure message.

Update:

I have also tried setting my client up like this:

    $.connection.hub.url = 'http://localhost:8199/signalr';
        var proxy = $.connection.testHub;
        proxy.client.addMessage = function(name){
            console.log(name);
    };

    $.connection.hub.start()
    .done(function () {
        console.log($.connection.hub.id);
        proxy.server.sendMessage()
            .done(function(val){
                console.log(val);
            });
     })
    .fail(function (e) {
        console.log('Failed to connect');
    });

I had little hope of this working as I feel that the issue is server side. But Just wanted to update on what I have tried here.

like image 509
Justin Smead Avatar asked Aug 04 '15 18:08

Justin Smead


2 Answers

It turned out that the error I was seeing in the browser was a red herring. There was not an issue with the CORS setup on the server side. I ended up clicking the url in the error from the console in chrome:

XMLHttpRequest cannot load http://localhost:8199/signalr/signalr/send?transport=serverSentEvents&clien…AxBg6iaFwlK50s2DnurE&connectionData=%5B%7B%22name%22%3A%22testhub%22%7D%5D. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost' is therefore not allowed access. The response had HTTP status code 500.

This took me to a .Net yellow screen of death that told me that parameter name s could not be null and there was a null reference exception.

In the end this turned out to be an issue with the dependency resolver. We are using a ninject Kernel in this project for dependency resolution. I was unaware that SignalR would need me to inform it of my dependency resolver if my hub class had a perameterless constructor however it did need that information. Below is what I ended up doing:

       app.Map("/signalr", map =>
        {
            var resolver = new NinjectSignalRDependencyResolver(kernel);
            GlobalHost.DependencyResolver = resolver;
            map.UseCors(CorsOptions.AllowAll);

            var hubConfig = new HubConfiguration { EnableDetailedErrors = true, EnableJSONP = true };
            map.RunSignalR(hubConfig);
        }

So the lesson to learn was click on the hyperlink and there might be a root error down deeper.

like image 68
Justin Smead Avatar answered Sep 19 '22 15:09

Justin Smead


Take a look at this one: http://www.asp.net/signalr/overview/guide-to-the-api/hubs-api-guide-javascript-client#crossdomain

See the note, where they are pointing out that, depending on browsers you use, you might need to fix different things.

SignalR 1.0.1 Cross-domain request (CORS) with Chrome

SignalR IE9 Cross Domain request don't work

Try EnableJSONP in your startup method:

    internal static IAppBuilder UseSignalr(this IAppBuilder app)
    {
        app.Map("/signalr", map =>
        {
           map.UseCors(CorsOptions.AllowAll);

            var hubConfig = new HubConfiguration {
               EnableDetailedErrors = true,
               EnableJSONP = true
            };
            map.RunSignalR(hubConfig);
        };
        return app;
    }
like image 29
DDan Avatar answered Sep 20 '22 15:09

DDan