Dela via


Skapa anpassade .NET.NET Aspire värdintegreringar

.NET .NET Aspire förbättrar utvecklingsupplevelsen genom att tillhandahålla återanvändbara byggstenar som kan användas för att snabbt ordna programberoenden och exponera dem för din egen kod. En av de viktigaste byggstenarna i ett Aspire-baserat program är resursen. Överväg koden nedan:

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);

I föregående kod finns fyra resurser representerade:

  1. cache: En Redis container.
  2. pgserver: En Postgres container.
  3. inventorydb: En databas som finns på pgserver.
  4. inventoryservice: Ett ASP.NET Core program.

De flesta .NET.NET Aspire-relaterad kod som den genomsnittliga utvecklaren skriver, fokuserar på att lägga till resurser i appmodell och skapa referenser mellan dem.

Viktiga element i en .NET.NET Aspire anpassad resurs

För att skapa en anpassad resurs i .NET.NET Aspire krävs följande:

  1. En anpassad resurstyp som implementerar IResource
  2. En tilläggsmetod för IDistributedApplicationBuilder med namnet Add{CustomResource} där {CustomResource} är namnet på den anpassade resursen.

När anpassade resurser kräver valfri konfiguration kan utvecklare vilja implementera With* suffixade tilläggsmetoder för att göra dessa konfigurationsalternativ identifierbara med hjälp av builder-mönstret.

Ett praktiskt exempel: MailDev

För att förstå hur du utvecklar anpassade resurser visar den här artikeln ett exempel på hur du skapar en anpassad resurs för MailDev. MailDev är ett verktyg med öppen källkod som tillhandahåller en lokal e-postserver som är utformad för att göra det möjligt för utvecklare att testa e-postutskicksbeteenden i sin app. Mer information finns i MailDevGitHub-lagringsplatsen.

I det här exemplet skapar du ett nytt .NET Aspire projekt som en testmiljö för den MailDev resurs som du skapar. Även om du kan skapa anpassade resurser i befintliga .NET Aspire projekt är det en bra idé att överväga om den anpassade resursen kan användas i flera .NET Aspire-baserade lösningar och bör utvecklas som en återanvändbar integrering.

Konfigurera startprojektet

Skapa ett nytt .NET.NET Aspire projekt som används för att testa den nya resurs som vi utvecklar.

dotnet new aspire -o MailDevResource
cd MailDevResource
dir

När projektet har skapats bör du se en lista som innehåller följande:

  • MailDevResource.AppHost: Den appvärd användes för att testa den anpassade resursen.
  • MailDevResource.ServiceDefaults: Tjänsten förinställningar projekt för användning i tjänsterelaterade projekt.
  • MailDevResource.sln: Lösningsfilen som refererar till båda projekten.

Kontrollera att projektet kan kompilera och köras framgångsrikt genom att köra följande kommando:

dotnet run --project MailDevResource.AppHost/MailDevResource.AppHost.csproj

Konsolutdata bör se ut ungefär så här:

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.

Välj länken instrumentpanel i webbläsaren för att se .NET.NET Aspire instrumentpanelen:

En skärmbild av den tomma .NET.NET Aspire instrumentpanelen för testprojektet.

Tryck på Ctrl+C för att stänga appen (du kan stänga webbläsarfliken).

Skapa bibliotek för resurstillägg

.NET Aspire resurser är bara klasser och metoder som finns i ett klassbibliotek som refererar till .NET Aspire Hosting-biblioteket (Aspire.Hosting). Genom att placera resursen i ett separat projekt kan du enklare dela den mellan .NET.NET Aspire-baserade appar och eventuellt paketera och dela den på NuGet.

  1. Skapa klassbiblioteksprojektet med namnet MailDev.Hosting.

    dotnet new classlib -o MailDev.Hosting
    
  2. Lägg till Aspire.Hosting i klassbiblioteket som en paketreferens.

    dotnet add ./MailDev.Hosting/MailDev.Hosting.csproj package Aspire.Hosting --version 9.0.0
    

    Viktig

    Den version som du anger här ska matcha den version av .NET.NET Aspire arbetsbelastning som är installerad.

  3. Lägg till klassbiblioteksreferens till projektet MailDevResource.AppHost.

    dotnet add ./MailDevResource.AppHost/MailDevResource.AppHost.csproj reference ./MailDev.Hosting/MailDev.Hosting.csproj
    
  4. Lägg till klassbiblioteksprojekt i lösningsfilen.

    dotnet sln ./MailDevResource.sln add ./MailDev.Hosting/MailDev.Hosting.csproj
    

