Introduction

Yesterday I wrote a blog about SignalR and just 5 seconds after posting it I got this on twitter.

So, here I am on a Sunday morning writing about SignalR and Hubs.

Why hubs? You ask.

Hubs provide a higher level RPC framework over a PersistentConnection. If you have different types of messages that you want to send between server and client then hubs is recommended so you don’t have to do your own dispatching.

It took me a while to figure this out, but I got there in the end.

The server

Setting up the server should have been easy. But it lacked something.

So watch out if you are working with VB.Net.

First I started to create my hub.

Imports Microsoft.AspNet.SignalR.Hubs

Public Class Plants
    Inherits Hub

    Dim _plants As IList(Of Plant)

    Public Sub New()
        _plants = New List(Of Plant)
        _plants.Add(New Plant With {.Id = 1, .Genus = "Fagus", .Species = "Sylvatica", .CommonNames = {"Common Beech"}})
    End Sub

    Public Function GetPlant(id As Integer) As Plant
        Return _plants.Where(Function(x) x.Id = id).FirstOrDefault
    End Function

End Class

This hub should return a plant for the id given or nothing when the id is not found.

If you start this you should get the url to your server.

if you browse to that url and add /signalr/hubs to it you should get something like this.

/*!

*

*

*/

///

///

(function ($, window) {

///

“u

But I did not get that. I got a 404 not found page instead. Which isn’t good.

And it was caused by the routes not being registered. Which normally happens via this cs file that is in your App_Start folder (which was created by the nuget package).

.Web.Routing;
using Microsoft.AspNet.SignalR;
using Microsoft.AspNet.SignalR.Hosting.AspNet;

[assembly: PreApplicationStartMethod(typeof(SignalRTesting.RegisterHubs), "Start")]

namespace SignalRTesting
{
    public static class RegisterHubs
    {
        public static void Start()
        {
            // Register the default hubs route: ~/signalr/hubs
            RouteTable.Routes.MapHubs();            
        }
    }
}

And normally you don’t need to setup any roots in your Global.asax.

But when I did. It worked.

So add a Global.asax and change it to this.

Imports System.Web.SessionState
Imports System.Web.Routing
Imports Microsoft.AspNet.SignalR

Public Class Global_asax
    Inherits System.Web.HttpApplication

    Sub Application_Start(ByVal sender As Object, ByVal e As EventArgs)
        RouteTable.Routes.MapHubs()
    End Sub


End Class```
And now your server should return the correct page on browsing to /signalr/hubs

## The client

First thing to try is to make a console client.

Look at the code of our server and see that we return an object of type Plant.

Our Plant object looks like this BTW.

```vbnet
Public Class Plant
    Public Property Id As Integer
    Public Property Genus As String
    Public Property Species As String
    Public Property CommonNames As String()
End Class```
The return means that only the caller will get that returnvalue, not any of the other clients.

And here is such a client.

```vbnet
Imports Microsoft.AspNet.SignalR.Client.Hubs
Imports Microsoft.AspNet.SignalR.Client

Module Module1

    Sub Main()
        Dim connection = New HubConnection("http://localhost:50865")

        Dim plants = connection.CreateHubProxy("Plants")

        connection.Start().Wait()

        Dim line As String = Nothing
        Console.WriteLine("type the id + enter to send, type exit + enter to exit.")
        While line <> "exit"
            line = Console.ReadLine()
            plants.Invoke(Of Object)("GetPlant", line).ContinueWith(Sub(data)
                                                                        If data.Result IsNot Nothing Then
                                                                            Console.WriteLine(data.Result.ToString)
                                                                        Else
                                                                            Console.WriteLine("No plant with that id.")
                                                                        End If
                                                                    End Sub)
        End While
    End Sub

End Module

And if you type 1 you should get this in return.

But we could have just use ServiceStack if we needed something like that.

So what is the point?

Let’s just say that we want to inform all our clients that someone just requested a plant with id 1 than we could do this instead.

Change the server code and start it up.

Imports Microsoft.AspNet.SignalR.Hubs

Public Class Plants
    Inherits Hub

    Dim _plants As IList(Of Plant)

    Public Sub New()
        _plants = New List(Of Plant)
        _plants.Add(New Plant With {.Id = 1, .Genus = "Fagus", .Species = "Sylvatica", .CommonNames = {"Common Beech"}})
    End Sub

    Public Function GetPlant(id As Integer) As Plant
        Clients.All.addMessage("Someone requested id: " & id)
        Return _plants.Where(Function(x) x.Id = id).FirstOrDefault
    End Function

End Class

As you can see I use Clients.All.addMessage to send a message to all Clients with the id that was requested.

Change the console client to this.

Imports Microsoft.AspNet.SignalR.Client.Hubs

Module Module1

    Sub Main()
        Dim connection = New HubConnection("http://localhost:50865")

        Dim plants = connection.CreateHubProxy("Plants")

        plants.On(Of String)("addMessage", Sub(data) Console.WriteLine(data.ToString()))

        connection.Start().Wait()

        Dim line As String = Nothing
        Console.WriteLine("type the id + enter to send, type exit + enter to exit.")
        While line <> "exit"
            line = Console.ReadLine()
            plants.Invoke(Of Object)("GetPlant", line).ContinueWith(Sub(data)
                                                                        If data.Result IsNot Nothing Then
                                                                            Console.WriteLine(data.Result.ToString)
                                                                        Else
                                                                            Console.WriteLine("No plant with that id.")
                                                                        End If
                                                                    End Sub)
        End While
    End Sub

End Module

I just added the plants.On method to intercept the addMessage events.

And now when I open multiple clients I get this.

Which is cool.

Conclusion

Hubs are what you will mostly use when you use SignalR.