Partager via


Créer des intégrations personnalisées d’hébergement pour .NET.NET Aspire

.NET .NET Aspire améliore l’expérience de développement en fournissant des blocs de construction réutilisables qui peuvent être utilisés pour organiser rapidement les dépendances d’application et les exposer à votre propre code. L’un des principaux blocs de construction d’une application Aspireest la ressource . Considérez le code ci-dessous :

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

Dans le code précédent, quatre ressources sont représentées :

  1. cache: conteneur Redis.
  2. pgserver: conteneur Postgres.
  3. inventorydb: base de données hébergée sur pgserver.
  4. inventoryservice: une application ASP.NET Core.

La plupart du code .NET.NET Aspireécrit par le développeur moyen concerne principalement l'ajout de ressources au modèle d’application et la création de références entre ces ressources.

Éléments clés d’une ressource personnalisée .NET.NET Aspire

La création d’une ressource personnalisée dans .NET.NET Aspire nécessite les éléments suivants :

  1. Type de ressource personnalisé qui implémente IResource
  2. Méthode d’extension pour IDistributedApplicationBuilder nommée Add{CustomResource}{CustomResource} est le nom de la ressource personnalisée.

Lorsque la ressource personnalisée nécessite une configuration facultative, les développeurs peuvent souhaiter implémenter With* méthodes d’extension suffixées pour rendre ces options de configuration faciles à découvrir à l’aide du patron de générateur .

Exemple pratique : MailDev

Pour comprendre comment développer des ressources personnalisées, cet article montre un exemple de création d’une ressource personnalisée pour MailDev. MailDev est un outil open source qui fournit un server de messagerie local conçu pour permettre aux développeurs de tester les comportements d’envoi de courrier électronique au sein de leur application. Pour plus d’informations, consultez le référentiel MailDevGitHub.

Dans cet exemple, vous créez un projet .NET Aspire en tant qu’environnement de test pour la ressource MailDev que vous créez. Même si vous pouvez créer des ressources personnalisées dans des projets .NET Aspire existants, il est judicieux de déterminer si la ressource personnalisée peut être utilisée dans plusieurs solutions basées sur des .NET Aspireet doit être développée en tant qu’intégration réutilisable.

Configurer le projet de démarrage

Créez un projet .NET.NET Aspire utilisé pour tester la nouvelle ressource que nous développons.

dotnet new aspire -o MailDevResource
cd MailDevResource
dir

Une fois le projet créé, vous devez voir une description contenant les éléments suivants :

  • MailDevResource.AppHost: l’hôte d’application utilisé pour tester la ressource personnalisée.
  • MailDevResource.ServiceDefaults: Le projet par défaut du service pour une utilisation dans les projets liés au service.
  • MailDevResource.sln: fichier de solution référençant les deux projets.

Vérifiez que le projet peut générer et s’exécuter correctement en exécutant la commande suivante :

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

La sortie de la console doit ressembler à ce qui suit :

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.

Sélectionnez le lien tableau de bord dans le navigateur pour afficher le tableau de bord .NET.NET Aspire :

Capture d’écran D’un tableau de bord .NET.NET Aspire vide pour le projet de test.

Appuyez sur Ctrl+C pour arrêter l’application (vous pouvez fermer l’onglet du navigateur).

Créer une bibliothèque pour l’extension de ressource

.NET Aspire ressources sont uniquement des classes et des méthodes contenues dans une bibliothèque de classes qui fait référence à la bibliothèque d’hébergement .NET Aspire (Aspire.Hosting). En plaçant la ressource dans un projet distinct, vous pouvez la partager plus facilement entre les applications basées sur .NET.NET Aspireet éventuellement empaqueter et la partager sur NuGet.

  1. Créez le projet de bibliothèque de classes nommé MailDev. Hébergement.

    dotnet new classlib -o MailDev.Hosting
    
  2. Ajoutez Aspire.Hosting à la bibliothèque de classes en tant que référence de package.

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

    Important

    La version que vous spécifiez ici doit correspondre à la version de la charge de travail .NET.NET Aspire installée.

  3. Ajoutez une référence de bibliothèque de classes au projet MailDevResource.AppHost.

    dotnet add ./MailDevResource.AppHost/MailDevResource.AppHost.csproj reference ./MailDev.Hosting/MailDev.Hosting.csproj
    
  4. Ajoutez un projet de bibliothèque de classes au fichier solution.

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

