Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Aspire migliora l'esperienza di sviluppo fornendo blocchi predefiniti riutilizzabili che possono essere usati per organizzare rapidamente le dipendenze dell'applicazione ed esporle al proprio codice. Uno dei blocchi predefiniti di base di un'applicazione basata su Aspireè la risorsa . Considerare il codice seguente:
var builder = DistributedApplication.CreateBuilder(args);
var redis = builder.AddRedis("cache");
var db = builder.AddPostgres("pgserver")
.AddDatabase("inventorydb");
builder.AddProject<Projects.InventoryService>("inventoryservice")
.WithReference(redis)
.WithReference(db);
Nel codice precedente sono rappresentate quattro risorse:
-
cache: un contenitore Redis. -
pgserver: un contenitore Postgres. -
inventorydb: Un database ospitato supgserver. -
inventoryservice: Un'applicazione ASP.NET Core.
La maggior parte del Aspirecodice correlato che lo sviluppatore medio scrive, si concentra sull'aggiunta di risorse al modello di app e sulla creazione di riferimenti tra di essi.
Elementi chiave di una Aspire risorsa personalizzata
La compilazione di una risorsa personalizzata in Aspire richiede quanto segue:
- Tipo di risorsa personalizzato che implementa IResource
- Metodo di estensione per IDistributedApplicationBuilder denominato
Add{CustomResource}in cui{CustomResource}è il nome della risorsa personalizzata.
Quando la risorsa personalizzata richiede una configurazione facoltativa, gli sviluppatori potrebbero voler implementare metodi di estensione con suffisso With* che rendano individuabili queste opzioni di configurazione usando il pattern builder .
Esempio pratico: MailDev
Per comprendere come sviluppare risorse personalizzate, questo articolo illustra un esempio di come creare una risorsa personalizzata per MailDev. MailDev è uno strumento open source che fornisce un server di posta locale progettato per consentire agli sviluppatori di testare i comportamenti di invio della posta elettronica all'interno dell'app. Per altre informazioni, vedere repository MailDevGitHub.
In questo esempio viene creato un nuovo progetto di Aspire come ambiente di test per la risorsa MailDev creata. Anche se è possibile creare risorse personalizzate nei progetti di Aspire esistenti, è consigliabile valutare se la risorsa personalizzata può essere usata in più soluzioni basate su Aspiree deve essere sviluppata come integrazione riutilizzabile.
Configurare il progetto iniziale
Creare un nuovo Aspire progetto usato per testare la nuova risorsa in fase di sviluppo.
dotnet new aspire -o MailDevResource
cd MailDevResource
dir
Dopo aver creato il progetto, verrà visualizzato un elenco contenente quanto segue:
-
MailDevResource.AppHost: AppHost usato per testare la risorsa personalizzata. -
MailDevResource.ServiceDefaults: il servizio imposta di default il progetto per i progetti correlati al servizio. -
MailDevResource.sln: file di soluzione che fa riferimento a entrambi i progetti.
Verificare che il progetto possa compilare ed eseguire correttamente eseguendo il comando seguente:
dotnet run --project MailDevResource.AppHost/MailDevResource.AppHost.csproj
L'output della console dovrebbe essere simile al seguente:
Building...
info: Aspire.Hosting.DistributedApplication[0]
Aspire version: 9.0.0
info: Aspire.Hosting.DistributedApplication[0]
Distributed application starting.
info: Aspire.Hosting.DistributedApplication[0]
Application host directory is:
..\docs-aspire\docs\extensibility\snippets\MailDevResource\MailDevResource.AppHost
info: Aspire.Hosting.DistributedApplication[0]
Now listening on: https://localhost:17251
info: Aspire.Hosting.DistributedApplication[0]
Login to the dashboard at https://localhost:17251/login?t=928db244c720c5022a7a9bf5cf3a3526
info: Aspire.Hosting.DistributedApplication[0]
Distributed application started. Press Ctrl+C to shut down.
Selezionare il collegamento dashboard nel browser per visualizzare il Aspire dashboard:
Premere CTRL+C per arrestare l'app (è possibile chiudere la scheda del browser).
Creare una libreria per l'estensione della risorsa
Aspire risorse sono solo classi e metodi contenuti all'interno di una libreria di classi che fa riferimento alla libreria di hosting Aspire (Aspire.Hosting). Inserendo la risorsa in un progetto separato, è possibile condividerla più facilmente tra app basate su Aspire e potenzialmente pacchettizzarla e condividerla su NuGet.
Creare il progetto di libreria di classi denominato MailDev. Hosting.
dotnet new classlib -o MailDev.HostingAggiungere
Aspire.Hostingalla libreria delle classi come riferimento del pacchetto.dotnet add ./MailDev.Hosting/MailDev.Hosting.csproj package Aspire.Hosting --version 9.0.0Importante
La versione specificata qui deve corrispondere alla versione dell'SDK Aspire usata nella soluzione.
Aggiungi il riferimento alla libreria di classi al progetto MailDevResource.AppHost.
dotnet add ./MailDevResource.AppHost/MailDevResource.AppHost.csproj reference ./MailDev.Hosting/MailDev.Hosting.csprojAggiungere un progetto di libreria di classi al file della soluzione.
dotnet sln ./MailDevResource.sln add ./MailDev.Hosting/MailDev.Hosting.csproj
Dopo aver eseguito i passaggi seguenti, è possibile avviare il progetto:
dotnet run --project ./MailDevResource.AppHost/MailDevResource.AppHost.csproj
Viene visualizzato un avviso nella console:
.\.nuget\packages\aspire.hosting.apphost\9.0.0\build\Aspire.Hosting.AppHost.targets(174,5): warning ASPIRE004: '..\MailDev.Hosting\MailDev.Hosting.csproj' is referenced by an A
spire Host project, but it is not an executable. Did you mean to set IsAspireProjectResource="false"? [D:\source\repos\docs-aspire\docs\extensibility\snippets\MailDevResource\MailDevResource.AppHost\MailDevRe
source.AppHost.csproj]
Questo perché Aspire considera i riferimenti al progetto in AppHost come se fossero progetti di servizio. Per indicare Aspire che il riferimento al progetto deve essere considerato come un progetto non di servizio, modificare i MailDevResource.AppHostMailDevResource.AppHost.csproj file di riferimento al MailDev.Hosting progetto in modo che siano i seguenti:
<ItemGroup>
<!-- The IsAspireProjectResource attribute tells Aspire to treat this
reference as a standard project reference and not attempt to generate
a metadata file -->
<ProjectReference Include="..\MailDev.Hosting\MailDev.Hosting.csproj"
IsAspireProjectResource="false" />
</ItemGroup>
Quando si avvia AppHost, non viene visualizzato alcun avviso nella console.
Definire i tipi di risorse
Oggetto MailDev. La libreria di classi di hosting contiene il tipo di risorsa e i metodi di estensione per l'aggiunta della risorsa ad AppHost. È consigliabile considerare prima di tutto l'esperienza che si vuole offrire agli sviluppatori quando si usa la risorsa personalizzata. Nel caso di questa risorsa personalizzata, si vuole che gli sviluppatori possano scrivere codice simile al seguente:
var builder = DistributedApplication.CreateBuilder(args);
var maildev = builder.AddMailDev("maildev");
builder.AddProject<Projects.NewsletterService>("newsletterservice")
.WithReference(maildev);
A tale scopo, è necessaria una risorsa personalizzata denominata MailDevResource che implementa IResourceWithConnectionString in modo che i consumatori possano usarla con l'estensione WithReference per inserire i dettagli della connessione per il server MailDev come stringa di connessione.
MailDev è disponibile come risorsa contenitore, quindi è anche possibile derivare da ContainerResource in modo da poter usare varie estensioni preesistenti incentrate sui contenitori in Aspire.
Sostituire il contenuto del file Class1.cs nel progetto MailDev.Hosting e rinominare il file in MailDevResource.cs con il codice seguente:
// For ease of discovery, resource types should be placed in
// the Aspire.Hosting.ApplicationModel namespace. If there is
// likelihood of a conflict on the resource name consider using
// an alternative namespace.
namespace Aspire.Hosting.ApplicationModel;
public sealed class MailDevResource(string name) : ContainerResource(name), IResourceWithConnectionString
{
// Constants used to refer to well known-endpoint names, this is specific
// for each resource type. MailDev exposes an SMTP endpoint and a HTTP
// endpoint.
internal const string SmtpEndpointName = "smtp";
internal const string HttpEndpointName = "http";
// An EndpointReference is a core Aspire type used for keeping
// track of endpoint details in expressions. Simple literal values cannot
// be used because endpoints are not known until containers are launched.
private EndpointReference? _smtpReference;
public EndpointReference SmtpEndpoint =>
_smtpReference ??= new(this, SmtpEndpointName);
// Required property on IResourceWithConnectionString. Represents a connection
// string that applications can use to access the MailDev server. In this case
// the connection string is composed of the SmtpEndpoint endpoint reference.
public ReferenceExpression ConnectionStringExpression =>
ReferenceExpression.Create(
$"smtp://{SmtpEndpoint.Property(EndpointProperty.HostAndPort)}"
);
}
Nella risorsa personalizzata precedente, le EndpointReference e le ReferenceExpression sono esempi di diversi tipi che implementano una raccolta di interfacce, ad esempio IManifestExpressionProvider, IValueProvidere IValueWithReferences. Per altre informazioni su questi tipi e sul relativo ruolo in Aspire, vedere i dettagli tecnici.
Definire le estensioni delle risorse
Per semplificare l'uso della risorsa personalizzata da parte degli sviluppatori, è necessario aggiungere al progetto AddMailDev un metodo di estensione denominato MailDev.Hosting. Il metodo di estensione AddMailDev è responsabile della configurazione della risorsa in modo che possa essere avviato correttamente come contenitore.
Aggiungere il codice seguente a un nuovo file denominato MailDevResourceBuilderExtensions.cs nel progetto MailDev.Hosting.
using Aspire.Hosting.ApplicationModel;
// Put extensions in the Aspire.Hosting namespace to ease discovery as referencing
// the Aspire hosting package automatically adds this namespace.
namespace Aspire.Hosting;
public static class MailDevResourceBuilderExtensions
{
/// <summary>
/// Adds the <see cref="MailDevResource"/> to the given
/// <paramref name="builder"/> instance. Uses the "2.1.0" tag.
/// </summary>
/// <param name="builder">The <see cref="IDistributedApplicationBuilder"/>.</param>
/// <param name="name">The name of the resource.</param>
/// <param name="httpPort">The HTTP port.</param>
/// <param name="smtpPort">The SMTP port.</param>
/// <returns>
/// An <see cref="IResourceBuilder{MailDevResource}"/> instance that
/// represents the added MailDev resource.
/// </returns>
public static IResourceBuilder<MailDevResource> AddMailDev(
this IDistributedApplicationBuilder builder,
string name,
int? httpPort = null,
int? smtpPort = null)
{
// The AddResource method is a core API within Aspire and is
// used by resource developers to wrap a custom resource in an
// IResourceBuilder<T> instance. Extension methods to customize
// the resource (if any exist) target the builder interface.
var resource = new MailDevResource(name);
return builder.AddResource(resource)
.WithImage(MailDevContainerImageTags.Image)
.WithImageRegistry(MailDevContainerImageTags.Registry)
.WithImageTag(MailDevContainerImageTags.Tag)
.WithHttpEndpoint(
targetPort: 1080,
port: httpPort,
name: MailDevResource.HttpEndpointName)
.WithEndpoint(
targetPort: 1025,
port: smtpPort,
name: MailDevResource.SmtpEndpointName);
}
}
// This class just contains constant strings that can be updated periodically
// when new versions of the underlying container are released.
internal static class MailDevContainerImageTags
{
internal const string Registry = "docker.io";
internal const string Image = "maildev/maildev";
internal const string Tag = "2.1.0";
}
Convalidare l'integrazione personalizzata all'interno di AppHost
Ora che la struttura di base per la risorsa personalizzata è stata completata, è possibile testarla in un progetto AppHost reale. Aprire il file AppHost.cs nel progetto MailDevResource.AppHost e aggiornarlo con il codice seguente:
var builder = DistributedApplication.CreateBuilder(args);
var maildev = builder.AddMailDev("maildev");
builder.Build().Run();
Dopo aver aggiornato il AppHost.cs file, avviare il progetto AppHost e aprire il dashboard:
dotnet run --project ./MailDevResource.AppHost/MailDevResource.AppHost.csproj
Dopo alcuni istanti il dashboard mostra che la risorsa maildev è in esecuzione e sarà disponibile un collegamento ipertestuale che passa all'app Web MailDev, che mostra il contenuto di ogni messaggio di posta elettronica inviato dall'app.
Il Aspire dashboard dovrebbe essere simile al seguente:
L'app Web MailDev dovrebbe essere simile alla seguente:
Aggiungere un .NET progetto di servizio ad AppHost per il test
Quando Aspire riesce a lanciare con successo l'integrazione MailDev, è il momento di utilizzare le informazioni di connessione per MailDev all'interno di un progetto di .NET. In Aspire è comune che ci sia un pacchetto di hosting e uno o più pacchetti di componenti. Si consideri ad esempio:
-
pacchetto di hosting: usato per rappresentare le risorse all'interno del modello di app.
Aspire.Hosting.Redis
-
Pacchetti di Componenti: usati per configurare e consumare librerie client.
Aspire.StackExchange.RedisAspire.StackExchange.Redis.DistributedCachingAspire.StackExchange.Redis.OutputCaching
Nel caso della risorsa MailDev, la piattaforma .NET dispone già di un semplice client SMTP (Mail Transfer Protocol) sotto forma di SmtpClient. In questo esempio si usa questa API esistente per semplicità, anche se altri tipi di risorse possono trarre vantaggio dalle librerie di integrazione personalizzate per aiutare gli sviluppatori.
Per testare lo scenario end-to-end, è necessario un progetto .NET in cui è possibile inserire le informazioni di connessione per la risorsa MailDev. Aggiungere un progetto API Web:
Creare un nuovo progetto .NET denominato MailDevResource.NewsletterService.
dotnet new webapi --use-minimal-apis -o MailDevResource.NewsletterServiceAggiungere un riferimento al progetto MailDev.Hosting.
dotnet add ./MailDevResource.NewsletterService/MailDevResource.NewsletterService.csproj reference ./MailDev.Hosting/MailDev.Hosting.csprojAggiungere un riferimento al progetto MailDevResource.AppHost.
dotnet add ./MailDevResource.AppHost/MailDevResource.AppHost.csproj reference ./MailDevResource.NewsletterService/MailDevResource.NewsletterService.csprojAggiungere il nuovo progetto al file della soluzione.
dotnet sln ./MailDevResource.sln add ./MailDevResource.NewsletterService/MailDevResource.NewsletterService.csproj
Dopo aver aggiunto il progetto e aver aggiornato i riferimenti, aprire il AppHost.cs del progetto MailDevResource.AppHost.csproj e aggiornare il file di origine in modo che sia simile al seguente:
var builder = DistributedApplication.CreateBuilder(args);
var maildev = builder.AddMailDev("maildev");
builder.AddProject<Projects.MailDevResource_NewsletterService>("newsletterservice")
.WithReference(maildev);
builder.Build().Run();
Dopo aver aggiornato il AppHost.cs file, avviare di nuovo AppHost. Verificare quindi che il servizio newsletter sia stato avviato e che la variabile di ambiente ConnectionStrings__maildev sia stata aggiunta al processo. Nella pagina Risorse, trova la riga newsletterservice e seleziona il collegamento Visualizza nella colonna Dettagli.
Lo screenshot precedente mostra le variabili di ambiente per il progetto newsletterservice. La variabile di ambiente ConnectionStrings__maildev è la stringa di connessione inserita nel progetto dalla risorsa maildev.
Usare la stringa di connessione per inviare messaggi
Per usare i dettagli di connessione SMTP inseriti nel progetto di servizio newsletter, si deve inserire un'istanza di SmtpClient nel contenitore di iniezione delle dipendenze come singleton. Aggiungere il codice seguente al file Program.cs nel progetto MailDevResource.NewsletterService per configurare il servizio singleton. Nella classe Program aggiungere il codice seguente subito dopo il commento // Add services to the container:
builder.Services.AddSingleton<SmtpClient>(sp =>
{
var smtpUri = new Uri(builder.Configuration.GetConnectionString("maildev")!);
var smtpClient = new SmtpClient(smtpUri.Host, smtpUri.Port);
return smtpClient;
});
Suggerimento
Questo frammento di codice si basa sul SmtpClientufficiale, tuttavia; questo tipo è obsoleto in alcune piattaforme e non consigliato in altri. Per un approccio più moderno con MailKit, vedere Creare integrazioni client personalizzateAspire.
Per testare il client, aggiungere due semplici metodi subscribe e unsubscribe POST al servizio newsletter. Aggiungere il codice seguente per sostituire la chiamata "weatherforecast" MapGet nel file Program.cs del progetto MailDevResource.NewsletterService per configurare le route ASP.NET Core.
app.MapPost("/subscribe", async (SmtpClient smtpClient, string email) =>
{
using var message = new MailMessage("newsletter@yourcompany.com", email)
{
Subject = "Welcome to our newsletter!",
Body = "Thank you for subscribing to our newsletter!"
};
await smtpClient.SendMailAsync(message);
});
app.MapPost("/unsubscribe", async (SmtpClient smtpClient, string email) =>
{
using var message = new MailMessage("newsletter@yourcompany.com", email)
{
Subject = "You are unsubscribed from our newsletter!",
Body = "Sorry to see you go. We hope you will come back soon!"
};
await smtpClient.SendMailAsync(message);
});
Suggerimento
Ricorda di fare riferimento ai namespace System.Net.Mail e Microsoft.AspNetCore.Mvc in Program.cs se l'editor di codice non li aggiunge automaticamente.
Dopo aver aggiornato il Program.cs file, avviare AppHost e usare il browser oppure curl per raggiungere gli URL seguenti (in alternativa, se si usa Visual Studio è possibile usare .http i file):
POST /subscribe?email=test@test.com HTTP/1.1
Host: localhost:7251
Content-Type: application/json
Per usare questa API, è possibile usare curl per inviare la richiesta. Il comando curl seguente invia una richiesta HTTP POST all'endpoint subscribe e si aspetta un valore della stringa di query email per iscriversi alla newsletter. L'intestazione Content-Type è impostata su application/json per indicare che il corpo della richiesta è in formato JSON:The Content-Type header is set to application/json to indicate that the request body is in JSON format.:
curl -H "Content-Type: application/json" --request POST https://localhost:7251/subscribe?email=test@test.com
L'API successiva è l'endpoint unsubscribe. Questo endpoint viene usato per annullare la sottoscrizione alla newsletter.
POST /unsubscribe?email=test@test.com HTTP/1.1
Host: localhost:7251
Content-Type: application/json
Per annullare la sottoscrizione alla newsletter, è possibile usare il comando curl seguente, passando un parametro email all'endpoint unsubscribe come stringa di query:
curl -H "Content-Type: application/json" --request POST https://localhost:7251/unsubscribe?email=test@test.com
Suggerimento
Assicurarsi di sostituire con https://localhost:7251 la porta corretta localhost (l'URL dell'AppHost in esecuzione).
Se tali chiamate API restituiscono una risposta corretta (HTTP 200, Ok), sarà possibile selezionare nella risorsa maildev il dashboard e il MailDev UI mostrerà i messaggi di posta elettronica inviati all'endpoint SMTP.
Dettagli tecnici
Nelle sezioni seguenti vengono illustrati vari dettagli tecnici che sono importanti per comprendere quando si sviluppano risorse personalizzate per Aspire.
Rete sicura
In questo esempio, la risorsa MailDev è una risorsa contenitore esposta al computer host tramite HTTP e SMTP. La risorsa MailDev è uno strumento di sviluppo e non è destinata all'uso in produzione. Per usare invece HTTPS, vedere MailDev: Configurare https.
Quando si sviluppano risorse personalizzate che espongono endpoint di rete, è importante considerare le implicazioni di sicurezza della risorsa. Ad esempio, se la risorsa è un database, è importante assicurarsi che il database sia sicuro e che la stringa di connessione non sia esposta alla rete Internet pubblica.
Il tipo ReferenceExpression e EndpointReference
Nel codice precedente il MailDevResource aveva due proprietà:
-
SmtpEndpoint: tipo EndpointReference. -
ConnectionStringExpression: tipo ReferenceExpression.
Questi tipi sono tra i diversi che vengono usati in Aspire per rappresentare i dati di configurazione, che non vengono finalizzati fino a quando il progetto di Aspire non viene eseguito o pubblicato nel cloud tramite uno strumento come Azure Developer CLI (azd).
Il problema fondamentale che questi tipi aiutano a risolvere è posticipare la risoluzione delle informazioni di configurazione concrete fino a quando tutte le informazioni sono disponibili.
Ad esempio, il MailDevResource espone una proprietà denominata ConnectionStringExpression come richiesto dall'interfaccia IResourceWithConnectionString. Il tipo della proprietà viene ReferenceExpression e viene creato passando una stringa interpolata al metodo Create.
public ReferenceExpression ConnectionStringExpression =>
ReferenceExpression.Create(
$"smtp://{SmtpEndpoint.Property(EndpointProperty.HostAndPort)}"
);
La firma per il metodo Create è la seguente:
public static ReferenceExpression Create(
in ExpressionInterpolatedStringHandler handler)
Non si tratta di un argomento String normale. Il metodo usa il modello di gestore di stringhe interpolato , per acquisire il modello di stringa interpolata e i valori a cui fa riferimento per consentire l'elaborazione personalizzata. Nel caso di Aspire, questi dettagli vengono acquisiti in un oggetto ReferenceExpression che può essere valutato come ogni valore a cui fa riferimento nella stringa interpolata diventa disponibile.
Ecco come funziona il flusso di esecuzione:
- Una risorsa che implementa IResourceWithConnectionString viene aggiunta al modello , ad esempio
AddMailDev(...). - Il
IResourceBuilder<MailDevResource>viene passato al WithReference che dispone di un sovraccarico speciale per la gestione delle implementazioni IResourceWithConnectionString. -
WithReferenceincapsula la risorsa in un'istanza ConnectionStringReference e l'oggetto viene acquisito in un EnvironmentCallbackAnnotation, che viene valutato dopo che il progetto Aspire è stato compilato e avviato. - Il processo che fa riferimento alla stringa di connessione inizia Aspire a valutare l'espressione. Prima ottiene il ConnectionStringReference e poi chiama IValueProvider.GetValueAsync.
- Il metodo
GetValueAsyncottiene il valore della proprietà ConnectionStringExpression per ottenere l'istanza di ReferenceExpression. - Il metodo IValueProvider.GetValueAsync chiama quindi GetValueAsync per elaborare la stringa interpolata acquisita in precedenza.
- Poiché la stringa interpolata contiene riferimenti ad altri tipi di riferimento, ad esempio EndpointReference vengono valutati e sostituiti con valori reali( che in questo momento sono ora disponibili).
Pubblicazione del manifesto
L'interfaccia IManifestExpressionProvider è progettata per risolvere il problema di condivisione delle informazioni di connessione tra le risorse in fase di distribuzione. La soluzione per questo particolare problema è descritta nella panoramica della Aspire rete del ciclo interno. Analogamente allo sviluppo locale, molti dei valori sono necessari per configurare l'app, ma non possono essere determinati fino a quando l'app non viene distribuita tramite uno strumento, ad esempio azd (Azure Developer CLI).
Per risolvere questo problema Aspire , produce un file manifesto interpretato azd da altri strumenti di distribuzione. Anziché specificare valori concreti per le informazioni di connessione tra le risorse viene usata una sintassi di espressione che gli strumenti di distribuzione valutano. In genere il file manifesto non è visibile agli sviluppatori, ma è possibile generarne uno per l'ispezione manuale. Il comando seguente può essere usato in AppHost per produrre un manifesto.
dotnet run --project MailDevResource.AppHost/MailDevResource.AppHost.csproj -- --publisher manifest --output-path aspire-manifest.json
Questo comando produce un file manifesto simile al seguente:
{
"resources": {
"maildev": {
"type": "container.v0",
"connectionString": "smtp://{maildev.bindings.smtp.host}:{maildev.bindings.smtp.port}",
"image": "docker.io/maildev/maildev:2.1.0",
"bindings": {
"http": {
"scheme": "http",
"protocol": "tcp",
"transport": "http",
"targetPort": 1080
},
"smtp": {
"scheme": "tcp",
"protocol": "tcp",
"transport": "tcp",
"targetPort": 1025
}
}
},
"newsletterservice": {
"type": "project.v0",
"path": "../MailDevResource.NewsletterService/MailDevResource.NewsletterService.csproj",
"env": {
"OTEL_DOTNET_EXPERIMENTAL_OTLP_EMIT_EXCEPTION_LOG_ATTRIBUTES": "true",
"OTEL_DOTNET_EXPERIMENTAL_OTLP_EMIT_EVENT_LOG_ATTRIBUTES": "true",
"OTEL_DOTNET_EXPERIMENTAL_OTLP_RETRY": "in_memory",
"ASPNETCORE_FORWARDEDHEADERS_ENABLED": "true",
"ConnectionStrings__maildev": "{maildev.connectionString}"
},
"bindings": {
"http": {
"scheme": "http",
"protocol": "tcp",
"transport": "http"
},
"https": {
"scheme": "https",
"protocol": "tcp",
"transport": "http"
}
}
}
}
}
Poiché MailDevResource implementa IResourceWithConnectionString, la logica di pubblicazione del manifesto in Aspire riconosce che, anche se MailDevResource è una risorsa contenitore, necessita comunque di un campo connectionString. Il campo connectionString fa riferimento ad altre parti della risorsa maildev nel manifesto per produrre la stringa finale:
{
// ... other content omitted.
"connectionString": "smtp://{maildev.bindings.smtp.host}:{maildev.bindings.smtp.port}"
}
Aspire sa come formare questa stringa perché esamina ConnectionStringExpression e compila la stringa finale tramite l'interfaccia IManifestExpressionProvider (nello stesso modo in cui viene usata l'interfaccia IValueProvider ).
Il MailDevResource viene incluso automaticamente nel manifesto perché è derivato da ContainerResource. Gli autori di risorse possono scegliere di sopprimere l'output del contenuto nel manifesto utilizzando il metodo di estensione ExcludeFromManifest sul generatore di risorse.
public static IResourceBuilder<MailDevResource> AddMailDev(
this IDistributedApplicationBuilder builder,
string name,
int? httpPort = null,
int? smtpPort = null)
{
var resource = new MailDevResource(name);
return builder.AddResource(resource)
.WithImage(MailDevContainerImageTags.Image)
.WithImageRegistry(MailDevContainerImageTags.Registry)
.WithImageTag(MailDevContainerImageTags.Tag)
.WithHttpEndpoint(
targetPort: 1080,
port: httpPort,
name: MailDevResource.HttpEndpointName)
.WithEndpoint(
targetPort: 1025,
port: smtpPort,
name: MailDevResource.SmtpEndpointName)
.ExcludeFromManifest(); // This line was added
}
È necessario considerare attentamente se la risorsa deve essere presente nel manifesto o se deve essere eliminata. Se la risorsa viene aggiunta al manifesto, deve essere configurata in modo che sia sicura e sicura da usare.
Sommario
Nell'esercitazione sulle risorse personalizzate si è appreso come creare una risorsa di Aspire personalizzata che usa un'applicazione in contenitori esistente (MailDev). È stato quindi usato per migliorare l'esperienza di sviluppo locale semplificando il test delle funzionalità di posta elettronica che potrebbero essere usate all'interno di un'app. Queste informazioni possono essere applicate per sviluppare altre risorse personalizzate da utilizzare nelle applicazioni basate su Aspire. Questo esempio specifico non includeva integrazioni personalizzate, ma è possibile creare integrazioni personalizzate per semplificare l'uso della risorsa da parte degli sviluppatori. In questo scenario è stato possibile basarsi sulla classe SmtpClient esistente nella piattaforma .NET per inviare messaggi di posta elettronica.