Get started with Azure Service Bus topics and subscriptions (.NET)

This quickstart shows how to send messages to a Service Bus topic and receive messages from a subscription to that topic by using the Azure.Messaging.ServiceBus .NET library.

In this quickstart, you'll do the following steps:

  1. Create a Service Bus namespace, using the Azure portal.
  2. Create a Service Bus topic, using the Azure portal.
  3. Create a Service Bus subscription to that topic, using the Azure portal.
  4. Write a .NET console application to send a set of messages to the topic.
  5. Write a .NET console application to receive those messages from the subscription.

Note

This quick start provides step-by-step instructions to implement a simple scenario of sending a batch of messages to a Service Bus topic and receiving those messages from a subscription of the topic. For more samples on other and advanced scenarios, see Service Bus .NET samples on GitHub.

  • This quick start shows you two ways of connecting to Azure Service Bus: connection string and passwordless. The first option shows you how to use a connection string to connect to a Service Bus namespace. The second option shows you how to use your security principal in Azure Active Directory and the role-based access control (RBAC) to connect to a Service Bus namespace. You don't need to worry about having hard-coded connection string in your code or in a configuration file or in secure storage like Azure Key Vault. If you are new to Azure, you may find the connection string option easier to follow. We recommend using the passwordless option in real-world applications and production environments. For more information, see Authentication and authorization.

Prerequisites

If you're new to the service, see Service Bus overview before you do this quickstart.

  • Azure subscription. To use Azure services, including Azure Service Bus, you need a subscription. If you don't have an existing Azure account, you can sign up for a trial subscription.
  • Visual Studio 2022. The sample application makes use of new features that were introduced in C# 10. You can still use the Service Bus client library with previous C# language versions, but the syntax may vary. To use the latest syntax, we recommend that you install .NET 6.0 or higher and set the language version to latest. If you're using Visual Studio, versions before Visual Studio 2022 aren't compatible with the tools needed to build C# 10 projects.

Create a namespace in the Azure portal

To begin using Service Bus messaging entities in Azure, you must first create a namespace with a name that is unique across Azure. A namespace provides a scoping container for Service Bus resources within your application.

To create a namespace:

  1. Sign in to the Azure portal

  2. In the left navigation pane of the portal, select All services, select Integration from the list of categories, hover the mouse over Service Bus, and then select Create on the Service Bus tile.

    Image showing selection of Create a resource, Integration, and then Service Bus in the menu.

  3. In the Basics tag of the Create namespace page, follow these steps:

    1. For Subscription, choose an Azure subscription in which to create the namespace.

    2. For Resource group, choose an existing resource group in which the namespace will live, or create a new one.

    3. Enter a name for the namespace. The namespace name should adhere to the following naming conventions:

      • The name must be unique across Azure. The system immediately checks to see if the name is available.
      • The name length is at least 6 and at most 50 characters.
      • The name can contain only letters, numbers, hyphens "-".
      • The name must start with a letter and end with a letter or number.
      • The name doesn't end with "-sb" or "-mgmt".
    4. For Location, choose the region in which your namespace should be hosted.

    5. For Pricing tier, select the pricing tier (Basic, Standard, or Premium) for the namespace. For this quickstart, select Standard.

      Important

      If you want to use topics and subscriptions, choose either Standard or Premium. Topics/subscriptions aren't supported in the Basic pricing tier.

      If you selected the Premium pricing tier, specify the number of messaging units. The premium tier provides resource isolation at the CPU and memory level so that each workload runs in isolation. This resource container is called a messaging unit. A premium namespace has at least one messaging unit. You can select 1, 2, 4, 8 or 16 messaging units for each Service Bus Premium namespace. For more information, see Service Bus Premium Messaging.

    6. Select Review + create at the bottom of the page.

      Image showing the Create a namespace page

    7. On the Review + create page, review settings, and select Create.

  4. Once the deployment of the resource is successful, select Go to resource on the deployment page.

    Image showing the deployment succeeded page with the Go to resource link.

  5. You see the home page for your service bus namespace.

    Image showing the home page of the Service Bus namespace created.

Get the connection string

Creating a new namespace automatically generates an initial Shared Access Signature (SAS) policy with primary and secondary keys, and primary and secondary connection strings that each grant full control over all aspects of the namespace. See Service Bus authentication and authorization for information about how to create rules with more constrained rights for regular senders and receivers.