Une fois les étapes suivantes effectuées, vous pouvez lancer le projet :

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

Cela entraîne l’affichage d’un avertissement dans la 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]

Cela est dû au fait que .NET.NET Aspire traite les références de projet dans l’hôte d’application comme s’il s’agit de projets de service. Pour indiquer .NET.NET Aspire que la référence du projet doit être traitée comme un projet non-service, modifiez la référence de fichiers MailDevResource.AppHostMailDevResource.AppHost.csproj au projet MailDev.Hosting comme suit :

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

Maintenant, lorsque vous lancez l’hôte de l’application, aucun avertissement n’est affiché sur la console.

Définir les types de ressources

Le MailDev. L’hébergement bibliothèque de classes contient le type de ressource et les méthodes d’extension pour ajouter la ressource à l’hôte de l’application. Vous devez d’abord réfléchir à l’expérience que vous souhaitez donner aux développeurs lors de l’utilisation de votre ressource personnalisée. Dans le cas de cette ressource personnalisée, vous souhaitez que les développeurs puissent écrire du code comme suit :

var builder = DistributedApplication.CreateBuilder(args);

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

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

Pour ce faire, vous avez besoin d’une ressource personnalisée nommée MailDevResource qui implémente IResourceWithConnectionString afin que les consommateurs puissent l’utiliser avec WithReference extension pour injecter les détails de connexion de l'MailDevserver en tant que chaîne de connexion.

MailDev est disponible en tant que ressource de conteneur. Vous pouvez donc également dériver de ContainerResource afin que nous puissions utiliser différentes extensions prédéfinies axées sur des conteneurs dans .NET.NET Aspire.

Remplacez le contenu du fichier Class1.cs dans le projet MailDev.Hosting, puis renommez le fichier en MailDevResource.cs par le code suivant :

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

Dans la ressource personnalisée précédente, les EndpointReference et les ReferenceExpression sont des exemples de plusieurs types qui implémentent une collection d’interfaces, telles que IManifestExpressionProvider, IValueProvideret IValueWithReferences. Pour plus d’informations sur ces types et leur rôle dans .NET.NET Aspire, consultez détails techniques.

Définir les extensions de ressource

Pour faciliter l’utilisation de la ressource personnalisée par les développeurs, une méthode d’extension nommée AddMailDev doit être ajoutée au projet MailDev.Hosting. La méthode d’extension AddMailDev est chargée de configurer la ressource afin qu’elle puisse démarrer correctement en tant que conteneur.

Ajoutez le code suivant à un nouveau fichier nommé MailDevResourceBuilderExtensions.cs dans le MailDev. Hébergement projet :

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

Valider l’intégration personnalisée à l’intérieur de l’hôte de l’application

Maintenant que la structure de base de la ressource personnalisée est terminée, il est temps de le tester dans un projet AppHost réel. Ouvrez le fichier Program.cs dans le projet MailDevResource.AppHost et mettez-le à jour avec le code suivant :

var builder = DistributedApplication.CreateBuilder(args);

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

builder.Build().Run();

Après avoir mis à jour le fichier Program.cs, lancez le projet hôte d’application et ouvrez le tableau de bord :

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

Après quelques instants, le tableau de bord indique que la ressource maildev est en cours d’exécution et qu’un lien hypertexte est disponible pour accéder à l’application web MailDev, qui affiche le contenu de chaque courrier électronique envoyé par votre application.

Le tableau de bord .NET.NET Aspire doit ressembler à ce qui suit :

MailDev ressource visible dans .NET Aspire tableau de bord.

l’application web MailDev doit ressembler à ce qui suit :

MailDev interface utilisateur web s’exécutant en tant que conteneur géré par .NET Aspire.

Ajouter un projet de service .NET à l’hôte d’application à des fins de test

