Documentation
The hard part of learning NServiceBus isn't the API,
it's understanding the distributed systems philosophy behind it.
Start learning about this philosophy on the overview page.
From there, continue on to a description of architectural principles.
Below you can find the full contents and an FAQ further down.
You can also see what other developers have written up on the wiki
as well as search the discussion group archives via this site.
Contents
FAQ
How's messaging different?
In regular communications between clients and servers, both machines need to be
up and running, and so do the software processes. If either process or machine
goes down, then communication cannot continue.
In non-durable messaging, processes can be up or down at any point in time.
Sending a message involves putting it in an outgoing queue on the same machine.
At the point, the sending process can go down and nothing bad will happen.
The messaging infrastructure then tries to get that message to the target machine
in collaboration with its counterpart on that machine. When that message arrives,
if the process is down, the message just sits in a queue waiting. When the process
comes up, it can process the message.
Durable messaging does all of the above but durably. When the message is put
in the output queue, it's written to disk - so that even if the sender crashes
at that point, the message won't be lost. When the message is transferred to the target
machine, it is written to disk there (and then deleted from the sender's disk).
That way, even if the target machine crashes at some point, the message won't be lost.
In short, both machines need to be online at the same time just long enough to
transfer the message safely, and no more than that.
How do I define a message?
public class MyMessage : IMessage { }
OR
public interface IMyMessage : IMessage { }
One of the advantages of using interfaces to define messages instead of classes
is that you get "multiple inheritance" - one message can extend multiple other messages.
This is useful for solving a specific class of versioning problems.
Say that your business logic represents a state machine with states X and Y.
When your system gets into state X, it publishes a message - EnteredStateX.
When your system gets into state Y, it publishes a message - EnteredStateY.
(For more information on how to publishe a message, see below)
In the next version of your system, you add a new state Z, which represents
the co-existence of both X and Y. So, you define a message EnteredStateZ which
inherits both EnteredStateX and EnteredStateY.
When your system publishes EnteredStateZ, clients subscribed to either (or both)
EnteredStateX or EnteredStateY will be notified.
Without the ability to have a message extend multiple others, you'd have to
use composition. This would prevent the infrastructure from knowing how to
automatically route messages to pre-existing subscribers of the composed messages.
How do I specify store & forward for a message?
This is the default mode in version 2.0, but not in 1.9.
[Recoverable]
public class MyMessage : IMessage { }
How do I specify that I don't want a message to be written to disk?
This is the default mode in version 1.9, but not in 2.0.
[Express]
public class MyMessage : IMessage { }
How do I get old messages to be discarded?
[TimeToBeReceived(“00:01:00”)] // one minute
[Recoverable]
public class MyMessage { }
If a message wasn't able to be *received* by the target process in the given
timeframe, including all time in queues and in transit, the message will be discarded.
How do I instantiate a message?
var msg = new MyMessage();
OR
var msg = Bus.CreateInstance<IMyMessage>();
How do I send a message?
Bus.Send(messageObject);
OR (Instantiate and send all at once):
Bus.Send<IMyMessage>( (m) => { m.Prop1 = v1;
m.Prop2 = v2; });
How do I specify to which destination a message will be sent?
Configure destination for message type:
In <UnicastBusConfig>, under <MessageEndpointMappings>
<add Messages=“assembly”
endpoint=“destination”>
OR
<add Messages=“type” endpoint=“destination”>
Destinations can be QueueName@ServerName, or just QueueName on the same machine.
You can also call:
Bus.Send(string destination, params
IMessage[] msgs);
though not recommended for application-level code.
How do I handle a message?
Write a class that implements IMessageHandler<T> where T is message type
public class H1 : IMessageHandler<MyMessage>
{
public void Handle(MyMessage message)
{
}
}
How do I handle all kinds of messages
Write a handler for IMessage as follows:
public class H1 : IMessageHandler<IMessage>
{
public void Handle(IMessage message)
{
// do something relevant for all messages
}
}
How do I specify the order in which handlers are invoked?
If you're writing your own host:
NServiceBus.Configure.With()
...
.UnicastBus()
.LoadMessageHandlers(First<H1>.Then<H2>().AndThen<H3>().AndThen<H4>() //etc)
...
If you're using the generic host
public class EndpointConfig : IConfigureThisEndpoint, ISpecifyMessageHandlerOrdering
{
public void SpecifyOrder(Order order)
{
order.Specify(First<H1>.Then<H2>().AndThen<H3>().AndThen<H4>() //etc);
}
}
If you only want to specify a single handler (with your own host)
NServiceBus.Configure.With()
...
.UnicastBus()
.LoadMessageHandlers<FIRST<YourHandler>>()
...
If you only want to specify a single handler (with the generic host)
public class EndpointConfig : IConfigureThisEndpoint, ISpecifyMessageHandlerOrdering
{
public void SpecifyOrder(Order order)
{
order.Specify<FIRST<YourHandler>>();
}
}
How do I get a reference to IBus in my message handler?
public class H1 : IMessageHandler<MyMessage>
{
public IBus Bus { get; set; }
public void Handle(MyMessage message)
{
// use Bus for something
}
}
How do I get additional information about a message?
public class H1 : IMessageHandler<MyMessage>
{
public IBus Bus { get; set; }
public void Handle(MyMessage message)
{
// use Bus.CurrentMessageContext
// contains Id, ReturnAddress, and Headers
}
}
How do I reply to a request?
public class H1 : IMessageHandler<MyMessage>
{
public IBus Bus { get; set; }
public void Handle(MyMessage message)
{
Bus.Reply<MyResponse>();
// can call reply multiple times
// useful for "streaming" back a lot of data
}
}
How do I call a web service?
Don't.
At least not from within a message handler doing business logic.
The reason for this has to do with fault tolerance. If the web service that you're calling is
unavailable or slow, the call to the web service will likely blow up with an HttpTimeoutException.
This becomes problematic when you call multiple web services and/or reply/send/publish messages
as a part of the same method.
See below for how exceptions should be handled.
The recommended approach to integrating with an external web service is to put an adapter process
between your business logic and the web service. Have your handler send a message to that adapter process
which, in turn, invokes the web service.
How do I handle responses client-side?
Can handle like any regular message, have a class implement
IMessageHandler<MyResponse>
Can register a callback when sending request:
Bus.Send(request).Register(asyncCallback,
state)
Callback only fires on first response, then is cleaned up to prevent memory
leaks. Doesn’t survive restarts – not suitable for server-side
How do I publish a message?
Bus.Publish(messageObject);
OR (Instantiate and publish all at once):
Bus.Publish<IMyMessage>( (m) => { m.Prop1 = v1;
m.Prop2 = v2; });
How do I publish a message from a web app?
Don't.
When communicating from a web application to a back end process, don't Bus.Publish
the message. Rather, Bus.Send it. Configure the destination that the message is sent to
as described above in the section "How do I specify to which destination a message will be sent?".
How's publishing a message different from just sending it?
While the two may seem almost equivalent, they mean very different things.
A lot of conventions have been set up in the infrastructure so that no additional
configuration is needed to do either. Treating the two the same will make it
difficult for you to have the routing infrastructure "just work".
When sending a message, NServiceBus assumes that you're a client sending
a command or request of sorts to a server. When publishing a message, NServiceBus
assumes that you're a server notifying previously subscribed parties about an
event *that's already happened*.
In the case of sending a message, the sender is required to have a <MessageEndpointMapping>
entry in its configuration specifying where the message should be sent to. In the case
of publishing a message, the publisher is not expected to have that entry in its configuration.
Subscribers are the ones that need to have that entry.
In short, it's the different meaning of the message that should guide you.
How do I subscribe to a message?
If you have a message handler for a message which is configured as belonging
to a different endpoint (specified with a MessageEndpointMapping in your
<UnicastBusConfig> section - see above),
then the infrastructure will automatically subscribe to that message.
You can also choose to *not* have the infrastructure automatically subscribe
by specifying ConfigUnicastBus.DoNotAutoSubscribe()
in the fluent configuration API or by implementing IDontWant.ToSubscribeAutomatically
when using the generic host (see below).
In order to manually subscribe to, and unsubscribe from a message, call
Bus.Subscribe<MyMessage>()
OR
Bus.Unsubscribe<MyMessage>()
How do I handle exceptions?
Don't.
NServiceBus has exception catching and handling logic of its own which surrounds all calls to user code.
When an exception bubbles through to the NServiceBus infrastructure, it rolls back the transaction on
a transactional endpoint, causing the message to be returned to the queue, and any messages that user code
tried to send or publish to be undone as well.
At that point, NServiceBus will retry to handle that message a configurable number of times (default of 5)
and if the message fails on every one of those retries, the message will then be moved to the configured
error queue.
Administrators should monitor that error queue so that they can see when problems occur.
The message in the error queue contains the source queue and machine so that the administrator can go
see what's wrong with that node and possibly correct the problem (like bringing up a database that
went down).
Once the administrator corrects the problem, they can use the ReturnToSourceQueue.exe tool to
send the relevant message back to its original queue so that it can be processed again - this time
successfully.
How do I expose an NServiceBus endpoint as a web service?
Inherit from NServiceBus.Webservice<TCommand, TErrorCode> as shown below. TCommand is the
message type of the request and needs to implement IMessage. TErrorCode must be an enumerated type,
and should represent the result of processing the command.
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[ToolboxItem(false)]
public class MyWebService : NServiceBus.Webservice<Command, ErrorCodes> { }
If you want to expose a web service which returns a response message rather than just an error code,
the recommendation is to reconsider your design. For example, if you want to perform queries like
GetCustomersByRegionRequest and CustomersByRegionResponse, that should not be implemented using messaging.
See the topic of Command/Query Separation (CQS) for more information.
Connect with others in the NServiceBus community.