När följande steg har utförts kan du starta projektet:

dotnet run --project ./MailDevResource.AppHost/MailDevResource.AppHost.csproj

Detta resulterar i att en varning visas för konsolen:

.\.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]

Detta beror på att .NET.NET Aspire behandlar projektreferenser i appvärden som om de vore tjänsteprojekt. Om du vill meddela .NET.NET Aspire att projektreferensen ska behandlas som ett icke-tjänstprojekt ändrar du MailDevResource.AppHostMailDevResource.AppHost.csproj-filreferensen till MailDev.Hosting-projektet så att den blir följande:

<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>

Nu när du startar appvärden visas ingen varning för konsolen.

Definiera resurstyperna

Den MailDev. Värd för-klassbiblioteket innehåller resurstyp och tilläggsmetoder för att lägga till resursen i appvärden. Du bör först tänka på den upplevelse som du vill ge utvecklare när du använder din anpassade resurs. När det gäller den här anpassade resursen vill du att utvecklare ska kunna skriva kod som följande:

var builder = DistributedApplication.CreateBuilder(args);

var maildev = builder.AddMailDev("maildev");

builder.AddProject<Projects.NewsletterService>("newsletterservice")
       .WithReference(maildev);

För att uppnå detta behöver du en anpassad resurs med namnet MailDevResource som implementerar IResourceWithConnectionString så att användarna kan använda den med WithReference tillägg för att mata in anslutningsinformationen för MailDev-servern som en anslutningssträng.

MailDev är tillgängligt som en containerresurs, så du vill också härleda från ContainerResource så att vi kan använda olika befintliga containerfokuserade tillägg i .NET.NET Aspire.

Ersätt innehållet i Class1.cs-filen i MailDev.Hosting-projektet och byt namn på filen till MailDevResource.cs med följande kod:

// 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)}"
        );
}

I föregående anpassade resurs är EndpointReference och ReferenceExpression exempel på flera typer som implementerar en samling gränssnitt, till exempel IManifestExpressionProvider, IValueProvideroch IValueWithReferences. Mer information om dessa typer och deras roll i .NET.NET Aspirefinns i teknisk information.

Definiera resurstilläggen

För att göra det enkelt för utvecklare att använda den anpassade resursen måste en tilläggsmetod med namnet AddMailDev läggas till i MailDev.Hosting projektet. AddMailDev-tilläggsmetoden är ansvarig för att konfigurera resursen så att den framgångsrikt kan starta som en container.

Lägg till följande kod i en ny fil med namnet MailDevResourceBuilderExtensions.cs i MailDev.Hosting-projekt:

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";
}

Verifiera anpassad integrering i appvärden

Nu när den grundläggande strukturen för den anpassade resursen är klar är det dags att testa den i ett riktigt AppHost-projekt. Öppna filen Program.cs i projektet MailDevResource.AppHost och uppdatera den med följande kod:

var builder = DistributedApplication.CreateBuilder(args);

var maildev = builder.AddMailDev("maildev");

builder.Build().Run();

När du har uppdaterat Program.cs-filen, kör igång programvärdprojektet och öppna instrumentpanelen:

dotnet run --project ./MailDevResource.AppHost/MailDevResource.AppHost.csproj

Efter en liten stund visar instrumentpanelen att den maildev resursen körs och att en hyperlänk är tillgänglig som navigerar till MailDev webbapp, som visar innehållet i varje e-postmeddelande som appen skickar.

Instrumentpanelen .NET.NET Aspire bör se ut ungefär så här:

MailDev resurs som visas på .NET Aspire instrumentpanelen.

Webbappen MailDev bör se ut ungefär så här:

MailDev webbaserat användargränssnitt som körs som en container som hanteras av .NET Aspire.

Lägga till ett .NET tjänstprojekt till appvärden för testning

