Appearance
RPC Serialization Formats
ActualLab.Rpc supports multiple serialization formats with automatic version negotiation between clients and servers. This enables gradual upgrades and interoperability between different Fusion versions.
Overview
RPC serialization has two layers:
- Argument serialization: How method arguments are encoded
- Message serialization: How RPC messages (containing arguments) are framed
Each combination of these is packaged as an RpcSerializationFormat.
Available Formats
Text Formats (JSON)
| Format | Key | Description |
|---|---|---|
SystemJsonV5 | json5 | System.Text.Json with V4 arguments, V3 messages |
NewtonsoftJsonV5 | njson5 | Newtonsoft.Json with V4 arguments, V3 messages |
Binary Formats (MemoryPack)
| Format | Key | Description |
|---|---|---|
MemoryPackV5 | mempack5 | V4 args, V4 messages |
MemoryPackV5C | mempack5c | Compact variant of V5 |
MemoryPackV6 | mempack5 | V4 args, V5 messages |
MemoryPackV6C | mempack5c | Compact variant of V5 |
Binary Formats (MessagePack)
| Format | Key | Description |
|---|---|---|
MessagePackV5 | msgpack5 | V4 args, V4 messages |
MessagePackV5C | msgpack5c | Compact variant of V5 |
MessagePackV6 | msgpack5 | V4 args, V5 messages |
MessagePackV6C | msgpack5c | Compact variant of V5 |
Binary Formats (Nerdbank.MessagePack)
These formats require the ActualLab.Serialization.NerdbankMessagePack package. They are not registered by default — call RpcNerdbankSerializationFormat.Register() at startup to enable them.
| Format | Key | Description |
|---|---|---|
NerdbankMessagePackV6 | nmsgpack6 | Nerdbank.MessagePack, V4 args, V5 messages |
NerdbankMessagePackV6C | nmsgpack6c | Compact variant of V6 |
Format Selection
Default Format
The default format is typically MemoryPackV5C (or latest version) for .NET 6+ and MessagePackV5C for .NET Standard.
Client-Server Negotiation
When a client connects, it requests its preferred serialization format via a URL parameter (e.g., <endpoint>?f=msgpack6&clientId=...). The server accepts the connection if it supports that format. Once connected, both parties simultaneously exchange RpcHandshake messages:
Accessing All Formats
cs
// All registered formats
ImmutableList<RpcSerializationFormat> all = RpcSerializationFormat.All;
// Find by key
var format = RpcSerializationFormat.All.First(f => f.Key == "mempack6c");Format Structure
Each RpcSerializationFormat consists of:
cs
public sealed class RpcSerializationFormatExample(
string key,
Func<RpcArgumentSerializer> argumentSerializerFactory,
Func<RpcPeer, RpcMessageSerializer> messageSerializerFactory)
{
public string Key { get; } = key;
public RpcArgumentSerializer ArgumentSerializer { get; } = argumentSerializerFactory();
public Func<RpcPeer, RpcMessageSerializer> MessageSerializerFactory { get; } = messageSerializerFactory;
}| Property | Description |
|---|---|
Key | Unique string identifier for negotiation |
ArgumentSerializer | Serializes method arguments |
MessageSerializerFactory | Creates message serializers per peer |
Version Differences
Argument Serializer Versions
| Version | Description |
|---|---|
| V4 | Latest, best performance |
Message Serializer Versions
| Version | Variants | Description |
|---|---|---|
| V4 | Normal, Compact | Was optimal up to Fusion v11.5.X |
| V5 | Normal, Compact | Saves 1 byte per message over V4 |
Compact vs Normal
Compact variants (*C suffix) use smaller message framing at a slight CPU cost. Choose compact for:
- Lower bandwidth scenarios
- When message overhead is significant relative to payload
Configuring Formats
Enabling Nerdbank.MessagePack Formats
Add the ActualLab.Serialization.NerdbankMessagePack package and call Register() at startup:
cs
// Register nmsgpack6 / nmsgpack6c formats
RpcNerdbankSerializationFormat.Register();Registering Additional Formats
cs
RpcSerializationFormat.All = RpcSerializationFormat.All.Add(
new RpcSerializationFormat(
"custom",
() => new MyArgumentSerializer(),
peer => new MyMessageSerializer(peer)));Removing Formats
To disable older formats for security:
cs
// To disable older formats for security:
RpcSerializationFormat.All = RpcSerializationFormat.All
.RemoveAll(f => f.Key.StartsWith("mempack5") || f.Key.StartsWith("msgpack5"));Format Selection Factors
When choosing formats, consider:
| Factor | Recommendation |
|---|---|
| Performance | Binary formats (MemoryPack > MessagePack > JSON) |
| Debugging | JSON formats (human-readable) |
| Compatibility | MessagePack for .NET Standard clients |
| Bandwidth | Compact variants (*C) |
| Security | Latest versions, disable V1 |
Serialization in RPC Pipeline
- Client serializes method arguments using
ArgumentSerializer - Arguments are wrapped in an
RpcMessageand serialized byMessageSerializer - Binary data is sent over WebSocket
- Server deserializes in reverse order
Related Topics
- Core Serialization - General serialization infrastructure
- RPC Key Concepts - RPC architecture overview
- Configuration Options - RPC configuration
