Consuming RabbitMQ Messages in ASP.NET MVC

TLDR: You want to set up RabbitMQ in an ASP.NET process to persistently consume messages, and do something (like dump them to a database). This has to be independent of the life-cycle of an ASP.NET/MVC (W3WP.exe) worker process.

I experimented with several variations of the Hello World C# RabbitMQ tutorial. In the end, two changes made this work, and persistently consume messages, from my ASP.NET MVC application:

  • I kept static references to IConnection and IModel
  • I removed the using statements around the connection and model

What’s confusing is that static variables with using statements doesn’t work; it consumes all messages, but only displays the oldest one.

Regardless, the set of changes is relatively small. Here’s what I did in Global.asax.cs:

  • Declare IConnection and IModel static variables in your MvcApplication class
  • On Application_Start, paste the entire sample; make sure you change the use of connection and channel to use your static versions, and not to be in using statements
  • Add an Application_End method that closes the channel and connection

Below is a typical freshly-generated Global.asax.cs for MVC5, with these changes:

public class MvcApplication : System.Web.HttpApplication
    {
        private static IConnection connection;
        private static IModel channel;

        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            GlobalConfiguration.Configure(WebApiConfig.Register);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);

            this.SetupRabbitMqSubscriber();
        }

        protected void Application_End()
        {
            channel.Close(200, "Goodbye!");
            connection.Close();
        }

        private void SetupRabbitMqSubscriber()
        {
            var factory = new ConnectionFactory() { HostName = "localhost" };
            connection = factory.CreateConnection();
            channel = connection.CreateModel();
            channel.QueueDeclare(queue: "hello", durable: false, exclusive: false, autoDelete: false, arguments: null);

            var consumer = new EventingBasicConsumer(channel);
            consumer.Received += (model, ea) =>
            {
                var body = ea.Body;
                var message = Encoding.UTF8.GetString(body);
                // Display message
            };
            channel.BasicConsume(queue: "hello", noAck: true, consumer: consumer);
        }
    }

This essentially keeps a persistent connection open to the RabbitMQ server, so long as the w3wp.exe process survives.

About Ashiq Alibhai, PMP

Ashiq has been coding C# since 2005. A desktop, web, and RIA application developer, he's touched ASP.NET MVC, ActiveRecord, Silverlight, NUnit, and all kinds of exciting .NET technologies. He started C# City in order to accelerate his .NET learning.
This entry was posted in Libraries, Web and tagged , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *