Using Message Pack with ASP.NET Core SignalR

This post shows how SignalR could be used to send messages between different C# console clients using Message Pack as the protocol. An ASP.NET Core web application is used to host the SignalR Hub.

Code: https://github.com/damienbod/AspNetCoreAngularSignalR

Posts in this series

History

2018-05-31 Updated Microsoft.AspNetCore.SignalR 2.1

2018-05-08 Updated Microsoft.AspNetCore.SignalR 2.1 rc1

Setting up the Message Pack SignalR server

Add the Microsoft.AspNetCore.SignalR and the Microsoft.AspNetCore.SignalR.MsgPack NuGet packages to the ASP.NET Core server application where the SignalR Hub will be hosted. The Visual Studio NuGet Package Manager can be used for this.

Or just add it directly to the .csproj project file.

1
2
3
4
5
6
<PackageReference
  Include="Microsoft.AspNetCore.SignalR"
  Version="1.0.0-rc1-final" />
<PackageReference
  Include="Microsoft.AspNetCore.SignalR.Protocols.MessagePack"
  Version="1.0.0-rc1-final" />

Setup a SignalR Hub as required. This is done by implementing the Hub class.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
using Dtos;
using Microsoft.AspNetCore.SignalR;
using System.Threading.Tasks;
 
namespace AspNetCoreAngularSignalR.SignalRHubs
{
    // Send messages using Message Pack binary formatter
    public class LoopyMessageHub : Hub
    {
        public Task Send(MessageDto data)
        {
            return Clients.All.SendAsync("Send", data);
        }
    }
}

A DTO class is created to send the Message Pack messages. Notice that the class is a plain C# class with no Message Pack attributes, or properties.

1
2
3
4
5
6
7
8
9
10
11
12
13
using System;
 
namespace Dtos
{
    public class MessageDto
    {
        public Guid Id { get; set; }
 
        public string Name { get; set; }
 
        public int Amount { get; set; }
    }
}

Then add the Message Pack protocol to the SignalR service.

1
2
services.AddSignalR()
.AddMessagePackProtocol();

And configure the SignalR Hub in the Startup class Configure method of the ASP.NET Core server application.

1
2
3
4
app.UseSignalR(routes =>
{
    routes.MapHub<LoopyMessageHub>("/loopymessage");
});

Setting up the Message Pack SignalR client

Add the Microsoft.AspNetCore.SignalR.Client and the Microsoft.AspNetCore.SignalR.Client.MsgPack NuGet packages to the SignalR client console application.

The packages are added to the project file.

1
2
3
4
5
6
<PackageReference
  Include="Microsoft.AspNetCore.SignalR.Client"
  Version="1.0.0" />
<PackageReference
  Include="Microsoft.AspNetCore.SignalR.Protocols.MessagePack"
  Version="1.0.0" />

Create a Hub client connection using the Message Pack Protocol. The Url must match the URL configuration on the server.

1
2
3
4
5
6
7
8
9
10
11
12
13
public static async Task SetupSignalRHubAsync()
{
    _hubConnection = new HubConnectionBuilder()
         .WithUrl("https://localhost:44324/loopymessage")
         .AddMessagePackProtocol()
         .ConfigureLogging(factory =>
         {
             factory.AddConsole();
             factory.AddFilter("Console", level => level >= LogLevel.Trace);
         }).Build();
 
     await _hubConnection.StartAsync();
}

The Hub can then be used to send or receive SignalR messages using the Message Pack as the binary serializer.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
using Dtos;
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.SignalR.Client;
using Microsoft.Extensions.Logging;
using Microsoft.AspNetCore.SignalR.Protocol;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
 
namespace ConsoleSignalRMessagePack
{
    class Program
    {
        private static HubConnection _hubConnection;
 
        public static void Main(string[] args) => MainAsync().GetAwaiter().GetResult();
 
        static async Task MainAsync()
        {
            await SetupSignalRHubAsync();
            _hubConnection.On<MessageDto>("Send", (message) =>
            {
                Console.WriteLine($"Received Message: {message.Name}");
            });
            Console.WriteLine("Connected to Hub");
            Console.WriteLine("Press ESC to stop");
            do
            {
                while (!Console.KeyAvailable)
                {
                    var message = Console.ReadLine();
                    await _hubConnection.SendAsync("Send", new MessageDto() { Id = Guid.NewGuid(), Name = message, Amount = 7 });
                    Console.WriteLine("SendAsync to Hub");
                }
            }
            while (Console.ReadKey(true).Key != ConsoleKey.Escape);
 
            await _hubConnection.DisposeAsync();
        }
 
        public static async Task SetupSignalRHubAsync()
        {
            _hubConnection = new HubConnectionBuilder()
                 .WithUrl("https://localhost:44324/loopymessage")
                 .AddMessagePackProtocol()
                 .ConfigureLogging(factory =>
                 {
                     factory.AddConsole();
                     factory.AddFilter("Console", level => level >= LogLevel.Trace);
                 }).Build();
 
             await _hubConnection.StartAsync();
        }
    }
}

Testing

Start the server application, and 2 console applications. Then you can send and receive SignalR messages, which use Message Pack as the protocol.


Links:

https://msgpack.org/

https://github.com/aspnet/SignalR

https://github.com/aspnet/SignalR#readme

https://radu-matei.com/blog/signalr-core/

Add comment