Sending messages

Component: NServiceBus | Nuget: NServiceBus (Version: 6.x)

NServiceBus supports sending different types of messages (see Messages, Events, and Commands) to any endpoint. Messages can be sent either when the bus is started or as part of handling another message. When a message arrives at an endpoint, it goes through a pipeline of processing steps.

Outside a message handler

In some cases, messages that need to be sent may not be related to an incoming message. Some examples are:

  • Sending a command when a HTML form is submitted in an ASP.NET application.
  • Publishing an event when the user clicks a button on a GUI application (see Publish and Handle an Event).

To send a message when the bus is started:

Edit
var endpointInstance = await Endpoint.Start(endpointConfiguration)
    .ConfigureAwait(false);
var message = new MyMessage();
await endpointInstance.Send(message)
    .ConfigureAwait(false);
Send is an asynchronous operation - when the invocation ends it does not mean that the message has actually been sent. In scenarios where a large number of messages are sent in a short period it might be beneficial, from performance perspective, to limit number of outstanding send operations pending for completion. Sample approaches that can be used to limit the number of send tasks can be found in Writing Async Handlers.

Inside the incoming message processing pipeline

In some cases, messages might need to be sent as part of handling a message such as, inside a regular message handler, a saga, or in some advanced cases as part of extending the message handling pipeline. In this scenario, all the send operations are linked to the incoming message. The send operations take part in the same transaction scope as that of the message handler, thereby ensuring that the send operations rollback if the handling of the message fails at any stage of the message processing pipeline.

To send a message from inside a message handler:

Edit
public class MyMessageHandler :
    IHandleMessages<MyMessage>
{
    public Task Handle(MyMessage message, IMessageHandlerContext context)
    {
        var otherMessage = new OtherMessage();
        return context.Send(otherMessage);
    }
}

The message can also be an interface rather than a concrete class:

Edit
await endpoint.Send<IMyMessage>(
        messageConstructor: message =>
        {
            message.MyProperty = "Hello world";
        })
    .ConfigureAwait(false);
In Versions 5 and below, the operations are available on the IBus which can be accessed using constructor or property injection. In Versions 6 and above, the message handlers have access to the IMessageHandlerContext parameter, which can be used to dispatch messages on the bus.

Overriding the default routing

The SendOptions object can be used to override the default routing.

Using the destination address:

Edit
var options = new SendOptions();
options.SetDestination("MyDestination");
await endpoint.Send(new MyMessage(), options)
    .ConfigureAwait(false);
// or
await endpoint.Send<MyMessage>("MyDestination", m => { })
    .ConfigureAwait(false);

Using the ID of the target instance:

Edit
var options = new SendOptions();
options.RouteToSpecificInstance("MyInstance");
var message = new MyMessage();
await endpoint.Send(message, options)
    .ConfigureAwait(false);

Sending to self

Sending a message to the same endpoint, i.e. Sending to self can be done in two ways.

An endpoint can send a message to any of its instances:

Edit
var options = new SendOptions();
options.RouteToThisEndpoint();
await endpoint.Send(new MyMessage(), options)
    .ConfigureAwait(false);
// or
await endpoint.SendLocal(new MyMessage())
    .ConfigureAwait(false);

Or, it can request a message to be routed to itself, i.e. the same instance.

This option is only possible when endpoint instance ID has been specified
Edit
var options = new SendOptions();
options.RouteToThisInstance();
var message = new MyMessage();
await endpoint.Send(message, options)
    .ConfigureAwait(false);

Influencing the reply behavior

The sender of the message can also control how the reply messages are received. When a receiving endpoint replies to a message, by default the reply message will be routed to any instance of the sending endpoint.

To explicitly control the reply message to be dispatched to a particular instance:

Edit
var options = new SendOptions();
options.RouteReplyToThisInstance();
var message = new MyMessage();
await endpoint.Send(message, options)
    .ConfigureAwait(false);

To send the reply message to any instance of the endpoint:

Edit
var options = new SendOptions();
options.RouteReplyToAnyInstance();
var message = new MyMessage();
await endpoint.Send(message, options)
    .ConfigureAwait(false);

The sender can also request the reply to be routed to a specific transport address

Edit
var options = new SendOptions();
options.RouteReplyTo("MyDestination");
var message = new MyMessage();
await endpoint.Send(message, options)
    .ConfigureAwait(false);

Dispatching a message immediately

While its usually best to let NServiceBus handle all exceptions, there are some scenarios where messages might need to be sent regardless of if the message handler succeeds or not. For example, sending a reply notifying that there was a problem with processing the message.

By specifying immediate dispatch, outgoing messages will not be batched or enlisted in the current receive transaction even if the transport has support for it.

Suppressing the ambient transaction to have the outgoing message sent immediately is possible:

Edit
using (new TransactionScope(TransactionScopeOption.Suppress, TransactionScopeAsyncFlowOption.Enabled))
{
    var message = new MyMessage();
    await context.SendLocal(message)
        .ConfigureAwait(false);
}
Suppressing transaction scopes only works for MSMQ and SQL transports in DTC mode. Other transports or disabled DTC may result in unexpected behavior.

The preferred approach is to use the the explicit immediate dispatch API.

Edit
var options = new SendOptions();
options.RequireImmediateDispatch();
var message = new MyMessage();
await context.Send(message, options)
    .ConfigureAwait(false);

Related Articles

  • Message routing
    How NServiceBus routes messages between the endpoints.
  • Messages as Interfaces
    NServiceBus allows supports the use interfaces as well as standard XSD and class serialization.

Last modified