NServiceBus takes instances of .NET objects (messages, events, and commands) and sends/receives them over a specified transport. As part of this process, the object must be serialized and deserialized. NServiceBus achieves this using serializers.
It's possible to transition to another serialization format while still remaining compatible with messages in-flight that used the previous serialization format. This is accomplished by adding the previous serialization format as an additional deserializer, which is supported in NServiceBus versions 6 and above. This way, messages serialized before the transition (including saga timeouts and delayed messages) can still be understood while new messages use the new serializer.
The System.Text.Json serializer provides an effective general-purpose serializer appropriate for most use cases based on the JSON serialization built into .NET. JSON provides a good combination of compactness, human readability, and performance.
Other serializers are supported in order to enable specific performance or integration requirements.
Supported serializers
Configuring a serializer
A serializer must be configured using the endpointConfiguration.
API. Refer to the dedicated documentation pages for each available serializer for more information about the specific configuration.
The same serializer must be used by the sending endpoint to serialize messages and by the receiving endpoint to deserialize them, unless additional deserializers are specified.
Using a custom serializer
Besides the officially supported and community maintained serializers, it is also possible to implement and register a custom serializer.
Specifying additional deserializers
To support sending and receiving messages between endpoints using different serializers, additional deserialization capability may be specified. It is possible to register additional deserializers to process incoming messages. Additionally, if a deserializer requires custom settings, they can be provided during its registration.
// Configures new default serialization
var mySerializer = endpointConfiguration.UseSerialization<MyCustomSerializerDefinition>();
mySerializer.Settings("serializerSetting");
// Configures additional deserializer, like the previous (default) serializer to be compatible with in-flight messages.
endpointConfiguration.AddDeserializer<XmlSerializer>();
When using multiple deserializers make sure that there's only one type registered per given ContentType
.
Immutable message types
It is possible to use immutable types as messages. NServiceBus does not restrict this; It depends on the chosen serializer implementation if it supports deserializing to non public properties and/or using non-default constructors to initialize types.
When messages are in serialized form "on the wire" it makes no difference if mutable or immutable message types are used.
The System.Text.Json serializer and Newtonsoft JSON Serializer by default support immutable messages types.
Security
The deserialization target type is defined by the incoming message. Although NServiceBus only deserializes message payloads that are considered a valid message type, side effects in constructor methods or property setters of message contracts may be abused by an attacker with access to the transport infrastructure.
To avoid unintended behavior during message deserialization, avoid executing code with side effects as part of constructors and property setters of message types.
Dynamic type loading
Incoming messages might refer to a message type that has not yet been loaded by the endpoint. In these cases, the endpoint will automatically try to load the specified message type at runtime. This behavior can be disabled:
var serializerSettings = endpointConfiguration.UseSerialization<XmlSerializer>();
serializerSettings.DisableDynamicTypeLoading();
When disabling dynamic type loading, all expected message types must be detected at endpoint startup time via assembly scanning.
Message type inference
When an incoming message does not provide message type information via the NServiceBus.
header, the serializer can attempt to determine the message type based on the message's content (e.g., using Json.NET's TypeNameHandling
setting). The exact capabilities and behavior depends heavily on the specific serializer being used but might introduce unintended security vulnerabilities. The endpoint can be configured to fail message processing immediately when the NServiceBus.
header does not contain a valid message type without passing the message content to the serializer:
var serializerSettings = endpointConfiguration.UseSerialization<XmlSerializer>();
serializerSettings.DisableMessageTypeInference();