Skip to content
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: 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>
Loading