Une fois que .NET Aspire a réussi à lancer l’intégration de MailDev, il est temps de consommer les informations de connexion pour MailDev dans un projet de .NET. Dans .NET.NET Aspire il est courant qu’il y ait un package d’hébergement et un ou plusieurs packages de composants . Prenons l’exemple suivant :

  • package d’hébergement: utilisé pour représenter des ressources dans le modèle d’application.
    • Aspire.Hosting.Redis
  • Packages de composants: utilisés pour configurer et consommer des bibliothèques client.
    • Aspire.StackExchange.Redis
    • Aspire.StackExchange.Redis.DistributedCaching
    • Aspire.StackExchange.Redis.OutputCaching

Dans le cas de la ressource MailDev, la plateforme .NET dispose déjà d’un client SMTP (Mail Transfer Protocol) simple sous la forme de SmtpClient. Dans cet exemple, vous utilisez cette API existante par souci de simplicité, bien que d’autres types de ressources puissent tirer parti des bibliothèques d’intégration personnalisées pour aider les développeurs.

Pour tester le scénario de bout en bout, vous avez besoin d’un projet .NET dans lequel nous pouvons injecter les informations de connexion pour la ressource MailDev. Ajoutez un projet d’API web :

  1. Créez un projet .NET nommé MailDevResource.NewsletterService.

    dotnet new webapi --use-minimal-apis -o MailDevResource.NewsletterService
    
  2. Ajoutez une référence au projet MailDev.Hosting.

    dotnet add ./MailDevResource.NewsletterService/MailDevResource.NewsletterService.csproj reference ./MailDev.Hosting/MailDev.Hosting.csproj
    
  3. Ajoutez une référence au projet MailDevResource.AppHost.

    dotnet add ./MailDevResource.AppHost/MailDevResource.AppHost.csproj reference ./MailDevResource.NewsletterService/MailDevResource.NewsletterService.csproj
    
  4. Ajoutez le nouveau projet au fichier solution.

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

Une fois le projet ajouté et les références mis à jour, ouvrez l'Program.cs du projet MailDevResource.AppHost.csproj et mettez à jour le fichier source pour ressembler à ce qui suit :

var builder = DistributedApplication.CreateBuilder(args);

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

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

builder.Build().Run();

Après avoir mis à jour le fichier Program.cs, lancez à nouveau l’hôte de l’application. Vérifiez ensuite que le service bulletin d’informations a démarré et que la variable d’environnement ConnectionStrings__maildev a été ajoutée au processus. Dans la page Ressources , recherchez la ligne , puis sélectionnez le lien Afficher dans la colonne Détails :

variables d’environnement pour le service de newsletter dans le tableau de bord .NET.NET Aspire.

La capture d’écran précédente montre les variables d’environnement du projet newsletterservice. La variable d’environnement ConnectionStrings__maildev est la chaîne de connexion qui a été injectée dans le projet par la ressource maildev.

Utiliser la chaîne de connexion pour envoyer des messages

Pour utiliser les détails de connexion SMTP qui ont été injectés dans le projet de service de bulletin d’informations, vous injectez une instance de SmtpClient dans le conteneur d’injection de dépendances en tant que singleton. Ajoutez le code suivant au fichier Program.cs dans le projet MailDevResource.NewsletterService pour configurer le service singleton. Dans la classe Program, immédiatement après le commentaire // Add services to the container, ajoutez le code suivant :

builder.Services.AddSingleton<SmtpClient>(sp =>
{
    var smtpUri = new Uri(builder.Configuration.GetConnectionString("maildev")!);

    var smtpClient = new SmtpClient(smtpUri.Host, smtpUri.Port);

    return smtpClient;
});

Pourboire

Cet extrait de code s’appuie sur le SmtpClientofficiel, cependant ; ce type est obsolète sur certaines plateformes et n’est pas recommandé pour d’autres. Pour une approche plus moderne à l’aide de MailKit, consultez Créer des intégrations de .NET Aspireclient personnalisées.

Pour tester le client, ajoutez deux méthodes POST simples subscribe et unsubscribe au service de newsletter. Ajoutez le code suivant en remplaçant l’appel « weatherforecast » MapGet dans le fichier Program.cs du projet MailDevResource.NewsletterService pour configurer les itinéraires 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);
});