A client can use the connection string to connect to the Service Bus namespace. To copy the primary connection string for your namespace, follow these steps:

  1. On the Service Bus Namespace page, select Shared access policies on the left menu.

  2. On the Shared access policies page, select RootManageSharedAccessKey.

  3. In the Policy: RootManageSharedAccessKey window, select the copy button next to Primary Connection String, to copy the connection string to your clipboard for later use. Paste this value into Notepad or some other temporary location.

    Screenshot shows an S A S policy called RootManageSharedAccessKey, which includes keys and connection strings.

    You can use this page to copy primary key, secondary key, primary connection string, and secondary connection string.

Create a topic using the Azure portal

  1. On the Service Bus Namespace page, select Topics on the left menu.

  2. Select + Topic on the toolbar.

  3. Enter a name for the topic. Leave the other options with their default values.

  4. Select Create.

    Image showing the Create topic page.

Create a subscription to the topic

  1. Select the topic that you created in the previous section.

    Image showing the selection of topic from the list of topics.

  2. On the Service Bus Topic page, select + Subscription on the toolbar.

    Image showing the Add subscription button.

  3. On the Create subscription page, follow these steps:

    1. Enter S1 for name of the subscription.

    2. Enter 3 for Max delivery count.

    3. Then, select Create to create the subscription.

      Image showing the Create subscription page.

Authenticate the app to Azure

Application requests to most Azure Services must be authorized. Using the DefaultAzureCredential class provided by the Azure Identity client library is the recommended approach for implementing passwordless connections to Azure services in your code.

You can also authorize requests to Azure services using passwords, connection strings, or other credentials directly. However, this approach should be used with caution. Developers must be diligent to never expose these secrets in an unsecure location. Anyone who gains access to the password or secret key is able to authenticate. DefaultAzureCredential offers improved management and security benefits over the account key to allow passwordless authentication. Both options are demonstrated in the following example.

DefaultAzureCredential is a class provided by the Azure Identity client library for .NET. To learn more about DefaultAzureCredential, see the DefaultAzureCredential overview. DefaultAzureCredential supports multiple authentication methods and determines which method should be used at runtime. This approach enables your app to use different authentication methods in different environments (local vs. production) without implementing environment-specific code.

For example, your app can authenticate using your Visual Studio sign-in credentials when developing locally, and then use a managed identity once it has been deployed to Azure. No code changes are required for this transition.

Assign roles to your Azure AD user

When developing locally, make sure that the user account that connects to Azure Service Bus has the correct permissions. You'll need the Azure Service Bus Data Owner role in order to send and receive messages. To assign yourself this role, you'll need the User Access Administrator role, or another role that includes the Microsoft.Authorization/roleAssignments/write action. You can assign Azure RBAC roles to a user using the Azure portal, Azure CLI, or Azure PowerShell. Learn more about the available scopes for role assignments on the scope overview page.

The following example assigns the Azure Service Bus Data Owner role to your user account, which provides full access to Azure Service Bus resources. In a real scenario, follow the Principle of Least Privilege to give users only the minimum permissions needed for a more secure production environment.

Azure built-in roles for Azure Service Bus

For Azure Service Bus, the management of namespaces and all related resources through the Azure portal and the Azure resource management API is already protected using the Azure RBAC model. Azure provides the below Azure built-in roles for authorizing access to a Service Bus namespace:

If you want to create a custom role, see Rights required for Service Bus operations.

Important

In most cases, it will take a minute or two for the role assignment to propagate in Azure. In rare cases, it may take up to eight minutes. If you receive authentication errors when you first run your code, wait a few moments and try again.

  1. In the Azure portal, locate your service bus namespace using the main search bar or left navigation.

  2. On the overview page, select Access control (IAM) from the left-hand menu.

  3. On the Access control (IAM) page, select the Role assignments tab.

  4. Select + Add from the top menu and then Add role assignment from the resulting drop-down menu.

    A screenshot showing how to assign a role.

  5. Use the search box to filter the results to the desired role. For this example, search for Azure Service Bus Data Owner and select the matching result. Then choose Next.

  6. Under Assign access to, select User, group, or service principal, and then choose + Select members.

  7. In the dialog, search for your Azure AD username (usually your user@domain email address) and then choose Select at the bottom of the dialog.

  8. Select Review + assign to go to the final page, and then Review + assign again to complete the process.

Sign in and add the Azure Identity package

You can authorize access to the service bus namespace using the following steps:

Make sure you're authenticated with the same Azure AD account you assigned the role to. You can authenticate via the Azure CLI, Visual Studio, or Azure PowerShell.

Sign-in to Azure through the Azure CLI using the following command:

az login

