Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Service Bus] ReadMe DI Snippets #37863

Merged
merged 1 commit into from
Jul 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions eng/Packages.Data.props
Original file line number Diff line number Diff line change
Expand Up @@ -198,16 +198,16 @@
<PackageReference Update="Azure.Messaging.ServiceBus" Version="7.15.0" />
<PackageReference Update="Azure.ResourceManager.Compute" Version="1.0.0" />
<PackageReference Update="Azure.ResourceManager.CognitiveServices" Version="1.1.0" />
<PackageReference Update="Azure.ResourceManager.KeyVault" Version="1.0.0" />
<PackageReference Update="Azure.ResourceManager.ManagedServiceIdentities" Version="1.0.0" />
<PackageReference Update="Azure.ResourceManager.KeyVault" Version="1.0.0" />
<PackageReference Update="Azure.ResourceManager.ManagedServiceIdentities" Version="1.0.0" />
<PackageReference Update="Azure.ResourceManager.Network" Version="1.1.0" />
<PackageReference Update="Azure.ResourceManager.OperationalInsights" Version="1.0.0" />
<PackageReference Update="Azure.ResourceManager.PrivateDns" Version="1.0.0" />
<PackageReference Update="Azure.ResourceManager.PrivateDns" Version="1.0.0" />
<PackageReference Update="Azure.ResourceManager.Resources" Version="1.4.0" />
<PackageReference Update="Azure.ResourceManager.Storage" Version="1.1.0" />
<PackageReference Update="Azure.ResourceManager.EventHubs" Version="1.0.0" />
<PackageReference Update="Azure.Search.Documents" Version="11.2.0" />
<PackageReference Update="Azure.Security.KeyVault.Keys" Version="4.4.0" />
<PackageReference Update="Azure.Security.KeyVault.Keys" Version="4.4.0" />
<PackageReference Update="Azure.Security.KeyVault.Secrets" Version="4.2.0-beta.4" />
<PackageReference Update="Azure.Storage.Blobs" Version="12.13.1" />
<PackageReference Update="Azure.Storage.Files.DataLake" Version="12.8.0" />
Expand Down Expand Up @@ -249,13 +249,13 @@
<PackageReference Update="Microsoft.Azure.WebJobs.Extensions" Version="5.0.0" />
<PackageReference Update="Microsoft.Azure.WebJobs.Extensions.Http" Version="3.0.2" />
<PackageReference Update="Microsoft.CSharp" Version="4.7.0" />
<PackageReference Update="Microsoft.Extensions.Azure" Version="1.0.0" />
<PackageReference Update="Microsoft.Extensions.Azure" Version="1.6.3" />
<PackageReference Update="Microsoft.Extensions.Configuration.Binder" Version="2.1.10" />
<PackageReference Update="Microsoft.Extensions.Configuration.Json" Version="5.0.0" />
<PackageReference Update="Microsoft.Extensions.Configuration" Version="5.0.0" />
<PackageReference Update="Microsoft.Extensions.DependencyInjection" Version="3.1.32" />
<PackageReference Update="Microsoft.Extensions.PlatformAbstractions" Version="1.1.0" />
<PackageReference Update="Microsoft.Graph" Version="4.52.0" />
<PackageReference Update="Microsoft.Graph" Version="4.52.0" />
<PackageReference Update="Microsoft.NET.Test.Sdk" Version="17.0.0" />
<PackageReference Update="Microsoft.NET.Sdk.Functions" Version="4.2.0" />
<PackageReference Update="Microsoft.Rest.ClientRuntime" Version="[2.3.24, 3.0.0)" />
Expand Down
100 changes: 71 additions & 29 deletions sdk/servicebus/Azure.Messaging.ServiceBus/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,13 @@ string fullyQualifiedNamespace = "yournamespace.servicebus.windows.net";
await using var client = new ServiceBusClient(fullyQualifiedNamespace, new DefaultAzureCredential());
```

### Working with Sessions

[Sessions](https://docs.microsoft.com/azure/service-bus-messaging/message-sessions) provide a mechanism for grouping related messages. In order to use sessions, you need to be working with a session-enabled entity.

- [Sending and receiving session messages](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/servicebus/Azure.Messaging.ServiceBus/samples/Sample03_SendReceiveSessions.md)
- [Using the session processor](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/servicebus/Azure.Messaging.ServiceBus/samples/Sample05_SessionProcessor.md)

### Registering with ASP.NET Core dependency injection

To inject `ServiceBusClient` as a dependency in an ASP.NET Core app, install the Azure client library integration for ASP.NET Core package.
Expand All @@ -409,60 +416,95 @@ To inject `ServiceBusClient` as a dependency in an ASP.NET Core app, install the
dotnet add package Microsoft.Extensions.Azure
```

