0

I refer to a previous post of mine where I got some help connecting to SignalR cross domains Here and I used This example to build my POC. However, the example I used was for a single

I am still trying to figure out how the magic of SignalR works and I think I understand most of it, but somehow I am not getting this to work. My code connects fine to the hub and if I leave it on, I will continue getting the pong result from the pings being sent.

However, I do not seem to get any response from my hub. Here is all the code I have, hope someone can point me in the right direction:

Startup.cs:

public partial class Startup
{
    public void Configuration(IAppBuilder app)
    {
        .
        .
        .

        app.UseCors(_CorsOptions.Value);

        // Branch the pipeline here for requests that start with "/signalr"
        app.Map("/signalr", map =>
        {
            map.RunSignalR(new HubConfiguration { EnableDetailedErrors = true });
        });
    }

    private static Lazy<CorsOptions> _CorsOptions = new Lazy<CorsOptions>(() =>
    {
        return new CorsOptions
        {
            PolicyProvider = new CorsPolicyProvider
            {
                PolicyResolver = context =>
                {
                    var policy = new CorsPolicy();

                    foreach (string allowedCOrsOrigin in ConfigurationManager.AppSettings["AllowedCORS-Origins"].Split(',').ToArray())
                    {
                        if(!string.IsNullOrEmpty(allowedCOrsOrigin) && !policy.Origins.Contains(allowedCOrsOrigin))
                        {
                            policy.Origins.Add(allowedCOrsOrigin);
                        }
                    }

                    policy.AllowAnyMethod = true;
                    policy.AllowAnyHeader = true;
                    policy.SupportsCredentials = true;
                    return Task.FromResult(policy);
                }
            }
        };
    });
}

_SignalBase.cs:

public abstract class _SignalRBase<THub> : ApiController where THub : IHub
{
    private readonly Lazy<IHubContext> _hub = new Lazy<IHubContext>(
        () => GlobalHost.ConnectionManager.GetHubContext<THub>()
    );

    protected IHubContext Hub
    {
        get { return _hub.Value; }
    }
}

FooHub.cs:

[HubName("foos")]
public class FooHub : Hub { }

FooController.cs:

[RoutePrefix("api/foo")]
public class FooController : _SignalRBase<FooHub>
{
    public IHttpActionResult Bar(FooDTO foo)
    {
        // notify all connected clients            
        Microsoft.AspNet.SignalR.GlobalHost.ConnectionManager.GetHubContext<FooHub>()
            .Clients.All.newFoo(foo);

        return Ok(foo);
    }
}

FooDTO.cs:

public class FooDTO
{
    public int First { get; set; }

    public int Second { get; set; }
}

Sender.html

<div class="container">
    <div class="row">
        <div class="col-md-12">
            <button type="button" ng-click="DoSignalR()" ></button>
        </div>
    </div>
</div>

<!-- Reference the autogenerated SignalR hub script -->
<script src="//localhost:31374/signalr/hubs"></script>

Receiver.html:

<div class="container">
    <div class="row">
        <div class="col-md-12">
            <div>
                <ul>
                    <li ng-repeat="foo in receivedFoos">
                        Foo {{foo.First}} &amp; {{foo.Second}}
                    </li>
                </ul>
            </div>
        </div>
    </div>
</div>

<!-- Reference the autogenerated SignalR hub script -->
<script src="//localhost:31374/signalr/hubs"></script>

Angular controller:

.controller('SignalRCtrl', function ($scope, TESTSignalR, $rootScope) {    
    $scope.receivedFoos = [];

    var newFoo = function(data) {
        console.log("newFoo function");
        $scope.$apply(function () {
            $scope.receivedFoos.push(data);
        });
    };

    TESTSignalR.initialize(newFoo);

    //  Sender    
    $scope.DoSignalR = function() {        
        var FooDTO = {
            "First": 1234,
            "Second": 3456
        };

        TESTSignalR.DoSignalR(FooDTO);
    };
})

Angular service:

.factory('TESTSignalR', function($http, APIPath, $rootScope) {    
    var proxy = null;

    var initialize = function (callback) {

        // fetch connection object and create proxy
        var connection = $.hubConnection();
        this.proxy = connection.createHubProxy('foos');

        $.connection.hub.url = "http://localhost:31374/signalr";

        // start connection
        $.connection.hub.start({ xdomain: true })
            .done(function () {
                console.log('Connected to signalR. connectionId : ' + $.connection.hub.id); 
            })
            .fail(function () {
                console.log('Could not connect to signalR!');
            });

        var hubConnection = $.connection.foos;

        hubConnection.client.newFoo = function(data) {
            callback(data);
        };
    };

    var DoSignalR = function (foo) {
        var url = "http://localhost:31374/api/foo/bar";

        $http.post(url, foo)
        .success(function(response) {
            console.log(response);
        })
        .error(function(error) {
        console.log(error);
        });
    }

    return {
        initialize: initialize,
        DoSignalR: DoSignalR
    };
})

EDIT : I updated the code above to reflect the latest changes which @Sal-Niro pointed out. It should all be working fine now

Community
  • 1
  • 1
Ebbs
  • 1,030
  • 3
  • 20
  • 38

1 Answers1

1

It looks like you are trying to invoke a Hub method in the context of your FooController which you'll to make a slightly different call to do so. Is there a reason why are you doing this from the controller and not calling a server hub method from the client? Try the following if you need to invoke from the controller

[RoutePrefix("api/foo")]
public class FooController : ApiController
{
    public IHttpActionResult Bar(FooDTO foo)
    {
        // notify all connected clients
        GolbalHost.ConnectionManager.GetHubContext<FooHub>().Clients.All.newFoo(foo);

        return Ok(foo);
    }
}

It's also possible you are not entirely referencing your proxy correctly to your [HubName("foos")] hub. Observing your implementation of newFoo, try the following

var hubConnection = $.connection.foos; 

hubConnection.client.newFoo = function(data) {
    // data
}
scniro
  • 16,844
  • 8
  • 62
  • 106
  • I'm just of the opinion that it would be easier to understand/maintain if the logic is in the same place, but opinions are meant to be changed and if it would be more in line with convention, then I would rather do it differently. The idea is that if I have a list on a page (receiver), I want to be able to send the object I want to be removed to that page from the sender. Like a list of rooms in a hotel, one not being available anymore if it is booked up by someone else. The Bar action would be the Booking action and I want to notify all pages with rooms which ones aren't available anymore – Ebbs May 07 '15 at 18:47