2
votes

I have an n-tier application, which has a WCF service exposing all my business logic, hosted as a windows service, with a MVC application as the client, consuming the services.

Most of the examples out there shows SignalR within the MVC application. I have tried extracting the Hub out into a separate DLL like this:

Hub.dll

public class Chat : Hub
{

    public void Send(string message)
    {
        Clients.All.addMessage(message);
    }
}

and trying to call the Send() from my MVC cshtml, even after adding Hub.dll as a reference, doesn't work.

This is the javascript in my cshtml file:

<script type="text/javascript">
    $(function() {
        // Proxy created on the fly          
        var chat = $.connection.chat;

        // Declare a function on the chat hub so the server can invoke it          
        chat.client.addMessage = function(message) {
            $('#messages').append('<li>' + message + '</li>');
        };

        // Start the connection
        $.connection.hub.start().done(function() {
            $("#broadcast").click(function() {
                // Call the chat method on the server
                chat.server.send($('#msg').val());
            });
        });
    });
</script>

While the code above is a very basic example, an example of what I would like to accomplish would be similar to those SignalR progress bar tutorials out there, except the progress reporting will be done by my business layer.

To further elaborate, I would like to do something like this:

1) MVC client calls PerformLongRunningTaskA() through the hosted WCF service.

2) WCF service invokes method in business layer

3) Business layer starts PerformLongRunningTaskA()

4) Business layer reports progress back to MVC client 10%..20%..etc till 100% (using SignalR?)

This how my project structure is roughly like: presentation - MVC app service layer - WCF service (hosted on windows service) business layer - all my business logic data layer - Entityframework

EDIT:

The above now works. It was some javascript error on my part.

I have created another console app, to simulate my business DLL to trigger off signalr to broadcast an event like this:

class Program
{
    static void Main(string[] args)
    {
      Say("HEY");
    }
    public static void Say(string message)
    {
        var context = GlobalHost.ConnectionManager.GetHubContext<Chat>();
        context.Clients.All.say(message);
    }
}

I have added Hub.dll as a reference to my console project, but the above now doesn't work. No error messages, nothing. it just runs normally, but my MVC app doesn't display the message.

1
Can you explain how it "doesn't work" in greater detail? Does calling $.connection.hub.start() or chat.server.send($('#msg').val()) fail? Are any requests from the client receiving non-200 response statuses?halter73
You can't just add a reference to the dll that has the hubs in it and expect it to work. SignalR clients are connected to the server where SignalR is running. You can't broadcast from outside that server.davidfowl

1 Answers

5
votes

If you pretend to broadcast messages you need to be in the "Service context", what I mean by that is that you have to have access to the hosted Hub context.

If you need to broadcast from a Console app, you can create methods in your Hub that allow you to do so, and make your console application a client of the main SignalR server. Details on how to create a .net console SignalR client: SignalR Client Hubs

If you need to have the "hosted context" in the console app, then try SelfHost SignalR SelfHost

Cheers,