Tworzenie integracji niestandardowego hostingu .NET.NET Aspire
.NET .NET Aspire usprawnia środowisko programistyczne, udostępniając bloki konstrukcyjne wielokrotnego użytku, które mogą służyć do szybkiego rozmieszczania zależności aplikacji i uwidaczniania ich we własnym kodzie. Jednym z kluczowych bloków konstrukcyjnych aplikacji opartej na Aspirejest zasób . Rozważ poniższy kod:
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);
W poprzednim kodzie są reprezentowane cztery zasoby:
-
cache
: kontener Redis. -
pgserver
: kontener Postgres. -
inventorydb
: baza danych hostowana wpgserver
. -
inventoryservice
: aplikacja typu ASP.NET Core.
Większość kodu związanego z .NET.NET Aspire, który pisze przeciętny deweloper, koncentruje się na dodawaniu zasobów do modelu aplikacji i tworzeniu odwołań między nimi.
Kluczowe elementy zasobu niestandardowego .NET.NET Aspire
Utworzenie zasobu niestandardowego w .NET.NET Aspire wymaga następujących czynności:
- Niestandardowy typ zasobu implementujący IResource
- Metoda rozszerzenia dla IDistributedApplicationBuilder o nazwie
Add{CustomResource}
, gdzie{CustomResource}
jest nazwą zasobu niestandardowego.
Jeśli zasób niestandardowy wymaga opcjonalnej konfiguracji, deweloperzy mogą chcieć zaimplementować metody rozszerzenia z sufiksami With*
, aby umożliwić wykrywanie tych opcji konfiguracji przy użyciu wzorca budowniczego .
Praktyczny przykład: MailDev
Aby dowiedzieć się, jak opracowywać zasoby niestandardowe, w tym artykule przedstawiono przykład tworzenia zasobu niestandardowego dla MailDev. MailDev to narzędzie typu open source, które udostępnia lokalny serwer poczty, który umożliwia deweloperom testowanie zachowań wysyłania wiadomości e-mail w aplikacji. Aby uzyskać więcej informacji, zobacz MailDevGitHub repozytorium.
W tym przykładzie utworzysz nowy projekt .NET Aspire jako środowisko testowe dla tworzonego zasobu MailDev. Chociaż można tworzyć zasoby niestandardowe w istniejących projektach .NET Aspire, warto rozważyć, czy zasób niestandardowy może być używany w wielu rozwiązaniach opartych na .NET Aspirei powinien zostać opracowany jako integracja wielokrotnego użytku.
Konfigurowanie projektu startowego
Utwórz nowy projekt .NET.NET Aspire używany do testowania nowego zasobu, który opracowujemy.
dotnet new aspire -o MailDevResource
cd MailDevResource
dir
Po utworzeniu projektu powinna zostać wyświetlona lista zawierająca następujące elementy:
-
MailDevResource.AppHost
: host aplikacji używany do testowania zasobu niestandardowego. -
MailDevResource.ServiceDefaults
: Usługa domyślna dla projektu do użycia w projektach związanych z usługą. -
MailDevResource.sln
: plik rozwiązania odwołujące się do obu projektów.
Sprawdź, czy projekt może pomyślnie skompilować i uruchomić, wykonując następujące polecenie:
dotnet run --project MailDevResource.AppHost/MailDevResource.AppHost.csproj
Dane wyjściowe konsoli powinny wyglądać podobnie do następujących:
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.
Wybierz link pulpitu nawigacyjnego w przeglądarce, aby wyświetlić pulpit nawigacyjny .NET.NET Aspire:
Naciśnij naciśnij Ctrl+C, aby zamknąć aplikację (możesz zamknąć kartę przeglądarki).
Tworzenie biblioteki dla rozszerzenia zasobu
.NET Aspire zasoby to nic innego jak klasy i metody zawarte w bibliotece klas odwołującej się do biblioteki hostowania .NET Aspire (Aspire.Hosting
). Umieszczając zasób w osobnym projekcie, można łatwiej udostępnić go między aplikacjami bazującymi na .NET.NET Aspireoraz potencjalnie spakować i opublikować na NuGet.
Utwórz projekt biblioteki klas o nazwie MailDev. Hosting.
dotnet new classlib -o MailDev.Hosting
Dodaj
Aspire.Hosting
do biblioteki klas jako odwołanie do pakietu.dotnet add ./MailDev.Hosting/MailDev.Hosting.csproj package Aspire.Hosting --version 9.0.0
Ważny
Określona w tym miejscu wersja powinna być zgodna z wersją zainstalowanego obciążenia .NET.NET Aspire.
Dodaj odwołanie do biblioteki klas do projektu MailDevResource.AppHost.
dotnet add ./MailDevResource.AppHost/MailDevResource.AppHost.csproj reference ./MailDev.Hosting/MailDev.Hosting.csproj
Dodaj projekt biblioteki klas do pliku rozwiązania.
dotnet sln ./MailDevResource.sln add ./MailDev.Hosting/MailDev.Hosting.csproj
Po wykonaniu następujących kroków możesz uruchomić projekt:
dotnet run --project ./MailDevResource.AppHost/MailDevResource.AppHost.csproj
Spowoduje to wyświetlenie ostrzeżenia w konsoli:
.\.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]
Dzieje się tak, ponieważ .NET.NET Aspire traktuje odwołania do projektu na hoście aplikacji tak, jakby były projektami usług. Aby poinformować .NET.NET Aspire, że odwołanie do projektu powinno być traktowane jako projekt nieusługowy, zmodyfikuj pliki MailDevResource.AppHostMailDevResource.AppHost.csproj odwołania do projektu MailDev.Hosting
w następujący sposób:
<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>
Teraz po uruchomieniu hosta aplikacji nie ma ostrzeżenia wyświetlanego w konsoli.
Definiowanie typów zasobów
MailDev. Biblioteka klas .Hosting zawiera typ zasobów i metody rozszerzeń służące do dodawania zasobu do hosta aplikacji. Najpierw należy zastanowić się nad doświadczeniem, które chcesz zapewnić deweloperom podczas korzystania z zasobu niestandardowego. W przypadku tego zasobu niestandardowego chcesz, aby deweloperzy mogli pisać kod podobny do następującego:
var builder = DistributedApplication.CreateBuilder(args);
var maildev = builder.AddMailDev("maildev");
builder.AddProject<Projects.NewsletterService>("newsletterservice")
.WithReference(maildev);
Aby to osiągnąć, potrzebny jest zasób niestandardowy o nazwie MailDevResource
, który implementuje IResourceWithConnectionString, dzięki czemu użytkownicy mogą go używać z rozszerzeniem WithReference w celu wstrzyknięcia szczegółów połączenia dla serwera MailDev jako łańcuch połączeniowy.
MailDev jest dostępny jako zasób kontenera, więc warto wywodzić się z ContainerResource, aby móc korzystać z różnych istniejących rozszerzeń skoncentrowanych na kontenerach w .NET.NET Aspire.
Zastąp zawartość pliku Class1.cs w projekcie MailDev.Hosting
i zmień nazwę pliku na MailDevResource.cs następującym kodem:
// 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)}"
);
}
W poprzednim zasobie niestandardowym EndpointReference i ReferenceExpression są przykładami kilku typów, które implementują kolekcję interfejsów, takich jak IManifestExpressionProvider, IValueProvideri IValueWithReferences. Aby uzyskać więcej informacji na temat tych typów i ich roli w .NET.NET Aspire, zobacz szczegóły techniczne .
Definiowanie rozszerzeń zasobów
Aby ułatwić deweloperom korzystanie z zasobu niestandardowego, należy dodać metodę rozszerzenia o nazwie AddMailDev
do projektu MailDev.Hosting. Metoda rozszerzenia AddMailDev
jest odpowiedzialna za skonfigurowanie zasobu, aby umożliwić pomyślne uruchomienie go jako kontenera.
Dodaj następujący kod do nowego pliku o nazwie MailDevResourceBuilderExtensions.cs w projekcie 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";
}
Zatwierdź integrację niestandardową wewnątrz hosta aplikacji
Teraz, gdy podstawowa struktura zasobu niestandardowego została ukończona, nadszedł moment, aby przetestować ją w projekcie AppHost. Otwórz plik Program.cs w projekcie MailDevResource.AppHost i zaktualizuj go przy użyciu następującego kodu:
var builder = DistributedApplication.CreateBuilder(args);
var maildev = builder.AddMailDev("maildev");
builder.Build().Run();
Po zaktualizowaniu pliku Program.cs uruchom projekt hosta aplikacji i otwórz pulpit nawigacyjny:
dotnet run --project ./MailDevResource.AppHost/MailDevResource.AppHost.csproj
Po kilku chwilach pulpit nawigacyjny pokazuje, że zasób maildev
jest uruchomiony, a hiperlink będzie dostępny, który przechodzi do MailDev aplikacji internetowej, która pokazuje zawartość każdej wiadomości e-mail wysyłanej przez aplikację.
Pulpit nawigacyjny .NET.NET Aspire powinien wyglądać podobnie do następującego:
Aplikacja internetowa MailDev powinna wyglądać podobnie do następującej:
Dodawanie projektu usługi .NET do hosta aplikacji na potrzeby testowania
Po tym, jak .NET Aspire pomyślnie uruchomi integrację MailDev, należy wykorzystać informacje o połączeniu dla MailDev w projekcie .NET. W .NET.NET Aspire często występuje hosting pakietu i co najmniej jeden pakiet składników . Rozważmy na przykład:
-
pakiet hostingowy: służy do reprezentowania zasobów w modelu aplikacji.
Aspire.Hosting.Redis
-
Pakiety składników: służy do konfigurowania i korzystania z bibliotek klienckich.
Aspire.StackExchange.Redis
Aspire.StackExchange.Redis.DistributedCaching
Aspire.StackExchange.Redis.OutputCaching
W przypadku zasobu MailDev platforma .NET ma już prostego klienta protokołu transferu poczty (SMTP) w postaci SmtpClient. W tym przykładzie używasz tego istniejącego interfejsu API dla uproszczenia, chociaż inne typy zasobów mogą korzystać z niestandardowych bibliotek integracji, aby pomóc deweloperom.
Do przetestowania kompleksowego scenariusza potrzebny jest projekt .NET, do którego można wstrzyknąć informacje o połączeniu dla zasobu MailDev. Dodaj projekt internetowego interfejsu API:
Utwórz nowy projekt .NET o nazwie MailDevResource.NewsletterService.
dotnet new webapi --use-minimal-apis -o MailDevResource.NewsletterService
Dodaj odwołanie do projektu MailDev.Hosting.
dotnet add ./MailDevResource.NewsletterService/MailDevResource.NewsletterService.csproj reference ./MailDev.Hosting/MailDev.Hosting.csproj
Dodaj odwołanie do projektu MailDevResource.AppHost.
dotnet add ./MailDevResource.AppHost/MailDevResource.AppHost.csproj reference ./MailDevResource.NewsletterService/MailDevResource.NewsletterService.csproj
Dodaj nowy projekt do pliku rozwiązania.
dotnet sln ./MailDevResource.sln add ./MailDevResource.NewsletterService/MailDevResource.NewsletterService.csproj
Po dodaniu projektu i zaktualizowaniu odwołań, otwórz Program.cs z projektu MailDevResource.AppHost.csproj i zaktualizuj plik źródłowy, aby wyglądał następująco:
var builder = DistributedApplication.CreateBuilder(args);
var maildev = builder.AddMailDev("maildev");
builder.AddProject<Projects.MailDevResource_NewsletterService>("newsletterservice")
.WithReference(maildev);
builder.Build().Run();
Po zaktualizowaniu pliku Program.cs ponownie uruchom hosta aplikacji. Następnie sprawdź, czy usługa biuletynu została uruchomiona i czy do procesu została dodana zmienna środowiskowa ConnectionStrings__maildev
. Na stronie Zasoby znajdź wiersz newsletterservice
i wybierz link View w kolumnie Szczegóły.
Powyższy zrzut ekranu przedstawia zmienne środowiskowe dla projektu newsletterservice
. Zmienna środowiskowa ConnectionStrings__maildev
to parametry połączenia, które zostały wprowadzone do projektu przez zasób maildev
.
Wysyłanie komunikatów przy użyciu parametrów połączenia
Aby użyć szczegółów połączenia SMTP wprowadzonych do projektu usługi biuletynu, należy wstrzyknąć instancję SmtpClient do kontenera wstrzykiwania zależności jako singleton. Dodaj następujący kod do pliku Program.cs w projekcie MailDevResource.NewsletterService, aby skonfigurować usługę singleton. W klasie Program
natychmiast po komentarzu // Add services to the container
dodaj następujący kod:
builder.Services.AddSingleton<SmtpClient>(sp =>
{
var smtpUri = new Uri(builder.Configuration.GetConnectionString("maildev")!);
var smtpClient = new SmtpClient(smtpUri.Host, smtpUri.Port);
return smtpClient;
});
Napiwek
Ten fragment kodu opiera się na oficjalnym SmtpClient
, jednak ten typ jest przestarzały na niektórych platformach i nie jest zalecany na innych. Aby uzyskać bardziej nowoczesne podejście korzystające z zestawu MailKit, zobacz Utwórz niestandardowe integracje klientów .NET.NET Aspire.
Aby przetestować klienta, dodaj dwie proste metody subscribe
i unsubscribe
POST do usługi biuletynu. Dodaj następujący kod, zastępując wywołanie "weatherforecast" MapGet
w pliku Program.cs projektu MailDevResource.NewsletterService, aby skonfigurować trasy 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);
});
Napiwek
Pamiętaj, aby odwołać się do System.Net.Mail
i Microsoft.AspNetCore.Mvc
przestrzeni nazw w Program.cs, jeśli edytor kodu nie doda ich automatycznie.
Po zaktualizowaniu pliku Program.cs uruchom hosta aplikacji i użyj przeglądarki lub curl
, aby uzyskać następujące adresy URL (alternatywnie, jeśli używasz Visual Studio możesz użyć .http
plików):
POST /subscribe?email=test@test.com HTTP/1.1
Host: localhost:7251
Content-Type: application/json
Aby użyć tego interfejsu API, możesz wysłać żądanie przy użyciu curl
. Następujące polecenie curl
wysyła żądanie HTTP POST
do punktu końcowego subscribe
i oczekuje wartości ciągu zapytania email
, aby zapisać się na biuletyn. Nagłówek Content-Type
jest ustawiony na application/json
, aby wskazać, że treść żądania jest w formacie JSON.:
curl -H "Content-Type: application/json" --request POST https://localhost:7251/subscribe?email=test@test.com
Następnym interfejsem API jest punkt końcowy unsubscribe
. Ten punkt końcowy służy do anulowania subskrypcji biuletynu.
POST /unsubscribe?email=test@test.com HTTP/1.1
Host: localhost:7251
Content-Type: application/json
Aby anulować subskrypcję biuletynu, możesz użyć następującego polecenia curl
, przekazując parametr email
do punktu końcowego unsubscribe
jako ciąg zapytania:
curl -H "Content-Type: application/json" --request POST https://localhost:7251/unsubscribe?email=test@test.com
Napiwek
Upewnij się, że zastąpisz https://localhost:7251
poprawnym portem localhost (adresem URL uruchomionego hosta aplikacji).
Jeśli wywołania interfejsu API zwracają pomyślną odpowiedź (HTTP 200, OK), wówczas powinno być możliwe wybranie zasobu maildev
pulpitu nawigacyjnego, a MailDev UI będzie wyświetlać wiadomości e-mail wysłane do punktu końcowego SMTP.
Szczegóły techniczne
W poniższych sekcjach omówiono różne szczegóły techniczne, które są istotne do zrozumienia podczas tworzenia zasobów niestandardowych dla .NET.NET Aspire.
Bezpieczna sieć
W tym przykładzie zasób MailDev jest zasobem kontenera, który jest udostępniany maszynie hosta za pośrednictwem protokołu HTTP i SMTP. Zasób MailDev jest narzędziem programistycznym i nie jest przeznaczony do użytku produkcyjnego. Aby zamiast tego użyć protokołu HTTPS, zobacz MailDev: KonfigurowanieHTTPS.
Podczas tworzenia zasobów niestandardowych, które uwidaczniają punkty końcowe sieci, ważne jest, aby wziąć pod uwagę implikacje zabezpieczeń zasobu. Na przykład jeśli zasób jest bazą danych, należy upewnić się, że baza danych jest bezpieczna i że parametry połączenia nie są widoczne dla publicznego Internetu.
Typ ReferenceExpression
i EndpointReference
W poprzednim kodzie MailDevResource
miał dwie właściwości:
-
SmtpEndpoint
: typ EndpointReference. -
ConnectionStringExpression
: typ ReferenceExpression.
Te typy są jednymi z kilku, które są używane w .NET Aspire do reprezentowania danych konfiguracji, które nie są finalizowane, dopóki projekt .NET Aspire nie zostanie uruchomiony lub opublikowany w chmurze za pośrednictwem narzędzia takiego jak Azure Developer CLI (azd
).
Podstawowym problemem, który ten typ pomaga rozwiązać, jest opóźnienie rozwiązania konkretnych informacji o konfiguracji do momentu, gdy wszystkie informacje są dostępne.
Na przykład MailDevResource
uwidacznia właściwość o nazwie ConnectionStringExpression
zgodnie z wymaganiami interfejsu IResourceWithConnectionString. Typ właściwości jest ReferenceExpression i jest tworzony przez przekazanie ciągu interpolowanego do metody Create.
public ReferenceExpression ConnectionStringExpression =>
ReferenceExpression.Create(
$"smtp://{SmtpEndpoint.Property(EndpointProperty.Host)}:{SmtpEndpoint.Property(EndpointProperty.Port)}"
);
Podpis metody Create jest następujący:
public static ReferenceExpression Create(
in ExpressionInterpolatedStringHandler handler)
To nie jest zwykły argument String. Metoda wykorzystuje wzorzec składni obsługi ciągów interpolowanych , aby przechwycić szablon ciągu interpolowanego oraz wartości w nim referowane, umożliwiając przetwarzanie niestandardowe. W przypadku .NET.NET Aspirete szczegóły są przechwytywane w ReferenceExpression, które można ocenić, gdy każda wartość przywoływana w interpolowanym ciągu staje się dostępna.
Oto jak przebiega wykonywanie:
- Zasób, który implementuje IResourceWithConnectionString, jest dodawany do modelu (na przykład
AddMailDev(...)
). -
IResourceBuilder<MailDevResource>
jest przekazywana do WithReference, która ma specjalne przeciążenie do obsługi implementacji IResourceWithConnectionString. -
WithReference
opakowuje zasób w wystąpieniu ConnectionStringReference, a obiekt jest przechwytywany w EnvironmentCallbackAnnotation, który jest oceniany po zbudowaniu i uruchomieniu projektu .NET.NET Aspire. - Gdy proces, który odwołuje się do ciągu połączenia, rozpoczyna się, .NET.NET Aspire zaczyna oceniać wyrażenie. Najpierw pobiera ConnectionStringReference, a następnie wywołuje IValueProvider.GetValueAsync.
- Metoda
GetValueAsync
pobiera wartość właściwości ConnectionStringExpression, aby pobrać wystąpienie ReferenceExpression. - Następnie metoda IValueProvider.GetValueAsync wywołuje GetValueAsync w celu przetworzenia wcześniej przechwyconego ciągu interpolowanego.
- Ponieważ ciąg interpolowany zawiera odwołania do innych typów odwołań, takich jak EndpointReference są one również oceniane i zastępowane wartością rzeczywistą (która w tej chwili jest teraz dostępna).
Publikowanie manifestu
Interfejs IManifestExpressionProvider został zaprojektowany w celu rozwiązania problemu udostępniania informacji o połączeniu między zasobami podczas wdrażania. Rozwiązanie tego konkretnego problemu zostało opisane w .NET.NET Aspire omówienie sieci wewnętrznej pętli. Podobnie jak w przypadku programowania lokalnego wiele wartości jest niezbędnych do skonfigurowania aplikacji, ale nie można ich określić, dopóki aplikacja nie zostanie wdrożona za pomocą narzędzia, takiego jak azd
(Azure Developer CLI).
Aby rozwiązać ten problem, .NET.NET Aspire tworzy plik manifestu, który azd
i inne narzędzia wdrażania interpretują. Zamiast określać konkretne wartości informacji o połączeniu między zasobami używana jest składnia wyrażeń, które oceniają narzędzia wdrażania. Ogólnie rzecz biorąc, plik manifestu nie jest widoczny dla deweloperów, ale można go wygenerować do ręcznej inspekcji. Poniższe polecenie można użyć na hoście aplikacji w celu utworzenia manifestu.
dotnet run --project MailDevResource.AppHost/MailDevResource.AppHost.csproj -- --publisher manifest --output-path aspire-manifest.json
To polecenie tworzy plik manifestu podobny do następującego:
{
"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"
}
}
}
}
}
Ponieważ MailDevResource
implementuje IResourceWithConnectionString logiki publikowania manifestu w .NET.NET Aspire wie, że mimo że MailDevResource
jest zasobem kontenera, wymaga również pola connectionString
. Pole connectionString
odwołuje się do innych części zasobu maildev
w manifeście w celu utworzenia końcowego ciągu:
{
// ... other content omitted.
"connectionString": "smtp://{maildev.bindings.smtp.host}:{maildev.bindings.smtp.port}"
}
.NET .NET Aspire wie, jak utworzyć ten ciąg, ponieważ analizuje ConnectionStringExpression i tworzy końcowy ciąg za pośrednictwem interfejsu IManifestExpressionProvider (w taki sam sposób jak używany jest interfejs IValueProvider).
MailDevResource
automatycznie zostaje uwzględniona w manifeście, ponieważ pochodzi z ContainerResource. Autorzy zasobów mogą pominąć wyprowadzanie zawartości do manifestu przy użyciu metody rozszerzenia ExcludeFromManifest w konstruktorze zasobów.
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
}
Należy wziąć pod uwagę, czy zasób powinien znajdować się w manifeście, czy też należy go pominąć. Jeśli zasób jest dodawany do manifestu, należy go skonfigurować w taki sposób, aby był bezpieczny i bezpieczny do użycia.
Streszczenie
W samouczku dotyczącym zasobów niestandardowych przedstawiono sposób tworzenia niestandardowego zasobu .NET Aspire korzystającego z istniejącej konteneryzowanej aplikacji (MailDev). Następnie użyto tej funkcji, aby ulepszyć środowisko programowania lokalnego, ułatwiając testowanie możliwości poczty e-mail, które mogą być używane w aplikacji. Te nauki mogą zostać zastosowane do tworzenia innych zasobów niestandardowych, które mogą być używane w aplikacjach opartych na .NET.NET Aspire. W tym konkretnym przykładzie nie uwzględniliśmy żadnych integracji niestandardowych, ale można utworzyć niestandardowe integracje, aby ułatwić deweloperom korzystanie z zasobu. W tym scenariuszu można było polegać na istniejącej klasie SmtpClient
na platformie .NET do wysyłania wiadomości e-mail.