När .NET Aspire lyckas starta MailDev-integrationen är det väl dags att använda anslutningsinformationen för MailDev i ett .NET-projekt. I .NET.NET Aspire är det vanligt att det finns ett värdpaket och ett eller flera komponentpaket. Tänk till exempel på följande:

  • Värdpaket: Används för att representera resurser i appmodellen.
    • Aspire.Hosting.Redis
  • Komponentpaket: Används för att konfigurera och använda klientbibliotek.
    • Aspire.StackExchange.Redis
    • Aspire.StackExchange.Redis.DistributedCaching
    • Aspire.StackExchange.Redis.OutputCaching

När det gäller den MailDev resursen har .NET-plattformen redan en SMTP-klient (Simple Mail Transfer Protocol) i form av SmtpClient. I det här exemplet använder du det här befintliga API:et för enkelhetens skull, även om andra resurstyper kan dra nytta av anpassade integrationsbibliotek för att hjälpa utvecklare.

För att testa scenariot från slutpunkt till slutpunkt behöver du ett .NET projekt som vi kan mata in anslutningsinformationen i för den MailDev resursen. Lägg till ett webb-API-projekt:

  1. Skapa ett nytt .NET projekt med namnet MailDevResource.NewsletterService.

    dotnet new webapi --use-minimal-apis -o MailDevResource.NewsletterService
    
  2. Lägg till en referens till MailDev.Hosting projektet.

    dotnet add ./MailDevResource.NewsletterService/MailDevResource.NewsletterService.csproj reference ./MailDev.Hosting/MailDev.Hosting.csproj
    
  3. Lägg till en referens till MailDevResource.AppHost projektet.

    dotnet add ./MailDevResource.AppHost/MailDevResource.AppHost.csproj reference ./MailDevResource.NewsletterService/MailDevResource.NewsletterService.csproj
    
  4. Lägg till det nya projektet i lösningsfilen.

    dotnet sln ./MailDevResource.sln add ./MailDevResource.NewsletterService/MailDevResource.NewsletterService.csproj
    

När projektet har lagts till och referenser har uppdaterats öppnar du Program.cs för MailDevResource.AppHost.csproj-projektet och uppdaterar källfilen så att den ser ut så här:

var builder = DistributedApplication.CreateBuilder(args);

var maildev = builder.AddMailDev("maildev");

builder.AddProject<Projects.MailDevResource_NewsletterService>("newsletterservice")
       .WithReference(maildev);

builder.Build().Run();

När du har uppdaterat Program.cs-filen startar du appvärden igen. Kontrollera sedan att nyhetsbrevstjänsten startade och att miljövariabeln ConnectionStrings__maildev lades till i processen. På sidan Resurser letar du reda på raden newsletterservice och väljer länken Visa i kolumnen Information:

Miljövariabler för nyhetsbrevstjänsten i .NET.NET Aspire instrumentpanel.

Föregående skärmbild visar miljövariablerna för newsletterservice-projektet. Miljövariabeln ConnectionStrings__maildev är anslutningssträngen som har matats in i projektet av den maildev resursen.

Använda anslutningssträng för att skicka meddelanden

För att använda SMTP-anslutningsinformationen som har införlivats i nyhetsbrevstjänstprojektet, injicerar du en instans av SmtpClient i beroendeinjektionscontainern som en singleton. Lägg till följande kod i Program.cs-filen i MailDevResource.NewsletterService-projektet för att konfigurera singleton-tjänsten. Lägg till följande kod direkt efter Program-kommentaren i klassen // 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;
});

Tips

Det här kodfragmentet förlitar sig dock på den officiella SmtpClient. den här typen är föråldrad på vissa plattformar och rekommenderas inte för andra. En modernare metod med MailKitfinns i Skapa anpassade .NET.NET Aspire klientintegreringar.

Om du vill testa klienten lägger du till två enkla subscribe- och unsubscribe POST-metoder i nyhetsbrevstjänsten. Lägg till följande kod som ersätter "weatherforecast" MapGet-anropet i Program.cs-filen i projektet MailDevResource.NewsletterService för att konfigurera ASP.NET Core vägar:

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);
});

Tips

Kom ihåg att referera till namnrymderna System.Net.Mail och Microsoft.AspNetCore.Mvc i Program.cs om kodredigeraren inte lägger till dem automatiskt.