To use DefaultAzureCredential, add the Azure.Identity package to your application.

  1. In Solution Explorer, right-click the Dependencies node of your project. Select Manage NuGet Packages.

  2. In the resulting window, search for Azure.Identity. Select the appropriate result, and select Install.

    A screenshot showing how to add the identity package.

Launch Visual Studio and sign-in to Azure

You can authorize access to the service bus namespace using the following steps:

  1. Launch Visual Studio. If you see the Get started window, select the Continue without code link in the right pane.

  2. Select the Sign in button in the top right of Visual Studio.

    Screenshot showing the button to sign in to Azure using Visual Studio.

  3. Sign-in using the Azure AD account you assigned a role to previously.

    Screenshot showing the account selection.

Send messages to the topic

This section shows you how to create a .NET console application to send messages to a Service Bus topic.

Note

This quick start provides step-by-step instructions to implement a simple scenario of sending a batch of messages to a Service Bus topic and receiving those messages from a subscription of the topic. For more samples on other and advanced scenarios, see Service Bus .NET samples on GitHub.

Create a console application

  1. In Visual Studio, select File -> New -> Project menu.
  2. On the Create a new project dialog box, do the following steps: If you don't see this dialog box, select File on the menu, select New, and then select Project.
    1. Select C# for the programming language.

    2. Select Console for the type of the application.

    3. Select Console App from the results list.

    4. Then, select Next.

      Image showing the Create a new project dialog box with C# and Console selected

  3. Enter TopicSender for the project name, ServiceBusTopicQuickStart for the solution name, and then select Next.
  4. On the Additional information page, select Create to create the solution and the project.

Add the NuGet packages to the project

  1. Select Tools > NuGet Package Manager > Package Manager Console from the menu.

  2. Run the following command to install the Azure.Messaging.ServiceBus NuGet package.

    Install-Package Azure.Messaging.ServiceBus
    
  3. Run the following command to install the Azure.Identity NuGet package.

    Install-Package Azure.Identity
    

Add code to send messages to the topic

  1. Replace the contents of Program.cs with the following code. The important steps are outlined below, with additional information in the code comments.

    1. Creates a ServiceBusClient object using the DefaultAzureCredential object. DefaultAzureCredential will automatically discover and use the credentials of your Visual Studio login to authenticate to Azure Service Bus.
    2. Invokes the CreateSender method on the ServiceBusClient object to create a ServiceBusSender object for the specific Service Bus topic.
    3. Creates a ServiceBusMessageBatch object by using the ServiceBusSender.CreateMessageBatchAsync.
    4. Add messages to the batch using the ServiceBusMessageBatch.TryAddMessage.
    5. Sends the batch of messages to the Service Bus topic using the ServiceBusSender.SendMessagesAsync method.

    Important

    Update placeholder values (<NAMESPACE-NAME> and <TOPIC-NAME>) in the code snippet with names of your Service Bus namespace and topic.

    using System.Threading.Tasks;
    using Azure.Messaging.ServiceBus;
    using Azure.Identity;
    
    // the client that owns the connection and can be used to create senders and receivers
    ServiceBusClient client;
    
    // the sender used to publish messages to the topic
    ServiceBusSender sender;
    
    // number of messages to be sent to the topic
    const int numOfMessages = 3;
    
    // The Service Bus client types are safe to cache and use as a singleton for the lifetime
    // of the application, which is best practice when messages are being published or read
    // regularly.
    
    //TODO: Replace the "<NAMESPACE-NAME>" and "<TOPIC-NAME>" placeholders.
    client = new ServiceBusClient(
        "<NAMESPACE-NAME>.servicebus.chinacloudapi.cn",
        new DefaultAzureCredential());
    sender = client.CreateSender("<TOPIC-NAME>");
    
    // create a batch 
    using ServiceBusMessageBatch messageBatch = await sender.CreateMessageBatchAsync();
    
    for (int i = 1; i <= numOfMessages; i++)
    {
        // try adding a message to the batch
        if (!messageBatch.TryAddMessage(new ServiceBusMessage($"Message {i}")))
        {
            // if it is too large for the batch
            throw new Exception($"The message {i} is too large to fit in the batch.");
        }
    }
    
    try
    {
        // Use the producer client to send the batch of messages to the Service Bus topic
        await sender.SendMessagesAsync(messageBatch);
        Console.WriteLine($"A batch of {numOfMessages} messages has been published to the topic.");
    }
    finally
    {
        // Calling DisposeAsync on client types is required to ensure that network
        // resources and other unmanaged objects are properly cleaned up.
        await sender.DisposeAsync();
        await client.DisposeAsync();
    }
    
    Console.WriteLine("Press any key to end the application");
    Console.ReadKey();
    
  2. Build the project, and ensure that there are no errors.

  3. Run the program and wait for the confirmation message.

    A batch of 3 messages has been published to the topic
    

    Important

    In most cases, it will take a minute or two for the role assignment to propagate in Azure. In rare cases, it may take up to eight minutes. If you receive authentication errors when you first run your code, wait a few moments and try again.

  4. In the Azure portal, follow these steps:

    1. Navigate to your Service Bus namespace.

    2. On the Overview page, in the bottom-middle pane, switch to the Topics tab, and select the Service Bus topic. In the following example, it's mytopic.

      Select topic

    3. On the Service Bus Topic page, In the Messages chart in the bottom Metrics section, you can see that there are three incoming messages for the topic. If you don't see the value, wait for a few minutes, and refresh the page to see the updated chart.

      Messages sent to the topic

    4. Select the subscription in the bottom pane. In the following example, it's S1. On the Service Bus Subscription page, you see the Active message count as 3. The subscription has received the three messages that you sent to the topic, but no receiver has picked them yet.

      Messages received at the subscription

