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!

2 Flavours of mutators

We have 2 types of message mutators, one that operates on the applicative messages and another one that operates on the physical transport messages. 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. A sample of this using data annotations to validate messages can be found in the MessageMutator sample included in the NServiceBus download. We use this type of mutator internally to do things like property encryption and serialization/de serialization of properties to and from the DataBus. The other type of mutator, Transport message mutators, are created by implementing the IMutateTransportMessages interface. As mentioned earlier 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 a exception the message will be aborted, rolled back to the queue and retried. If a client side (outgoing) message mutator throws the exception will bubble up to the method calling bus.Send|Publish.

In closing

Hopefully this helped you understand what the message mutators are and how you can use the to bend the NServiceBus pipeline to your will.