integrazione di .NET AspireAzure Service Bus
Include: integrazione dell'hosting e integrazione con
Client
Azure Service Bus è un broker di messaggi aziendale completamente gestito con code di messaggi e argomenti di pubblicazione-sottoscrizione. L'integrazione .NET AspireAzure Service Bus consente di connettersi alle istanze di Azure Service Bus da applicazioni .NET.
Integrazione del servizio di hosting
Il .NET.NET AspireAzure Service Bus che ospita l'integrazione modella le varie risorse del bus di servizio come i tipi seguenti:
- AzureServiceBusResource: rappresenta una risorsa di Azure Service Bus.
- AzureServiceBusEmulatorResource: rappresenta una risorsa emulatore di Azure Service Bus.
Per accedere a questi tipi e alle API per esprimerli, aggiungere il pacchetto NuGet 📦Aspire.Hosting.Azure.ServiceBus nel progetto host dell'app .
- .NET CLI dell'interfaccia della riga di comando
- PackageReference
dotnet add package Aspire.Hosting.Azure.ServiceBus
Per altre informazioni, vedere dotnet add package o Manage package dependencies in .NET applications.
Aggiungi la risorsa Azure Service Bus
Nel progetto host dell'app, si può chiamare AddAzureServiceBus per aggiungere e restituire un generatore di risorse Azure Service Bus.
var builder = DistributedApplication.CreateBuilder(args);
var serviceBus = builder.AddAzureServiceBus("messaging");
// After adding all resources, run the app...
Quando si aggiunge un AzureServiceBusResource all'host dell'app, consente l'accesso ad altre API utili per aggiungere code e argomenti. In altre parole, è necessario aggiungere un AzureServiceBusResource
prima di aggiungere qualsiasi altra risorsa di Service Bus.
Importante
Quando chiami AddAzureServiceBus, chiama implicitamente AddAzureProvisioning, che aggiunge il supporto per la generazione dinamica delle risorse Azure durante l'avvio dell'app. L'app deve configurare l'abbonamento e la località appropriate. Per altre informazioni, vedere Configurazione.
Gestione delle risorse Bicep generato
Se non si ha familiarità con Bicep, si tratta di un linguaggio specifico del dominio per definire le risorse Azure. Con .NET.NET Aspirenon è necessario scrivere Bicep a mano, ma le API di provisioning generano Bicep automaticamente. Quando pubblichi la tua app, il Bicep generato viene fornito insieme al file di manifesto. Quando si aggiunge una risorsa Azure Service Bus, viene generato il seguente Bicep:
@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
Il Bicep precedente è un modulo che effettua il provisioning di un namespace Azure Service Bus con le seguenti impostazioni predefinite:
-
sku
: Lo SKU dello spazio dei nomi del Service Bus. Il valore predefinito è Standard. -
location
: Posizione dello spazio dei nomi del Service Bus. Il valore predefinito è la posizione del gruppo di risorse.
Oltre al namespace di Service Bus, esegue anche il provisioning di un ruolo incorporato Azure controllo degli accessi in base al ruolo (Azure RBAC) di Azure Service Bus Data Owner. Il ruolo viene assegnato al gruppo di risorse dello spazio dei nomi di Service Bus. Per altre informazioni, vedere Azure Service Bus Proprietario dei dati.
Personalizzare l'infrastruttura di provisioning
Tutte le risorse .NET AspireAzure sono sottoclassi del tipo di AzureProvisioningResource. Questo tipo consente la personalizzazione del Bicep generato fornendo un'API fluente per configurare le risorse Azure, utilizzando l'API ConfigureInfrastructure<T>(IResourceBuilder<T>, Action<AzureResourceInfrastructure>). Ad esempio, è possibile configurare lo SKU, il percorso e altro ancora. L'esempio seguente illustra come personalizzare la risorsa Azure Service Bus:
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");
});
Il codice precedente:
- Concatena una chiamata all'API ConfigureInfrastructure:
- Il parametro infra è un'istanza del tipo di AzureResourceInfrastructure.
- Le risorse provisionabili si recuperano chiamando il metodo GetProvisionableResources().
- Viene recuperato il singolo ServiceBusNamespace.
- Il ServiceBusNamespace.Sku è stato creato con un ServiceBusSkuTier.Premium
- Un tag viene aggiunto allo spazio dei nomi del bus di servizio con una chiave di
ExampleKey
e un valore diExample value
.
Sono disponibili molte altre opzioni di configurazione per personalizzare la risorsa Azure Service Bus. Per altre informazioni, vedere Azure.Provisioning.ServiceBus. Per ulteriori informazioni, consultare Azure. Personalizzazione dell'approvvigionamento.
Connettersi a uno spazio dei nomi Azure Service Bus esistente
Potrebbe essere disponibile uno spazio dei nomi Azure Service Bus esistente a cui connettersi. Anziché rappresentare una nuova risorsa Azure Service Bus, è possibile aggiungere una stringa di connessione all'host dell'app. Per aggiungere una connessione a uno spazio dei nomi Azure Service Bus esistente, chiamare il metodo AddConnectionString:
var builder = DistributedApplication.CreateBuilder(args);
var serviceBus = builder.AddConnectionString("messaging");
builder.AddProject<Projects.WebApplication>("web")
.WithReference(serviceBus);
// After adding all resources, run the app...
Nota
Le stringhe di connessione vengono usate per rappresentare un'ampia gamma di informazioni di connessione, tra cui connessioni di database, broker di messaggi, URI degli endpoint e altri servizi. Nella nomenclatura .NET.NET Aspire, il termine "stringa di connessione" è utilizzato per rappresentare qualsiasi tipo di informazioni di connessione.
La stringa di connessione viene configurata nella configurazione dell'host dell'app, in genere in segreti utente, nella sezione ConnectionStrings
. L'host dell'app inserisce questa stringa di connessione come variabile di ambiente in tutte le risorse dipendenti, ad esempio:
{
"ConnectionStrings": {
"messaging": "Endpoint=sb://{namespace}.servicebus.windows.net/;SharedAccessKeyName={key_name};SharedAccessKey={key_value};"
}
}
La risorsa dipendente può accedere alla stringa di connessione inserita chiamando il metodo GetConnectionString e passando il nome della connessione come parametro, in questo caso "messaging"
. L'API GetConnectionString
è un'abbreviazione di IConfiguration.GetSection("ConnectionStrings")[name]
.
Aggiungi Azure Service Bus coda
Per aggiungere una coda di Azure Service Bus, chiamare il metodo AddServiceBusQueue sul IResourceBuilder<AzureServiceBusResource>
:
var builder = DistributedApplication.CreateBuilder(args);
var serviceBus = builder.AddAzureServiceBus("messaging");
serviceBus.AddServiceBusQueue("queue");
// After adding all resources, run the app...
Quando chiami AddServiceBusQueue(IResourceBuilder<AzureServiceBusResource>, String, String), questo configura le risorse di Service Bus per avere una coda denominata queue
. La coda viene creata nello spazio dei nomi del Service Bus rappresentato dal AzureServiceBusResource
aggiunto in precedenza. Per ulteriori informazioni, vedere Code, argomenti e abbonamenti in Azure Service Bus.
Aggiungere Azure Service Bus argomento e sottoscrizione
Per aggiungere un argomento Azure Service Bus, chiamare il metodo AddServiceBusTopic nel IResourceBuilder<AzureServiceBusResource>
:
var builder = DistributedApplication.CreateBuilder(args);
var serviceBus = builder.AddAzureServiceBus("messaging");
serviceBus.AddServiceBusTopic("topic");
// After adding all resources, run the app...
Quando si chiama AddServiceBusTopic(IResourceBuilder<AzureServiceBusResource>, String, String), configura le risorse di Service Bus per avere un topic denominato topic
. L'argomento viene creato nello spazio dei nomi del Service Bus, rappresentato dal AzureServiceBusResource
che hai aggiunto in precedenza.
Per aggiungere una sottoscrizione per l'argomento, chiamare il metodo AddServiceBusSubscription nel IResourceBuilder<AzureServiceBusTopicResource>
e configurarlo usando il metodo WithProperties:
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...
Il codice precedente non solo aggiunge un argomento e crea e configura una sottoscrizione denominata sub1
per l'argomento. L'abbonamento ha un numero massimo di consegne di 10
e una regola denominata app-prop-filter-1
. La regola è un filtro di correlazione che filtra i messaggi in base alle proprietà ContentType
, CorrelationId
, Subject
, MessageId
, ReplyTo
, ReplyToSessionId
, SessionId
e SendTo
.
Per ulteriori informazioni, vedere Code, argomenti e abbonamenti in Azure Service Bus.
Aggiungi la risorsa dell'emulatore Azure Service Bus
Per aggiungere una risorsa dell'emulatore Azure Service Bus, concatenare una chiamata a un <IResourceBuilder<AzureServiceBusResource>>
all'API RunAsEmulator:
var builder = DistributedApplication.CreateBuilder(args);
var serviceBus = builder.AddAzureServiceBus("messaging")
.RunAsEmulator();
// After adding all resources, run the app...
Quando si chiama RunAsEmulator
, configura le risorse del bus di servizio per l'esecuzione in locale tramite un emulatore. L'emulatore in questo caso è l'emulatore Azure Service Bus. L'emulatore Azure Service Bus offre un ambiente locale gratuito per testare le app Azure Service Bus ed è un perfetto compagno all'integrazione dell'hosting .NET AspireAzure. L'emulatore non è installato, ma è accessibile per .NET.NET Aspire come contenitore. Quando si aggiunge un contenitore al host dell'applicazione, come illustrato nell'esempio precedente con l'immagine mcr.microsoft.com/azure-messaging/servicebus-emulator
(e l'immagine mcr.microsoft.com/azure-sql-edge
complementare), crea e avvia il contenitore all'avvio dell'host dell'applicazione. Per ulteriori informazioni, vedere Ciclo di vita delle risorse del contenitore.
Configurare il contenitore dell'emulatore del bus di servizio
Sono disponibili varie configurazioni per le risorse del contenitore, ad esempio è possibile configurare le porte del contenitore o fornire una configurazione di JSON che esegue l'override di tutti gli elementi.
Configurare la porta host del contenitore dell'emulatore del bus di servizio
Per impostazione predefinita, il contenitore dell'emulatore del bus di servizio quando configurato da .NET.NET Aspireespone gli endpoint seguenti:
Punto finale | Immagine | Porta contenitore | Porta host |
---|---|---|---|
emulator |
mcr.microsoft.com/azure-messaging/servicebus-emulator |
5672 | dinamico |
tcp |
mcr.microsoft.com/azure-sql-edge |
1433 | dinamico |
La porta su cui è in ascolto è dinamica per impostazione predefinita. All'avvio del contenitore, la porta viene mappata a una porta casuale sulla macchina host. Per configurare la porta dell'endpoint, concatenare le chiamate al generatore di risorse del contenitore fornito dal metodo RunAsEmulator
e quindi il WithHostPort(IResourceBuilder<AzureServiceBusEmulatorResource>, Nullable<Int32>) come illustrato nell'esempio seguente:
var builder = DistributedApplication.CreateBuilder(args);
var serviceBus = builder.AddAzureServiceBus("messaging").RunAsEmulator(
emulator =>
{
emulator.WithHostPort(7777);
});
// After adding all resources, run the app...
Il codice precedente configura l'endpoint emulator
esistente del contenitore dell'emulatore del bus di servizio per l'ascolto sulla porta 7777
. La porta del contenitore dell'emulatore del bus di servizio viene mappata alla porta host, come illustrato nella tabella seguente:
Nome del punto finale | Mappatura delle porte (container:host ) |
---|---|
emulator |
5672:7777 |
Configurare la configurazione del contenitore dell'emulatore del bus di servizio JSON
Il contenitore dell'emulatore del bus di servizio viene eseguito con un file di config.json predefinito. È possibile eseguire l'override di questo file completamente o aggiornare la configurazione JSON con una rappresentazione JsonNode della configurazione.
Per fornire un file di configurazione JSON personalizzato, chiamare il metodo WithConfigurationFile(IResourceBuilder<AzureServiceBusEmulatorResource>, String):
var builder = DistributedApplication.CreateBuilder(args);
var serviceBus = builder.AddAzureServiceBus("messaging").RunAsEmulator(
emulator =>
{
emulator.WithConfigurationFile(
path: "./messaging/custom-config.json");
});
Il codice precedente configura il contenitore dell'emulatore del bus di servizio per l'uso di un file di configurazione personalizzato JSON disponibile in ./messaging/custom-config.json
. Per eseguire invece l'override di proprietà specifiche nella configurazione predefinita, chiamare il metodo WithConfiguration(IResourceBuilder<AzureServiceBusEmulatorResource>, Action<JsonNode>):
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...
Il codice precedente recupera il nodo UserConfig
dalla configurazione predefinita. Aggiorna quindi le proprietà della prima coda impostando MaxDeliveryCount
su 5
, RequiresDuplicateDetection
su true
e DefaultMessageTimeToLive
su 2 hours
.
Verifica dell'integrità delle integrazioni di hosting
L'integrazione di hosting Azure Service Bus aggiunge automaticamente un controllo dell'integrità per la risorsa Service Bus. Il controllo di integrità verifica che il Bus di Servizio sia operativo e che possa essere stabilita una connessione.
L'integrazione dell'hosting si basa sul pacchetto NuGet 📦 AspNetCore.HealthChecks.AzureServiceBus.
Client integrazione
Per iniziare a usare l'integrazione client .NET AspireAzure Service Bus, installare il pacchetto NuGet 📦Aspire.Azure.Messaging.ServiceBus nel progetto che utilizza il client, ovvero nel progetto per l'applicazione che usa il client di Service Bus. L'integrazione client del Service Bus registra un'istanza di ServiceBusClient che puoi utilizzare per interagire con il Service Bus.
- .NET CLI dell'interfaccia della riga di comando
- PackageReference
dotnet add package Aspire.Azure.Messaging.ServiceBus
Aggiungere il client del Service Bus
Nel file Program.cs del progetto cliente, chiamate il metodo di estensione AddAzureServiceBusClient su qualsiasi IHostApplicationBuilder per registrare un ServiceBusClient da usare tramite il container per l'inserimento delle dipendenze. Il metodo accetta un parametro del nome di connessione.
builder.AddAzureServiceBusClient(connectionName: "messaging");
Suggerimento
Il parametro connectionName
deve corrispondere al nome usato quando si aggiunge la risorsa del bus di servizio nel progetto host dell'app. In altre parole, quando si chiama AddAzureServiceBus
e si specifica un nome di messaging
lo stesso nome deve essere usato quando si chiama AddAzureServiceBusClient
. Per altre informazioni, vedere Aggiungere Azure Service Bus risorsa.
È quindi possibile recuperare l'istanza di ServiceBusClient usando l'iniezione di dipendenze. Ad esempio, per recuperare la connessione da un servizio di esempio:
public class ExampleService(ServiceBusClient client)
{
// Use client...
}
Per ulteriori informazioni sull'iniezione di dipendenze, vedere .NET iniezione di dipendenze.
Aggiungere un client con chiave per Service Bus
In alcuni casi potrebbe essere necessario registrare più istanze di ServiceBusClient
con nomi di connessione diversi. Per registrare i client con chiavi del Service Bus, chiamare il metodo AddKeyedAzureServiceBusClient:
builder.AddKeyedAzureServiceBusClient(name: "mainBus");
builder.AddKeyedAzureServiceBusClient(name: "loggingBus");
Importante
Quando si usano i servizi con chiave, è previsto che la risorsa del Bus di Servizio abbia configurato due bus con nomi specifici, uno per mainBus
e uno per loggingBus
.
È quindi possibile ottenere le istanze di ServiceBusClient
usando la dependency injection. Ad esempio, per recuperare la connessione da un servizio di esempio:
public class ExampleService(
[FromKeyedServices("mainBus")] ServiceBusClient mainBusClient,
[FromKeyedServices("loggingBus")] ServiceBusClient loggingBusClient)
{
// Use clients...
}
Per ulteriori informazioni sui servizi con chiave, consultare la sezione .NET Inserimento delle Dipendenze: Servizi con Chiave.
Configurazione
L'integrazione .NET AspireAzure Service Bus offre più opzioni per configurare la connessione in base ai requisiti e alle convenzioni del progetto.
Usare una stringa di connessione
Quando si usa una stringa di connessione dalla sezione di configurazione ConnectionStrings
, è possibile specificare il nome della stringa di connessione quando si chiama il metodo AddAzureServiceBusClient:
builder.AddAzureServiceBusClient("messaging");
La stringa di connessione viene quindi recuperata dalla sezione di configurazione ConnectionStrings
:
{
"ConnectionStrings": {
"messaging": "Endpoint=sb://{namespace}.servicebus.windows.net/;SharedAccessKeyName={keyName};SharedAccessKey={key};"
}
}
Per altre informazioni su come formattare questa stringa di connessione, vedere la documentazione di ConnectionString.
Utilizzare i provider di configurazione
L'integrazione .NET AspireAzure Service Bus supporta Microsoft.Extensions.Configuration. Carica il AzureMessagingServiceBusSettings dalla configurazione utilizzando la chiave Aspire:Azure:Messaging:ServiceBus
. Il frammento di codice seguente è un esempio di un file appsettings.json che configura alcune delle opzioni:
{
"Aspire": {
"Azure": {
"Messaging": {
"ServiceBus": {
"ConnectionString": "Endpoint=sb://{namespace}.servicebus.windows.net/;SharedAccessKeyName={keyName};SharedAccessKey={key};",
"DisableTracing": false
}
}
}
}
}
Per lo schema completo dell'integrazione client del bus di servizio JSON, vedere Aspire.Azure.Messaging.ServiceBus/ConfigurationSchema.json.
Usare delegati inline
È anche possibile passare il delegato Action<AzureMessagingServiceBusSettings> configureSettings
per configurare alcune o tutte le opzioni in linea, ad esempio per disabilitare il tracciamento direttamente dal codice:
builder.AddAzureServiceBusClient(
"messaging",
static settings => settings.DisableTracing = true);
È anche possibile configurare il Azure.Messaging.ServiceBus.ServiceBusClientOptions usando il parametro facoltativo Action<ServiceBusClientOptions> configureClientOptions
del metodo AddAzureServiceBusClient
. Ad esempio, per impostare il suffisso dell'intestazione user-agent ServiceBusClientOptions.Identifier per tutte le richieste effettuate da questo client:
builder.AddAzureServiceBusClient(
"messaging",
configureClientOptions:
clientOptions => clientOptions.Identifier = "myapp");
Client verifiche di integrità dell'integrazione
Per impostazione predefinita, le integrazioni .NET.NET Aspire abilitano i controlli di integrità per tutti i servizi. Per altre informazioni, vedere panoramica delle integrazioni .NET.NET Aspire.
Integrazione .NET AspireAzure Service Bus:
- Aggiunge il controllo di integrità quando AzureMessagingServiceBusSettings.DisableTracing è
false
, tentando di connettersi al Service Bus. - Si integra con l'endpoint HTTP
/health
, il quale specifica che tutti i controlli di integrità registrati devono essere superati con successo affinché l'app sia considerata pronta per accettare il traffico.
Osservabilità e telemetria
.NET
.NET Aspire le integrazioni impostano automaticamente le configurazioni di registrazione, tracciamento e metriche, talvolta noti come i pilastri dell'osservabilità. Per altre informazioni sull'osservabilità e la telemetria dell'integrazione, vedere panoramica delle integrazioni .NET.NET Aspire. A seconda del servizio di backup, alcune integrazioni possono supportare solo alcune di queste funzionalità. Ad esempio, alcune integrazioni supportano la registrazione e la traccia, ma non le metriche. Le funzionalità di telemetria possono essere disabilitate anche usando le tecniche presentate nella sezione Configurazione
Registrazione
L'integrazione .NET AspireAzure Service Bus usa le categorie di log seguenti:
Azure.Core
Azure.Identity
Azure-Messaging-ServiceBus
Oltre a ottenere la diagnostica delle richieste Azure Service Bus per le richieste non riuscite, è possibile configurare le soglie di latenza per determinare quale diagnostica delle richieste riuscite Azure Service Bus verrà registrata correttamente. I valori predefiniti sono 100 ms per le operazioni punto e 500 ms per le operazioni non di punto.
builder.AddAzureServiceBusClient(
"messaging",
configureClientOptions:
clientOptions => {
clientOptions.ServiceBusClientTelemetryOptions = new()
{
ServiceBusThresholdOptions = new()
{
PointOperationLatencyThreshold = TimeSpan.FromMilliseconds(50),
NonPointOperationLatencyThreshold = TimeSpan.FromMilliseconds(300)
}
};
});
Tracciamento
L'integrazione .NET AspireAzure Service Bus genererà le attività di traccia seguenti usando 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
Il tracciamento Azure Service Bus è attualmente in anteprima, pertanto è necessario attivare l'interruttore sperimentale per garantire l'emissione delle tracce.
AppContext.SetSwitch("Azure.Experimental.EnableActivitySource", true);
Per altre informazioni, vedere Azure Service Bus: traccia distribuita e correlazione tramite la messaggistica del bus di servizio.
Metriche
L'integrazione .NET AspireAzure Service Bus attualmente non supporta le metriche per impostazione predefinita a causa di limitazioni con Azure SDK.
Vedere anche
- Azure Service Bus
- Panoramica delle integrazioni .NET.NET Aspire
- Panoramica delle integrazioni .NET AspireAzure
- .NET Aspire GitHub repository