Erstellen Sie benutzerdefinierte .NET.NET Aspire Hosting-Integrationen
.NET .NET Aspire verbessert das Entwicklungserlebnis, indem wiederverwendbare Bausteine bereitgestellt werden, die verwendet werden können, um Anwendungsabhängigkeiten schnell anzuordnen und sie Ihrem eigenen Code zur Verfügung zu stellen. Einer der wichtigsten Bausteine einer Aspire-basierten Anwendung ist die Ressource. Berücksichtigen Sie den folgenden Code:
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);
Im vorherigen Code sind vier Ressourcen dargestellt:
-
cache
: Ein Redis-Container. -
pgserver
: Ein Postgres-Container. -
inventorydb
: Eine datenbank, die aufpgserver
gehostet wird. -
inventoryservice
: Eine ASP.NET Core Anwendung.
Die meiste .NET.NET Aspire-bezogene Code, den der durchschnittliche Entwickler schreibt, konzentriert sich darauf, Ressourcen zum App-Modell hinzuzufügen sowie Verweise zwischen ihnen zu erstellen.
Wichtige Elemente einer .NET.NET Aspire benutzerdefinierten Ressource
Das Erstellen einer benutzerdefinierten Ressource in .NET.NET Aspire erfordert Folgendes:
- Ein benutzerdefinierter Ressourcentyp, der IResource implementiert
- Eine Erweiterungsmethode für IDistributedApplicationBuilder namens
Add{CustomResource}
wobei{CustomResource}
der Name der benutzerdefinierten Ressource ist.
Wenn eine benutzerdefinierte Ressource eine optionale Konfiguration erfordert, möchten Entwickler möglicherweise With*
suffixierten Erweiterungsmethoden implementieren, um diese Konfigurationsoptionen mithilfe des Generatormustersauffindbar zu machen.
Ein praktisches Beispiel: MailDev
Um zu verstehen, wie benutzerdefinierte Ressourcen entwickelt werden, zeigt dieser Artikel ein Beispiel für das Erstellen einer benutzerdefinierten Ressource für MailDev. MailDev ist ein Open-Source-Tool, das ein lokales E-Mail-server bietet, mit dem Entwickler E-Mail-Sendeverhalten innerhalb ihrer App testen können. Weitere Informationen finden Sie unter MailDevGitHub Repository.
In diesem Beispiel erstellen Sie ein neues .NET Aspire Projekt als Testumgebung für die MailDev Ressource, die Sie erstellen. Sie können zwar benutzerdefinierte Ressourcen in vorhandenen .NET Aspire Projekten erstellen, es empfiehlt sich jedoch, zu überlegen, ob die benutzerdefinierte Ressource in mehreren .NET Aspire-basierten Lösungen verwendet werden kann und als wiederverwendbare Integration entwickelt werden sollte.
Einrichten des Startprojekts
Erstellen Sie ein neues .NET.NET Aspire Projekt, das dazu dient, die neue Ressource zu testen, die wir entwickeln.
dotnet new aspire -o MailDevResource
cd MailDevResource
dir
Nachdem das Projekt erstellt wurde, sollte eine Auflistung mit den folgenden Einträgen angezeigt werden:
-
MailDevResource.AppHost
: Der -App-Host hat verwendet, um die benutzerdefinierte Ressource auszuprobieren. -
MailDevResource.ServiceDefaults
: Der -Dienst wird standardmäßig als-Projekt für dienstbezogene Projekte verwendet. -
MailDevResource.sln
: Die Lösungsdatei, die beide Projekte referenziert.
Stellen Sie sicher, dass das Projekt erfolgreich erstellt und ausgeführt werden kann, indem Sie den folgenden Befehl ausführen:
dotnet run --project MailDevResource.AppHost/MailDevResource.AppHost.csproj
Die Konsolenausgabe sollte etwa wie folgt aussehen:
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.
Wählen Sie den Link -Dashboard im Browser aus, um das .NET-.NET Aspire-Dashboard anzuzeigen.
Drücken Sie STRG+C-, um die App zu beenden (Sie können die Browserregisterkarte schließen).
Erstellen einer Bibliothek für die Ressourcenerweiterung
.NET Aspire Ressourcen sind einfach Klassen und Methoden, die in einer Klassenbibliothek enthalten sind, die auf die .NET Aspire Hosting-Bibliothek (Aspire.Hosting
) verweist. Indem Sie die Ressource in einem separaten Projekt platzieren, können Sie sie einfacher zwischen .NET.NET Aspire-basierten Apps teilen und sie potenziell verpacken und auf NuGet freigeben.
Erstellen Sie das Klassenbibliotheksprojekt mit dem Namen MailDev. Hosten.
dotnet new classlib -o MailDev.Hosting
Fügen Sie
Aspire.Hosting
als Paketreferenz zur Klassenbibliothek hinzu.dotnet add ./MailDev.Hosting/MailDev.Hosting.csproj package Aspire.Hosting --version 9.0.0
Wichtig
Die hier angegebene Version sollte mit der Version der installierten .NET.NET Aspire Workload übereinstimmen.
Fügen Sie den Klassenbibliotheksverweis zum Projekt MailDevResource.AppHost hinzu.
dotnet add ./MailDevResource.AppHost/MailDevResource.AppHost.csproj reference ./MailDev.Hosting/MailDev.Hosting.csproj
Fügen Sie der Projektmappendatei das Klassenbibliotheksprojekt hinzu.
dotnet sln ./MailDevResource.sln add ./MailDev.Hosting/MailDev.Hosting.csproj
Nachdem die folgenden Schritte ausgeführt wurden, können Sie das Projekt starten:
dotnet run --project ./MailDevResource.AppHost/MailDevResource.AppHost.csproj
Dies führt zu einer Warnung, die in der Konsole angezeigt wird:
.\.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]
Dies liegt daran, dass .NET.NET Aspire Projektverweise im App-Host so behandelt, als wären sie Dienstprojekte. Um .NET.NET Aspire mitzuteilen, dass der Projektverweis als nicht serviceorientiertes Projekt behandelt werden soll, ändern Sie die Verweise der MailDevResource.AppHostMailDevResource.AppHost.csproj-Dateien auf das MailDev.Hosting
-Projekt in Folgendes ab:
<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>
Wenn Sie nun den App-Host starten, wird in der Konsole keine Warnung angezeigt.
Definieren der Ressourcentypen
Die MailDev Klassenbibliothek für Hosting enthält die Methoden zum Hinzufügen der Ressourcentypen und Erweiterungen zum App-Host. Denken Sie zuerst an die Erfahrung, die Sie Entwicklern bei der Verwendung Ihrer benutzerdefinierten Ressource geben möchten. Im Fall dieser benutzerdefinierten Ressource möchten Sie, dass Entwickler Code wie den folgenden schreiben können:
var builder = DistributedApplication.CreateBuilder(args);
var maildev = builder.AddMailDev("maildev");
builder.AddProject<Projects.NewsletterService>("newsletterservice")
.WithReference(maildev);
Um dies zu erreichen, benötigen Sie eine benutzerdefinierte Ressource namens MailDevResource
, die IResourceWithConnectionString implementiert, damit Nutzer sie mit der WithReference-Erweiterung verwenden können, um die Verbindungsdetails der MailDevserver als Verbindungszeichenfolge bereitzustellen.
MailDev ist als Containerressource verfügbar, daher sollten Sie auch von ContainerResource ableiten, damit wir verschiedene bereits vorhandene containerorientierte Erweiterungen in .NET.NET Aspirenutzen können.
Ersetzen Sie den Inhalt der Datei Class1.cs im Projekt MailDev.Hosting
und benennen Sie sie mithilfe des folgenden Codes in MailDevResource.cs um.
// 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)}"
);
}
In der vorherigen benutzerdefinierten Ressource sind die EndpointReference und ReferenceExpression Beispiele für mehrere Typen, die eine Sammlung von Schnittstellen implementieren, z. B. IManifestExpressionProvider, IValueProviderund IValueWithReferences. Weitere Informationen zu diesen Typen und deren Rolle in .NET.NET Aspirefinden Sie unter technische Details.
Definieren Sie die Ressourcenerweiterungen
Um Entwicklern die Verwendung der benutzerdefinierten Ressource zu erleichtern, muss eine Erweiterungsmethode namens AddMailDev
dem MailDev.Hosting Projekt hinzugefügt werden. Die AddMailDev
Erweiterungsmethode ist für die Konfiguration der Ressource verantwortlich, damit sie erfolgreich als Container gestartet werden kann.
Fügen Sie den folgenden Code zu einer neuen Datei namens MailDevResourceBuilderExtensions.cs im MailDev.Hosting-Projekt hinzu.
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";
}
Validieren der benutzerdefinierten Integration im Apphost
Nachdem die grundlegende Struktur für die benutzerdefinierte Ressource abgeschlossen ist, ist es an der Zeit, sie in einem echten AppHost-Projekt zu testen. Öffnen Sie die Program.cs Datei im MailDevResource.AppHost Projekt, und aktualisieren Sie sie mit dem folgenden Code:
var builder = DistributedApplication.CreateBuilder(args);
var maildev = builder.AddMailDev("maildev");
builder.Build().Run();
Starten Sie nach dem Aktualisieren der Program.cs-Datei das App-Hostprojekt, und öffnen Sie das Dashboard:
dotnet run --project ./MailDevResource.AppHost/MailDevResource.AppHost.csproj
Nach kurzer Zeit zeigt das Dashboard an, dass die maildev
Ressource ausgeführt wird und ein Link verfügbar ist, der zu der MailDev Web-App führt, die den Inhalt jeder E-Mail anzeigt, die Ihre App sendet.
Das .NET.NET Aspire-Dashboard sollte etwa wie folgt aussehen:
Die MailDev-Web-App sollte etwa wie folgt aussehen:
Hinzufügen eines .NET-Dienstprojekts zum App-Host für Testzwecke
Sobald .NET Aspire die MailDev-Integration erfolgreich starten kann, ist es an der Zeit, die Verbindungsinformationen für MailDev in einem .NET-Projekt zu nutzen. In .NET.NET Aspire ist es üblich, dass es ein Hostingpaket und ein oder mehrere Komponentpaketegibt. Betrachten Sie zum Beispiel:
-
Hostingpaket: Wird verwendet, um Ressourcen innerhalb des App-Modells darzustellen.
Aspire.Hosting.Redis
-
Komponentenpakete: Werden verwendet, um client Bibliotheken zu konfigurieren und zu nutzen.
Aspire.StackExchange.Redis
Aspire.StackExchange.Redis.DistributedCaching
Aspire.StackExchange.Redis.OutputCaching
Im Falle der MailDev-Ressource verfügt die .NET-Plattform bereits über ein SMTP-client (Simple Mail Transfer Protocol) in Form von SmtpClient. In diesem Beispiel verwenden Sie diese vorhandene API aus Gründen der Einfachheit, obwohl andere Ressourcentypen von benutzerdefinierten Integrationsbibliotheken profitieren können, um Entwickler zu unterstützen.
Um das End-to-End-Szenario zu testen, benötigen Sie ein .NET-Projekt, in welches wir die Verbindungsinformationen für die MailDev-Ressource einfügen können. Hinzufügen eines Web-API-Projekts:
Erstellen Sie ein neues .NET Projekt mit dem Namen MailDevResource.NewsletterService.
dotnet new webapi --use-minimal-apis -o MailDevResource.NewsletterService
Fügen Sie einen Verweis auf das MailDev.Hosting Projekt hinzu.
dotnet add ./MailDevResource.NewsletterService/MailDevResource.NewsletterService.csproj reference ./MailDev.Hosting/MailDev.Hosting.csproj
Fügen Sie einen Verweis auf das MailDevResource.AppHost Projekt hinzu.
dotnet add ./MailDevResource.AppHost/MailDevResource.AppHost.csproj reference ./MailDevResource.NewsletterService/MailDevResource.NewsletterService.csproj
Fügen Sie das neue Projekt der Projektmappendatei hinzu.
dotnet sln ./MailDevResource.sln add ./MailDevResource.NewsletterService/MailDevResource.NewsletterService.csproj
Nachdem das Projekt hinzugefügt und die Verweise aktualisiert wurden, öffnen Sie das Program.cs des Projekts MailDevResource.AppHost.csproj, und aktualisieren Sie die Quelldatei so, dass sie wie folgt aussieht:
var builder = DistributedApplication.CreateBuilder(args);
var maildev = builder.AddMailDev("maildev");
builder.AddProject<Projects.MailDevResource_NewsletterService>("newsletterservice")
.WithReference(maildev);
builder.Build().Run();
Starten Sie nach dem Aktualisieren der Program.cs-Datei den App-Host erneut. Überprüfen Sie dann, ob der Newsletterdienst gestartet wurde und dass die Umgebungsvariable ConnectionStrings__maildev
dem Prozess hinzugefügt wurde. Suchen Sie auf der Seite Ressourcen die Zeile newsletterservice
, und wählen Sie den Link Ansicht in der Spalte Details aus:
Der vorherige Screenshot zeigt die Umgebungsvariablen für das newsletterservice
Projekt. Die Umgebungsvariable ConnectionStrings__maildev
ist die Verbindungszeichenfolge, die durch die Ressource maildev
in das Projekt eingefügt wurde.
Verwenden Sie die Verbindungszeichenfolge, um Nachrichten zu senden
Um die SMTP-Verbindungsdetails zu verwenden, die in das Newsletterdienstprojekt eingefügt wurden, geben Sie eine Instanz von SmtpClient als Singleton in den Container zum Einfügen von Abhängigkeiten ein. Fügen Sie der datei Program.cs im MailDevResource.NewsletterService Projekt den folgenden Code hinzu, um den Singleton-Dienst einzurichten. Fügen Sie in der Program
Klasse unmittelbar nach dem // Add services to the container
Kommentar den folgenden Code hinzu:
builder.Services.AddSingleton<SmtpClient>(sp =>
{
var smtpUri = new Uri(builder.Configuration.GetConnectionString("maildev")!);
var smtpClient = new SmtpClient(smtpUri.Host, smtpUri.Port);
return smtpClient;
});
Tipp
Dieser Codeausschnitt basiert jedoch auf dem offiziellen SmtpClient
; Dieser Typ ist auf einigen Plattformen veraltet und wird für andere nicht empfohlen. Einen moderneren Ansatz mit MailKit-finden Sie unter Erstellen von benutzerdefinierten .NET Aspireclient Integrationen.
Um die clientzu testen, fügen Sie dem Newsletterdienst zwei einfache POST-Methoden, subscribe
und unsubscribe
, hinzu. Fügen Sie den folgenden Code hinzu, der den "weatherforecast" MapGet
Aufruf in der Datei Program.cs des MailDevResource.NewsletterService Projekts zum Einrichten der ASP.NET Core Routen ersetzt.
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);
});
Trinkgeld
Denken Sie daran, in Program.cs auf die System.Net.Mail
und Microsoft.AspNetCore.Mvc
Namespaces zu verweisen, wenn sie vom Code-Editor nicht automatisch hinzugefügt werden.
Sobald die Program.cs Datei aktualisiert wurde, starten Sie den App-Host, und verwenden Sie Ihren Browser, oder curl
, um die folgenden URLs aufzurufen (alternativ, wenn Sie Visual Studio verwenden, können Sie .http
Dateien verwenden):
POST /subscribe?email=test@test.com HTTP/1.1
Host: localhost:7251
Content-Type: application/json
Um diese API zu verwenden, können Sie curl
verwenden, um die Anforderung zu senden. Der folgende curl
-Befehl sendet eine HTTP-POST
-Anfrage an den subscribe
-Endpunkt und erwartet einen email
-Abfragezeichenfolgenwert, um den Newsletter zu abonnieren. Der Content-Type
-Header wird auf application/json
gesetzt, um anzugeben, dass der Anforderungstext im JSON-Format vorliegt.
curl -H "Content-Type: application/json" --request POST https://localhost:7251/subscribe?email=test@test.com
Der nächste API-Endpunkt ist unsubscribe
. Dieser Endpunkt wird verwendet, um das Abonnement des Newsletters abbestellen zu können.
POST /unsubscribe?email=test@test.com HTTP/1.1
Host: localhost:7251
Content-Type: application/json
Um den Newsletter abzubestellen, können Sie den folgenden curl
-Befehl verwenden und einen email
-Parameter als Abfragezeichenfolge an den unsubscribe
-Endpunkt übergeben.
curl -H "Content-Type: application/json" --request POST https://localhost:7251/unsubscribe?email=test@test.com
Tipp
Stellen Sie sicher, dass Sie die https://localhost:7251
durch den richtigen localhost Port (die URL des ausgeführten App-Hosts) ersetzen.
Wenn diese API-Aufrufe eine erfolgreiche Antwort (HTTP 200, OK) zurückgeben, sollten Sie auf der maildev
Ressource das Dashboard auswählen können, und die MailDev UI zeigt die E-Mails an, die an den SMTP-Endpunkt gesendet wurden.
Technische Details
In den folgenden Abschnitten werden verschiedene technische Details erläutert, die bei der Entwicklung von benutzerdefinierten Ressourcen für .NET.NET Aspirewichtig sind.
Sicheres Netzwerk
In diesem Beispiel ist die MailDev Ressource eine Containerressource, die für den Hostcomputer über HTTP und SMTP verfügbar gemacht wird. Die MailDev Ressource ist ein Entwicklungstool und ist nicht für die Produktionsverwendung vorgesehen. Um stattdessen HTTPS zu verwenden, siehe MailDev: Konfigurieren von HTTPS.
Bei der Entwicklung benutzerdefinierter Ressourcen, die Netzwerkendpunkte verfügbar machen, ist es wichtig, die Sicherheitsauswirkungen der Ressource zu berücksichtigen. Wenn es sich bei der Ressource beispielsweise um eine Datenbank handelt, ist es wichtig, sicherzustellen, dass die Datenbank sicher ist und dass die Verbindungszeichenfolge nicht für das öffentliche Internet verfügbar gemacht wird.
Der typ ReferenceExpression
und EndpointReference
Im vorherigen Code verfügte die MailDevResource
über zwei Eigenschaften:
-
SmtpEndpoint
: EndpointReference Typ. -
ConnectionStringExpression
: ReferenceExpression Typ.
Diese Typen gehören zu den verschiedenen Typen, die innerhalb von .NET Aspire verwendet werden, um Konfigurationsdaten darzustellen, die erst abgeschlossen sind, wenn das .NET Aspire-Projekt entweder ausgeführt oder über ein Tool wie Azure Developer CLI (azd
)in der Cloud veröffentlicht wird.
Das grundlegende Problem, das diese Typen zu lösen helfen, besteht darin, die Lösung konkreter Konfigurationsinformationen zu verzögern, bis alle die Informationen verfügbar sind.
Beispielsweise stellt MailDevResource
eine Eigenschaft namens ConnectionStringExpression
bereit, wie sie von der Schnittstelle IResourceWithConnectionString benötigt wird. Der Typ der Eigenschaft ist ReferenceExpression und wird erstellt, indem eine interpolierte Zeichenfolge an die Create-Methode übergeben wird.
public ReferenceExpression ConnectionStringExpression =>
ReferenceExpression.Create(
$"smtp://{SmtpEndpoint.Property(EndpointProperty.Host)}:{SmtpEndpoint.Property(EndpointProperty.Port)}"
);
Die Signatur für die Create-Methode lautet wie folgt:
public static ReferenceExpression Create(
in ExpressionInterpolatedStringHandler handler)
Dies ist kein reguläres String Argument. Die Methode verwendet den interpolierten Handlermuster , um die interpolierte Zeichenfolgenvorlage und die darin referenzierten Werte zu erfassen und so eine benutzerdefinierte Verarbeitung zu ermöglichen. Im Falle von .NET.NET Aspirewerden diese Details in einer ReferenceExpression erfasst, die ausgewertet werden kann, sobald jeder in der interpolierten Zeichenfolge referenzierte Wert verfügbar ist.
So funktioniert der Ausführungsfluss:
- Dem Modell wird eine Ressource hinzugefügt, die IResourceWithConnectionString implementiert (z. B.
AddMailDev(...)
). - Die
IResourceBuilder<MailDevResource>
wird an die WithReference übergeben, die über eine spezielle Überladung für die Verarbeitung der IResourceWithConnectionString Implementierer verfügt. - Die
WithReference
umschließt die Ressource in einer ConnectionStringReference Instanz und das Objekt wird in einer EnvironmentCallbackAnnotation erfasst, die nach dem Erstellen des .NET.NET Aspire Projekts ausgewertet wird und mit der Ausführung beginnt. - Wenn der Prozess, der auf die Verbindungszeichenfolge verweist, beginnt, beginnt .NET.NET Aspire mit der Auswertung des Ausdrucks. Zuerst erhält sie die ConnectionStringReference und ruft IValueProvider.GetValueAsyncauf.
- Die
GetValueAsync
-Methode ruft den Wert der ConnectionStringExpression-Eigenschaft ab, um auf die ReferenceExpression-Instanz zuzugreifen. - Die IValueProvider.GetValueAsync-Methode ruft dann GetValueAsync auf, um die zuvor erfasste interpolierte Zeichenfolge zu verarbeiten.
- Da die interpolierte Zeichenfolge Verweise auf andere Bezugstypen enthält, z. B. EndpointReference, werden diese ebenfalls ausgewertet und durch den derzeit verfügbaren realen Wert ersetzt.
Manifestveröffentlichung
Die IManifestExpressionProvider-Schnittstelle wurde entwickelt, um das Problem der Weitergabe von Verbindungsinformationen zwischen Ressourcen bei deren Bereitstellung zu lösen. Die Lösung für dieses spezielle Problem wird in der .NET.NET Aspire Übersicht des Inner-Loop-Netzwerksbeschrieben. Ähnlich wie bei der lokalen Entwicklung sind viele Werte erforderlich, um die App zu konfigurieren. Allerdings können diese erst bestimmt werden, wenn die App mit einem Tool wie azd
(Azure Developer CLI) bereitgestellt wird.
Um dieses Problem zu lösen, erzeugt .NET.NET Aspire eine Manifestdatei, die azd
und andere Bereitstellungstools interpretieren. Anstatt konkrete Werte für Verbindungsinformationen zwischen Ressourcen anzugeben, wird eine Ausdruckssyntax verwendet, die von Bereitstellungstools ausgewertet wird. Im Allgemeinen ist die Manifestdatei für Entwickler nicht sichtbar, aber es ist möglich, eine für die manuelle Überprüfung zu generieren. Der folgende Befehl kann auf dem App-Host verwendet werden, um ein Manifest zu erstellen.
dotnet run --project MailDevResource.AppHost/MailDevResource.AppHost.csproj -- --publisher manifest --output-path aspire-manifest.json
Dieser Befehl erzeugt eine Manifestdatei wie die folgende:
{
"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"
}
}
}
}
}
Da die MailDevResource
IResourceWithConnectionString die Manifestveröffentlichungslogik in .NET.NET Aspire implementiert, weiß, dass MailDevResource
eine Containerressource ist, benötigt sie auch ein connectionString
Feld. Das connectionString
-Feld verweist auf andere Teile der maildev
-Ressource im Manifest, um den endgültigen String zu generieren.
{
// ... other content omitted.
"connectionString": "smtp://{maildev.bindings.smtp.host}:{maildev.bindings.smtp.port}"
}
.NET .NET Aspire weiß, wie diese Zeichenfolge erstellt wird, da sie sich ConnectionStringExpression ansieht und die endgültige Zeichenfolge über die IManifestExpressionProvider-Schnittstelle aufbaut (ähnlich wie die IValueProvider-Schnittstelle).
Die MailDevResource
wird automatisch im Manifest enthalten, da sie von ContainerResourceabgeleitet wird. Ressourcenautoren können die Ausgabe von Inhalten im Manifest mithilfe der ExcludeFromManifest Erweiterungsmethode im Ressourcen-Generator unterdrücken.
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
}
Es sollte sorgfältig geprüft werden, ob die Ressource im Manifest vorhanden sein soll oder ob sie unterdrückt werden soll. Wenn die Ressource dem Manifest hinzugefügt wird, sollte sie so konfiguriert werden, dass sie sicher und sicher zu verwenden ist.
Zusammenfassung
Im Lernprogramm für benutzerdefinierte Ressourcen haben Sie erfahren, wie Sie eine benutzerdefinierte .NET Aspire Ressource erstellen, die eine vorhandene containerisierte Anwendung (MailDev) verwendet. Anschließend haben Sie dies verwendet, um die lokale Entwicklungsumgebung zu verbessern, indem Sie E-Mail-Funktionen, die in einer App verwendet werden können, einfach testen können. Diese Erkenntnisse können auf die Erstellung anderer benutzerdefinierter Ressourcen angewendet werden, die in .NET.NET Aspire-basierten Anwendungen verwendet werden können. Dieses spezifische Beispiel enthielt keine benutzerdefinierten Integrationen, aber es ist möglich, benutzerdefinierte Integrationen zu erstellen, um Entwicklern die Verwendung der Ressource zu erleichtern. In diesem Szenario konnten Sie sich auf die vorhandene SmtpClient
Klasse in der .NET-Plattform verlassen, um E-Mails zu senden.