Receive messages from a subscription

In this section, you'll create a .NET console application that receives messages from the subscription to the Service Bus topic.

Note

This quick start provides step-by-step instructions to implement a simple scenario of sending a batch of messages to a Service Bus topic and receiving those messages from a subscription of the topic. For more samples on other and advanced scenarios, see Service Bus .NET samples on GitHub.

Create a project for the receiver

  1. In the Solution Explorer window, right-click the ServiceBusTopicQuickStart solution, point to Add, and select New Project.
  2. Select Console application, and select Next.
  3. Enter SubscriptionReceiver for the Project name, and select Next.
  4. On the Additional information page, select Create.
  5. In the Solution Explorer window, right-click SubscriptionReceiver, and select Set as a Startup Project.

Add the NuGet packages to the project

  1. Select Tools > NuGet Package Manager > Package Manager Console from the menu.

  2. Select SubscriptionReceiver for Default project drop-down list.

  3. Run the following command to install the Azure.Messaging.ServiceBus NuGet package.

    Install-Package Azure.Messaging.ServiceBus
    
  4. Run the following command to install the Azure.Identity NuGet package.

    Install-Package Azure.Identity
    

Add code to receive messages from the subscription

In this section, you'll add code to retrieve messages from the subscription.

  1. Replace the existing contents of Program.cs with the following properties and methods:

    using System.Threading.Tasks;
    using Azure.Messaging.ServiceBus;
    using Azure.Identity;
    
    // the client that owns the connection and can be used to create senders and receivers
    ServiceBusClient client;
    
    // the processor that reads and processes messages from the subscription
    ServiceBusProcessor processor;    
    
    // handle received messages
    async Task MessageHandler(ProcessMessageEventArgs args)
    {
        string body = args.Message.Body.ToString();
        Console.WriteLine($"Received: {body} from subscription.");
    
        // complete the message. messages is deleted from the subscription. 
        await args.CompleteMessageAsync(args.Message);
    }
    
    // handle any errors when receiving messages
    Task ErrorHandler(ProcessErrorEventArgs args)
    {
        Console.WriteLine(args.Exception.ToString());
        return Task.CompletedTask;
    }
    
  2. Append the following code to the end of Program.cs.

    • Creates a ServiceBusClient object using the DefaultAzureCredential object. DefaultAzureCredential will automatically discover and use the credentials of your Visual Studio login to authenticate to Azure Service Bus.
    • Invokes the CreateProcessor method on the ServiceBusClient object to create a ServiceBusProcessor object for the specified Service Bus topic.
    • Specifies handlers for the ProcessMessageAsync and ProcessErrorAsync events of the ServiceBusProcessor object.
    • Starts processing messages by invoking the StartProcessingAsync on the ServiceBusProcessor object.
    • When user presses a key to end the processing, invokes the StopProcessingAsync on the ServiceBusProcessor object.

    Important

    Update placeholder values (<NAMESPACE-NAME>, <TOPIC-NAME>, <SUBSCRIPTION-NAME>) in the code snippet with names of your Service Bus namespace, topic, and subscription.

    For more information, see code comments.

    // The Service Bus client types are safe to cache and use as a singleton for the lifetime
    // of the application, which is best practice when messages are being published or read
    // regularly.
    //
    // Create the clients that we'll use for sending and processing messages.
    // TODO: Replace the <NAMESPACE-NAME> placeholder
    client = new ServiceBusClient(
        "<NAMESPACE-NAME>.servicebus.chinacloudapi.cn",
        new DefaultAzureCredential());
    
    // create a processor that we can use to process the messages
    // TODO: Replace the <TOPIC-NAME> and <SUBSCRIPTION-NAME> placeholders
    processor = client.CreateProcessor("<TOPIC-NAME>", "<SUBSCRIPTION-NAME>", new ServiceBusProcessorOptions());
    
    try
    {
        // add handler to process messages
        processor.ProcessMessageAsync += MessageHandler;
    
        // add handler to process any errors
        processor.ProcessErrorAsync += ErrorHandler;
    
        // start processing 
        await processor.StartProcessingAsync();
    
        Console.WriteLine("Wait for a minute and then press any key to end the processing");
        Console.ReadKey();
    
        // stop processing 
        Console.WriteLine("\nStopping the receiver...");
        await processor.StopProcessingAsync();
        Console.WriteLine("Stopped receiving messages");
    }
    finally
    {
        // Calling DisposeAsync on client types is required to ensure that network
        // resources and other unmanaged objects are properly cleaned up.
        await processor.DisposeAsync();
        await client.DisposeAsync();
    }
    
  3. Here's what your Program.cs should look like:

    using System;
    using System.Threading.Tasks;
    using Azure.Messaging.ServiceBus;
    using Azure.Identity;
    
    // the client that owns the connection and can be used to create senders and receivers
    ServiceBusClient client;
    
    // the processor that reads and processes messages from the subscription
    ServiceBusProcessor processor;
    
    // handle received messages
    async Task MessageHandler(ProcessMessageEventArgs args)
    {
        string body = args.Message.Body.ToString();
        Console.WriteLine($"Received: {body} from subscription.");
    
        // complete the message. messages is deleted from the subscription. 
        await args.CompleteMessageAsync(args.Message);
    }
    
    // handle any errors when receiving messages
    Task ErrorHandler(ProcessErrorEventArgs args)
    {
        Console.WriteLine(args.Exception.ToString());
        return Task.CompletedTask;
    }
    
    // The Service Bus client types are safe to cache and use as a singleton for the lifetime
    // of the application, which is best practice when messages are being published or read
    // regularly.
    //
    // Create the clients that we'll use for sending and processing messages.
    // TODO: Replace the <NAMESPACE-NAME> placeholder
    client = new ServiceBusClient(
        "<NAMESPACE-NAME>.servicebus.chinacloudapi.cn",
        new DefaultAzureCredential());
    
    // create a processor that we can use to process the messages
    // TODO: Replace the <TOPIC-NAME> and <SUBSCRIPTION-NAME> placeholders
    processor = client.CreateProcessor("<TOPIC-NAME>", "<SUBSCRIPTION-NAME>", new ServiceBusProcessorOptions());
    
    try
    {
        // add handler to process messages
        processor.ProcessMessageAsync += MessageHandler;
    
        // add handler to process any errors
        processor.ProcessErrorAsync += ErrorHandler;
    
        // start processing 
        await processor.StartProcessingAsync();
    
        Console.WriteLine("Wait for a minute and then press any key to end the processing");
        Console.ReadKey();
    
        // stop processing 
        Console.WriteLine("\nStopping the receiver...");
        await processor.StopProcessingAsync();
        Console.WriteLine("Stopped receiving messages");
    }
    finally
    {
        // Calling DisposeAsync on client types is required to ensure that network
        // resources and other unmanaged objects are properly cleaned up.
        await processor.DisposeAsync();
        await client.DisposeAsync();
    }
    
  4. Build the project, and ensure that there are no errors.

  5. Run the receiver application. You should see the received messages. Press any key to stop the receiver and the application.

    Wait for a minute and then press any key to end the processing
    Received: Message 1 from subscription: S1
    Received: Message 2 from subscription: S1
    Received: Message 3 from subscription: S1
    
    Stopping the receiver...
    Stopped receiving messages
    
  6. Check the portal again.

    • On the Service Bus Topic page, in the Messages chart, you see three incoming messages and three outgoing messages. If you don't see these numbers, wait for a few minutes, and refresh the page to see the updated chart.

      Messages sent and received

    • On the Service Bus Subscription page, you see the Active message count as zero. It's because a receiver has received messages from this subscription and completed the messages.

      Active message count at the subscription at the end

Next steps

See the following documentation and samples: