Category Archives: Architecture

Beware of changing variable names in SOAP Webservices

When improving upon your SOAP webservices currently in production, it might occur to you to change variable names in method signatures to make the more readable and conform to your coding practices. After these are the small incremental improvements we make to reduce our technical debt. But before doing this, please beware of the ramifications.

A WSDL describing a SOAP webservice is “strongly typed” in the sense that method signatures including method names, variable names and their types, once defined, cannot be changed with breaking backward compatibility. And Since SOAP does not provide an easy way for clients to detect an API change, altering either of the constructs that define your WSDL guarantees a temporal disruption of service due to your current API consumers.

For example, say you have a SOAP webservice exposing this method:

public Report GetReport(string ReportName)

which is defined as part of your WSDL. If you later change this this method to say

public Report GetReport(string reportName)

the service will receive null as the reportName in some client implementations. Others may simply crash since this endpoint is no longer known. If one is spending quite some time working with SOAP based services on a daily basis, it becomes almost of a second nature to regenerate the client proxy based on the published WSDL to ensure consistency otherwise, you get these strange behaviors. However, if you are spending a lot of time in RESTFul services, chances are you are not worrying about these types of problems. In this case, there is a good chance you will rename a webservice API parameter name in the name of improving readability (nothing wrong with that) only to find out that the next morning none of your clients are able to connect to your API.

And no, unit tests will not catch this.

Advertisements

A simple cross platform status bar micro service

These days, with all the buzz and best practices around micro-services, Clean Code and KISS, one should be proud of themselves after creating a simple, small and cross platform micro-service to further advocate the power of these patterns and demonstrate how easy developing robust, maintainable and beautiful code can be. Any complex problem can be broken down into small manageable chunks.

Requirement was to add a status bar to a WPF application to indicate progress of some background calculations. I wanted to use MVVM and also wanted to be able to access the main application’s status bar from anywhere in the application, mostly from the ViewModels. ViewModels are currently being injected services from the Unity container so I thought, hey, why not create a simple StatusBarService that can be bound to a StatusBar control, which the ViewModel can the control from there? I did something similar year ago but this approach is more mature and greatly simplified.

