Events
17 Mar, 23 - 21 Mar, 23
Join the meetup series to build scalable AI solutions based on real-world use cases with fellow developers and experts.
Register nowThis browser is no longer supported.
Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.
Includes:
Hosting integration and
Client integration
Azure Service Bus is a fully managed enterprise message broker with message queues and publish-subscribe topics. The .NET Aspire Azure Service Bus integration enables you to connect to Azure Service Bus instances from .NET applications.
The .NET Aspire Azure Service Bus hosting integration models the various Service Bus resources as the following types:
To access these types and APIs for expressing them, add the 📦 Aspire.Hosting.Azure.ServiceBus NuGet package in the app host project.
dotnet add package Aspire.Hosting.Azure.ServiceBus
For more information, see dotnet add package or Manage package dependencies in .NET applications.
In your app host project, call AddAzureServiceBus to add and return an Azure Service Bus resource builder.
var builder = DistributedApplication.CreateBuilder(args);
var serviceBus = builder.AddAzureServiceBus("messaging");
// After adding all resources, run the app...
When you add an AzureServiceBusResource to the app host, it exposes other useful APIs to add queues and topics. In other words, you must add an AzureServiceBusResource
before adding any of the other Service Bus resources.
Important
When you call AddAzureServiceBus, it implicitly calls AddAzureProvisioning—which adds support for generating Azure resources dynamically during app startup. The app must configure the appropriate subscription and location. For more information, see Configuration.
If you're new to Bicep, it's a domain-specific language for defining Azure resources. With .NET Aspire, you don't need to write Bicep by-hand, instead the provisioning APIs generate Bicep for you. When you publish your app, the generated Bicep is output alongside the manifest file. When you add an Azure Service Bus resource, the following Bicep is generated:
@description('The location for the resource(s) to be deployed.')
param location string = resourceGroup().location
param sku string = 'Standard'
param principalType string
param principalId string
resource service_bus 'Microsoft.ServiceBus/namespaces@2024-01-01' = {
name: take('servicebus-${uniqueString(resourceGroup().id)}', 50)
location: location
properties: {
disableLocalAuth: true
}
sku: {
name: sku
}
tags: {
'aspire-resource-name': 'service-bus'
}
}
resource service_bus_AzureServiceBusDataOwner 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
name: guid(service_bus.id, principalId, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '090c5cfd-751d-490a-894a-3ce6f1109419'))
properties: {
principalId: principalId
roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '090c5cfd-751d-490a-894a-3ce6f1109419')
principalType: principalType
}
scope: service_bus
}
output serviceBusEndpoint string = service_bus.properties.serviceBusEndpoint
The preceding Bicep is a module that provisions an Azure Service Bus namespace with the following defaults:
sku
: The SKU of the Service Bus namespace. The default is Standard.location
: The location for the Service Bus namespace. The default is the resource group's location.In addition to the Service Bus namespace, it also provisions an Azure role-based access control (Azure RBAC) built-in role of Azure Service Bus Data Owner. The role is assigned to the Service Bus namespace's resource group. For more information, see Azure Service Bus Data Owner.
All .NET Aspire Azure resources are subclasses of the AzureProvisioningResource type. This type enables the customization of the generated Bicep by providing a fluent API to configure the Azure resources—using the ConfigureInfrastructure<T>(IResourceBuilder<T>, Action<AzureResourceInfrastructure>) API. For example, you can configure the sku, location, and more. The following example demonstrates how to customize the Azure Service Bus resource:
builder.AddAzureServiceBus("service-bus")
.ConfigureInfrastructure(infra =>
{
var serviceBusNamespace = infra.GetProvisionableResources()
.OfType<ServiceBusNamespace>()
.Single();
serviceBusNamespace.Sku = new ServiceBusSku
{
Tier = ServiceBusSkuTier.Premium
};
serviceBusNamespace.Tags.Add("ExampleKey", "Example value");
});
The preceding code:
ExampleKey
and a value of Example value
.There are many more configuration options available to customize the Azure Service Bus resource. For more information, see Azure.Provisioning.ServiceBus. For more information, see Azure.Provisioning customization.
You might have an existing Azure Service Bus namespace that you want to connect to. Instead of representing a new Azure Service Bus resource, you can add a connection string to the app host. To add a connection to an existing Azure Service Bus namespace, call the AddConnectionString method:
var builder = DistributedApplication.CreateBuilder(args);
var serviceBus = builder.AddConnectionString("messaging");
builder.AddProject<Projects.WebApplication>("web")
.WithReference(serviceBus);
// After adding all resources, run the app...
Note
Connection strings are used to represent a wide range of connection information, including database connections, message brokers, endpoint URIs, and other services. In .NET Aspire nomenclature, the term "connection string" is used to represent any kind of connection information.
The connection string is configured in the app host's configuration, typically under User Secrets, under the ConnectionStrings
section. The app host injects this connection string as an environment variable into all dependent resources, for example:
{
"ConnectionStrings": {
"messaging": "Endpoint=sb://{namespace}.servicebus.windows.net/;SharedAccessKeyName={key_name};SharedAccessKey={key_value};"
}
}
The dependent resource can access the injected connection string by calling the GetConnectionString method, and passing the connection name as the parameter, in this case "messaging"
. The GetConnectionString
API is shorthand for IConfiguration.GetSection("ConnectionStrings")[name]
.
To add an Azure Service Bus queue, call the AddServiceBusQueue method on the IResourceBuilder<AzureServiceBusResource>
:
var builder = DistributedApplication.CreateBuilder(args);
var serviceBus = builder.AddAzureServiceBus("messaging");
serviceBus.AddServiceBusQueue("queue");
// After adding all resources, run the app...
When you call AddServiceBusQueue
, it configures your Service Bus resources to have a queue named queue
. The queue is created in the Service Bus namespace that's represented by the AzureServiceBusResource
that you added earlier. For more information, see Queues, topics, and subscriptions in Azure Service Bus.
To add an Azure Service Bus topic, call the AddServiceBusTopic method on the IResourceBuilder<AzureServiceBusResource>
:
var builder = DistributedApplication.CreateBuilder(args);
var serviceBus = builder.AddAzureServiceBus("messaging");
serviceBus.AddServiceBusTopic("topic");
// After adding all resources, run the app...
When you call AddServiceBusTopic
, it configures your Service Bus resources to have a topic named topic
. The topic is created in the Service Bus namespace that's represented by the AzureServiceBusResource
that you added earlier.
To add a subscription for the topic, call the AddServiceBusSubscription method on the IResourceBuilder<AzureServiceBusTopicResource>
and configure it using the WithProperties method:
using Aspire.Hosting.Azure;
var builder = DistributedApplication.CreateBuilder(args);
var serviceBus = builder.AddAzureServiceBus("messaging");
var topic = serviceBus.AddServiceBusTopic("topic");
topic.AddServiceBusSubscription("sub1")
.WithProperties(subscription =>
{
subscription.MaxDeliveryCount = 10;
subscription.Rules.Add(
new AzureServiceBusRule("app-prop-filter-1")
{
CorrelationFilter = new()
{
ContentType = "application/text",
CorrelationId = "id1",
Subject = "subject1",
MessageId = "msgid1",
ReplyTo = "someQueue",
ReplyToSessionId = "sessionId",
SessionId = "session1",
SendTo = "xyz"
}
});
});
// After adding all resources, run the app...
The preceding code not only adds a topic and creates and configures a subscription named sub1
for the topic. The subscription has a maximum delivery count of 10
and a rule named app-prop-filter-1
. The rule is a correlation filter that filters messages based on the ContentType
, CorrelationId
, Subject
, MessageId
, ReplyTo
, ReplyToSessionId
, SessionId
, and SendTo
properties.
For more information, see Queues, topics, and subscriptions in Azure Service Bus.
To add an Azure Service Bus emulator resource, chain a call on an <IResourceBuilder<AzureServiceBusResource>>
to the RunAsEmulator
API:
var builder = DistributedApplication.CreateBuilder(args);
var serviceBus = builder.AddAzureServiceBus("messaging")
.RunAsEmulator();
// After adding all resources, run the app...
When you call RunAsEmulator
, it configures your Service Bus resources to run locally using an emulator. The emulator in this case is the Azure Service Bus Emulator. The Azure Service Bus Emulator provides a free local environment for testing your Azure Service Bus apps and it's a perfect companion to the .NET Aspire Azure hosting integration. The emulator isn't installed, instead, it's accessible to .NET Aspire as a container. When you add a container to the app host, as shown in the preceding example with the mcr.microsoft.com/azure-messaging/servicebus-emulator
image (and the companion mcr.microsoft.com/azure-sql-edge
image), it creates and starts the container when the app host starts. For more information, see Container resource lifecycle.
There are various configurations available for container resources, for example, you can configure the container's ports or providing a wholistic JSON configuration which overrides everything.
By default, the Service Bus emulator container when configured by .NET Aspire, exposes the following endpoints:
Endpoint | Image | Container port | Host port |
---|---|---|---|
emulator |
mcr.microsoft.com/azure-messaging/servicebus-emulator |
5672 | dynamic |
tcp |
mcr.microsoft.com/azure-sql-edge |
1433 | dynamic |
The port that it's listening on is dynamic by default. When the container starts, the port is mapped to a random port on the host machine. To configure the endpoint port, chain calls on the container resource builder provided by the RunAsEmulator
method as shown in the following example:
var builder = DistributedApplication.CreateBuilder(args);
var serviceBus = builder.AddAzureServiceBus("messaging").RunAsEmulator(
emulator =>
{
emulator.WithHostPort(7777);
});
// After adding all resources, run the app...
The preceding code configures the Service Bus emulator container's existing emulator
endpoint to listen on port 7777
. The Service Bus emulator container's port is mapped to the host port as shown in the following table:
Endpoint name | Port mapping (container:host ) |
---|---|
emulator |
5672:7777 |
The Service Bus emulator container runs with a default config.json file. You can override this file entirely, or update the JSON configuration with a JsonNode representation of the configuration.
To provide a custom JSON configuration file, call the WithConfigurationFile
method:
var builder = DistributedApplication.CreateBuilder(args);
var serviceBus = builder.AddAzureServiceBus("messaging").RunAsEmulator(
emulator =>
{
emulator.WithConfigurationFile(
path: "./messaging/custom-config.json");
});
The preceding code configures the Service Bus emulator container to use a custom JSON configuration file located at ./messaging/custom-config.json
. To instead override specific properties in the default configuration, call the WithConfiguration
method:
var builder = DistributedApplication.CreateBuilder(args);
var serviceBus = builder.AddAzureServiceBus("messaging").RunAsEmulator(
emulator =>
{
emulator.WithConfiguration(
(JsonNode configuration) =>
{
var userConfig = configuration["UserConfig"];
var ns = userConfig["Namespaces"][0];
var firstQueue = ns["Queues"][0];
var properties = firstQueue["Properties"];
properties["MaxDeliveryCount"] = 5;
properties["RequiresDuplicateDetection"] = true;
properties["DefaultMessageTimeToLive"] = "PT2H";
});
});
// After adding all resources, run the app...
The preceding code retrieves the UserConfig
node from the default configuration. It then updates the first queue's properties to set the MaxDeliveryCount
to 5
, RequiresDuplicateDetection
to true
, and DefaultMessageTimeToLive
to 2 hours
.
The Azure Service Bus hosting integration automatically adds a health check for the Service Bus resource. The health check verifies that the Service Bus is running and that a connection can be established to it.
The hosting integration relies on the 📦 AspNetCore.HealthChecks.AzureServiceBus NuGet package.
To get started with the .NET Aspire Azure Service Bus client integration, install the 📦 Aspire.Azure.Messaging.ServiceBus NuGet package in the client-consuming project, that is, the project for the application that uses the Service Bus client. The Service Bus client integration registers a ServiceBusClient instance that you can use to interact with Service Bus.
dotnet add package Aspire.Azure.Messaging.ServiceBus
In the Program.cs file of your client-consuming project, call the AddAzureServiceBusClient extension method on any IHostApplicationBuilder to register a ServiceBusClient for use via the dependency injection container. The method takes a connection name parameter.
builder.AddAzureServiceBusClient(connectionName: "messaging");
Tip
The connectionName
parameter must match the name used when adding the Service Bus resource in the app host project. In other words, when you call AddAzureServiceBus
and provide a name of messaging
that same name should be used when calling AddAzureServiceBusClient
. For more information, see Add Azure Service Bus resource.
You can then retrieve the ServiceBusClient instance using dependency injection. For example, to retrieve the connection from an example service:
public class ExampleService(ServiceBusClient client)
{
// Use client...
}
For more information on dependency injection, see .NET dependency injection.
There might be situations where you want to register multiple ServiceBusClient
instances with different connection names. To register keyed Service Bus clients, call the AddKeyedAzureServiceBusClient method:
builder.AddKeyedAzureServiceBusClient(name: "mainBus");
builder.AddKeyedAzureServiceBusClient(name: "loggingBus");
Important
When using keyed services, it's expected that your Service Bus resource configured two named buses, one for the mainBus
and one for the loggingBus
.
Then you can retrieve the ServiceBusClient
instances using dependency injection. For example, to retrieve the connection from an example service:
public class ExampleService(
[FromKeyedServices("mainBus")] ServiceBusClient mainBusClient,
[FromKeyedServices("loggingBus")] ServiceBusClient loggingBusClient)
{
// Use clients...
}
For more information on keyed services, see .NET dependency injection: Keyed services.
The .NET Aspire Azure Service Bus integration provides multiple options to configure the connection based on the requirements and conventions of your project.
When using a connection string from the ConnectionStrings
configuration section, you can provide the name of the connection string when calling the AddAzureServiceBusClient method:
builder.AddAzureServiceBusClient("messaging");
Then the connection string is retrieved from the ConnectionStrings
configuration section:
{
"ConnectionStrings": {
"messaging": "Endpoint=sb://{namespace}.servicebus.windows.net/;SharedAccessKeyName={keyName};SharedAccessKey={key};"
}
}
For more information on how to format this connection string, see the ConnectionString documentation.
The .NET Aspire Azure Service Bus integration supports Microsoft.Extensions.Configuration. It loads the AzureMessagingServiceBusSettings from configuration by using the Aspire:Azure:Messaging:ServiceBus
key. The following snippet is an example of a appsettings.json file that configures some of the options:
{
"Aspire": {
"Azure": {
"Messaging": {
"ServiceBus": {
"ConnectionString": "Endpoint=sb://{namespace}.servicebus.windows.net/;SharedAccessKeyName={keyName};SharedAccessKey={key};",
"DisableTracing": false
}
}
}
}
}
For the complete Service Bus client integration JSON schema, see Aspire.Azure.Messaging.ServiceBus/ConfigurationSchema.json.
Also you can pass the Action<AzureMessagingServiceBusSettings> configureSettings
delegate to set up some or all the options inline, for example to disable tracing from code:
builder.AddAzureServiceBusClient(
"messaging",
static settings => settings.DisableTracing = true);
You can also set up the Azure.Messaging.ServiceBus.ServiceBusClientOptions using the optional Action<ServiceBusClientOptions> configureClientOptions
parameter of the AddAzureServiceBusClient
method. For example to set the ServiceBusClientOptions.Identifier user-agent header suffix for all requests issues by this client:
builder.AddAzureServiceBusClient(
"messaging",
configureClientOptions:
clientOptions => clientOptions.Identifier = "myapp");
By default, .NET Aspire integrations enable health checks for all services. For more information, see .NET Aspire integrations overview.
The .NET Aspire Azure Service Bus integration:
false
, which attempts to connect to the Service Bus./health
HTTP endpoint, which specifies all registered health checks must pass for app to be considered ready to accept traffic..NET Aspire integrations automatically set up Logging, Tracing, and Metrics configurations, which are sometimes known as the pillars of observability. For more information about integration observability and telemetry, see .NET Aspire integrations overview. Depending on the backing service, some integrations may only support some of these features. For example, some integrations support logging and tracing, but not metrics. Telemetry features can also be disabled using the techniques presented in the Configuration section.
The .NET Aspire Azure Service Bus integration uses the following log categories:
Azure.Core
Azure.Identity
Azure-Messaging-ServiceBus
In addition to getting Azure Service Bus request diagnostics for failed requests, you can configure latency thresholds to determine which successful Azure Service Bus request diagnostics will be logged. The default values are 100 ms for point operations and 500 ms for non point operations.
builder.AddAzureServiceBusClient(
"messaging",
configureClientOptions:
clientOptions => {
clientOptions.ServiceBusClientTelemetryOptions = new()
{
ServiceBusThresholdOptions = new()
{
PointOperationLatencyThreshold = TimeSpan.FromMilliseconds(50),
NonPointOperationLatencyThreshold = TimeSpan.FromMilliseconds(300)
}
};
});
The .NET Aspire Azure Service Bus integration will emit the following tracing activities using OpenTelemetry:
Message
ServiceBusSender.Send
ServiceBusSender.Schedule
ServiceBusSender.Cancel
ServiceBusReceiver.Receive
ServiceBusReceiver.ReceiveDeferred
ServiceBusReceiver.Peek
ServiceBusReceiver.Abandon
ServiceBusReceiver.Complete
ServiceBusReceiver.DeadLetter
ServiceBusReceiver.Defer
ServiceBusReceiver.RenewMessageLock
ServiceBusSessionReceiver.RenewSessionLock
ServiceBusSessionReceiver.GetSessionState
ServiceBusSessionReceiver.SetSessionState
ServiceBusProcessor.ProcessMessage
ServiceBusSessionProcessor.ProcessSessionMessage
ServiceBusRuleManager.CreateRule
ServiceBusRuleManager.DeleteRule
ServiceBusRuleManager.GetRules
Azure Service Bus tracing is currently in preview, so you must set the experimental switch to ensure traces are emitted.
AppContext.SetSwitch("Azure.Experimental.EnableActivitySource", true);
For more information, see Azure Service Bus: Distributed tracing and correlation through Service Bus messaging.
The .NET Aspire Azure Service Bus integration currently doesn't support metrics by default due to limitations with the Azure SDK.
.NET Aspire feedback
.NET Aspire is an open source project. Select a link to provide feedback:
Events
17 Mar, 23 - 21 Mar, 23
Join the meetup series to build scalable AI solutions based on real-world use cases with fellow developers and experts.
Register nowTraining
Module
Implement message-based communication workflows with Azure Service Bus - Training
Discover how to write code in .NET applications using Azure Service Bus for communications that can handle high demand, low bandwidth, and hardware failures.
Certification
Microsoft Certified: Azure for SAP Workloads Specialty - Certifications
Demonstrate planning, migration, and operation of an SAP solution on Microsoft Azure while you leverage Azure resources.
Documentation
.NET Aspire Azure Event Hubs integration - .NET Aspire
This article describes the .NET Aspire Azure Event Hubs integration features and capabilities.
Use .NET Aspire messaging integrations in ASP.NET Core - .NET Aspire
Learn how to connect an ASP.NET Core app to messaging services using .NET Aspire integrations.
.NET Aspire Azure Functions integration (Preview) - .NET Aspire
Learn how to integrate Azure Functions with .NET Aspire.