När Program.cs-filen har uppdaterats startar du appvärden och använder webbläsaren eller curl för att träffa följande URL:er (om du använder Visual Studio kan du använda .http filer):

POST /subscribe?email=test@test.com HTTP/1.1
Host: localhost:7251
Content-Type: application/json

Om du vill använda det här API:et kan du använda curl för att skicka begäran. Följande curl-kommando skickar en HTTP-POST-begäran till subscribe-slutpunkten och förväntar sig att ett email-frågesträngsvärde används för att prenumerera på nyhetsbrevet. Content-Type-huvudet är inställt på application/json för att ange att begärandetexten är i JSON format.:

curl -H "Content-Type: application/json" --request POST https://localhost:7251/subscribe?email=test@test.com

Nästa API är unsubscribe slutpunkten. Den här slutpunkten används för att avbryta prenumerationen på nyhetsbrevet.

POST /unsubscribe?email=test@test.com HTTP/1.1
Host: localhost:7251
Content-Type: application/json

Om du vill avbryta prenumerationen på nyhetsbrevet kan du använda följande curl kommando och skicka en email-parameter till unsubscribe slutpunkt som en frågesträng:

curl -H "Content-Type: application/json" --request POST https://localhost:7251/unsubscribe?email=test@test.com

Tips

Se till att du ersätter https://localhost:7251 med den korrekta localhost-porten (URL för den applikationsvärd som du kör).

Om dessa API-anrop returnerar ett lyckat svar (HTTP 200, OK) bör du kunna välja på maildev resurs instrumentpanelen och MailDev UI visar de e-postmeddelanden som har skickats till SMTP-slutpunkten.

e-postmeddelanden som visas i MailDev användargränssnittet

Teknisk information

I följande avsnitt beskrivs olika tekniska detaljer som är viktiga att förstå när du utvecklar anpassade resurser för .NET.NET Aspire.

Skydda nätverk

I det här exemplet är den MailDev resursen en containerresurs som exponeras för värddatorn via HTTP och SMTP. Den MailDev resursen är ett utvecklingsverktyg och är inte avsedd för produktionsanvändning. Om du i stället vill använda HTTPS läser du MailDev: Konfigurera HTTPS-.

När du utvecklar anpassade resurser som exponerar nätverksslutpunkter är det viktigt att ta hänsyn till resursens säkerhetskonsekvenser. Om resursen till exempel är en databas är det viktigt att se till att databasen är säker och att anslutningssträngen inte exponeras för det offentliga Internet.

Typen ReferenceExpression och EndpointReference

I föregående kod hade MailDevResource två egenskaper:

Dessa typer är bland flera som används i hela .NET Aspire för att representera konfigurationsdata, som inte slutförs förrän .NET Aspire projektet antingen körs eller publiceras i molnet via ett verktyg som Azure Developer CLI (azd).

Det grundläggande problem som dessa typer hjälper till att lösa är att skjuta upp lösningen av konkret konfigurationsinformation tills alla informationen är tillgänglig.

Till exempel exponerar MailDevResource en egenskap som heter ConnectionStringExpression som krävs av IResourceWithConnectionString-gränssnittet. Egenskapens typ är ReferenceExpression och skapas genom att en interpolerad sträng skickas till metoden Create.

public ReferenceExpression ConnectionStringExpression =>
    ReferenceExpression.Create(
        $"smtp://{SmtpEndpoint.Property(EndpointProperty.Host)}:{SmtpEndpoint.Property(EndpointProperty.Port)}"
    );

Signaturen för metoden Create är följande:

public static ReferenceExpression Create(
    in ExpressionInterpolatedStringHandler handler)

Det här är inte ett vanligt String argument. Metoden använder mönstret interpolerad stränghanterare, för att avbilda den interpolerade strängmallen och de värden som refereras i den för att tillåta anpassad bearbetning. När det gäller .NET.NET Aspiresamlas dessa uppgifter in i en ReferenceExpression som kan utvärderas när varje värde som refereras i den interpolerade strängen blir tillgängligt.