The service in its entirety as follows:

 public class StatusBarService : IStatusBarService, INotifyPropertyChanged
    {
        public StatusBarService()
        {
            ProgressBarVisibility = Visibility.Hidden;
            Name = null;
            Message = "Ready";
        }

        public string Name { get; private set; }

        private bool _isIndeterminate;
        public bool IsIndeterminate
        {
            get { return _isIndeterminate; }
            set
            {
                _isIndeterminate = value;
                OnPropertyChanged();

                if (!_isIndeterminate)
                {
                    ProgressBarVisibility = Visibility.Hidden;
                }
                else
                {
                    ProgressBarVisibility = Visibility.Visible;
                }
            }
        }

        public void StartIsIndeterminate(string message)
        {
            IsIndeterminate = true;
            Message = message;
        }

        public void StopIsIndeterminate(string message)
        {
            IsIndeterminate = false;
            Message = message;
        }

        private string _message;
        public string Message
        {
            get { return _message; }
            set
            {
                _message = value;
                OnPropertyChanged();
            }
        }

        private Visibility _progressBarVisibility;
        public Visibility ProgressBarVisibility
        {
            get { return _progressBarVisibility; }
            set
            {
                _progressBarVisibility = value;
                OnPropertyChanged();
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        [NotifyPropertyChangedInvocator]
        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }

It is cross platform and does not care how you use it.

You can register it with your IoC container and modify your ViewModel constructors to be injected an instance of IStatusBarService. Once you have access in your ViewModel, you can control any Statusbar as you see fit. Only caveat is ensuring the StatusBarService is bound to the DataContext of the StatusBar it should be controlling.

Happy Coding.

Factories or Providers: what is your chosen terminology?

The Factory pattern in plain language is about encapsulating an entity that is responsible for creating stuff provided with a given context. For example, say I wanted to create such an entity responsible for created different implementations of an ILoggerFacade interface defined as such:


public interface ILoggerFacade
{
void Error(object error);
void Info(object info);
}

I could define an ILoggerFacadeFactory interface as follows:


public interface ILoggerFacadeFactory
{
ILoggerFacade CreateLogger(object owner);
}

and have an implementation for Console, log4Net or other logging libraries as follows:

public class ConsoleLoggerFacadeFactory : ILoggerFacadeFactory
{
public ILoggerFacade CreateLogger(object owner)
{
return new ConsoleLoggerFacade(owner);
}
}


public class Log4NetLoggerFacadeFactory : ILoggerFacadeFactory
{
public ILoggerFacade CreateLogger(object owner)
{
return new Log4NetLoggerFacade(owner);
}
}

Then this becomes a matter of registering the appropriate factory in an IoC container, such as Unity, to create the logger as desired:

   ioc.Register<ILoggerFacadeFactory, Log4NetLoggerFacadeFactory>();

This way, I can easily change the type of logger I use in my application via configuration. I use this pattern extensively, especially with 3rd party libraries. I have used this to abstract message queue implementations for MSMQ, RabbitMQ and ZeroMQ, logging and even for UI elements such as DataGrids, DataCharts and Docking containers, without thinking much about the nomenclature.

Recently, however, this terminology has caused some excitement in my professional circles. Others will rather call these types of entity factories, entity providers for good cause. After all, a provider provides stuff. Factories or Providers sort of provide similar responsibilities even though I would argue that factories create stuff while providers do not necessary do so. Either way, there is no right or wrong answer here although I tend to lean toward calling entity creators, factories, for the very reason that the create stuff by typically calling some sort of constructor on the object class.

Just like an automobile factory manufactures cars, an entity factory instantiates new objects. An automotive dealer, on the otherhand, is an auto provider but cannot be considered an automobile factory. This is the way I distinguish these responsibilities. In fact, a provider can be given reference to a factory that will create stuff that is requested of it, it not in its inventory. Distinct responsibilities.

This is the way I see it. What are your thoughts?

Some defensive coding practices against environmetal uncertainties – part 1

1. Always consider Environment.CurrentDirectory as opposed to Assembly.GetExecutingAssembly().Location, when getting current working directory.

This innocent looking line of code causes grief.

var pathToSqliteDatabase = Path.Combine(Assembly.GetExecutingAssembly().Location, "SqliteDb.db3");

Why?

Let’s just first ignore the fact that a test harness should be going directly to a database since this is part of the problem. But if you are running a test harness that has to resolve a location to an SQLite database instance you will get interesting results.

If using MSTest, the above line of code resolves to the current test project’s working folder. So if your test project was in c:\dev\SQliteAdventures, pathToSqliteDatabase to be

c:\dev\SQliteAdventures\bin\Debug

However, if you decided to change to NUnit and have ReShaper installed, the same above line of code now resolves to some random location:

In my case, it looked like this:

C:\Users\knji\AppData\Local\Temp\jahvgmug.pjb\s5hvswgs.kil\SQliteAdventures\assembly\dl3\086a6c5d\1860476f_4375d001\

Changing the above line of code to

var pathToSqliteDatabase = Path.Combine(Environment.CurrentDirectory, "SqliteDb.db3");

will return the current result regardless of the operating environment. So this is preferable here.

2. Carefully consider using x86 vs x64 versions of 3rd party dependencies.

The System.Data.SQLite.dll .NET connector for SQLite, for example comes, with an x86 and x64 version. When executing tests using MSTest, x86 version of the is required since the MStest runner executes within the 32 bit Visual Studio process. However, if you are running NUnit via ReSharper, which executes within its own 64 bit process called JetBrains.ReSharper.TaskRunner.CLR45.x64.exe, you need the x64 bit version of this dll otherwise you get image loading exception. Besides testing against abstractions or fakes, I do not yet know to automate this. Ideas always welcomed.

To be continued…..

Abstracting message queue creation using the factory pattern

You had to create several additional modules for an existing enterprise solution but did not know which of the various message queues to use: your options are MSMQ, ZeroMQ, RabbitMQ, Azure, etc.
You decided to postpone this decision to latter in the game but in the meantime, abstracted away functionality of the message queue behind an interface that looks like this:

  public interface IMessageQueue : IDisposable
    {
        string Address { get; }
        IDictionary<string, string> Properties { get; }
        void InitializeInboundQueue(MessageQueueCreationContext creationContext);
        void InitializeOutboundQueue(MessageQueueCreationContext creationContext);
        void Send(Message message, string messageTopic = null);
        void Listen(Action<Message> onMessageReceived, string routingKey = null);
        void Receive(Action<Message> onMessageReceived);
        IMessageQueue GetResponseQueue();
        IMessageQueue GetReplyQueue(Message message);
    }

The creation context class looks like this:

  [Serializable]
    public class MessageQueueSpecs : IEquatable<MessageQueueSpecs>
    {
        public bool Equals(MessageQueueSpecs other)
        {
            if (ReferenceEquals(null, other)) return false;
            if (ReferenceEquals(this, other)) return true;
            return 
                string.Equals(Name, other.Name) && 
                string.Equals(Address, other.Address) && 
                MessagePattern == other.MessagePattern && 
                Direction == other.Direction && 
                string.Equals(MessageTopic, other.MessageTopic) && 
                string.Equals(HostName, other.HostName);
        }

        public override int GetHashCode()
        {
            unchecked
            {
                var hashCode = (Name != null ? Name.GetHashCode() : 0);
                hashCode = (hashCode*397) ^ (Address != null ? Address.GetHashCode() : 0);
                hashCode = (hashCode*397) ^ (int) MessagePattern;
                hashCode = (hashCode*397) ^ (int) Direction;
                hashCode = (hashCode*397) ^ (MessageTopic != null ? MessageTopic.GetHashCode() : 0);
                hashCode = (hashCode*397) ^ (HostName != null ? HostName.GetHashCode() : 0);
                return hashCode;
            }
        }

        public static bool operator ==(MessageQueueSpecs left, MessageQueueSpecs right)
        {
            return Equals(left, right);
        }

        public static bool operator !=(MessageQueueSpecs left, MessageQueueSpecs right)
        {
            return !Equals(left, right);
        }

        public MessageQueueSpecs()
        {
            AdditionalProperties = new Dictionary<string, string>(5);
            Name = GetType().FullName + DateTime.UtcNow;
        }

        public string Name { get; set; }
        public string Address { get; set; }
        public MessagePattern MessagePattern { get; set; }
        public Direction Direction { get; set; }
        public ISerializer Serializer { get; set; }
        public IDictionary<string, string> AdditionalProperties { get; set; }
        public string MessageTopic { get; set; }
        public string HostName { get; set; }

        public bool IsValid()
        {
            if (Serializer == null)
                return false;

            return true;
        }

        public override bool Equals(object obj)
        {
            if (ReferenceEquals(null, obj)) return false;
            if (ReferenceEquals(this, obj)) return true;
            if (obj.GetType() != this.GetType()) return false;
            return Equals((MessageQueueSpecs) obj);
        }

        public string GetUid()
        {
            return typeof (MessageQueueSpecs) + Name + Direction + GetHashCode();
        }

To delegate the creation of message queues to an independent entity that can be passed to stakeholders via IoC, we define an IMessageQueueFactory as listed below:

 
  public interface IMessageQueueFactory
    {
        IMessageQueue CreateInboundQueue(MessageQueueSpecs specs);
        IMessageQueue CreateOutnboundQueue(MessageQueueSpecs specs);
    }

The interface can possibly be simplified using only one method but two methods gives the API clarity and also gives us the flexibility to define different parameters for inbound or outbound queues among others, possibly segregating the interface if need be.

The implementation of the IMessageQueueFactory depends on how many different types of message queues we want to support in the solution. To keep things simple, we will assume that only one type of message queue will be used in this solution and the one we choose is RabbitMQ.

The implementation of IMessageQueueFactory for RabbitMQ is as follows:

  public class RabbitMessageQueueFactory : IMessageQueueFactory
    {
        private readonly MemoryCache _cache = new MemoryCache("RabbitMessageQueueFactory");
        
        public IMessageQueue CreateInboundQueue(MessageQueueSpecs specs)
        {
            return GetOrCreateQueue(specs);
        }
        
        public IMessageQueue CreateOutnboundQueue(MessageQueueSpecs specs)
        {
            return GetOrCreateQueue(specs);
        }

        private IMessageQueue GetOrCreateQueue(MessageQueueSpecs specs)
        {
            var cacheKey = specs.GetUid();
            var queueObj = _cache.Get(cacheKey);
            if (queueObj != null)
                return (IMessageQueue) queueObj;

            var queue = new RabbitMessageQueue(specs);
            _cache.Add(cacheKey, queue, new CacheItemPolicy());

            return queue;
        }
    }

Creating inbound and outbound RabbitMQ queues follow a similar pattern based on our message queue implementation so construction is easy. To use our factory, we can register it with an IoC container such as Unity or AutoFac or create an instance and pass it to interested parties.

For the sake of completeness, RabbitMessageQueue and MessageQueueBase is implemented as follows:


   public sealed class RabbitMessageQueue : MessageQueueBase
    {
        private readonly ISerializer _serializer;
        private IConnection _connection;
        private IModel _channel;
        private QueueingBasicConsumer _consumer;

        public string ExchangeType
        {
            get { return GetProperty(ExchangeTypePropertyName, "topic"); }
        }

        public string Exchange
        {
            get { return GetProperty(ExchangePropertyName, "topic"); }
        }

        public RabbitMessageQueue(MessageQueueSpecs specs)
        {
            _serializer = specs.Serializer;
        
            CopyProperties(specs.AdditionalProperties);
            ReconcileProperties(specs);
            InitializeInboundQueue(specs);
            InitializeOutboundQueue(specs);
        }
        
        private void ReconcileProperties(MessageQueueSpecs specs)
        {
            ReconcileProperty(MessageTopicPropertyName, () => specs.MessageTopic);
            ReconcileProperty(ExchangePropertyName, () => specs.Address);
            ReconcileProperty(ExchangeTypePropertyName, () => specs.MessagePattern == MessagePattern.PublishSubscribe ? "topic" : "fanout");
        }

        private void CopyProperties(IEnumerable<KeyValuePair<string, string>> properties)
        {
            if (properties != null)
            {
                foreach (var property in properties)
                {
                    AddProperty(property.Key, property.Value);
                }
            }
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing && _channel != null)
            {
                _channel.Dispose();
                _connection.Dispose();
            }
        }

        protected override string GetAddress(string queueName)
        {
            throw new NotImplementedException();
        }

        private void CreateInboundQueue(MessageQueueSpecs specs)
        {
            var exchange = CreateChannel(specs);

            //2. create a non-durable, exclusive, autodelete queue with a generated name
            var result = _channel.QueueDeclare();
            var routingKey = specs.MessageTopic ?? string.Empty;
            //3. bind to the exclusive queue created above
            _channel.QueueBind(result.QueueName, exchange, routingKey);

            //4. now get message from queue
            _consumer = new QueueingBasicConsumer(_channel);
            _channel.BasicConsume(result.QueueName, true, _consumer);
        }

        private string CreateChannel(MessageQueueSpecs specs)
        {
            var hostName = specs.HostName ?? GetProperty(HostNamePropertyName, "localhost");
            var factory = new ConnectionFactory { HostName = hostName };
               
            _connection = factory.CreateConnection();
            _channel = _connection.CreateModel();

            _channel.ExchangeDeclare(Exchange, ExchangeType); 
            return Exchange;
        }

        private void CreateOutboundQueue(MessageQueueSpecs specs)
        {
            CreateChannel(specs);
        }

        public override void InitializeInboundQueue(MessageQueueSpecs specs)
        {
            Initialize(Direction.Inbound, specs.Address, specs.MessagePattern);
            // NOTE: for fanout, it apears as though we can use the same initializations defined in CreateInboundQueue
            CreateInboundQueue(specs);
        }

        public override void InitializeOutboundQueue(MessageQueueSpecs specs)
        {
            Initialize(Direction.Outbound, specs.Address, specs.MessagePattern);
            // NOTE: for fanout, it apears as though we can use the same initializations defined in CreateInboundQueue
            CreateOutboundQueue(specs);
        }

        public override void Send<T>(T message, string messageTopic = null)
        {
            var body = _serializer.MessageToBytes<T>(message);
            var exchange = GetProperty(ExchangePropertyName, Name);// "authentictions";
            if (string.IsNullOrEmpty(messageTopic))
                messageTopic = GetProperty(MessageTopicPropertyName, string.Empty);

            _channel.BasicPublish(exchange, messageTopic, null, body);
        }
    
        public override void Receive<T>(Action<T> onMessageReceived)
        {
            var ea = _consumer.Queue.Dequeue();
            var body = ea.Body;
            onMessageReceived.Invoke(_serializer.BytesToMessage<T>(body));
        }

        public override IMessageQueue GetResponseQueue()
        {
            throw new NotImplementedException();
        }

        public override IMessageQueue GetReplyQueue(Message message)
        {
            throw new NotImplementedException();
        }

        public override string ToString()
        {
            var properties = Properties;
            if (properties == null)
            {
                properties = new Dictionary<string, string>();
            }

            var propertyInfo = GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public);
            foreach (var pinfo in propertyInfo)
            {
                if (properties.ContainsKey(pinfo.Name)) continue;

                var value = pinfo.GetValue(this);
                properties.Add(pinfo.Name, value != null ? value.ToString() : string.Empty);    
            }

            var sb = new StringBuilder(100);
            foreach (var kvp in properties)
            {
                sb.AppendLine(string.Format("\t {0}:{1}", kvp.Key, kvp.Value));
            }
            return sb.ToString();
        }
    }

public abstract class MessageQueueBase : IMessageQueue
    {
        public const string ExchangePropertyName = "Exchange";
        public const string ExchangeTypePropertyName = "ExchangeType";
        public const string MessageTopicPropertyName = "MessageTopic";
        public const string HostNamePropertyName = "HostName";

        private readonly IDictionary<string, string> _properties = new Dictionary<string, string>(10);

        protected void Initialize(Direction direction, string name, MessagePattern pattern)
        {
            Name = name;
            Direction = direction;
            MessagePattern = pattern;
           
        }

        protected void ReconcileProperty(string name,Func<string> valueFactory)
        {
            if (!Properties.ContainsKey(name))
            {
                Properties.Add(name,  valueFactory.Invoke());
            }
        }

        public void AddProperty(string name, string value)
        {
            _properties.Add(name, value);
        }

        public string GetProperty(string propertyName, string defaultValue)
        {
            if (_properties.ContainsKey(propertyName))
                return _properties[propertyName];

            return defaultValue;
        }

        public string Name { get; private set; }
        public Direction Direction { get; private set; }
        public string Address { get; private set; }
        public MessagePattern MessagePattern { get; private set; }

        public IDictionary<string, string> Properties
        {
            get { return _properties; }
        }

        public abstract void InitializeInboundQueue(MessageQueueSpecs specs);

        public abstract void InitializeOutboundQueue(MessageQueueSpecs specs);

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        protected abstract void Dispose(bool disposing);
        protected abstract string GetAddress(string queueName);

        public void Send(Message message, string messageTopic = null)
        {
            Send<Message>(message, messageTopic);
        }

        public abstract void Send<T>(T message, string messageTopic = null) where T : class;

        public void Listen(Action<Message> onMessageReceived, string routingKey = null)
        {
            Listen<Message>(onMessageReceived, routingKey);
        }

        public virtual void Listen<T>(Action<T> onMessageReceived, string routingKey = null) where T : class
        {
            Console.WriteLine(" [*] Waiting for messages." +
                             "To exit press CTRL+C");

            while (true)
            {
                Receive(onMessageReceived);
            }
        }

        public abstract void Receive<T>(Action<T> onMessageReceived);

        public void Receive(Action<Message> onMessageReceived)
        {
            Receive<Message>(onMessageReceived);
        }
        public abstract IMessageQueue GetResponseQueue();
        public abstract IMessageQueue GetReplyQueue(Message message);
    }

Happy coding!

How do you organize core projects in your .NET solution

There has always been a constant struggle on how to organize core or infrastructural projects in my .NET solutions. See, I started back in the day of the Composite Application Block (CAB) and with the early version of the Microsoft Enterprise Libraries from the Patterns and Practices group. Ten years ago when you created a desktop solution using the CAB template you had an organizational structure that contained infrastructural projects like so:

infrastructure layout

With modules looking like this:

These modules use services defined in Infrastructure.Services but via dependency injection. Over the years, this pattern has influenced the structure of my past and current solutions.

While I do like the pattern, there has always been a persistent challenge of determining what goes where? The original premise of Infrastructure.Dictionary was to contain all business entity definitions or what we we call the business model. Infrastructure.Interface was supposed to contain service interfaces the idea being that these two projects together define the system API. What ended up happening as the solution became bigger is interfaces and UI elements started creeping into Infrastructure.Dictionary.

Recently, I decided to rethink this approach of having two separate projects:

All modules that reference Infrastructure.Interface, must also reference Infrastructure.Dictionary. In a solution containing 30 projects, there is a single project that references Instructure.Dictionary and not Infrastructure.Interface. This project which contains symbology editors for points, lines and polygons cannot be used deployed on its own,therefore, it must be deployed within the same process space in which Infrastructure.Dictionary has been loaded. Does it make sense to continue separating Infrastruture.Dictionary and Infrastructure.Interface projects. Should I just have a single project called Infrastructure.Core?

What are others doing?

Getting started with NServiceBus and RabbitMQ in 15 minutes

Assumptions:

You have downloaded and installed RabbitMQ.  To confirm your RabbitMQ service is running go to  the RabbitMQ Portal and ensure the service is running.

1. Create client class Library called Infrastructure.Messages and a folder in this libary called Events.
2. Create the following class in the Events folder:

  [Serializable]
    public class AuthInitiationRequestEvent 
    {
        public string EventSource { get; set; }
        public DateTime Timestamp { get; set; }
        public string Source { get; set; }
        public string UserName { get; set; }
      
        public override string ToString()
        {
            return string.Format("Timestamp:{3}, Event Source: {0}, Org: {1}, Source: {2}, User: {3} ", 
                EventSource,
                Source, UserName,
                Timestamp);
        }
    }

2. Create a new Console project called Publisher. This Publisher project will contain a client that publishes messages to a bus.

All instructions from this point uses the Publishers project.

3. Add a reference to NServiceBus and NServiceBus RabbitMQ using NuGet.

4. Create a class called AuthenticationClient that starts and stops as follows:

 public class AuthenticationClient 
    {
        public IBus Bus { get; private set; }

        public AuthenticationClient(IBus bus)
        {
            Bus = bus;
        }

        public void Start()
        {
            var random = new Random(100);
            var processName = Process.GetCurrentProcess().ProcessName;
            var processId = Process.GetCurrentProcess().Id;
            //var exchange = "authentications";
        
            while (true)
            {
                var stopWatch = new Stopwatch();
                stopWatch.Start();

                //2. create a message, that can be anything since it is a byte array
                for (var i = 0; i < 1000; i++)
                {
                    var orgId = random.Next(1000);
                    var authEvent = new AuthInitiationRequestEvent(i, "GearHeads" + orgId, String.Format("{0}:{1}", processId, processName));
                    SendMessage(authEvent);
                    Thread.Sleep(5);
                }

                stopWatch.Stop();
                Console.ReadLine();

                Console.WriteLine("====================================================");
                Console.WriteLine("[x] done sending 1000 messages in " + stopWatch.ElapsedMilliseconds);
                Console.WriteLine("[x] Sending reset counter to consumers.");

                Console.ReadLine();
            }
        }

        private void SendMessage<T>(T message)
        {
            Bus.Publish(message);
            Console.WriteLine(" [x] Sent {0}", message);
        }

        public void Stop()
        {
            Console.WriteLine("Authentication Service ended");
        }
    }

Now, we need to create an instance of this class, pass it a bus so that it can publish messages. First we need to create a bus and configure it.

5. Modify Program.Start to include the following lines of code:

  static void Main(string[] args)
        {
            var busConfiguration = new BusConfiguration();

            // this will be the name of this endpoint
            busConfiguration.EndpointName("Publishers.Authentications");

            // we are using JSON serialization
            busConfiguration.UseSerialization<JsonSerializer>();

            // we are using RabbitMQ as our messaging transport.  Other options are MSMQ
            busConfiguration.UseTransport<RabbitMQTransport>();

            // we are using In memory persistence for messages
            busConfiguration.UsePersistence<InMemoryPersistence>();

              // NOTE: this is important and has to be set on publisher and subscriber endpoints.
            // We are using unobstrusive mode, so our messages/events do not have to implement IMessage, IEvent, etc
            var conventionsBuilder = busConfiguration.Conventions();
            conventionsBuilder.DefiningEventsAs(t => t.Namespace != null && t.Namespace == "Infrastructure.Messages.Events");         
         
            busConfiguration.EnableInstallers();
            
            // we create the bus
            var startableBus = Bus.Create(busConfiguration);
            using (var bus = startableBus.Start())
            {
               new AuthenticationClient(bus).Start();
            }
        }

All good work so far. Now we need to establish configuration to tell RabbitMQ. When using RabbitMQ directly, you specify this when constructing the ConnectionFactory. We also need to tell NServiceBus the destination queue for each type of message. When using RabbitMQ directly, you specify this when declaring an exchange on the connection channel object.

7. To configure the location of the broker using RabbitMQ we add a connectionString element as follows:

  <connectionStrings>
    <add name="NServiceBus/Transport" connectionString="host=localhost"/>
  </connectionStrings>

8. If you have followed all these steps so far, compile and run the project and you should see the messages being sent and written to the console.

9. To define the queue or exchange where we want this messages to be sent to, add the following lines to app.Config:

  <UnicastBusConfig>
    <MessageEndpointMappings>
      <add Assembly="Infrastructure.Messages" Namespace="Infrastructure.Messages.Events" Endpoint="Publishers.Authentications" />
    </MessageEndpointMappings>
  </UnicastBusConfig>

We are basically creating an AuthInitiationRequestEvent with some properties and sending this off to the bus. We are sending these messages to an exchange called “Publishers.Authentications”. This could have been called anything. In RabbitMQ, a exchange represents a queue for a specific set of messages. Subscribers interested in these messages will have to listen to the same queue which in this case is called Publishers.Authentications.

10. Before running the project, add this configuration section to app.config:

  <configSections>

<section name="UnicastBusConfig" type="NServiceBus.Config.UnicastBusConfig, NServiceBus.Core"/>
  </configSections>

11. If you run the AuthClient project, now you should see messages being printed to the console.

All of this work has been to create the publisher of messages to the bus. Now, let us move to the subscriber. Its job will be simple. Subscribe to the messages and write the messages to the Visual Studio console.

12. Create a new Console project called Subscribers. This project will contain a service that will subscribe to a certain type of message published onto the bus and print them to the console. Not only is the subscriber interested in a certain type of message, it will listen only to messages published onto a certain queue.

The following instructions now refer to Subscribersproject.
13. Using NuGet, add references to NServiceBus and NServiceBus RabbitMQ.
14. Create an AuthenticationService class that implements IHandleMessages interface defined NServiceBus core assembly.

public class AuthenticationService : IHandleMessages<AuthInitiationRequestEvent>
    {
        public void Handle(AuthInitiationRequestEvent message)
        {
            Console.WriteLine(message);
        }
    }

How do we hook this subscriber to the bus? By default, NServiceBus uses auto subscription by scanning assemblies for IHandleMessage implementations. But we need to configure the bus and create the subscriber’s entry point

15. Add the following lines of code to Program.Start in Subscribers project.

  static void Main(string[] args)
        {
            var busConfiguration = new BusConfiguration();

            // this will be the name of this endpoint
            busConfiguration.EndpointName("AuthEventConsumer.ConsoleWriter");

            // we are using JSON serialization
            busConfiguration.UseSerialization<JsonSerializer>();

            // we are using RabbitMQ as our messaging transport.  Other options are MSMQ
            busConfiguration.UseTransport<RabbitMQTransport>();

            // we are using In memory persistence for messages
            busConfiguration.UsePersistence<InMemoryPersistence>();

   // NOTE: this is important and has to be set on publisher and subscriber endpoints.
            // We are using unobstrusive mode, so our messages/events do not have to implement IMessage, IEvent, etc
            var conventionsBuilder = busConfiguration.Conventions();
            conventionsBuilder.DefiningEventsAs(t => t.Namespace != null && t.Namespace == "Infrastructure.Messages.Events");                 

            busConfiguration.EnableInstallers();
           
            var startableBus = Bus.Create(busConfiguration);
            using (startableBus.Start())
            {
                Console.WriteLine("To exit, Ctrl + C");
                Console.ReadLine();
            }
        }

16. Since our broker is running on the local machine, open app.config for the Subscribers project and add the following lines:

  <connectionStrings>
    <add name="NServiceBus/Transport" connectionString="host=localhost"/>
  </connectionStrings>

We also need to tell the subscriber the queue or exchange from which it should retrieve its messages from. We do this by configuring a MessageEndpointMapping as follows:

  <UnicastBusConfig>
    <MessageEndpointMappings>
      <add Assembly="Infrastructure.Messages" Namespace="Infrastructure.Messages.Events" Endpoint="Publishers.Authentications" />
    </MessageEndpointMappings>
  </UnicastBusConfig>

What we are saying here is that messages in Infrastructure.Message assembly within the Infrastructure.Messages.Events namespace should be retrieve from Publishers.Authentications queue or endpoint. Please note that the subscriber endpoint must match the publisher’s endpoint.

When sending a message using pub/sub with RabbitMQ you need to specify at a minimum the name of an exchange where the publisher sends the message and where the subscriber should listen for messages. In addition, you need to specify the machine on which your RabbitMQ broker is running on. The NServiceBus endpoint name, I am guessing, serves as the RabbitMQ exchange, while the connection setting of host=localhost specifies the machine on which the broker is running.

17. Again, for the configuration to not throw an exception, you will need an NServiceBus configuration section as follows:

  <configSections>

<section name="UnicastBusConfig" type="NServiceBus.Config.UnicastBusConfig, NServiceBus.Core"/>
  </configSections>

As you’ve probably determined, the settings in app.config for the publisher and subscriber should look exactly the same as follows:

<?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>
  <connectionStrings>
    <add name="NServiceBus/Transport" connectionString="host=localhost"/>
  </connectionStrings>
  <UnicastBusConfig>
    <MessageEndpointMappings>
      <add Assembly="Infrastructure.Messages" Endpoint="Publishers.Authentications" />
    </MessageEndpointMappings>
  </UnicastBusConfig>
  <MessageForwardingInCaseOfFaultConfig ErrorQueue="error" />
</configuration>

18. Run both client and producer projects and see what happens… 🙂