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

2023-01-08 Updated Angular 15, .NET 7
2021-01-25 Updated Angular 11.1.0 .NET 5, ngrx implementation
2020-03-21 updated packages, fixed Admin UI STS
2019-08-18 Updated ASP.NET Core 3.0, Angular 8.2.2
2019-02-06 Updated Angular 7.2.4, latest NGRX, SignalR CORS fix
2018-12-12 Updated .NET Core 2.2, ASP.NET Core SignalR 1.1.0, Angular 7.1.3
2018-05-31 Updated Microsoft.AspNetCore.SignalR 2.1
2018-05-08 Updated Microsoft.AspNetCore.SignalR 2.1 rc1, Angular 6
2018-03-15 Updated signalr Microsoft.AspNetCore.SignalR 1.0.0-preview1-final, Angular 5.2.8, @aspnet/signalr 1.0.0-preview1-update1

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.

<PackageReference 
	Include="Microsoft.AspNetCore.SignalR" 
	Version="1.1.0" />
<PackageReference 
	Include="Microsoft.AspNetCore.SignalR.Protocols.MessagePack" 
	Version="7.0.1" />

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

using Microsoft.AspNetCore.SignalR;

namespace AspNetCoreAngularSignalR.SignalRHubs;

public class LoopyHub : Hub
{
    public Task Send(string 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.

namespace Dtos;

public class MessageDto
{
    public Guid Id { get; set; }

    public string Name { get; set; } = string.Empty;

    public int Amount { get; set; }
}

Then add the Message Pack protocol to the SignalR service.

services.AddSignalR().AddMessagePackProtocol();

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

app.MapHub<LoopyHub>("/loopy");
app.MapHub<NewsHub>("/looney");
app.MapHub<LoopyMessageHub>("/loopymessage");
app.MapHub<ImagesMessageHub>("/zub");

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.

<PackageReference 
	Include="Microsoft.AspNetCore.SignalR.Client" 
	Version="7.0.1" />
<PackageReference 
	Include="Microsoft.AspNetCore.SignalR.Protocols.MessagePack" 
	Version="7.0.1" />

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

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.

static async Task MainAsync()
{
	await SetupSignalRHubAsync();
	if(_hubConnection != null )
	{
		_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();
				if (message != null)
				{
					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);
	}
}

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/

7 comments

  1. […] Using Message Pack with ASP.NET Core SignalR | Software Engineering – Damien Bowden […]

  2. The big question remains, would you want to do this? How much longer does it take (with all the extra js needed) for the hub connection to be established? Is is faster than using json payloads? Can it compete with gzip content from controller methods? At least this is what I’d like to know 🙂

    1. Hi mortenmertner, yes correct, but depending on your payload, the message pack serializer payload is smaller, and faster so it makes sense for example with a backend service to service communication

      Greetings Damien

      1. Maybe. It only makes sense if it’s actually faster. Given that browsers deserialize JSON natively it is not a given that a binary format (which is decoded by JS) is faster. The only given is that it takes up fewer bytes on the wire. Performance benchmarks for large and small payloads are needed.

      2. yes, you are correct when the client is a browser app, but in this example, the client is a console application, or could be a second backend service, and then it would be faster.

        Greetings Damien

  3. Wael Emara · · Reply

    What is the message delivery reliability here, and how this compares against Akka.NET.

  4. […] Using message pack with ASP.NET Core SignalR […]

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.