SignalR
This library provides a MessagePack-based Hub Protocol implementation for ASP.NET Core SignalR, offering significant performance improvements over the default JSON protocol.
Benefits
- Smaller Payloads: MessagePack produces significantly smaller payloads compared to JSON
- Faster Serialization: Binary serialization is typically faster than text-based formats
- Type Safety: Leverages MessagePack's type-safe serialization system
- NativeAOT Compatible: Works seamlessly with .NET Native AOT compilation
Installation
Install the NuGet package:
<PackageReference Include="Nerdbank.MessagePack.SignalR" Version="x.x.x" />
Add a call to AddMessagePackProtocol to your builder class, as demonstrated in the configuration samples below.
Configuration
SignalR being an RPC system requires a provider for type shapes for all parameter and return types used in your RPC methods. This can be ReflectionTypeShapeProvider.Default or (preferably) via the PolyType source generator using a witness class
The sample configurations below will be using the witness class approach.
[GenerateShapeFor<bool>] // add as many attributes as necessary for each RPC parameter and return type.
partial class Witness;
Server Configuration
Add the MessagePack protocol to your SignalR hub:
var builder = WebApplication.CreateBuilder(args);
// Add SignalR with MessagePack protocol
builder.Services.AddSignalR()
.AddMessagePackProtocol(Witness.ShapeProvider);
var app = builder.Build();
// Configure hub endpoint
app.MapHub<ChatHub>("/chatHub");
Custom Serializer Configuration
You can provide a custom MessagePack serializer with specific configuration:
var customSerializer = new MessagePackSerializer
{
// Your custom configuration
};
builder.Services.AddSignalR()
.AddMessagePackProtocol(Witness.ShapeProvider, customSerializer);
Client Configuration
For .NET SignalR clients, add the MessagePack protocol to your connection:
var connection = new HubConnectionBuilder()
.WithUrl("https://example.com/chatHub")
.AddMessagePackProtocol(Witness.ShapeProvider)
.Build();
await connection.StartAsync();
Client with Custom Serializer
var serializer = new MessagePackSerializer
{
// custom configuration
};
var connection = new HubConnectionBuilder()
.WithUrl("https://example.com/chatHub")
.AddMessagePackProtocol(Witness.ShapeProvider, serializer)
.Build();
Supported Message Types
The MessagePack Hub Protocol supports all SignalR message types:
InvocationMessage
: Method calls from client to serverStreamInvocationMessage
: Streaming method callsCompletionMessage
: Method call completionsStreamItemMessage
: Individual stream itemsCancelInvocationMessage
: Stream cancellationsPingMessage
: Keep-alive pingsCloseMessage
: Connection close notificationsAckMessage
: AcknowledgementsSequenceMessage
: Sequence messages
Hub Implementation
Your SignalR hubs work exactly the same way with the MessagePack protocol:
public class ChatHub : Hub
{
public async Task SendMessage(string user, string message)
{
await this.Clients.All.SendAsync("ReceiveMessage", user, message);
}
public async IAsyncEnumerable<string> StreamData(
[EnumeratorCancellation] CancellationToken cancellationToken)
{
for (int i = 0; i < 10; i++)
{
yield return $"Data {i}";
await Task.Delay(1000, cancellationToken);
}
}
}
Performance Considerations
The MessagePack protocol generally provides better performance characteristics:
- Bandwidth: 20-50% smaller payload sizes compared to JSON
- CPU: Faster serialization/deserialization, especially for complex objects
- Memory: Lower memory allocation during serialization
Consider using MessagePack when:
- You have high-frequency message exchanges
- Your messages contain complex data structures
- Bandwidth is a concern (mobile applications, metered connections)
- You need maximum performance
Compatibility
The MessagePack Hub Protocol is compatible with:
- ASP.NET Core 8.0 and later
- .NET SignalR clients
- NativeAOT compilation
- All standard SignalR features (groups, user connections, etc.)
While SignalR comes with its own MessagePack implementation, it does so by relying on the MessagePack-CSharp library, which is harder to use and not NativeAOT safe. Nerdbank.MessagePack.SignalR provides a comparably high performance, easier to use and NativeAOT-safe alternative. It is compatible with other MessagePack implementations that follow the same protocol as prescribed by SignalR in their spec.
Migration from JSON Protocol
Migration is straightforward and requires minimal code changes:
- Install the
Nerdbank.MessagePack.SignalR
package - Add .AddMessagePackProtocol to your SignalR registration
- Update clients to use the MessagePack protocol
- No changes needed to your Hub methods or client method calls
Both server and clients must use the same protocol for communication.