The .NET Core Configuration system is extremely powerful and flexible. One of the features that I use the most is its capability to bind structured settings from a source (e.g. JSON file) to a C# object.
A very good example of this is obtaining RabbitMQ settings so that you can populate the ConnectionFactory
. In the past, I’ve created a DTO (class) for this, and a parser that could populate this class based on a connection string format that I invented on the spot out of necessity. The good news is that you don’t have to do this any more. .NET Core configuration allows you to bind your config to an object, even if it’s coming from a third party library. Let’s see how.
Typical RabbitMQ Configuration
First, in order to use RabbitMQ, we need to install the RabbitMQ Client NuGet package.
Install-Package RabbitMQ.Client
Next, we’ll typically create a connection by means of the ConnectionFactory
. We’ll need to populate the necessary fields, whether directly or by reading them from config. Technically, most of the settings below are not necessary because defaults are assumed if not provided, but we’ll include them anyway as we’re not assuming everyone is connecting to RabbitMQ on localhost.
var connectionFactory = new ConnectionFactory() { HostName = "localhost", UserName = "guest", Password = "guest", VirtualHost = "/", AutomaticRecoveryEnabled = true, RequestedHeartbeat = 30 };
If we use .NET Core configuration, we don’t even need to do this any more.
Connection Settings From JSON File
Let’s start by adding a new text file to the project called appsettings.json. From its properties, change it to copy to the output directory on build (Copy always and Copy if newer are both fine). In the file, we’ll add the JSON equivalent of what we have in ConnectionFactory
above:
{ "RabbitMqConnection": { "HostName": "localhost", "Username": "guest", "Password": "guest", "VirtualHost": "/", "AutomaticRecoveryEnabled": true, "RequestedHeartbeat": 30 } }
Now, we need a way to read this JSON file and bind it to a ConnectionFactory
object. To do that, we need the following NuGet packages:
Install-Package Microsoft.Extensions.Configuration Install-Package Microsoft.Extensions.Configuration.Json Install-Package Microsoft.Extensions.Configuration.Binder
The .NET Core configuration system is split into multiple packages, so you can bring in only what you actually need. The first package is the heart of the framework, and you don’t need to install it directly because the second and third packages will both bring it in as a dependency when you install them. As for the Json and Binder packages, we’ll see what they do in a minute.
.NET Core configuration is loaded by means of a ConfigurationBuilder
object. In our case, we’ll have:
var config = new ConfigurationBuilder() .AddJsonFile("appsettings.json") .Build();
The AddJsonFile()
extension method is provided by the Json package (the second one we installed earlier). The result of this is an object which implements IConfigurationRoot
, and we can use this to read our settings.
Next, we’ll prepare an empty ConnectionFactory
object that the binder will populate from the configuration in the next step.
var connectionFactory = new ConnectionFactory();
Finally, we can bind the entire “RabbitMqConnection” section of the appsettings.json file to our ConnectionFactory
object, using the Bind()
method (provided via the Binder package we installed earlier):
config.GetSection("RabbitMqConnection").Bind(connectionFactory);
If the key-value pairs in the JSON section match properties on the connectionFactory
object, they will be set. You’ll know it worked because RequestedHeartbeat
has a default value of 60, but it will be overridden by the value of 30 from appsettings.json.
Testing Connectivity
Now that you are populating the ConnectionFactory
, you can connect in the same way as you used to before. This should suffice, as you’ll get an exception if your connection settings are incorrect:
using (var conn = connectionFactory.CreateConnection()) { Console.WriteLine("Connected!"); // ... Console.ReadLine(); }
But if you want to make damn sure that you can actually interact with RabbitMQ, you can write a minimal consumer, and then send it messages via the Management Plugin’s Web UI:
using (var conn = connectionFactory.CreateConnection()) using (var channel = conn.CreateModel()) { Console.WriteLine("Connected!"); const string queueName = "madrid"; channel.QueueDeclare(queueName, true, false, false, null); var consumer = new EventingBasicConsumer(channel); consumer.Received += (s, a) => Console.WriteLine("Message received!"); channel.BasicConsume(queueName, true, consumer); Console.ReadLine(); }
Wondering about the name of the queue? It’s because I found lots of them in Madrid. No kidding:
Summary
The point here was to show you how you can read settings from a section of a JSON file and have it directly deserialized into an object, using the binder feature of .NET Core configuration. The example here is specific to RabbitMQ, but you can use the same approach with any class you like, as long as the properties have public setters.
Also, remember that .NET Core configuration actually targets .NET Standard. That means you can use it not only with .NET Core apps, but also in the full .NET Framework, and any other compatible runtimes.