Send and Receive Messages with .NET SDK
Architecture Overview
┌──────────────────┐ ┌──────────────────┐
│ Sender Console │ │ Receiver Console │
│ App │ │ App │
└────────┬─────────┘ └────────┬─────────┘
│ │
│ ServiceBusSender ServiceBusReceiver
│ │
▼ ▼
┌─────────────────────────────────────────────────────────────────────┐
│ Azure Service Bus Namespace │
│ ┌───────────────────────────────────────────────────────────────┐ │
│ │ orders-queue │ │
│ │ [Msg1] [Msg2] [Msg3] ──────────────────────────▶ [Consumer] │ │
│ └───────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────┘
Prerequisites
| Requirement | Details |
|---|---|
| .NET SDK | 8.0+ |
| Service Bus Namespace | From previous tutorial |
| Queue | orders-queue created |
| IDE | Visual Studio / VS Code / Rider |
Step 1 — Create a Console Application
dotnet new console -n ServiceBusDemo
cd ServiceBusDemo
Step 2 — Install the NuGet Package
dotnet add package Azure.Messaging.ServiceBus
Step 3 — Send a Single Message
using Azure.Messaging.ServiceBus;
const string connectionString = "<YOUR_CONNECTION_STRING>";
const string queueName = "orders-queue";
await using var client = new ServiceBusClient(connectionString);
ServiceBusSender sender = client.CreateSender(queueName);
var message = new ServiceBusMessage("Hello, Service Bus!");
await sender.SendMessageAsync(message);
Console.WriteLine("Message sent successfully.");

Step 4 — Send a Batch of Messages
using Azure.Messaging.ServiceBus;
const string connectionString = "<YOUR_CONNECTION_STRING>";
const string queueName = "orders-queue";
await using var client = new ServiceBusClient(connectionString);
ServiceBusSender sender = client.CreateSender(queueName);
using ServiceBusMessageBatch batch = await sender.CreateMessageBatchAsync();
for (int i = 1; i <= 10; i++)
{
var message = new ServiceBusMessage($"Order #{i}");
if (!batch.TryAddMessage(message))
{
throw new Exception($"Message {i} too large for batch.");
}
}
await sender.SendMessagesAsync(batch);
Console.WriteLine($"Sent batch of {batch.Count} messages.");
Step 5 — Receive Messages
using Azure.Messaging.ServiceBus;
const string connectionString = "<YOUR_CONNECTION_STRING>";
const string queueName = "orders-queue";
await using var client = new ServiceBusClient(connectionString);
ServiceBusReceiver receiver = client.CreateReceiver(queueName);
Console.WriteLine("Receiving messages...");
IReadOnlyList<ServiceBusReceivedMessage> messages =
await receiver.ReceiveMessagesAsync(maxMessages: 10, maxWaitTime: TimeSpan.FromSeconds(5));
foreach (ServiceBusReceivedMessage msg in messages)
{
Console.WriteLine($"Received: {msg.Body}");
await receiver.CompleteMessageAsync(msg);
}
Console.WriteLine($"Processed {messages.Count} messages.");

Step 6 — Complete vs Abandon Messages
| Action | Method | Effect |
|---|---|---|
| Complete | CompleteMessageAsync() | Removes message from queue |
| Abandon | AbandonMessageAsync() | Returns message to queue, increments delivery count |
| Defer | DeferMessageAsync() | Moves to deferred state, receive by sequence number |
| Dead-letter | DeadLetterMessageAsync() | Moves to dead-letter sub-queue |
foreach (ServiceBusReceivedMessage msg in messages)
{
try
{
ProcessOrder(msg.Body.ToString());
await receiver.CompleteMessageAsync(msg);
}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex.Message}. Abandoning message.");
await receiver.AbandonMessageAsync(msg);
}
}
Step 7 — Connection String vs Managed Identity
Connection String (development)
await using var client = new ServiceBusClient(connectionString);
Managed Identity (production recommended)
dotnet add package Azure.Identity
using Azure.Identity;
using Azure.Messaging.ServiceBus;
const string fullyQualifiedNamespace = "sb-demo-namespace.servicebus.windows.net";
await using var client = new ServiceBusClient(
fullyQualifiedNamespace,
new DefaultAzureCredential());
| Approach | Use Case | Security |
|---|---|---|
| Connection String | Local dev, quick tests | Shared secret — rotate regularly |
| Managed Identity | Production, Azure-hosted apps | No secrets to manage |
| Workload Identity | Kubernetes / AKS | Federated token exchange |
Assign RBAC Role for Managed Identity
az role assignment create \
--assignee <PRINCIPAL_ID> \
--role "Azure Service Bus Data Sender" \
--scope /subscriptions/<SUB_ID>/resourceGroups/rg-servicebus-demo/providers/Microsoft.ServiceBus/namespaces/sb-demo-namespace

Summary
- ✅ Created a .NET console app with the Service Bus SDK
- ✅ Sent single and batch messages
- ✅ Received and completed messages
- ✅ Understood Complete vs Abandon semantics
- ✅ Configured Managed Identity for production
Previous: Create a Service Bus Namespace and Queue