Getting Started

Change/Move Message Type

Component: NServiceBus
NuGet Package: NServiceBus (9.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 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")
                    Console.WriteLine("Message received from SamplePhase1 assembly, changing to SamplePhase2 assembly");

                    return AssemblyLoadContext.Default.LoadFromAssemblyName(new AssemblyName("SamplePhase2"));

                return AssemblyLoadContext.Default.LoadFromAssemblyName(assemblyName);
            typeResolver: (assembly, typeName, ignoreCase) =>
                if (typeName == "CreateOrderPhase1")
                    Console.WriteLine("CreateOrderPhase1 received, changing to CreateOrderPhase2");

                    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
    .NET messaging systems require serialization and deserialization of objects sent/received over transports. NServiceBus achieves this using serializers.