Creare integrazioni di hosting di .NET.NET Aspire personalizzate
.NET .NET 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
: contenitore Postgres. -
inventorydb
: Un database ospitato supgserver
. -
inventoryservice
: un'applicazione ASP.NET Core.
La maggior parte del codice correlato .NET.NET Aspireche lo sviluppatore medio scrive, si concentra sull'aggiunta di risorse al modello di app e la creazione di riferimenti tra di essi.
Elementi chiave di una risorsa personalizzata .NET.NET Aspire
La creazione di una risorsa personalizzata in .NET.NET 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 elettronica locale progettato per consentire agli sviluppatori di testare i comportamenti di invio di posta elettronica all'interno dell'app. Per altre informazioni, vedere repository MailDevGitHub.
In questo esempio viene creato un nuovo progetto di .NET Aspire come ambiente di test per la risorsa MailDev creata. Anche se è possibile creare risorse personalizzate nei progetti di .NET Aspire esistenti, è consigliabile valutare se la risorsa personalizzata può essere usata in più soluzioni basate su .NET Aspiree deve essere sviluppata come integrazione riutilizzabile.
Configurare il progetto iniziale
Crea un nuovo progetto .NET.NET Aspire utilizzato per testare la nuova risorsa che stiamo sviluppando.
dotnet new aspire -o MailDevResource
cd MailDevResource
dir
Dopo aver creato il progetto, verrà visualizzato un elenco contenente quanto segue:
-
MailDevResource.AppHost
: l'host dell'applicazione utilizzato 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 dashboard .NET.NET Aspire:
Premere CTRL+C per arrestare l'app (è possibile chiudere la scheda del browser).
Creare una libreria per l'estensione della risorsa
.NET Aspire risorse sono solo classi e metodi contenuti all'interno di una libreria di classi che fa riferimento alla libreria di hosting .NET Aspire (Aspire.Hosting
). Inserendo la risorsa in un progetto separato, è possibile condividerla più facilmente tra le app basate su .NET.NET Aspiree potenzialmente creare un pacchetto e condividerla in NuGet.
Creare il progetto di libreria di classi denominato MailDev. Hosting.
dotnet new classlib -o MailDev.Hosting
Aggiungere
Aspire.Hosting
alla libreria delle classi come riferimento del pacchetto.dotnet add ./MailDev.Hosting/MailDev.Hosting.csproj package Aspire.Hosting --version 9.0.0
Importante
La versione specificata qui deve corrispondere alla versione del carico di lavoro .NET.NET Aspire installato.
Aggiungi il riferimento alla libreria di classi al progetto MailDevResource.AppHost.
dotnet add ./MailDevResource.AppHost/MailDevResource.AppHost.csproj reference ./MailDev.Hosting/MailDev.Hosting.csproj
Aggiungere 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]
Ciò è dovuto al fatto che .NET.NET Aspire considera i riferimenti al progetto nell'host dell'app come se fossero progetti di servizio. Per indicare a .NET.NET Aspire che il riferimento al progetto deve essere trattato come un progetto non di servizio, modificare il riferimento ai file di MailDevResource.AppHostMailDevResource.AppHost.csproj per il progetto MailDev.Hosting
nel modo seguente:
<ItemGroup>
<!-- The IsAspireProjectResource attribute tells .NET 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 l'host dell'app, non viene visualizzato alcun avviso nella console.
Definire i tipi di risorse
Oggetto MailDev. L'hosting libreria di classi contiene il tipo di risorsa e i metodi di estensione per l'aggiunta della risorsa all'host dell'app. È 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 MailDevserver come stringa di connessione.
MailDev è disponibile come risorsa contenitore, quindi vorrai anche derivare da ContainerResource per poter utilizzare varie estensioni preesistenti incentrate sui contenitori in .NET.NET 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 .NET 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.Host)}:{SmtpEndpoint.Property(EndpointProperty.Port)}"
);
}
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 ulteriori informazioni su questi tipi e sul loro ruolo in .NET.NET Aspire, consultare i dettagli tecnici .
Definire le estensioni delle risorse
Per semplificare l'uso della risorsa personalizzata da parte degli sviluppatori, è necessario aggiungere al progetto MailDev.Hosting un metodo di estensione denominato AddMailDev
. 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 .NET 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 .NET 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 dell'host dell'app
Ora che la struttura di base per la risorsa personalizzata è stata completata, è possibile testarla in un progetto AppHost reale. Aprire il file Program.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 file Program.cs, avviare il progetto host dell'app 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 dashboard .NET.NET Aspire dovrebbe essere simile al seguente:
L'app Web MailDev dovrebbe essere simile alla seguente:
Aggiungere un progetto di servizio .NET all'host dell'app per il test
Quando .NET 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 .NET.NET Aspire è comune che esista 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 utilizzare le librerie di client.
Aspire.StackExchange.Redis
Aspire.StackExchange.Redis.DistributedCaching
Aspire.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.NewsletterService
Aggiungere un riferimento al progetto MailDev.Hosting.
dotnet add ./MailDevResource.NewsletterService/MailDevResource.NewsletterService.csproj reference ./MailDev.Hosting/MailDev.Hosting.csproj
Aggiungere un riferimento al progetto MailDevResource.AppHost.
dotnet add ./MailDevResource.AppHost/MailDevResource.AppHost.csproj reference ./MailDevResource.NewsletterService/MailDevResource.NewsletterService.csproj
Aggiungere 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 Program.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 file Program.cs, avviare di nuovo l'host dell'app. 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 SmtpClient
ufficiale, tuttavia; questo tipo è obsoleto in alcune piattaforme e non consigliato in altri. Per un approccio più moderno usando MailKit, vedere Creare integrazioni di .NET Aspireclient personalizzate.
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);
});
Consiglio
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 file Program.cs, avviare l'host dell'app e usare il browser oppure curl
per raggiungere gli URL seguenti (in alternativa, se si usa Visual Studio è possibile usare .http
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
Consiglio / Suggerimento / Mancia (select based on context)
Assicurati di sostituire il https://localhost:7251
con la porta corretta localhost (l'URL dell'host dell'app che stai eseguendo).
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 .NET.NET 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 di ReferenceExpression.
Questi tipi sono tra i diversi che vengono usati in .NET Aspire per rappresentare i dati di configurazione, che non vengono finalizzati fino a quando il progetto di .NET 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, sta rinviando la risoluzione delle informazioni di configurazione concrete fino a tutte le 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.Host)}:{SmtpEndpoint.Property(EndpointProperty.Port)}"
);
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 .NET.NET Aspire, questi dettagli vengono acquisiti in un ReferenceExpression che può essere valutato quando ogni valore menzionato 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. - Il
WithReference
avvolge la risorsa in un'istanza di ConnectionStringReference e l'oggetto viene catturato in un EnvironmentCallbackAnnotation che viene valutato dopo che il progetto .NET.NET Aspire è stato compilato e avviato. - Quando il processo che fa riferimento alla stringa di connessione inizia .NET.NET Aspire inizia a valutare l'espressione. Prima ottiene il ConnectionStringReference e poi chiama IValueProvider.GetValueAsync.
- Il metodo
GetValueAsync
ottiene 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 rete di ciclo interno .NET.NET Aspire. 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 .NET.NET Aspire produce un file manifesto che azd
e altri strumenti di distribuzione interpretano. 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 sull'host dell'applicazione per produrre un manifest.
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é il MailDevResource
implementa la IResourceWithConnectionString logica di pubblicazione del manifesto, .NET.NET Aspire sa che anche se MailDevResource
è una risorsa contenitore, necessita anche 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}"
}
.NET .NET Aspire è in grado di formare questa stringa perché esamina ConnectionStringExpression e compila la stringa finale tramite l'interfaccia IManifestExpressionProvider (in modo analogo all'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 .NET 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 alla compilazione di altre risorse personalizzate che possono essere usate nelle applicazioni basate su .NET.NET 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.