The message pipeline in NServiceBus 2.X pretty much consisted of what we called message modules.
They served their purpose but didn’t quite give you the full control over the message pipeline needed to do more advanced things. Another major shortcoming was that there was no way to hook into the pipeline at the sending/client side of the message conversation.
When introducing the DataBus feature of NServiceBus 3.0 we came up with the notion of message mutators to solve a specific requirement to change the content of a message before and after sending it on the wire.
The message mutators turned out to be a nice addition to our pipeline both in terms of their ability to change message content but also to serve as more fine grained hooks into the pipeline.
Lets take a look at how to use them!
The 2 Flavors of Mutators
NServiceBus enables 2 types of message mutators:
Applicative Messages Mutators
Message mutators is used to change/react to individual messages being send or received.
The IMessageMutator interface lets you implement hooks for both the sending side and the receiving side.
If you only need one or the other you can implement one of the more fine grained IMutateOutgoingMessages or IMutateIncomingMessages.
Reacting to individual messages can be used to perform things like validation of outgoing/incoming messages. Have a look at the Message Mutators Sample to see it in action.
NServiceBus uses this type of mutator internally to do things like property encryption and serialization/de serialization of properties to and from the DataBus.
Transport Messages Mutators
Transport message mutators, are created by implementing the IMutateTransportMessages interface.
This type of mutator works on the entire transport message and is useful for things like compression, header manipulation etc.
A full explanation of the syntax used can be found here.
Remember that message mutators are NOT automatically registered in the container so in order for them to be invoked you need to register them in the container your self.
When should I use a message mutator?
Just like the recommendation for headers, message mutators should only be used for infrastructure purposes.
So as a rule of thumb only consider using message mutators so solve technical requirements.
What happens if a mutator throws an exception?
If a server side (incoming) mutator throws an exception the message will be aborted, rolled back to the queue and retried.
If a client side (outgoing) message mutator throws an exception, the exception will bubble up to the method calling bus.Send or bus.Publish.