RabbitMQ Topic Exchange in C# to Publish or Consume Messages

In rabbitmq, Topic Exchange will perform a wildcard match between the routing key and the routing pattern specified in the binding to publish messages to the queue.

 

Generally, in rabbitmq when the producer creates a message that will not directly send to the queue, instead first the message will be sent to exchanges, then after that, a routing agent reads and sends it to the appropriate queue with help of header attributes, bindings, and routing keys.

 

In rabbitmq, we have different types of exchanges available are

 

  • Direct
  • Fanout
  • Topic
  • Headers

To know more about exchanges in rabbitmq, check this RabbitMQ Exchanges.

 

In Topic Exchange, the routing key must be defined with a dot(.) delimiter like “*.bombay.*” or “#.bombay” or “Bombay.#” then only the message will be added to the queue otherwise the messages will not be stored in the queue.

 

For example, I have 2 queues one is Bombay and another one is Delhi then the user must send a routing key that will match the pattern of the routing key which we defined while binding the queue to exchange then only the message will be added to the queue, else the message will be lost.

 

Here, while defining a routing key pattern if we use a * (star) then that can be a substitute for exactly one word and # (hash) can be a substitute for zero or more words.

 

Following is the pictorial representation of message flow in rabbit topic exchange.

 

RabbitMQ Topic Exchange Process Flow Diagram

 

Now, we will learn how to use Topic Exchange to push and read messages from rabbitmq in c# or .net application with examples.

C# Create RequestRabbitMQ Application

Let’s create a simple console application with the Name “RequestRabbitMQ” as shown below to publish messages to the rabbitmq queue using topic exchange in c#.

 

Create C# Console Application to Publish Messages to RabbitMQ

 

After creating an application, now we will add the “RabbitMQ.Client” NuGet package in our c# application to communicate with rabbitmq server to publish or consume messages from queues in rabbitmq.

Add RabbitMQ.Client NuGet Package

In c#, we can publish or consume messages from rabbitmq by using RabbitMQ.Client NuGet package for that, right-click on your application and select Manage NuGet Packages as shown below.

 

C# Add RabbitMQ.Client Nuget Package Reference to Application

 

Now search for RabbitMQ.Client package and install it in your application as shown below.

 

C# Adding RabbitMQ.Client NuGet Package Reference

 

Following is another way to install RabbitMQ.Client package by using Package Manager Console as shown below by entering the following command.

 

Command to install - Install-Package RabbitMQ.Client -Version 5.1.0 

 

C# Add RabbitMQ.Client Nuget Package Reference from Package Manager Console

 

Before we start writing a code in c# to publish messages to rabbitmq, we will create a topic exchange, queue and will bind a queue to exchange using the web admin console.

RabbitMQ Create Topic Exchange

To create an exchange in rabbitmq web management portal, open http://localhost:15672/#/exchanges url and then go to Add a new exchange panel and enter details as shown below by selecting Type as “topic” and click on Add exchange button to create an exchange (topic.exchange).

 

Create Topic Exchange in RabbitMQ Management Console

 

After creating an exchange (topic.exchange), next, we will create two queues (topic.bombay.queue and topic.delhi.queue) with different routing keys and bind them to the exchange (“topic.exchange”) in the web management portal.

RabbitMQ Create a Queue

To create a queue in rabbitmq web management portal, open http://localhost:15672/#/queues url and then go to Add a new queue panel and enter details as shown below, and click on Add queue button to create a queue (topic.bombay.queue).

 

Create a Queue in RabbitMQ Web Management Portal

 

Same way, repeat the above steps to create another queue with the name “topic.delhi.queue” as shown below.

 

Create a Queue in RabbitMQ Web Management Portal

 

After creating the queues, if you go to the Queues panel it will show the list of available queues as shown below.

 

RabbitMQ List of Available Queues

 

After adding queues, next we will bind defined queues to exchange (“topic.exchange”).

RabbitMQ Bind Queue to Exchange

To bind a queue with an exchange, click on queue (topic.bombay.queue) name, then the Bindings panel will expand and enter details like exchange name as “topic.exchange” and routing key pattern as “*.Bombay.*” and click on Bind button like as shown below.

 

