Inserimento delle dipendenze con Azure SDK per .NET
Questo articolo illustra come registrare i client del servizio di Azure dalle librerie client di Azure più recenti per .NET per l'inserimento delle dipendenze in un'app .NET. Ogni app .NET moderna viene avviata usando le istruzioni fornite in un file Program.cs.
Installare i pacchetti
Per registrare e configurare i client del servizio da un pacchetto con prefisso-Azure.
:
Installare il pacchetto Microsoft.Extensions.Azure nel progetto:
dotnet add package Microsoft.Extensions.Azure
Installare il pacchetto Azure.Identity per configurare un tipo
TokenCredential
da usare per l'autenticazione di tutti i client registrati che accettano tale tipo:dotnet add package Azure.Identity
A scopo dimostrativo, il codice di esempio in questo articolo usa le librerie Segreti dell'insieme di credenziali delle chiavi, Archiviazione BLOB, bus di servizio e OpenAI di Azure. Installare i pacchetti seguenti per seguire questa procedura:
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
Registrare client e sottoclient
Un client di servizio è il punto di ingresso dell'API per un servizio di Azure, da cui gli utenti della libreria possono richiamare tutte le operazioni fornite dal servizio e possono implementare facilmente gli scenari più comuni. Per semplificare la progettazione di un'API, i gruppi di chiamate di servizio possono essere organizzati in base a tipi di sottoclient più piccoli. Ad esempio, ServiceBusClient
può registrare ServiceBusSender
sottoclient aggiuntivi per la pubblicazione di messaggi o ServiceBusReceiver
sottoclient per l'utilizzo dei messaggi.
Nel file Program.cs, richiamare il metodo di estensione AddAzureClients per registrare un client per ogni servizio. Gli esempi di codice seguenti forniscono indicazioni sui generatori di applicazioni dagli spazi dei nomi Microsoft.AspNetCore.Builder
e Microsoft.Extensions.Hosting
.
using Azure.Identity;
using Azure.Messaging.ServiceBus;
using Azure.Messaging.ServiceBus.Administration;
using Microsoft.Extensions.Azure;
using Azure.AI.OpenAI;
WebApplicationBuilder builder = WebApplication.CreateBuilder(args);
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");
// 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));
});
WebApplication app = builder.Build();
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", credential);
var queueNames = new List<string>();
// Because the result is async, the queue names 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 (QueueProperties queue in adminClient.GetQueuesAsync())
{
queueNames.Add(queue.Name);
}
return queueNames;
}
Nel codice precedente:
- I segreti dell'insieme di credenziali delle chiavi, l'archiviazione BLOB e i client bus di servizio vengono registrati rispettivamente usando AddSecretClient, AddBlobServiceClient e AddServiceBusClientWithNamespace. Gli argomenti tipizzati
Uri
estring
vengono passati. Per evitare di specificare questi URL in modo esplicito, vedere la sezione Archiviare configurazione separatamente dal codice. - DefaultAzureCredential viene usato per soddisfare il requisito dell'argomento
TokenCredential
per ogni client registrato. Quando viene creato uno dei client,DefaultAzureCredential
viene usato per l'autenticazione. - I sottoclient del bus di servizio vengono registrati per ogni coda nel servizio usando il sottoclient e i tipi di opzione corrispondenti. I nomi delle code per i sottoclient vengono recuperati usando un metodo separato all'esterno della registrazione del servizio perché il metodo
GetQueuesAsync
deve essere eseguito in modo asincrono. - Un client OpenAI di Azure viene registrato usando una factory client personalizzata tramite il AddClient metodo , che fornisce il controllo sulla modalità di creazione di un'istanza client. Le factory client personalizzate sono utili nei casi seguenti:
- È necessario usare altre dipendenze durante la costruzione del client.
- Un metodo di estensione di registrazione non esiste per il client del servizio che si vuole registrare.
Usare i client registrati
Dopo aver registrato i client, come descritto nella sezione Registrare client e sottoclient, è ora possibile usarli. Nell'esempio seguente viene usato l'inserimento del costruttore per ottenere il client di archiviazione BLOB e una factory per i client secondari del mittente del bus di servizio in un controller API ASP.NET Core:
[ApiController]
[Route("[controller]")]
public class MyApiController : ControllerBase
{
private readonly BlobServiceClient _blobServiceClient;
private readonly ServiceBusSender _serviceBusSender;
public MyApiController(
BlobServiceClient blobServiceClient,
IAzureClientFactory<ServiceBusSender> senderFactory)
{
_blobServiceClient = blobServiceClient;
_serviceBusSender = senderFactory.CreateClient("myQueueName");
}
[HttpGet]
public async Task<IEnumerable<string>> Get()
{
BlobContainerClient containerClient =
_blobServiceClient.GetBlobContainerClient("demo");
var results = new List<string>();
await foreach (BlobItem blob in containerClient.GetBlobsAsync())
{
results.Add(blob.Name);
}
return results.ToArray();
}
}
Archiviare configurazione separatamente dal codice
Nella sezione Registrare client e sottoclient sono state passate in modo esplicito le variabili tipizzata Uri
ai costruttori client. Questo approccio può causare problemi quando si esegue codice in ambienti diversi durante lo sviluppo e la produzione. Il team .NET suggerisce di archiviare tali configurazioni nei file JSON dipendenti dall'ambiente. Ad esempio, è possibile avere un file appsettings.Development.json contenente le impostazioni dell'ambiente di sviluppo. Un altro file appsettings.Production.json conterrà le impostazioni dell'ambiente di produzione e così via. Il formato di file è:
{
"AzureDefaults": {
"Diagnostics": {
"IsTelemetryDisabled": false,
"IsLoggingContentEnabled": true
},
"Retry": {
"MaxRetries": 3,
"Mode": "Exponential"
}
},
"KeyVault": {
"VaultUri": "https://mykeyvault.vault.azure.net"
},
"ServiceBus": {
"Namespace": "<your_namespace>.servicebus.windows.net"
},
"Storage": {
"ServiceUri": "https://mydemoaccount.storage.windows.net"
}
}
È possibile aggiungere qualsiasi proprietà dalla classe ClientOptions nel file JSON. Le impostazioni nel file di configurazione JSON possono essere recuperate usando IConfiguration.
builder.Services.AddAzureClients(clientBuilder =>
{
clientBuilder.AddSecretClient(
builder.Configuration.GetSection("KeyVault"));
clientBuilder.AddBlobServiceClient(
builder.Configuration.GetSection("Storage"));
clientBuilder.AddServiceBusClientWithNamespace(
builder.Configuration["ServiceBus:Namespace"]);
clientBuilder.UseCredential(new DefaultAzureCredential());
// Set up any default settings
clientBuilder.ConfigureDefaults(
builder.Configuration.GetSection("AzureDefaults"));
});
Nel campione JSON precedente:
- I nomi delle chiavi di primo livello
AzureDefaults
,KeyVault
,ServiceBus
eStorage
sono arbitrari. Tutti gli altri nomi delle chiavi hanno valore e la serializzazione JSON viene eseguita senza distinzione tra maiuscole e minuscole. - Il valore letterale di oggetto
AzureDefaults.Retry
:- Rappresenta le impostazioni della configurazione dei criteri di ripetizione.
- Corrisponde alla proprietà Retry. All'interno del valore letterale di oggetto si trova la chiave
MaxRetries
, che corrisponde alla proprietà MaxRetries.
- I valori della chiave
KeyVault:VaultUri
,ServiceBus:Namespace
eStorage:ServiceUri
vengono mappati rispettivamente agli argomenti tipizzatiUri
estring
rispettivamente degli overload del costruttore Azure.Security.KeyVault.Secrets.SecretClient.SecretClient(Uri, TokenCredential, SecretClientOptions), Azure.Messaging.ServiceBus.ServiceBusClient.ServiceBusClient(String) e Azure.Storage.Blobs.BlobServiceClient.BlobServiceClient(Uri, TokenCredential, BlobClientOptions). Le variantiTokenCredential
dei costruttori vengono utilizzate perché un valore predefinitoTokenCredential
viene impostato tramite la chiamata al metodo Microsoft.Extensions.Azure.AzureClientFactoryBuilder.UseCredential(TokenCredential).
Configurare più client di servizio con nomi diversi
Si supponga di avere due account di archiviazione: uno per le informazioni private e un altro per le informazioni pubbliche. L'app trasferisce i dati dal pubblico all'account di archiviazione privato dopo un'operazione. È necessario avere due client del servizio di archiviazione. Per distinguere questi due client, usare il metodo di estensione WithName:
builder.Services.AddAzureClients(clientBuilder =>
{
clientBuilder.AddBlobServiceClient(
builder.Configuration.GetSection("PublicStorage"));
clientBuilder.AddBlobServiceClient(
builder.Configuration.GetSection("PrivateStorage"))
.WithName("PrivateStorage");
});
Usando un controller ASP.NET Core come esempio, accedere al client del servizio denominato usando l'interfaccia IAzureClientFactory<TClient>:
public class HomeController : Controller
{
private readonly BlobServiceClient _publicStorage;
private readonly BlobServiceClient _privateStorage;
public HomeController(
BlobServiceClient defaultClient,
IAzureClientFactory<BlobServiceClient> clientFactory)
{
_publicStorage = defaultClient;
_privateStorage = clientFactory.CreateClient("PrivateStorage");
}
}
Il client del servizio senza nome è ancora disponibile nello stesso modo di prima. I client denominati sono incrementali.
Configurare un nuovo criterio di ripetizione
A un certo punto, è possibile modificare le impostazioni predefinite per un client del servizio. Ad esempio, è possibile che si vogliano impostazioni di ripetizione diverse o usare una versione diversa dell'API del servizio. È possibile impostare le impostazioni di ripetizione a livello globale o in base al servizio. Si supponga di avere il file appsettings.json nel progetto ASP.NET Core:
{
"AzureDefaults": {
"Retry": {
"maxRetries": 3
}
},
"KeyVault": {
"VaultUri": "https://mykeyvault.vault.azure.net"
},
"ServiceBus": {
"Namespace": "<your_namespace>.servicebus.windows.net"
},
"Storage": {
"ServiceUri": "https://store1.storage.windows.net"
},
"CustomStorage": {
"ServiceUri": "https://store2.storage.windows.net"
}
}
È possibile modificare i criteri di ripetizione in base alle proprie esigenze, ad esempio:
builder.Services.AddAzureClients(clientBuilder =>
{
// Establish the global defaults
clientBuilder.ConfigureDefaults(
builder.Configuration.GetSection("AzureDefaults"));
clientBuilder.UseCredential(new DefaultAzureCredential());
// A Key Vault Secrets client using the global defaults
clientBuilder.AddSecretClient(
builder.Configuration.GetSection("KeyVault"));
// A Blob Storage client with a custom retry policy
clientBuilder.AddBlobServiceClient(
builder.Configuration.GetSection("Storage"))
.ConfigureOptions(options => options.Retry.MaxRetries = 10);
clientBuilder.AddServiceBusClientWithNamespace(
builder.Configuration["ServiceBus:Namespace"])
.ConfigureOptions(options => options.RetryOptions.MaxRetries = 10);
// A named storage client with a different custom retry policy
clientBuilder.AddBlobServiceClient(
builder.Configuration.GetSection("CustomStorage"))
.WithName("CustomStorage")
.ConfigureOptions(options =>
{
options.Retry.Mode = Azure.Core.RetryMode.Exponential;
options.Retry.MaxRetries = 5;
options.Retry.MaxDelay = TimeSpan.FromSeconds(120);
});
});
È anche possibile inserire override dei criteri di ripetizione nel file appsettings.json:
{
"KeyVault": {
"VaultUri": "https://mykeyvault.vault.azure.net",
"Retry": {
"maxRetries": 10
}
}
}