Så här fungerar körningsflödet:

  1. En resurs som implementerar IResourceWithConnectionString läggs till i modellen (till exempel AddMailDev(...)).
  2. IResourceBuilder<MailDevResource> skickas till WithReference som har en särskild överlagring för hantering av IResourceWithConnectionString implementorer.
  3. WithReference omsluter resursen i en ConnectionStringReference-instans och objektet avbildas i en EnvironmentCallbackAnnotation som utvärderas när .NET.NET Aspire projektet har skapats och börjar köras.
  4. När processen som refererar till anslutningssträngen startar .NET.NET Aspire börjar utvärdera uttrycket. Den hämtar först ConnectionStringReference och anropar IValueProvider.GetValueAsync.
  5. Metoden GetValueAsync hämtar värdet för egenskapen ConnectionStringExpression för att hämta ReferenceExpression-instansen.
  6. Metoden IValueProvider.GetValueAsync anropar sedan GetValueAsync för att bearbeta den tidigare insamlade interpolerade strängen.
  7. Eftersom den interpolerade strängen innehåller referenser till andra referenstyper, till exempel EndpointReference utvärderas de också och det verkliga värdet ersätts (som nu är tillgängligt).

Manifestpublicering

Gränssnittet IManifestExpressionProvider är utformat för att lösa problemet med att dela anslutningsinformation mellan resurser vid distributionen. Lösningen på det här problemet beskrivs i .NET.NET Aspire översikt över nätverk i inre loopar. På samma sätt som för lokal utveckling är många av värdena nödvändiga för att konfigurera appen, men de kan inte fastställas förrän appen distribueras via ett verktyg, till exempel azd (Azure Developer CLI).

För att lösa det här problemet skapar .NET.NET Aspire en manifestfil som azd och andra distributionsverktyg tolkar. I stället för att ange konkreta värden för anslutningsinformation mellan resurser används en uttryckssyntax som distributionsverktyg utvärderar. I allmänhet är manifestfilen inte synlig för utvecklare, men det är möjligt att generera en för manuell inspektion. Kommandot nedan kan användas på appvärden för att skapa ett manifest.

dotnet run --project MailDevResource.AppHost/MailDevResource.AppHost.csproj -- --publisher manifest --output-path aspire-manifest.json

Det här kommandot skapar en manifestfil som liknar följande:

{
  "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"
        }
      }
    }
  }
}

Eftersom MailDevResource implementerar IResourceWithConnectionString manifestpubliceringslogik i .NET.NET Aspire vet att även om MailDevResource är en containerresurs behöver den också ett connectionString fält. Fältet connectionString refererar till andra delar av maildev resursen i manifestet för att skapa den sista strängen:

{
    // ... other content omitted.
    "connectionString": "smtp://{maildev.bindings.smtp.host}:{maildev.bindings.smtp.port}"
}

.NET .NET Aspire vet hur du bildar den här strängen eftersom den tittar på ConnectionStringExpression och bygger upp den sista strängen via IManifestExpressionProvider-gränssnittet (på ungefär samma sätt som det IValueProvider gränssnittet används).

MailDevResource tas automatiskt med i manifestet eftersom det härleds från ContainerResource. resursförfattare kan välja att utesluta innehållsutmatning till manifestet med hjälp av ExcludeFromManifest-tilläggsmetoden i resursbyggaren.

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
}

Du bör noga överväga om resursen ska finnas i manifestet eller om den ska ignoreras. Om resursen läggs till i manifestet bör den konfigureras på ett sådant sätt att den är säker och säker att använda.

Sammanfattning

I självstudien om anpassade resurser lärde du dig hur du skapar en anpassad .NET Aspire resurs som använder ett befintligt containerbaserat program (MailDev). Sedan använde du det för att förbättra den lokala utvecklingsupplevelsen genom att göra det enkelt att testa e-postfunktioner som kan användas i en app. Dessa lärdomar kan användas för att skapa andra anpassade resurser som kan användas i .NET.NET Aspire-baserade program. Det här specifika exemplet innehöll inga anpassade integreringar, men det är möjligt att skapa anpassade integreringar för att göra det enklare för utvecklare att använda resursen. I det här scenariot kunde du förlita dig på den befintliga SmtpClient-klassen i .NET-plattformen för att skicka e-postmeddelanden.

Nästa steg