Skip to content
davidfowl edited this page Nov 8, 2011 · 49 revisions

Hubs (Server)

Hubs provide a higher level MVC style 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.

To get started using Hubs, create a class that derives from Hub.

public class MyHub : Hub 
{
}

Unlike low level PersistentConnections, there's no need to specify a route for the hub as they are automatically accessible over a special url (/signalr/hubs).

Client Calling the server

To expose methods on the hub that you want to be callable from the client. Simply declare a public method:

public class MyHub : Hub
{
     public string Send(string data)
     {
         return data;
     }
}

This makes the Send method callable from any SignalR client.

SignalR will handle the binding of complex objects and arrays of objects automatically.

public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
}

public class MyHub : Hub
{
     public string ExtractName(Person person)
     {
         return person.Name;
     }
}

Server calling the client

To call client event/methods from the server use the Clients property.

public class MyHub : Hub
{
     public void Send(string data)
     {
         Clients.addMessage(data);
     }
}

The above code will invoke the addMessage method on the client with specified data.

NOTE: Parameters passed to the method will be JSON serialized before being sent to the client

Calling methods on specific clients or groups

Invoking methods on the the Clients property will broadcast that message to all connected clients. But there are some cases where we want to send a message to specific clients or groups. We can use the indexer on the Clients object to specify a group name or a client id. You can also use the Caller property on the Hub to invoke methods on the calling client.

public class MyHub : Hub
{
     public void Send(string data)
     {
         // Invoke a method on the calling client
         Caller.addMessage(data);

         // Similar to above, the more verbose way
         Clients[Context.ClientId].addMessage(data);

         // Invoke addMessage on all clients in group foo
         Clients["foo"].addMessage(data);
     }
}

NOTE: Even it the group does not exist, the indexer will never be null.

How it works

Under the covers the Clients/Caller property is a dynamic object that wraps an IConnection. Method calls on that object call Broadcast with method invocation data that the clients interprets.

Return types

  • Anything you return from the hub will be serialized into JSON and sent to the client.
  • You may also return Task/Task<T> from a hub if you need to do async work.

Example

public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
}

public class MyHub : Hub
{
     public Person Send(string data)
     {
         // This will be serialized into JSON
         return new Person { Name = "John Doe", Age = 40 };
     }
     
     public Task<int> AsyncWork() {
         return Task.Factory.StartNew(() => 
         {
             // Don't do this in the real world
             Thread.Sleep(500);
             return 10;
         });
     }
}

Round-tripping state between client and server

  • Any state sent from the client can be accessed via the Caller property.
  • You can also set client side state just by setting any property on Caller.

Example

public class MyHub : Hub
{
     public void Send(string data)
     {
         // Access the id property set from the client.
         string id = Caller.id;

         // Set a property on the client state
         Caller.name = "SignalR";
     }
}

Detecting disconnected clients in Hubs

Unlike PersistentConnections, Hubs don't have a Disconnect event. To detect disconnect when using hubs, implement the IDisconnect interface:

public class MyHub : Hub, IDisconnect
{
    public void Disconnect()
    {
        // Query the database to find the user by it's client id.
        var user = db.Users.Where(u => u.ClientId == Context.ClientId);
        Clients.disconnected(user.Name);
    }
}

Whenever a client disconnects, the Disconnect method will be invoked on all hubs that implement IDisconnect. When this method is called you can use Context.ClientId to access the client that disconnected.

NOTE: This method is called from the server, that means state on the Caller object, as well as the HubContext's User and Cookies will not be populated.

Hub API

NOTE: Hubs are per call, that is, each call from the client to the hub will create a new hub instance. So don't setup static event handlers in hub methods.

HubContext Context

  • Gets the HubContext for this hub request.

dynamic Hub.Caller

  • Gets the dynamic object that represents the calling client (i.e the client that invoked the hub method).

dynamic Clients

  • Gets the dynamic object that represents all connected clients.

IGroupManager GroupManager

  • Gets the group manager for this Hub.

Task AddToGroup(string groupName)

Add the calling client to the specified group.

  • groupName - name of the group to add the client to

Example

public class MyHub : Hub
{
     public void JoinRoom(string room)
     {
         AddToGroup(room);
     }
}

Task RemoveFromGroup(string groupName)

Remove the calling client to the specified group.

  • groupName - name of the group to remove the client from

Example

public class MyHub : Hub
{
     public void LeaveRoom(string room)
     {
         RemoveFromGroup(room);
     }
}

HubContext API

Encapsulates all Connection-specific information about an individual Hub request.

string ClientId

  • Gets client id of the client that invoked the hub.

HttpCookieCollection Cookies

  • Gets the cookies that were part of the initial http request.

IPrincipal User

  • Gets the user that was part of the initial http request.

Broadcasting over a Hub from outside of a Hub

Sometimes you have some arbitrary code in an application that you want to be able to notify all clients connected when some event occurs. An example of this might be a background task that sends data at a certain interval.

In these scenarios, you can get a the clients property for a Hub by calling Hub.GetClients<T>

dynamic clients = Hub.GetConnection<MyHub>();

Once you have the clients property, you can call methods like you would if you were inside the hub.

You can also get access to the group manager for the hub by casting to an IGroupManager:

var groupManager = clients as IGroupManager;

NOTE: This API is far from complete and is subject to change.

Clone this wiki locally