Step-by-step guide to creating Pub Sub with NServiceBus

Recently I have been tasked with creating a prototype of an application using NServiceBus. However I found that the current documentation/samples can be a little difficult to follow. I’m guessing because a) it’s recently changed to v3 and some of the docs haven’t been upgraded b) when you “grow up” with a project it’s often difficult to remember what problems newbies will have. So I’ve decided to write this guide to help me remember and if it’s useful to anyone else then great. So here goes;

  1. Create a new project as a class library called ‘Messages’

  2. Add a class file called ‘MyEvent.cs’:

    using System;
    
    namespace Messages
    {
        public class MyEvent
        {
            public Guid EventId { get; set; }
        }
    }
    

  3. Create a new project as a class library called ‘Publisher’

  4. Add references to log4net.dll, NServiceBus.dll, NServiceBus.Core.dll, and NServiceBus.Host.exe (yes exe)

    if you installed using NUGet these will be in your package files, otherwise you’ll need to download NServiceBus and grab them from the install location’s binaries folder

  5. Add a project reference to ‘Messages’

  6. Add an app.config to the project

    This is configuring the queue where any messages that are deemed in error will go

     <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
      <configSections>
        <section name="MessageForwardingInCaseOfFaultConfig" type="NServiceBus.Config.MessageForwardingInCaseOfFaultConfig, NServiceBus.Core" />
      </configSections>
    
      <MessageForwardingInCaseOfFaultConfig ErrorQueue="error"/>
    
      <runtime>
        <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
          <dependentAssembly>
            <assemblyIdentity name="Common.Logging"
                              publicKeyToken="af08829b84f0328e"
                              culture="neutral" />
            <bindingRedirect oldVersion="1.2.0.0"
                             newVersion="2.0.0.0"/>
          </dependentAssembly>
        </assemblyBinding>
      </runtime>
    </configuration>

  7. Add a class files called ServerEndpoint.cs and TestPublisher.cs, we’ll add the code later

  8. Add a config file called NServiceBus.Host.exe.config

    This is configuring the queue that we’ll be publishing message to, the value must match the qualified class name of the publisher’s project configuration class, we’ll do that next

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
      <appSettings>
        <add key="EndpointConfigurationType" value="Publisher.TestPublisherConfig, Publisher"/>
      </appSettings>
    </configuration>
    

  9. Now for the code in ServerEndpoint.cs

    The code uses an “ISupport” style to declare that it should be executed a bit like a console.main(). NSB uses injection to populate the bus property, so it will be available when Run() is executed

    using System;
    using NServiceBus;
    using Messages;
    
    namespace Publisher
    {
        public class ServerEndpoint : IWantToRunAtStartup
        {
            public IBus Bus { get; set; }
    
            public void Run()
            {            
                Console.WriteLine("Press 'Enter' to publish a message.To exit, Ctrl + C");
    
                while (Console.ReadLine() != null)
                {                
                    var eventMessage = new MyEvent();
                    eventMessage.EventId = Guid.NewGuid();
                    
                    Bus.Publish(eventMessage);
    
                    Console.WriteLine("Published event with Id {0}.", eventMessage.EventId);
                    Console.WriteLine("==========================================================================");
    
                }
            }
    
            public void Stop()
            {
    
            }
        }
    }
    

  10. Now to add the code for the core of the publisher code, ‘TestPublisher.cs’

    NSB likes to use the “ISupports” style, so here we can see the class explaining to NSB that it configures the endpoint, that it is a publisher and that NSB should call it as the endpoint starts. Inside the Init() it is explaining what types NSB should consider as implementing messages, i.e. our Messages dll.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using NServiceBus;
    
    namespace Publisher
    {
        public class TestPublisherConfig : IConfigureThisEndpoint, AsA_Publisher, IWantCustomInitialization
        {
            public void Init()
            {
                Configure.With()                
                    //this overrides the NServiceBus default convention of IEvent
                    .DefiningEventsAs(t => t.Namespace != null && t.Namespace.StartsWith("Messages"));
            }
        }    
    }
    

  11. Now we can move onto the subscriber, add a new project call ‘Subscriber’ as a class library
  12. Add the NSB references again, log4net.dll, NServiceBus.dll, NServiceBus.Core.dll, NServiceBus.Host.exe
  13. Add the project reference to ‘Messages’
  14. Add app.config file

    this will explain to NSB which messages we are listening for and where (the endpoint) to find them

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
      <configSections>
        <section name="MessageForwardingInCaseOfFaultConfig" type="NServiceBus.Config.MessageForwardingInCaseOfFaultConfig, NServiceBus.Core" />
        <section name="UnicastBusConfig" type="NServiceBus.Config.UnicastBusConfig, NServiceBus.Core" />
      </configSections>
      
      <MessageForwardingInCaseOfFaultConfig ErrorQueue="error"/>
      <UnicastBusConfig>
        <MessageEndpointMappings>
          <add Messages="Messages" Endpoint="Publisher" />
        </MessageEndpointMappings>
      </UnicastBusConfig>
    
    </configuration>
    
    

  15. Add a class file ‘EndPointConfig.cs’

    this is almost the same as for the publisher but notice is says AsA_Server this time rather than AsA_Publisher

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using NServiceBus;
    
    namespace Subscriber
    {
        public class EndPointConfig : IConfigureThisEndpoint, AsA_Server, IWantCustomInitialization
        {
            public void Init()
            {            
                    Configure.With()                
                    .DefiningEventsAs(t => t.Namespace != null && t.Namespace.StartsWith("Messages"));
            }
        }
    }
    
    

  16. now let’s add the final bit of code, the handler for the message. Create a class file ‘HandleMyEvent.cs’

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using NServiceBus;
    using log4net;
    using Messages;
    
    namespace SubScriber
    {
        public class HandleMyEvent : IHandleMessages<MyEvent>
        {
            public void Handle(MyEvent message)
            {
                Logger.Info(string.Format("Subscriber received MyEvent with Id {0}.", message.EventId));            
                Console.WriteLine("==========================================================================");
            }
    
            private static readonly ILog Logger = LogManager.GetLogger(typeof(MyEvent));
        }
    }
    
    

  17. almost there. We now need to have something to run. The NServiceBus.Host.Exe is going to do all the work but we have to do a couple of things. First Build (don’t run) the whole solution. Since we referenced the .exe this will be enough for Visual Studio to copy it to each project’s local bin folder
  18. For both Publisher and Subscriber open their projects and set the Debug->Start External Program to bin the NServiceBus.Host.Exe in their respective Debug\bin folders
  19. Now ensure they will both run by right clicking on the Solution and ‘Set Statup Projects…’. Ensure that both Publisher and Subscriber are ticked and Multiple Projects is selected
  20. Now run the solution and press enter in the Publisher. You should see the messages sent to the subscriber
  21. You can now add additional subscribers in exactly the same way, just be sure to correctly rename their namespaces to avoid clashes, NSB doesn’t like that
  22. That should be it. You can find out more about NServiceBus from the site documentation and the community group. Just be careful as when I wrote this some of the documentation is old and I found that confusing. I hope this was useful