CloudAMQP with .NET
We recommend the RabbitMQ .NET client, maintained by the RabbitMQ team. Version 7 has an async API, and recovers connections and consumers automatically.
dotnet new console --name AmqpExample
cd AmqpExample
dotnet add package RabbitMQ.Client
Publish and consume
Set CLOUDAMQP_URL to the AMQP URL from your instance’s details page in the
CloudAMQP console. Without it, the examples connect to a local broker.
Save the connection helper as Amqp.cs:
using RabbitMQ.Client;
namespace AmqpExample;
public static class Amqp
{
// Automatic recovery is on by default: the connection, channels and consumers are restored after a network failure
public static Task<IConnection> ConnectAsync()
{
var url = Environment.GetEnvironmentVariable("CLOUDAMQP_URL") ?? "amqp://guest:guest@localhost";
var factory = new ConnectionFactory { Uri = new Uri(url) };
return factory.CreateConnectionAsync();
}
}
Save the publisher as Publisher.cs:
using System.Text;
using RabbitMQ.Client;
namespace AmqpExample;
public static class Publisher
{
// With confirmation tracking, BasicPublishAsync returns once the broker has confirmed the message.
// This opens a channel per call; when publishing many messages, create the channel once and reuse it.
public static async Task PublishAsync(IConnection connection, string queue, string message)
{
var options = new CreateChannelOptions(publisherConfirmationsEnabled: true, publisherConfirmationTrackingEnabled: true);
await using var channel = await connection.CreateChannelAsync(options);
await channel.QueueDeclareAsync(queue, durable: true, exclusive: false, autoDelete: false);
var properties = new BasicProperties { Persistent = true };
await channel.BasicPublishAsync("", queue, mandatory: true, properties, Encoding.UTF8.GetBytes(message));
Console.WriteLine($" [x] Sent '{message}'");
}
}
Save the consumer as Worker.cs:
using System.Text;
using RabbitMQ.Client;
using RabbitMQ.Client.Events;
namespace AmqpExample;
public static class Worker
{
// The message is acked after the handler has processed it
public static async Task ConsumeAsync(IChannel channel, string queue, Func<string, Task> handler)
{
await channel.QueueDeclareAsync(queue, durable: true, exclusive: false, autoDelete: false);
await channel.BasicQosAsync(prefetchSize: 0, prefetchCount: 10, global: false);
var consumer = new AsyncEventingBasicConsumer(channel);
consumer.ReceivedAsync += async (_, delivery) =>
{
await handler(Encoding.UTF8.GetString(delivery.Body.Span));
await channel.BasicAckAsync(delivery.DeliveryTag, multiple: false);
};
await channel.BasicConsumeAsync(queue, autoAck: false, consumer);
}
}
Replace the generated Program.cs with this entry point:
using AmqpExample;
await using var connection = await Amqp.ConnectAsync();
switch (args.FirstOrDefault())
{
case "publish":
await Publisher.PublishAsync(connection, "hello", "Hello CloudAMQP!");
break;
case "worker":
await using (var channel = await connection.CreateChannelAsync())
{
await Worker.ConsumeAsync(channel, "hello", message =>
{
Console.WriteLine($" [x] Received '{message}'");
return Task.CompletedTask;
});
Console.WriteLine(" [*] Waiting for messages. To exit press CTRL+C");
var exit = new TaskCompletionSource();
Console.CancelKeyPress += (_, e) => { e.Cancel = true; exit.TrySetResult(); };
await exit.Task;
}
break;
default:
Console.Error.WriteLine("Usage: AmqpExample publish|worker");
return 1;
}
return 0;
Run dotnet run -- worker in one terminal and dotnet run -- publish in another.
A runnable example is in dotnet/rabbitmq-client in cloudamqp/examples.
Good to know
- Connect with the URL.
new ConnectionFactory { Uri = new Uri(url) }, where the URL is the one on your instance’s details page in the CloudAMQP console. Withamqps://the server certificate is verified. - Automatic recovery is on by default: after a network failure the client reconnects and restores channels, queues and consumers.
- Version 7 is async-only. Code written for 6.x (
CreateModel,EventingBasicConsumer) needs to move to the*Asyncmethods; see the migration guide. - Ack after processing, and set a prefetch limit with
BasicQosAsync, so a consumer doesn’t buffer more messages than it can handle.