Skip to content
Mogens Heller Grabe edited this page Jun 12, 2018 · 2 revisions

In several situations, Rebus will need to be able to determine who owns a particular message type - this is where the IRouter comes in.

Why is this relevant? It's relevant in two scenarios: Whenever you want to send a message and whenever you want to subscribe to messages, and in both cases you have decided that you want to rely on the bus routing your messages.

Note that this need can disappear for publish/subscribe if the transport natively supports topic-based publish subscribe, or if Rebus is configured with a centralized subscription storage. In these cases, bus.Subscribe will translate into some kind of subscribe operation at the transport level, or into directly registering the subscriber in the subscription storage.

Sending messages

When you send a message with await bus.Send(message), it is assumed that the message is some kind of command or request, and that the bus should figure out who the proper recipient is.

In this case, IRouter will be called with the message, asking it where to send that message. If Rebus is configured with the type-based router like this:

Configure.With(...)
    .(...)
    .Routing(r => {
        r.TypeBased()
            .Map<SomeMessage>("some-queue");
    })
    .Start();

then the router will simply use the message's type to look up a destination, where e.g. the message type SomeMessage would yield the queue some-queue given the configuration shown above.

Subscribing to messages

When you subscribe to messages of a given type with await bus.Subscribe<TEvent>(), it is assumed that TEvent is the type of some kind of event message, and that the bus should figure out who the publisher of those types of events is.

In this case, IRouter will be called with the TEventtype, asking it where to send a subscription message for the specified type.

What's this thing about owning a message?

It's just a way of putting it that will be true in most scenarios: If you structure your projects like this:

  • SomeService
  • SomeService.Messages

i.e. for each logical service in your application you have a correponding assembly of commands, requests/replies, and events, then you could say that the service owns those messages, and the following endpoint mapping would be sufficient for 99% of the cases in all the dependent services:

Configure.With(...)
    .Routing(r => r.TypeBased().MapAssemblyOf<SomeService.Messages.SomeMessage>("some-service.input"))
    .(...)

Manual routing

IRouter is only relevant when you want the bus to route your messages (which you should most of the time). You can, however, do a await bus.Advanced.Routing.Send(destination, msg) / await bus.Advanced.Routing.Subscribe<TEvent>(destination) in order to bypass the destination lookup, and have your messages sent explicitly to the specified endpoint.

Clone this wiki locally