Then register the client in the `Startup.ConfigureServices` method:
Then register the client where your services are configured. For ASP.NET Core applications, this is often directly in `Program.cs` or the `StartupConfigureServices` method:

```csharp
```C# Snippet:DependencyInjectionRegisterClient
public void ConfigureServices(IServiceCollection services)
{
services.AddAzureClients(builder =>
{
builder.AddServiceBusClient(Configuration.GetConnectionString("ServiceBus"));
builder.AddServiceBusClient("<< SERVICE BUS CONNECTION STRING >>");
});

services.AddControllers();
// Register other services, controllers, and other infrastructure.
}
```

To use the preceding code, add this to the configuration for your application:
For applications that prefer using a shared `Azure.Identity` credential for their clients, registration looks slightly different:

```json
{
"ConnectionStrings": {
"ServiceBus": "<connection_string>"
}
}
```C# Snippet:DependencyInjectionRegisterClientWithIdentity
public void ConfigureServices(IServiceCollection services)
{
services.AddAzureClients(builder =>
{
// This will register the ServiceBusClient using an Azure Identity credential.
builder.AddServiceBusClientWithNamespace("<< YOUR NAMESPACE >>.servicebus.windows.net");

// By default, DefaultAzureCredential is used, which is likely desired for most
// scenarios. If you need to restrict to a specific credential instance, you could
// register that instance as the default credential instead.
builder.UseCredential(new ManagedIdentityCredential());
});

// Register other services, controllers, and other infrastructure.
}
```

For applications that prefer using a shared `Azure.Identity` credential for their clients, registration looks slightly different:
It is also possible to register sub-clients, such as `ServiceBusSender` and `ServiceBusReceiver` with DI using the registered `ServiceBusClient` instance. For example, to register a sender for each queue that belongs to the namespace:

