Skip to content

Server Hub Implementation ​

SignalRGen currently doesn't generate any Hubs automatically, but nevertheless it helps you with implementing a type-safe SignalR Hub.

Interface to Server ​

Starting with an Interface ​

Here's a typical SignalR interface definition:

csharp
using SignalRGen.Abstractions;
using SignalRGen.Abstractions.Attributes;

namespace SignalRGen.Example.Contracts;

[HubClient(HubUri = "chat")]
public interface IChatHubContract : IBidirectionalHub<IChatHubServerToClient, IChatHubClientToServer>
{
}

public interface IChatHubServerToClient
{
    Task UserJoined(string user);
    Task UserLeft(string user);
    Task MessageReceived(string user, string message);
}

public interface IChatHubClientToServer
{
    Task SendMessage(string message);
}

Writing the Hub ​

With this interface, we can implement our Hub with type-safety. In our server project we will create a new class representing our Hub:

csharp
using Microsoft.AspNetCore.SignalR;
using SignalRGen.Example.Contracts;

namespace SignalRGen.Example.Server.Api.Hubs;

// This is our Hub on the server side.
// We use the two interfaces we defined above to also make the server side typesafe.
public class ChatHub : Hub<IChatHubServerToClient>, IChatHubClientToServer
{
    // We use the `OnConnectedAsync` method to notify the other clients that a new user joined.
    public override async Task OnConnectedAsync()
    {
        // The `UserJoined` is available as a method because we use the `IChatHubServerToClient` interface
        // in `Hub<IChatHubServerToClient>`
        await Clients.Others.UserJoined(Context.UserIdentifier ?? "Anonymous");
        await base.OnConnectedAsync();
    }

    // This method must be implemented here, as we implement the interface `IChatHubClientToServer`
    public Task SendMessage(string message)
    {
        var user = Context.UserIdentifier ?? "Anonymous";
        return Clients.Others.MessageReceived(user, message);
    }

    // We use the `OnDisconnectedAsync` method to notify the other clients that a user left.
    public override async Task OnDisconnectedAsync(Exception? exception)
    {
        // The `UserLeft` is available as a method because we use the `IChatHubServerToClient` interface
        // in `Hub<IChatHubServerToClient>`
        await Clients.Others.UserLeft(Context.UserIdentifier ?? "Anonymous");
        await base.OnDisconnectedAsync(exception);
    }
}

Wiring up the Hub ​

We have to tell our server project to listen on the proper URI and route to our Hub. For this we have to map it in the Program.cs:

csharp
// To wire up our ChatHub, we have to map it here.
// We use the `HubUri` from the generated client.
// This ensures that both client and server will use the same route.
app.MapHub<ChatHub>($"{ChatHubContractClient.HubUri}");

For this step we can use the generated HubClient to have a refactor save URI.