A first look into ASP.Net Core SignalR

I have not used the "old" SignalR, so this is actually my first time looking into SignalR. For the last year I have been using ASP.Net Core to setup quite a few APIs, so I feel I know that workflow now. With that in mind I am going to start looking into SignalR. My first look at I started with testing out davidfowl/SignalRCoreAlphaSample.

The first thing a started to do was to create an ASP.Net Core Razor application from the command line. dotnet new razor. Then I added the SignalR NuGet feed to the NuGet.config[1]. Adding a .npmrc file to the project root and adding the SignalR NPM feed[2] to be able to get the javascript client. In the project file I added the SignalR package Microsoft.AspNetCore.SignalR. Now I was ready to start setting up a basic test application to get a little feeling with SignalR.

First thing I added was creating a Chat hub. That was just a class inheriting from the class Hub.

public class Chat : Hub
    public override Task OnConnectedAsync()
        return Clients.All.InvokeAsync("Send", $"{Context.ConnectionId} joined");

    public override Task OnDisconnectedAsync(Exception exception)
        return Clients.All.InvokeAsync("Send", $"{Context.ConnectionId} left");

    public Task Send(string message)
        return Clients.All.InvokeAsync("Send", message);

In the ConfigureServices method I was adding services.AddSignalR(). There are an option of using AddSignalRCore() as well. I was a bit curios what the differences are between them so I looked into the source code at Github.

public static ISignalRBuilder AddSignalR(this IServiceCollection services, Action<HubOptions> configure)
    return services.AddSignalRCore();

public static ISignalRBuilder AddSignalRCore(this IServiceCollection services)
    services.AddSingleton(typeof(HubLifetimeManager<>), typeof(DefaultHubLifetimeManager<>));
    services.AddSingleton(typeof(IHubProtocolResolver), typeof(DefaultHubProtocolResolver));
    services.AddSingleton(typeof(IHubContext<>), typeof(HubContext<>));
    services.AddSingleton(typeof(HubEndPoint<>), typeof(HubEndPoint<>));
    services.AddScoped(typeof(IHubActivator<>), typeof(DefaultHubActivator<>));


    return new SignalRBuilder(services);

The AddSockets() adds the AddRouting, AddAuthorizationPolicyEvaluator() and try to add the HttpConnectionDispatcher.

The last piece to get a minimal test application was to include the javascript client to the Index.cshtml, a little javascript snippet and a form.

<div class="row">
    <div class="col">
        <form id="chat">
            <div class="form-group">
                <label for="message">Message</label>
                <input type="text" class="form-control" id="message" aria-describedby="emailHelp" placeholder="Enter email">
            <button type="submit" class="btn btn-primary" value="Send">Send</button>
    <div class="col">
        <ul id="messages"></ul>

<script src="~/js/signalr-client.min.js"></script>
    document.addEventListener('DOMContentLoaded', function () {
        let http = new signalR.HttpConnection(document.location.protocol + '//' + document.location.host + '/chat');
        let connection = new signalR.HubConnection(http);
        connection.on('send', data => {
            let child = document.createElement('li');
            child.innerText = data;
        document.getElementById('chat').addEventListener('submit', event => {
            let data = document.getElementById('message').value;
            connection.invoke('send', data);

Now I was ready to test the application and see if it worked. Since I like to use the command line I typed dotnet run and the site started. Opening the url in the browser and I had my little Chat application. The code for my signalr test application is available at Github.

  1. https://www.myget.org/F/signalr-alpha/api/v3/index.json ↩︎

  2. @aspnet:registry=https://www.myget.org/f/signalr-alpha/npm/ ↩︎

Teis Lindemark

Software developer, beer brewer and AGENT backer

Bergen, Norway https://teilin.net

Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer’s view in any way.