```csharp
var fullyQualifiedNamespace = "yournamespace.servicebus.windows.net";

public void ConfigureServices(IServiceCollection services)
```C# Snippet:DependencyInjectionRegisterSubClients
public async Task ConfigureServicesAsync(IServiceCollection services)
{
services.AddAzureClients(builder =>
// Query the available queues for the Service Bus namespace.
var adminClient = new ServiceBusAdministrationClient("<< SERVICE BUS CONNECTION STRING >>");
var queueNames = new List<string>();

// Because the result is async, they need to be captured to a standard list to avoid async
// calls when registering. Failure to do so results in an error with the services collection.
await foreach (var queue in adminClient.GetQueuesAsync())
{
// This will register the ServiceBusClient using the default credential.
builder.AddServiceBusClientWithNamespace(fullyQualifiedNamespace);
queueNames.Add(queue.Name);
}

// By default, DefaultAzureCredential is used, which is likely desired for most
// scenarios. If you need to restrict to a specific credential instance, you could
// register that instance as the default credential instead.
builder.UseCredential(new ManagedIdentityCredential());
// After registering the ServiceBusClient, register a named factory for each
// queue. This allows them to be lazily created and managed as singleton instances.

services.AddAzureClients(builder =>
{
builder.AddServiceBusClient("<< SERVICE BUS CONNECTION STRING >>");

foreach (var queueName in queueNames)
{
builder.AddClient<ServiceBusSender, ServiceBusClientOptions>((_, _, provider) =>
provider
.GetService<ServiceBusClient>()
.CreateSender(queueName)
)
.WithName(queueName);
}
});

services.AddControllers();
// Register other services, controllers, and other infrastructure.
}
```

For more details, see [Dependency injection with the Azure SDK for .NET](https://docs.microsoft.com/dotnet/azure/sdk/dependency-injection).
Because the senders are named for their associated queue, when injecting, you don't bind to them directly. Instead, you'll bind to a factory that can be used to retrieve the named sender:

### Working with Sessions
```C# Snippet:DependencyInjectionBindToNamedSubClients
public class ServiceBusSendingController : ControllerBase
{
private readonly ServiceBusSender _sender;

[Sessions](https://docs.microsoft.com/azure/service-bus-messaging/message-sessions) provide a mechanism for grouping related messages. In order to use sessions, you need to be working with a session-enabled entity.
public ServiceBusSendingController(IAzureClientFactory<ServiceBusSender> serviceBusSenderFactory)
{
// Though the method is called "CreateClient", the factory will manage the sender as a
// singleton, creating a new instance only on the first use.
_sender = serviceBusSenderFactory.CreateClient("<< QUEUE NAME >>");
}
}
```

- [Sending and receiving session messages](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/servicebus/Azure.Messaging.ServiceBus/samples/Sample03_SendReceiveSessions.md)
- [Using the session processor](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/servicebus/Azure.Messaging.ServiceBus/samples/Sample05_SessionProcessor.md)
For more details and examples, see [Dependency injection with the Azure SDK for .NET](https://learn.microsoft.com/dotnet/azure/sdk/dependency-injection).

## Troubleshooting

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
<PackageReference Include="Microsoft.Azure.Management.ResourceManager" />
<PackageReference Include="Microsoft.Azure.Management.ServiceBus" />
<PackageReference Include="Microsoft.Azure.Services.AppAuthentication" />
<PackageReference Include="Microsoft.Extensions.Azure" />
<PackageReference Include="Microsoft.Extensions.Configuration" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" />
<PackageReference Include="System.Net.WebSockets.Client" />
<PackageReference Include="System.ValueTuple" />
<PackageReference Include="NUnit" />
Expand All @@ -28,7 +31,7 @@
<PackageReference Include="System.Memory.Data" />
<PackageReference Include="Azure.Storage.Blobs" />
</ItemGroup>

<ItemGroup>
<Compile Include="$(AzureCoreSharedSources)EventSourceEventFormatting.cs" LinkBase="SharedSource\Azure.Core" />
</ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System.Collections.Generic;
using System.Threading.Tasks;
using Azure.Identity;
using Azure.Messaging.ServiceBus.Administration;
using Microsoft.Extensions.Azure;
using Microsoft.Extensions.DependencyInjection;
using NUnit.Framework;

namespace Azure.Messaging.ServiceBus.Tests
{
[TestFixture]
public class DependencyInjectionSnippets
{
public class ClientRegistrationConnectionString
{
#region Snippet:DependencyInjectionRegisterClient
public void ConfigureServices(IServiceCollection services)
{
services.AddAzureClients(builder =>
{
builder.AddServiceBusClient("<< SERVICE BUS CONNECTION STRING >>");
});

// Register other services, controllers, and other infrastructure.
}
#endregion
}

public class ClientRegistrationIdentity
{
#region Snippet:DependencyInjectionRegisterClientWithIdentity
public void ConfigureServices(IServiceCollection services)
{
services.AddAzureClients(builder =>
{
// This will register the ServiceBusClient using an Azure Identity credential.
builder.AddServiceBusClientWithNamespace("<< YOUR NAMESPACE >>.servicebus.windows.net");

// By default, DefaultAzureCredential is used, which is likely desired for most
// scenarios. If you need to restrict to a specific credential instance, you could
// register that instance as the default credential instead.
builder.UseCredential(new ManagedIdentityCredential());
});

// Register other services, controllers, and other infrastructure.
}
#endregion
}

public class SubClientRegistration
{
#region Snippet:DependencyInjectionRegisterSubClients
public async Task ConfigureServicesAsync(IServiceCollection services)
{
// Query the available queues for the Service Bus namespace.
var adminClient = new ServiceBusAdministrationClient("<< SERVICE BUS CONNECTION STRING >>");
var queueNames = new List<string>();

// Because the result is async, they need to be captured to a standard list to avoid async
// calls when registering. Failure to do so results in an error with the services collection.
await foreach (var queue in adminClient.GetQueuesAsync())
{
queueNames.Add(queue.Name);
}

// After registering the ServiceBusClient, register a named factory for each
// queue. This allows them to be lazily created and managed as singleton instances.

services.AddAzureClients(builder =>
{
builder.AddServiceBusClient("<< SERVICE BUS CONNECTION STRING >>");

foreach (var queueName in queueNames)
{
builder.AddClient<ServiceBusSender, ServiceBusClientOptions>((_, _, provider) =>
provider
.GetService<ServiceBusClient>()
.CreateSender(queueName)
)
.WithName(queueName);
}
});

// Register other services, controllers, and other infrastructure.
}
#endregion

#region Snippet:DependencyInjectionBindToNamedSubClients
public class ServiceBusSendingController : ControllerBase
{
private readonly ServiceBusSender _sender;

public ServiceBusSendingController(IAzureClientFactory<ServiceBusSender> serviceBusSenderFactory)
{
// Though the method is called "CreateClient", the factory will manage the sender as a
// singleton, creating a new instance only on the first use.
_sender = serviceBusSenderFactory.CreateClient("<< QUEUE NAME >>");
}
}
#endregion
}

// This is a dummy class pretending to be an ASP.NET controller. It is intended
// to allow the snippet to compile.
public class ControllerBase
{
}
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

#region Snippet:Managing_ServiceBus_AuthClient_Usings
using Azure.Identity;
#endregion

using NUnit.Framework;

namespace Azure.ResourceManager.ServiceBus.Tests.Samples
Expand All @@ -15,9 +12,7 @@ public class Readme
[Ignore("Only verifying that the sample builds")]
public void ClientAuth()
{
#region Snippet:Managing_ServiceBus_AuthClient
ArmClient armClient = new ArmClient(new DefaultAzureCredential());
#endregion
}
}
}