Getting Started

Change/Move Message Type

Component: NServiceBus
NuGet Package: NServiceBus (8.x)

This sample illustrates an approach for changing a message type. This includes any one, or multiple, of the following scenarios:

  • Moving a message type between assemblies.
  • Renaming a message type.
  • Renaming the assembly containing the message type.
  • Adding, removing or changing the strong name of the assembly containing the message type
This sample uses 2 "Phase" Endpoint Projects to illustrate the iterations of a single endpoint in one solution.


This sample shows moving a message using multiple of the above mentioned scenarios.

Phase 1

In the Phase 1 endpoint the message type is:

  • Named CreateOrderPhase1.
  • Exists in an assembly named SamplePhase1.
  • Exists in an assembly that is not strong named.

Phase 2

In the Phase 2 endpoint the message type is:

  • Named CreateOrderPhase2.
  • Exists in an assembly named SamplePhase2.
  • Exists in an assembly that is strong named.


This change is achieved via the use of a IMutateIncomingTransportMessages.

The mutator is registered at endpoint startup:

endpointConfiguration.RegisterMessageMutator(new MessageIdentityMutator());

The mutator then replaces the NServiceBus.EnclosedMessageTypes header via the use of Type.GetType(typeName, assemblyResolver, typeResolver) API.

class MessageIdentityMutator :
    public Task MutateIncoming(MutateIncomingTransportMessageContext context)
        var headers = context.Headers;
        var messageTypeKey = "NServiceBus.EnclosedMessageTypes";
        if (!headers.TryGetValue(messageTypeKey, out var messageType))
            return Task.CompletedTask;

        var type = Type.GetType(
            typeName: messageType,
            assemblyResolver: assemblyName =>
                if (assemblyName.Name == "SamplePhase1")
                    return Assembly.Load("SamplePhase2");
                return Assembly.Load(assemblyName);
            typeResolver: (assembly, typeName, ignoreCase) =>
                if (typeName == "CreateOrderPhase1")
                    return typeof(CreateOrderPhase2);
                if (assembly != null)
                    return assembly.GetType(typeName);
                return Type.GetType(typeName);
            throwOnError: true);

        if (type == null)
            throw new Exception($"Could not determine type: {messageType}");
        headers[messageTypeKey] = type.AssemblyQualifiedName;

        return Task.CompletedTask;

Running the sample

When the sample is run both endpoints will startup. The Phase1 endpoint will send a CreateOrderPhase1 message to Phase2. Phase2 will then mutate the message into a CreateOrderPhase2 and handle the message.


Related Articles

  • Serialization
    Information about how messages are serialized and deserialized on a transport.

Last modified