Skip to content

Commit

Permalink
New AddClient example (#43205)
Browse files Browse the repository at this point in the history
* New AddClient examples

Co-authored-by: Scott Addie <[email protected]>

---------

Co-authored-by: Scott Addie <[email protected]>
  • Loading branch information
alexwolfmsft and scottaddie authored Oct 30, 2024
1 parent ddf598a commit 632d183
Show file tree
Hide file tree
Showing 8 changed files with 55 additions and 23 deletions.
12 changes: 8 additions & 4 deletions docs/azure/sdk/dependency-injection.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,13 @@ To register and configure service clients from an [`Azure.`-prefixed package](pa
dotnet add package Azure.Identity
```

For demonstration purposes, the sample code in this article uses the Key Vault Secrets, Blob Storage, and Service Bus libraries. Install the following packages to follow along:
For demonstration purposes, the sample code in this article uses the Key Vault Secrets, Blob Storage, Service Bus, and Azure OpenAI libraries. Install the following packages to follow along:

```dotnetcli
dotnet add package Azure.Security.KeyVault.Secrets
dotnet add package Azure.Storage.Blobs
dotnet add package Azure.Messaging.ServiceBus
dotnet add package Azure.AI.OpenAI
```

## Register clients and subclients
Expand All @@ -42,15 +43,15 @@ In the *Program.cs* file, invoke the <xref:Microsoft.Extensions.Azure.AzureClien

### [WebApplicationBuilder](#tab/web-app-builder)

:::code language="csharp" source="snippets/dependency-injection/WebApplicationBuilder/Program.cs" id="snippet_WebApplicationBuilder" highlight="10-26":::
:::code language="csharp" source="snippets/dependency-injection/WebApplicationBuilder/Program.cs" id="snippet_WebApplicationBuilder" highlight="9-34":::

### [HostApplicationBuilder](#tab/host-app-builder)

:::code language="csharp" source="snippets/dependency-injection/HostApplicationBuilder/Program.cs" highlight="12-30":::
:::code language="csharp" source="snippets/dependency-injection/HostApplicationBuilder/Program.cs" highlight="12-39":::

### [HostBuilder](#tab/host-builder)

:::code language="csharp" source="snippets/dependency-injection/HostBuilder/Program.cs" id="snippet_HostBuilder" highlight="11-26":::
:::code language="csharp" source="snippets/dependency-injection/HostBuilder/Program.cs" id="snippet_HostBuilder" highlight="10-34":::

---

Expand All @@ -59,6 +60,9 @@ In the preceding code:
* Key Vault Secrets, Blob Storage, and Service Bus clients are registered using the <xref:Microsoft.Extensions.Azure.SecretClientBuilderExtensions.AddSecretClient%2A>, <xref:Microsoft.Extensions.Azure.BlobClientBuilderExtensions.AddBlobServiceClient%2A> and <xref:Microsoft.Extensions.Azure.ServiceBusClientBuilderExtensions.AddServiceBusClientWithNamespace%2A>, respectively. The `Uri`- and `string`-typed arguments are passed. To avoid specifying these URLs explicitly, see the [Store configuration separately from code](#store-configuration-separately-from-code) section.
* <xref:Azure.Identity.DefaultAzureCredential> is used to satisfy the `TokenCredential` argument requirement for each registered client. When one of the clients is created, `DefaultAzureCredential` is used to authenticate.
* Service Bus subclients are registered for each queue on the service using the subclient and corresponding options types. The queue names for the subclients are retrieved using a separate method outside of the service registration because the `GetQueuesAsync` method must be run asynchronously.
* An Azure OpenAI client is registered using a custom client factory via the <xref:Microsoft.Extensions.Azure.AzureClientFactoryBuilder.AddClient%2A> method, which provides control over how a client instance is created. Custom client factories are useful in the following cases:
* You need to use other dependencies during the client construction.
* A registration extension method doesn't exist for the service client you want to register.

## Use the registered clients

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,6 @@
<PackageVersion Include="Microsoft.AspNetCore.OpenApi" Version="8.0.5" />
<PackageVersion Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
<PackageVersion Include="Swashbuckle.AspNetCore" Version="6.6.1" />
<PackageVersion Include="Azure.AI.OpenAI" Version="2.0.0" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,6 @@
<PackageReference Include="Azure.Storage.Blobs" />
<PackageReference Include="Microsoft.Extensions.Azure" />
<PackageReference Include="Microsoft.Extensions.Hosting" />
<PackageReference Include="Azure.AI.OpenAI" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,24 @@
using Azure.Messaging.ServiceBus.Administration;
using Microsoft.Extensions.Azure;
using Microsoft.Extensions.Hosting;

List<string> queueNames = await GetQueueNames();
using Azure.AI.OpenAI;

IHost host = Host.CreateDefaultBuilder(args)
.ConfigureServices(services =>
{
services.AddAzureClients(clientBuilder =>
services.AddAzureClients(async clientBuilder =>
{
// Register clients for each service
clientBuilder.AddSecretClient(new Uri("<key_vault_url>"));
clientBuilder.AddBlobServiceClient(new Uri("<storage_url>"));
clientBuilder.AddServiceBusClientWithNamespace("<your_namespace>.servicebus.windows.net");
clientBuilder.UseCredential(new DefaultAzureCredential());
// Set a credential for all clients to use by default
DefaultAzureCredential credential = new();
clientBuilder.UseCredential(credential);
// Register subclients for Service Bus
List<string> queueNames = await GetQueueNames(credential);
foreach (string queueName in queueNames)
{
clientBuilder.AddClient<ServiceBusSender, ServiceBusClientOptions>((_, _, provider) =>
Expand All @@ -27,16 +30,21 @@
_ => throw new InvalidOperationException("Unable to create ServiceBusClient")
}).WithName(queueName);
}
// Register a custom client factory
clientBuilder.AddClient<AzureOpenAIClient, AzureOpenAIClientOptions>(
(options, _, _) => new AzureOpenAIClient(
new Uri("<url_here>"), credential, options));
});
}).Build();

await host.RunAsync();

async Task<List<string>> GetQueueNames()
async Task<List<string>> GetQueueNames(DefaultAzureCredential credential)
{
// Query the available queues for the Service Bus namespace.
var adminClient = new ServiceBusAdministrationClient
("<your_namespace>.servicebus.windows.net", new DefaultAzureCredential());
("<your_namespace>.servicebus.windows.net", credential);
var queueNames = new List<string>();

// Because the result is async, the queue names need to be captured
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,6 @@
<PackageReference Include="Azure.Storage.Blobs" />
<PackageReference Include="Microsoft.Extensions.Azure" />
<PackageReference Include="Microsoft.Extensions.Hosting" />
<PackageReference Include="Azure.AI.OpenAI" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -3,37 +3,45 @@
using Azure.Messaging.ServiceBus;
using Azure.Messaging.ServiceBus.Administration;
using Microsoft.Extensions.Azure;

List<string> queueNames = await GetQueueNames();
using Azure.AI.OpenAI;

IHost host = Host.CreateDefaultBuilder(args)
.ConfigureServices(services =>
{
services.AddAzureClients(clientBuilder =>
services.AddAzureClients(async clientBuilder =>
{
// Register clients for each service
clientBuilder.AddSecretClient(new Uri("<key_vault_url>"));
clientBuilder.AddBlobServiceClient(new Uri("<storage_url>"));
clientBuilder.AddServiceBusClientWithNamespace("<your_namespace>.servicebus.windows.net");
clientBuilder.UseCredential(new DefaultAzureCredential());
// Set a credential for all clients to use by default
DefaultAzureCredential credential = new();
clientBuilder.UseCredential(credential);
// Register a subclient for each Service Bus Queue
List<string> queueNames = await GetQueueNames(credential);
foreach (string queue in queueNames)
{
clientBuilder.AddClient<ServiceBusSender, ServiceBusClientOptions>((_, _, provider) =>
provider.GetService<ServiceBusClient>().CreateSender(queue)
).WithName(queue);
}
// Register a custom client factory
clientBuilder.AddClient<AzureOpenAIClient, AzureOpenAIClientOptions>(
(options, _, _) => new AzureOpenAIClient(
new Uri("<url_here>"), credential, options));
});
}).Build();

await host.RunAsync();

async Task<List<string>> GetQueueNames()
async Task<List<string>> GetQueueNames(DefaultAzureCredential credential)
{
// Query the available queues for the Service Bus namespace.
var adminClient = new ServiceBusAdministrationClient
("<your_namespace>.servicebus.windows.net", new DefaultAzureCredential());
("<your_namespace>.servicebus.windows.net", credential);
var queueNames = new List<string>();

// Because the result is async, the queue names need to be captured
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,36 +3,44 @@
using Azure.Messaging.ServiceBus;
using Azure.Messaging.ServiceBus.Administration;
using Microsoft.Extensions.Azure;
using Azure.AI.OpenAI;

WebApplicationBuilder builder = WebApplication.CreateBuilder(args);

List<string> queueNames = await GetQueueNames();

builder.Services.AddAzureClients(clientBuilder =>
builder.Services.AddAzureClients(async clientBuilder =>
{
// Register clients for each service
clientBuilder.AddSecretClient(new Uri("<key_vault_url>"));
clientBuilder.AddBlobServiceClient(new Uri("<storage_url>"));
clientBuilder.AddServiceBusClientWithNamespace(
"<your_namespace>.servicebus.windows.net");
clientBuilder.UseCredential(new DefaultAzureCredential());
// Set a credential for all clients to use by default
DefaultAzureCredential credential = new();
clientBuilder.UseCredential(credential);
// Register a subclient for each Service Bus Queue
List<string> queueNames = await GetQueueNames(credential);
foreach (string queue in queueNames)
{
clientBuilder.AddClient<ServiceBusSender, ServiceBusClientOptions>(
(_, _, provider) => provider.GetService<ServiceBusClient>()
.CreateSender(queue)).WithName(queue);
.CreateSender(queue)).WithName(queue);
}
// Register a custom client factory
clientBuilder.AddClient<AzureOpenAIClient, AzureOpenAIClientOptions>(
(options, _, _) => new AzureOpenAIClient(
new Uri("<url_here>"), credential, options));
});

WebApplication app = builder.Build();

async Task<List<string>> GetQueueNames()
async Task<List<string>> GetQueueNames(DefaultAzureCredential credential)
{
// Query the available queues for the Service Bus namespace.
var adminClient = new ServiceBusAdministrationClient
("<your_namespace>.servicebus.windows.net", new DefaultAzureCredential());
("<your_namespace>.servicebus.windows.net", credential);
var queueNames = new List<string>();

// Because the result is async, the queue names need to be captured
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
<PackageReference Include="Microsoft.Extensions.Azure" />
<PackageReference Include="Microsoft.AspNetCore.OpenApi" />
<PackageReference Include="Swashbuckle.AspNetCore" />
<PackageReference Include="Azure.AI.OpenAI" />
</ItemGroup>

</Project>

0 comments on commit 632d183

Please sign in to comment.