Pourboire

N’oubliez pas de référencer les espaces de noms System.Net.Mail et Microsoft.AspNetCore.Mvc dans Program.cs si votre éditeur de code ne les ajoute pas automatiquement.

Une fois le fichier Program.cs mis à jour, lancez l’hôte de l’application et utilisez votre navigateur, ou curl pour atteindre les URL suivantes (sinon, si vous utilisez Visual Studio vous pouvez utiliser des fichiers .http) :

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

Pour utiliser cette API, vous pouvez utiliser curl pour envoyer la demande. La commande curl suivante envoie une requête HTTP POST au point de terminaison subscribe, et elle attend une valeur de chaîne de requête email pour s’abonner à la newsletter. L’en-tête Content-Type est défini sur application/json pour indiquer que le corps de la requête est au format JSON. :

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

L’API suivante est le point de terminaison unsubscribe. Ce point de terminaison est utilisé pour vous désabonner du bulletin d’informations.

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

Pour vous désabonner du bulletin d’informations, vous pouvez utiliser la commande curl suivante, en passant un paramètre email au point de terminaison unsubscribe en tant que chaîne de requête :

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

Pourboire

Veillez à remplacer le https://localhost:7251 par le port de localhost correct (URL de l’hôte de l’application que vous exécutez).

Si ces appels d’API retournent une réponse réussie (HTTP 200, Ok), vous devez être en mesure de sélectionner sur la ressource maildev ressource le tableau de bord et l'MailDev UI affiche les e-mails envoyés au point de terminaison SMTP.

e-mails visibles dans le MailDev de l’interface utilisateur

Détails techniques

Dans les sections suivantes, différents détails techniques sont abordés, qui sont importants à comprendre lors du développement de ressources personnalisées pour .NET.NET Aspire.

Mise en réseau sécurisée

Dans cet exemple, la ressource MailDev est une ressource de conteneur qui est exposée à l’ordinateur hôte via HTTP et SMTP. La ressource MailDev est un outil de développement qui n’est pas destiné à une utilisation en production. Pour utiliser le protocole HTTPS, consultez MailDev: Configurer https.

Lors du développement de ressources personnalisées qui exposent des points de terminaison réseau, il est important de prendre en compte les implications de sécurité de la ressource. Par exemple, si la ressource est une base de données, il est important de s’assurer que la base de données est sécurisée et que la chaîne de connexion n’est pas exposée à l’Internet public.

Type ReferenceExpression et EndpointReference

Dans le code précédent, le MailDevResource avait deux propriétés :

Ces types sont parmi plusieurs qui sont utilisés dans .NET Aspire pour représenter des données de configuration, qui ne sont pas finalisées tant que le projet .NET Aspire n’est pas exécuté ou publié dans le cloud via un outil tel que Azure Developer CLI (azd).

Le problème fondamental que ces types aident à résoudre, consiste à différer la résolution des informations de configuration concrètes jusqu’à ce que tous les les informations soient disponibles.

Par exemple, le MailDevResource expose une propriété appelée ConnectionStringExpression, comme requis par l’interface IResourceWithConnectionString. Le type de la propriété est ReferenceExpression et est créé en passant une chaîne interpolée à la méthode Create.

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

La signature de la méthode Create est la suivante :

public static ReferenceExpression Create(
    in ExpressionInterpolatedStringHandler handler)

Il ne s’agit pas d’un argument String standard. La méthode utilise le modèle de gestionnaire de chaînes interpolé , pour capturer le modèle de chaîne interpolé et les valeurs référencées dans celui-ci pour permettre un traitement personnalisé. Dans le cas de .NET.NET Aspire, ces détails sont capturés dans un ReferenceExpression qui peut être évalué à mesure que chaque valeur référencée dans la chaîne interpolée devient disponible.

