MSMQ Transport Configuration

Component: MSMQ Transport
Standard support for version 6.x of NServiceBus has expired. For more information see our Support Policy.

Receiving algorithm

Because of how the MSMQ API has been designed, the receive algorithm is more complex than other polling-driven transports (such as SQLServer).

The main loop uses GetMessageEnumerator2 to iterate over all messages available in the queue and creates a separate receiving task for each message.

MSMQ Label

This feature was added in version 6 and can be used to communicate with version 5 (and higher) endpoints. However it should not be used when communicating with earlier versions (2, 3 or 4) since in those versions the MSMQ Label was used to communicate certain NServiceBus implementation details.

Often when debugging MSMQ using native tools, it is helpful to have some custom text in the MSMQ Label. For example, the message type or the message id. As of version 6 the text used to apply to Message.Label can be controlled at configuration time using the ApplyLabelToMessages extension method. This method takes a delegate which will be passed the header collection and should return a string to use for the label. It will be called for all standard messages as well as audits, errors, and all control messages. The only exception to this rule is received messages with corrupted headers. In some cases it may be useful to use the Headers.ControlMessageHeader key to determine if a message is a control message. These messages will be forwarded to the error queue with no label applied. The returned string can be String.Empty for no label and must be at most 240 characters.

var transport = endpointConfiguration.UseTransport<MsmqTransport>();
// Set the msmq message label to the current Message Id
    labelGenerator: headers =>
        return headers[Headers.MessageId];

Transactions and delivery guarantees

MSMQ Transport supports the following Transport Transaction Modes:

  • Transaction scope (Distributed transaction)
  • Transport transaction - Send atomic with receive
  • Transport transaction - Receive only
  • Unreliable (Transactions disabled)

See also Controlling Transaction Scope Options.

Transaction scope (distributed transaction)

In this mode, the ambient transaction is started before receiving the message. The transaction encompasses all stages of processing including user data access and saga data access.

MSMQ does not support Snapshot isolation level. Snapshot isolation level is suitable only when persistence is required. This isolation level can be applied only on the persister if the transport and persistence do not share the same transaction. Lower the transport transaction mode to at least Sends atomic with receive, use WrapHandlersInATransactionScope, and pass IsolationLevel.Snapshot as a parameter. This has consistency issues as mentioned in the Transport Transactions Consistency Guarantees article

Native transactions

In version 6.1 and above, the MSMQ transport uses native transactions to support the ReceiveOnly and SendsAtomicWithReceive levels. With SendsAtomicWithReceive the native transaction for receiving messages is shared with sending operations. That means the message receive operation, and any send or publish operations, are committed atomically. When using ReceiveOnly, the transaction is not shared with sending operations and dispatched messages may not be rolled back in case the receiving transaction needs to abort.

Version 6.0 does not distinguish between ReceiveOnly and SendsAtomicWithReceive and both levels behave as SendsAtomicWithReceive.

Unreliable (transactions disabled)

In this mode, when a message is received, it is immediately removed from the input queue. If processing fails, the message is lost because the operation cannot be rolled back. Any other operation that is performed when processing the message is executed without a transaction and cannot be rolled back. This can lead to undesired side effects when message processing fails part way through.

Related Articles

Last modified