RabbitMQ Bind Queue to Topic Exchange

 

After binding a queue (topic.bombay.queue) to exchange (topic.exchange) with routing key pattern (*.Bombay.*), the binding will be as shown below.

 

Here, the routing pattern *.Bombay.* means it will accept a routing key which will contain any text on/before Bombay like “Order.Bombay.Pizza”, “Book.Bombay.Hotels”, “Visit.Bombay.Parks”, “List.Bombay.Colleges”, etc.

 

RabbitMQ Queue Binding with Topic Exchange

 

Same way bind a queue (topic.delhi.queue) with an exchange (topic.exchange) using the routing key pattern (Delhi.#) as shown below.

 

RabbitMQ Bind Queue to Topic Exchange

 

After binding a queue (topic.delhi.queue) to exchange (topic.exchange) with routing key pattern (Delhi.#), the binding will be as shown below.

 

RabbitMQ Queue Binding with Topic Exchange

 

After the completion of binding a queue to exchange, now we will publish messages from the c# application to rabbitmq queue using RabbitMQ.Client service.

C# Publish Messages to RabbitMQ

To publish messages to the rabbitmq queue, add a class with the name “Topicmessages.cs” in your application as shown below.

 

C# Create a Class to Publish Messages to RabbitMQ using Topic Exchange

 

Now, open the Topicmessages.cs class file and write the code as shown below.

Topicmessages.cs

using RabbitMQ.Client;
using System;
using System.Text;

public class Topicmessages
{
   private const string UName = "guest";
   private const string PWD = "guest";
   private const string HName = "localhost";

   public void SendMessage()
   {
      //Main entry point to the RabbitMQ .NET AMQP client
      var connectionFactory = new ConnectionFactory()
      {
         UserName = UName,
         Password = PWD,
         HostName = HName
      };
      var connection = connectionFactory.CreateConnection();
      var model = connection.CreateModel();
      var properties = model.CreateBasicProperties();
      properties.Persistent = false;
      byte[] messagebuffer = Encoding.Default.GetBytes("Message from Topic Exchange 'Bombay' ");
      model.BasicPublish("topic.exchange", "Message.Bombay.Email", properties, messagebuffer);
      Console.WriteLine("Message Sent From: topic.exchange ");
      Console.WriteLine("Routing Key: Message.Bombay.Email");
      Console.WriteLine("Message Sent");
   }
}

If you observe the above code, to establish a connection with rabbitmq server we are passing the required credentials along with the HostName to ConnectionFactory() method. After that, we are publishing a message (Message from Topic Exchange 'Bombay') to the queue by passing required parameters like an exchange, routing key, properties, and message to the BasicPublish method.

 

Here, we are sending a routing key as “Message.Bombay.Email” and it will match with the routing pattern (*.Bombay.*) and publish data to the respective queue (topic.bombay.queue).

 

Now open Program.cs class file and write a code in the Main method to call Topicmessages.cs class to get messages from rabbitmq.

Program.cs

Following is the code which we need to write in Program.cs class file Main method to publish messages to rabbitmq server.

 

using System;

namespace RequestRabbitMQ
{
  class Program
  {
    static void Main(string[] args)
    {
      Topicmessages topicmessages = new Topicmessages();
      topicmessages.SendMessage();
      Console.ReadLine();
    }
  }
}

When we execute the above c# program, we will get the result as shown below. 

 

C# Publish Message to RabbitMQ using Topic Exchange Example Result

 

After executing the above program, if we check the queue (topic.bombay.queue) details in the rabbitmq web management portal, the Ready column is having 1 as shown below which means the message was published successfully to the topic.bombay.queue.

 

RabbitMQ Queues with Published Messages

 

After publishing a message to the queue, now will learn how to consume or get messages from rabbitmq using RabbitMQ.Client service in c# or .net application with examples

C# Create RabbitMQConsumer Application

Let’s create a simple console application with the Name “RabbitMQConsumer” as shown below to consume or read messages from the rabbitmq queue.

 

C# Console Application to Read or Consume Messages from RabbitMQ

 

After creating an application, now add “RabbitMQ.Client” NuGet package reference to your application as we did in publishing the application to communicate with the rabbitmq server.

C# Consume Messages from RabbitMQ

After installing RabbitMQ.Client, next add a class with the name “MessageReceiver.cs” in your application as shown below to read or get messages from queues in rabbitmq.

 

C# Console Application Add New Class File to Read Messages from RabbitMQ

 

Now, open MessageReceiver.cs class file and write the code as shown below.

MessageReceiver.cs

using System;
using System.Text;
using RabbitMQ.Client;

namespace RabbitMQConsumer
{
   public class MessageReceiver : DefaultBasicConsumer
   {
     private readonly IModel _channel;
     public MessageReceiver(IModel channel)
     {
       _channel = channel;
     }
     public override void HandleBasicDeliver(string consumerTag, ulong deliveryTag, bool redelivered, string exchange, string routingKey, IBasicProperties properties, byte[] body)
     {
        Console.WriteLine($"Consuming Topic Message");
        Console.WriteLine(string.Concat("Message received from the exchange ", exchange));
        Console.WriteLine(string.Concat("Consumer tag: ", consumerTag));
        Console.WriteLine(string.Concat("Delivery tag: ", deliveryTag));
        Console.WriteLine(string.Concat("Routing tag: ", routingKey));
        Console.WriteLine(string.Concat("Message: ", Encoding.UTF8.GetString(body)));
        _channel.BasicAck(deliveryTag, false);
     }
   }
}

If you observe the above code, we created a MessageReceiver class and it’s inheriting from DefaultBasicConsumer class of RabbitMQ.Client service and we implemented a HandleBasicDeliver method by overriding it to receive a message body.

 

Now open Program.cs class file and write a code in the Main method to call MessageReceiver.cs class to get messages from rabbitmq.

Program.cs

Following is the code which we need to write in Program.cs class file Main method to receive data from rabbitmq server.

 

using System;
using RabbitMQ.Client;

namespace RabbitMQConsumer
{
  class Program
  {
    private const string UName = "guest";
    private const string Pwd = "guest";
    private const string HName = "localhost";

    static void Main(string[] args)
    {
       ConnectionFactory connectionFactory = new ConnectionFactory
       {
         HostName = HName,
         UserName = UName,
         Password = Pwd,
       };
       var connection = connectionFactory.CreateConnection();
       var channel = connection.CreateModel();
       // accept only one unack-ed message at a time
       // uint prefetchSize, ushort prefetchCount, bool global
       channel.BasicQos(0, 1, false);
       MessageReceiver messageReceiver = new MessageReceiver(channel);
       channel.BasicConsume("topic.bombay.queue", false, messageReceiver);
       Console.ReadLine();
    }
  }
}

If you observe the above example, to establish a connection with rabbitmq server we are passing the required credentials along with the HostName to ConnectionFactory() method. After that, we created a connection and channel by calling the “CreateConnection” and “CreateModel” methods and we set a prefetchCount to 1, so that it tells RabbitMQ not to give more than one message at a time to the worker.

 

Next, we created an instance of MessageReceiver class and passed IModel (channel) to it, in the final step we called the “BasicConsume” method and passed the queue name to it “topic.bombay.queue” along with we have set autoAck to false and passed the messageReceiver instance to it. 

 

Here, prefetchCount is used to tell RabbitMQ not to give more than one message at a time to the worker. Or, in other words, don't dispatch a new message to a worker until it has been processed and acknowledged the previous one. Instead, it will dispatch to the next worker that is not still busy. 

 

When we execute our application, we will get a message from the queue (topic.bombay.queue) as shown below.

 

C# Consume Messages from RabbitMQ using Topic Exchange Example Result

 

In the same way, we can publish and consume messages from the “topic.delhi.queue” queue by using routing keys like “Delhi.Pizza”, “Delhi.Hotels”, “Delhi.Parks”, “Delhi.Colleges”, etc. based on our requirements.