Voici comment fonctionne le flux d’exécution :

  1. Une ressource qui implémente IResourceWithConnectionString est ajoutée au modèle (par exemple, AddMailDev(...)).
  2. Le IResourceBuilder<MailDevResource> est transmis au WithReference, qui a une surcharge spéciale pour la gestion des implémentations IResourceWithConnectionString.
  3. Le WithReference encapsule la ressource dans une instance de ConnectionStringReference et l’objet est capturé dans un EnvironmentCallbackAnnotation qui est évalué après la génération du projet .NET.NET Aspire et commence à s’exécuter.
  4. Lorsque le processus qui référence la chaîne de connexion démarre .NET.NET Aspire commence à évaluer l’expression. Il obtient d’abord le ConnectionStringReference et appelle IValueProvider.GetValueAsync.
  5. La méthode GetValueAsync obtient la valeur de la propriété ConnectionStringExpression pour obtenir l’instance de ReferenceExpression.
  6. La méthode IValueProvider.GetValueAsync appelle ensuite GetValueAsync pour traiter la chaîne interpolée précédemment capturée.
  7. Étant donné que la chaîne interpolée contient des références à d’autres types de référence, tels que EndpointReference ils sont également évalués et des valeurs réelles substituées (qui, à ce stade, sont désormais disponibles).

Publication de manifeste

L’interface IManifestExpressionProvider est conçue pour résoudre le problème de partage des informations de connexion entre les ressources au moment du déploiement. La solution à ce problème particulier est décrite dans la .NET.NET Aspire vue d’ensemble de la mise en réseau en boucle interne. De même que le développement local, la plupart des valeurs sont nécessaires pour configurer l’application, mais elles ne peuvent pas être déterminées tant que l’application n’est pas déployée via un outil, tel que azd (Azure Developer CLI).

Pour résoudre ce problème, .NET.NET Aspire produit un fichier manifeste qui azd et d’autres outils de déploiement interprètent. Au lieu de spécifier des valeurs concrètes pour les informations de connexion entre les ressources, une syntaxe d’expression est utilisée pour les outils de déploiement qui évaluent. En règle générale, le fichier manifeste n’est pas visible par les développeurs, mais il est possible de en générer un pour l’inspection manuelle. La commande ci-dessous peut être utilisée sur l’hôte de l’application pour produire un manifeste.

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

Cette commande produit un fichier manifeste comme suit :

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

Étant donné que le MailDevResource implémente IResourceWithConnectionString la logique de publication de manifeste dans .NET.NET Aspire sait que même si MailDevResource est une ressource conteneur, il a également besoin d’un champ connectionString. Le champ connectionString fait référence à d’autres parties de la ressource maildev dans le manifeste pour produire la chaîne finale :

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

.NET .NET Aspire sait comment former cette chaîne, car elle examine ConnectionStringExpression et génère la chaîne finale via l’interface IManifestExpressionProvider (de la même façon que l’interface IValueProvider est utilisée).

Le MailDevResource est automatiquement inclus dans le manifeste, car il est dérivé de ContainerResource. Les auteurs de ressources peuvent choisir de supprimer la sortie du contenu dans le manifeste à l’aide de la méthode d’extension ExcludeFromManifest sur le générateur de ressources.

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
}

Une attention particulière doit être prise en compte pour déterminer si la ressource doit être présente dans le manifeste ou si elle doit être supprimée. Si la ressource est ajoutée au manifeste, elle doit être configurée de manière à être sûre et sécurisée à utiliser.

Résumé

Dans le didacticiel sur les ressources personnalisées, vous avez appris à créer une ressource de .NET Aspire personnalisée qui utilise une application conteneurisée existante (MailDev). Vous l’avez ensuite utilisé pour améliorer l’expérience de développement local en vous permettant de tester facilement les fonctionnalités de messagerie qui peuvent être utilisées dans une application. Ces enseignements peuvent être appliqués à la création d’autres ressources personnalisées qui peuvent être utilisées dans des applications basées sur .NET.NET Aspire. Cet exemple spécifique n’inclut pas d’intégrations personnalisées, mais il est possible de créer des intégrations personnalisées pour faciliter l’utilisation de la ressource par les développeurs. Dans ce scénario, vous avez pu vous appuyer sur la classe SmtpClient existante dans la plateforme .NET pour envoyer des e-mails.

Étapes suivantes