Search code examples
c#authenticationmessagingnservicebus

NServiceBus: specifying message order


I'm using NServiceBus in it's own process (so not using the Generic Host) and I would like to have multiple message handlers for a message in a specific order. For the Generic Host, you would implement ISpecifyMessageHandlerOrdering, but I don't know how to do this when hosting your own NServiceBus process since that interface is defined in NServiceBus.Host.exe and I haven't been able to find another way to do this.

The purpose of this is user authentication: before the actual message handler is invoked, I would first like to authenticate the sender of the message, which would happen in a different, more generic, message handler. The message will be of a type that contains the encrypted user name and password and/or a session ID. This type will be used for almost all commands sent to the server (everything but login I think). Is this an OK way to do user authentication using NServiceBus?

Currently, it picks up the second handler but not in the right order.

Update

As suggested by David I tried creating a IMessageModule and reading the headers from the CurrentMessageContext to authenticate the user.

I ran into some problems here:

  • The first time I send a message, the bus.CurrentMessageContext is null. Every time after that, it's filled in correctly and I can read the headers.
  • Calling bus.DoNotContinueDispatchingCurrentMessageToHandlers when the user is not authenticated does not stop the message handlers from being invoked. Neither does bus.Return(errorCode). Are there other ways I can do that?

Solution

  • As described in the NServiceBus FAQ on the documentation page:

    http://docs.particular.net/nservicebus/handlers/handler-ordering

    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>>();
         }
    }