Sending messages

Component: NServiceBus
NuGet Package NServiceBus (7-pre)
This page targets a pre-release version and is subject to change prior to the final release.

NServiceBus supports sending different types of messages (see Messages, Events, and Commands) to any endpoint. Messages can be sent either directly from the endpoint or as part of handling an incoming 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 directly from the endpoint:

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 a performance perspective, to limit the 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

Messages often need to be sent as part of handling an incoming message. When running in a transaction mode that supports it, these send operations take part in the same transaction as that of the message handler, thereby ensuring that the send operations roll back if the handling of the message fails at any stage of the message processing pipeline.

To send a message from inside a message handler:

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:

await endpoint.Send<IMyMessage>(
        messageConstructor: message =>
        {
            message.MyProperty = "Hello world";
        })
    .ConfigureAwait(false);

Using IMessageSession or IEndpointInstance to send messages inside a handler instead of the provided IMessageHandlerContext should be avoided.

Some of the dangers when using an IMessageSession or IEndpointInstance inside a message handler to send or publish messages are:

  • Those messages will not participate in the same transaction as that of the message handler. This could result in messages being dispatched or events published even if the message handler resulted in an exception and the operation was rolled back.
  • Those messages will not be part of the batching operation.
  • Those messages will not contain any important message header information that is available via the IMessageHandlerContext interface parameter, e.g., CorrelationId.

Overriding the default routing

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

Using the destination address:

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:

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 own instances:

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.
var options = new SendOptions();
options.RouteToThisInstance();
var message = new MyMessage();
await endpoint.Send(message, options)
    .ConfigureAwait(false);

Influencing the reply behavior

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

To send the reply message to the specific instance that sent the initial message:

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:

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

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

Dispatching a message immediately

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

This can be done by using the immediate dispatch API:

var options = new SendOptions();
options.RequireImmediateDispatch();
var message = new MyMessage();
await context.Send(message, options)
    .ConfigureAwait(false);
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.

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