Udostępnij za pośrednictwem


Tworzenie niestandardowych integracji .NET Aspireclient

Ten artykuł jest kontynuacją artykułu Create custom .NET.NET Aspire hosting integrations (Tworzenie niestandardowych integracji hostingu). Przeprowadzi Cię przez proces tworzenia integracji .NET Aspireclient, która używa MailKit do wysyłania wiadomości e-mail. Ta integracja jest następnie dodawana do utworzonej wcześniej aplikacji Biuletyn. W poprzednim przykładzie pominięto utworzenie integracji client, a zamiast tego oparto się na istniejącym .NETSmtpClient. Najlepiej używać SmtpClient od MailKit do wysyłania wiadomości e-mail zamiast oficjalnych .NETSmtpClient, ponieważ SmtpClient jest bardziej nowoczesny i obsługuje więcej funkcji/protokołów. Aby uzyskać więcej informacji, zobacz .NET SmtpClient: Uwagi.

Warunki wstępne

Jeśli śledzisz wcześniejsze kroki, powinieneś mieć aplikację Newsletter z opisanego artykułu Create custom .NET.NET Aspire hosting integration.

Napiwek

Ten artykuł został zainspirowany istniejącymi integracjami .NET.NET Aspire oraz oparty na oficjalnych wskazówkach zespołu. Istnieją miejsca, w których mówi się, że wskazówki różnią się i ważne jest, aby zrozumieć rozumowanie różnic. Aby uzyskać więcej informacji, zobacz .NET.NET Aspire wymagania dotyczące integracji.

Tworzenie biblioteki na potrzeby integracji

.NET .NET Aspire integracje są dostarczane jako pakiety NuGet, ale w tym przykładzie publikowanie pakietu NuGet wykracza poza zakres tego artykułu. Zamiast tego utworzysz projekt biblioteki klas, który zawiera integrację i odwołuje się do niego jako projekt. .NET Aspire pakiety integracji mają na celu opakować bibliotekę client, taką jak MailKit, oraz udostępniać dane telemetryczne gotowe do produkcji, kontrolę kondycji, możliwość konfiguracji i testowania. Zacznijmy od utworzenia nowego projektu biblioteki klas.

  1. Utwórz nowy projekt biblioteki klas o nazwie MailKit.Client w tym samym katalogu co MailDevResource.sln z poprzedniego artykułu.

    dotnet new classlib -o MailKit.Client
    
  2. Dodaj projekt do rozwiązania.

    dotnet sln ./MailDevResource.sln add MailKit.Client/MailKit.Client.csproj
    

Następnym krokiem jest dodanie wszystkich pakietów NuGet, na których opiera się integracja. Zamiast dodawać każdy pakiet jeden po drugim z interfejsu wiersza poleceń .NET, może być łatwiej skopiować i wkleić poniższy kod XML do pliku MailKit,Client.csproj.

<ItemGroup>
  <PackageReference Include="MailKit" Version="4.9.0" />
  <PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="9.0.0" />
  <PackageReference Include="Microsoft.Extensions.Resilience" Version="9.0.0" />
  <PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="9.0.0" />
  <PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks" Version="9.0.0" />
  <PackageReference Include="OpenTelemetry.Extensions.Hosting" Version="1.10.0" />
</ItemGroup>

Definiowanie ustawień integracji

Zawsze, gdy tworzysz integrację .NET Aspire, najlepiej jest dobrze zrozumieć bibliotekę client, na którą mapujesz. Za pomocą zestawu MailKit należy poznać ustawienia konfiguracji wymagane do nawiązania połączenia z protokołem SMTP (Simple Mail Transfer Protocol) server. Należy jednak również zrozumieć, czy biblioteka obsługuje zdrowotne kontrole , śledzenie oraz metryki . MailKit obsługuje śledzenie oraz metrykiza pośrednictwem swojej Telemetry.SmtpClient klasy. Podczas dodawania kontroli kondycjinależy użyć wszelkich ustanowionych lub istniejących kontroli kondycji, jeśli to możliwe. W przeciwnym razie możesz rozważyć wdrożenie własnego w ramach integracji. Dodaj następujący kod do projektu MailKit.Client w pliku o nazwie MailKitClientSettings.cs:

using System.Data.Common;

namespace MailKit.Client;

/// <summary>
/// Provides the client configuration settings for connecting MailKit to an SMTP server.
/// </summary>
public sealed class MailKitClientSettings
{
    internal const string DefaultConfigSectionName = "MailKit:Client";

    /// <summary>
    /// Gets or sets the SMTP server <see cref="Uri"/>.
    /// </summary>
    /// <value>
    /// The default value is <see langword="null"/>.
    /// </value>
    public Uri? Endpoint { get; set; }

    /// <summary>
    /// Gets or sets a boolean value that indicates whether the database health check is disabled or not.
    /// </summary>
    /// <value>
    /// The default value is <see langword="false"/>.
    /// </value>
    public bool DisableHealthChecks { get; set; }

    /// <summary>
    /// Gets or sets a boolean value that indicates whether the OpenTelemetry tracing is disabled or not.
    /// </summary>
    /// <value>
    /// The default value is <see langword="false"/>.
    /// </value>
    public bool DisableTracing { get; set; }

    /// <summary>
    /// Gets or sets a boolean value that indicates whether the OpenTelemetry metrics are disabled or not.
    /// </summary>
    /// <value>
    /// The default value is <see langword="false"/>.
    /// </value>
    public bool DisableMetrics { get; set; }

    internal void ParseConnectionString(string? connectionString)
    {
        if (string.IsNullOrWhiteSpace(connectionString))
        {
            throw new InvalidOperationException($"""
                    ConnectionString is missing.
                    It should be provided in 'ConnectionStrings:<connectionName>'
                    or '{DefaultConfigSectionName}:Endpoint' key.'
                    configuration section.
                    """);
        }

        if (Uri.TryCreate(connectionString, UriKind.Absolute, out var uri))
        {
            Endpoint = uri;
        }
        else
        {
            var builder = new DbConnectionStringBuilder
            {
                ConnectionString = connectionString
            };
            
            if (builder.TryGetValue("Endpoint", out var endpoint) is false)
            {
                throw new InvalidOperationException($"""
                        The 'ConnectionStrings:<connectionName>' (or 'Endpoint' key in
                        '{DefaultConfigSectionName}') is missing.
                        """);
            }

            if (Uri.TryCreate(endpoint.ToString(), UriKind.Absolute, out uri) is false)
            {
                throw new InvalidOperationException($"""
                        The 'ConnectionStrings:<connectionName>' (or 'Endpoint' key in
                        '{DefaultConfigSectionName}') isn't a valid URI.
                        """);
            }

            Endpoint = uri;
        }
    }
}

Powyższy kod definiuje klasę MailKitClientSettings z:

  • Endpoint właściwość reprezentująca łańcuch połączenia z serverSMTP.
  • DisableHealthChecks właściwość, która określa, czy są włączone kontrole kondycji.
  • DisableTracing właściwość, która określa, czy śledzenie jest włączone.
  • DisableMetrics właściwość, która określa, czy metryki są włączone.

Analizowanie logiki parametrów połączenia

Klasa ustawień zawiera również metodę ParseConnectionString, która przekształca ciąg połączenia w prawidłowy Uri. Konfiguracja powinna być podana w następującym formacie:

  • ConnectionStrings:<connectionName>: Ciąg połączenia do SMTP server.
  • MailKit:Client:ConnectionString: ciąg połączeniowy do SMTP server.

Jeśli żadna z tych wartości nie zostanie podana, zostanie zgłoszony wyjątek.

Uwidacznianie funkcji client

Celem integracji .NET Aspire jest uwidocznienie bazowej biblioteki client użytkownikom poprzez wstrzyknięcie zależności. W przypadku zestawu MailKit i w tym przykładzie klasa SmtpClient jest tym, co chcesz uwidocznić. Nie opakowujesz żadnych funkcji, ale raczej mapujesz ustawienia konfiguracji na klasę SmtpClient. Typowe jest uwidacznianie zarówno rejestracji standardowych, jak i usług kluczowych na potrzeby integracji. Rejestracje standardowe są używane, gdy istnieje tylko jedno wystąpienie usługi, a rejestracje usługi z kluczem są używane, gdy istnieje wiele wystąpień usługi. Czasami, aby uzyskać wiele rejestracji tego samego typu, należy użyć wzorca projektowego fabryki. Dodaj następujący kod do projektu MailKit.Client w pliku o nazwie MailKitClientFactory.cs:

using MailKit.Net.Smtp;

namespace MailKit.Client;

/// <summary>
/// A factory for creating <see cref="ISmtpClient"/> instances
/// given a <paramref name="smtpUri"/> (and optional <paramref name="credentials"/>).
/// </summary>
/// <param name="settings">
/// The <see cref="MailKitClientSettings"/> settings for the SMTP server
/// </param>
public sealed class MailKitClientFactory(MailKitClientSettings settings) : IDisposable
{
    private readonly SemaphoreSlim _semaphore = new(1, 1);

    private SmtpClient? _client;

    /// <summary>
    /// Gets an <see cref="ISmtpClient"/> instance in the connected state
    /// (and that's been authenticated if configured).
    /// </summary>
    /// <param name="cancellationToken">Used to abort client creation and connection.</param>
    /// <returns>A connected (and authenticated) <see cref="ISmtpClient"/> instance.</returns>
    /// <remarks>
    /// Since both the connection and authentication are considered expensive operations,
    /// the <see cref="ISmtpClient"/> returned is intended to be used for the duration of a request
    /// (registered as 'Scoped') and is automatically disposed of.
    /// </remarks>
    public async Task<ISmtpClient> GetSmtpClientAsync(
        CancellationToken cancellationToken = default)
    {
        await _semaphore.WaitAsync(cancellationToken);

        try
        {
            if (_client is null)
            {
                _client = new SmtpClient();

                await _client.ConnectAsync(settings.Endpoint, cancellationToken)
                             .ConfigureAwait(false);
            }
        }
        finally
        {
            _semaphore.Release();
        }       

        return _client;
    }

    public void Dispose()
    {
        _client?.Dispose();
        _semaphore.Dispose();
    }
}

Klasa MailKitClientFactory to fabryka, która tworzy instancję ISmtpClient na podstawie ustawień konfiguracji. Odpowiada za zwrócenie implementacji ISmtpClient, która ma aktywne połączenie ze skonfigurowanym SMTP server. Następnie należy udostępnić użytkownikom funkcję rejestrowania tej fabryki za pomocą kontenera wstrzykiwania zależności. Dodaj następujący kod do projektu MailKit.Client w pliku o nazwie MailKitExtensions.cs:

using MailKit;
using MailKit.Client;
using MailKit.Net.Smtp;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;

namespace Microsoft.Extensions.Hosting;

/// <summary>
/// Provides extension methods for registering a <see cref="SmtpClient"/> as a
/// scoped-lifetime service in the services provided by the <see cref="IHostApplicationBuilder"/>.
/// </summary>
public static class MailKitExtensions
{
    /// <summary>
    /// Registers 'Scoped' <see cref="MailKitClientFactory" /> for creating
    /// connected <see cref="SmtpClient"/> instance for sending emails.
    /// </summary>
    /// <param name="builder">
    /// The <see cref="IHostApplicationBuilder" /> to read config from and add services to.
    /// </param>
    /// <param name="connectionName">
    /// A name used to retrieve the connection string from the ConnectionStrings configuration section.
    /// </param>
    /// <param name="configureSettings">
    /// An optional delegate that can be used for customizing options.
    /// It's invoked after the settings are read from the configuration.
    /// </param>
    public static void AddMailKitClient(
        this IHostApplicationBuilder builder,
        string connectionName,
        Action<MailKitClientSettings>? configureSettings = null) =>
        AddMailKitClient(
            builder,
            MailKitClientSettings.DefaultConfigSectionName,
            configureSettings,
            connectionName,
            serviceKey: null);

    /// <summary>
    /// Registers 'Scoped' <see cref="MailKitClientFactory" /> for creating
    /// connected <see cref="SmtpClient"/> instance for sending emails.
    /// </summary>
    /// <param name="builder">
    /// The <see cref="IHostApplicationBuilder" /> to read config from and add services to.
    /// </param>
    /// <param name="name">
    /// The name of the component, which is used as the <see cref="ServiceDescriptor.ServiceKey"/> of the
    /// service and also to retrieve the connection string from the ConnectionStrings configuration section.
    /// </param>
    /// <param name="configureSettings">
    /// An optional method that can be used for customizing options. It's invoked after the settings are
    /// read from the configuration.
    /// </param>
    public static void AddKeyedMailKitClient(
        this IHostApplicationBuilder builder,
        string name,
        Action<MailKitClientSettings>? configureSettings = null)
    {
        ArgumentNullException.ThrowIfNull(name);

        AddMailKitClient(
            builder,
            $"{MailKitClientSettings.DefaultConfigSectionName}:{name}",
            configureSettings,
            connectionName: name,
            serviceKey: name);
    }

    private static void AddMailKitClient(
        this IHostApplicationBuilder builder,
        string configurationSectionName,
        Action<MailKitClientSettings>? configureSettings,
        string connectionName,
        object? serviceKey)
    {
        ArgumentNullException.ThrowIfNull(builder);

        var settings = new MailKitClientSettings();

        builder.Configuration
               .GetSection(configurationSectionName)
               .Bind(settings);

        if (builder.Configuration.GetConnectionString(connectionName) is string connectionString)
        {
            settings.ParseConnectionString(connectionString);
        }

        configureSettings?.Invoke(settings);

        if (serviceKey is null)
        {
            builder.Services.AddScoped(CreateMailKitClientFactory);
        }
        else
        {
            builder.Services.AddKeyedScoped(serviceKey, (sp, key) => CreateMailKitClientFactory(sp));
        }

        MailKitClientFactory CreateMailKitClientFactory(IServiceProvider _)
        {
            return new MailKitClientFactory(settings);
        }

        if (settings.DisableHealthChecks is false)
        {
            builder.Services.AddHealthChecks()
                .AddCheck<MailKitHealthCheck>(
                    name: serviceKey is null ? "MailKit" : $"MailKit_{connectionName}",
                    failureStatus: default,
                    tags: []);
        }

        if (settings.DisableTracing is false)
        {
            builder.Services.AddOpenTelemetry()
                .WithTracing(
                    traceBuilder => traceBuilder.AddSource(
                        Telemetry.SmtpClient.ActivitySourceName));
        }

        if (settings.DisableMetrics is false)
        {
            // Required by MailKit to enable metrics
            Telemetry.SmtpClient.Configure();

            builder.Services.AddOpenTelemetry()
                .WithMetrics(
                    metricsBuilder => metricsBuilder.AddMeter(
                        Telemetry.SmtpClient.MeterName));
        }
    }
}

Powyższy kod dodaje dwie metody rozszerzenia dla typu IHostApplicationBuilder, jedną dla standardowej rejestracji MailKit, a drugą dla rejestracji z kluczem MailKit.

Napiwek

Metody rozszerzeń integracji .NET.NET Aspire powinny rozszerzać typ IHostApplicationBuilder i stosować konwencję nazewnictwa Add<MeaningfulName>, gdzie <MeaningfulName> jest typem lub funkcją, którą dodajesz. W tym artykule metoda rozszerzenia AddMailKitClient służy do dodania MailKit client. Jest to prawdopodobnie bardziej zgodne z oficjalnymi wskazówkami dotyczącymi używania AddMailKitSmtpClient zamiast AddMailKitClient, ponieważ powoduje to zarejestrowanie tylko SmtpClient, a nie całej biblioteki MailKit.

Oba rozszerzenia ostatecznie polegają na prywatnej metodzie AddMailKitClient do rejestrowania MailKitClientFactory z kontenerem wstrzykiwania zależności jako usługa o określonym zakresie. Przyczyną zarejestrowania MailKitClientFactory jako usługi o określonym zakresie jest to, że operacje połączenia są uznawane za kosztowne i powinny być ponownie używane w tym samym zakresie, jeśli to możliwe. Innymi słowy w przypadku pojedynczego żądania należy użyć tego samego wystąpienia ISmtpClient. Fabryka utrzymuje instancję SmtpClient, którą tworzy, i usuwa ją.

Powiązanie konfiguracji

Jedną z pierwszych czynności, które wykonuje prywatna implementacja metod AddMailKitClient, jest powiązanie ustawień konfiguracji z klasą MailKitClientSettings. Klasa ustawień jest tworzona, a następnie Bind jest wywoływany z określoną sekcją konfiguracji. Następnie opcjonalny delegat configureSettings jest wywoływany z bieżącymi ustawieniami. Dzięki temu użytkownik może dodatkowo skonfigurować ustawienia, zapewniając, że ustawienia kodu ręcznego mają pierwszeństwo przed ustawieniami konfiguracji. Następnie, w zależności od tego, czy podano wartość serviceKey, MailKitClientFactory należy zarejestrować w kontenerze iniekcji zależności jako standardowej lub kluczowanej usługi.

Ważny

Celowe jest wywołanie przeciążenia implementationFactory podczas rejestrowania usług. Metoda CreateMailKitClientFactory zgłasza błąd, gdy konfiguracja jest nieprawidłowa. Dzięki temu tworzenie MailKitClientFactory zostanie odroczone, dopóki nie będzie potrzebne, a aplikacja nie spowoduje błędu, zanim rejestrowanie będzie dostępne.

Rejestracja kontroli kondycji i telemetrii została opisana nieco bardziej szczegółowo w poniższych sekcjach.

Dodawanie kontroli kondycji

Kontrola zdrowia to sposób monitorowania zdrowia integracji. Za pomocą MailKit możesz sprawdzić, czy połączenie SMTP z server jest prawidłowe. Dodaj następujący kod do projektu MailKit.Client w pliku o nazwie MailKitHealthCheck.cs:

using Microsoft.Extensions.Diagnostics.HealthChecks;

namespace MailKit.Client;

internal sealed class MailKitHealthCheck(MailKitClientFactory factory) : IHealthCheck
{
    public async Task<HealthCheckResult> CheckHealthAsync(
        HealthCheckContext context,
        CancellationToken cancellationToken = default)
    {
        try
        {
            // The factory connects (and authenticates).
            _ = await factory.GetSmtpClientAsync(cancellationToken);

            return HealthCheckResult.Healthy();
        }
        catch (Exception ex)
        {
            return HealthCheckResult.Unhealthy(exception: ex);
        }
    }
}

Poprzednia implementacja kontroli kondycji:

  • Implementuje interfejs IHealthCheck.
  • Akceptuje MailKitClientFactory jako podstawowy parametr konstruktora.
  • Spełnia metodę CheckHealthAsync poprzez:
    • Próba pobrania wystąpienia ISmtpClient z factory. Jeśli operacja powiedzie się, zwraca wartość HealthCheckResult.Healthy.
    • Jeśli zgłaszany jest wyjątek, zwraca HealthCheckResult.Unhealthy.

Jak wcześniej wskazano w rejestracji MailKitClientFactory, MailKitHealthCheck jest warunkowo zarejestrowany wraz z IHeathChecksBuilder:

if (settings.DisableHealthChecks is false)
{
    builder.Services.AddHealthChecks()
        .AddCheck<MailKitHealthCheck>(
            name: serviceKey is null ? "MailKit" : $"MailKit_{connectionName}",
            failureStatus: default,
            tags: []);
}

Użytkownik może pominąć kontrole kondycji, ustawiając właściwość DisableHealthChecks na true w konfiguracji. Typowym wzorcem dla integracji jest posiadanie opcjonalnych funkcji, a .NET.NET Aspire integracje zdecydowanie wspierają tego rodzaju konfiguracje. Aby uzyskać więcej informacji na temat kontroli kondycji i działającego przykładu zawierającego interfejs użytkownika, zobacz .NET AspireASP.NET Core HealthChecksUI sample.

Podłącz telemetrykę

Najlepszym rozwiązaniem jest to, że biblioteka MailKit client uwidacznia dane telemetryczne. .NET .NET Aspire mogą korzystać z tych danych telemetrycznych i wyświetlać je na pulpicie nawigacyjnym .NET.NET Aspire. W zależności od tego, czy śledzenie i metryki są włączone, dane telemetryczne są skonfigurowane, jak pokazano w poniższym fragmencie kodu.

if (settings.DisableTracing is false)
{
    builder.Services.AddOpenTelemetry()
        .WithTracing(
            traceBuilder => traceBuilder.AddSource(
                Telemetry.SmtpClient.ActivitySourceName));
}

if (settings.DisableMetrics is false)
{
    // Required by MailKit to enable metrics
    Telemetry.SmtpClient.Configure();

    builder.Services.AddOpenTelemetry()
        .WithMetrics(
            metricsBuilder => metricsBuilder.AddMeter(
                Telemetry.SmtpClient.MeterName));
}

Aktualizowanie usługi biuletynu

Po utworzeniu biblioteki integracji możesz teraz zaktualizować usługę Biuletyn, aby użyć biblioteki MailKit client. Pierwszym krokiem jest dodanie odwołania do projektu MailKit.Client. Dodaj odwołanie do projektu MailKit.Client.csproj do projektu MailDevResource.NewsletterService:

dotnet add ./MailDevResource.NewsletterService/MailDevResource.NewsletterService.csproj reference MailKit.Client/MailKit.Client.csproj

Następnie dodaj odwołanie do projektu ServiceDefaults:

dotnet add ./MailDevResource.NewsletterService/MailDevResource.NewsletterService.csproj reference MailDevResource.ServiceDefaults/MailDevResource.ServiceDefaults.csproj

Ostatnim krokiem jest zastąpienie istniejącego pliku Program.cs w projekcie MailDevResource.NewsletterService następującym kodem w języku C#:

using System.Net.Mail;
using MailKit.Client;
using MailKit.Net.Smtp;
using MimeKit;

var builder = WebApplication.CreateBuilder(args);

builder.AddServiceDefaults();

builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

// Add services to the container.
builder.AddMailKitClient("maildev");

var app = builder.Build();

app.MapDefaultEndpoints();

// Configure the HTTP request pipeline.

app.UseSwagger();
app.UseSwaggerUI();
app.UseHttpsRedirection();

app.MapPost("/subscribe",
    async (MailKitClientFactory factory, string email) =>
{
    ISmtpClient client = await factory.GetSmtpClientAsync();

    using var message = new MailMessage("newsletter@yourcompany.com", email)
    {
        Subject = "Welcome to our newsletter!",
        Body = "Thank you for subscribing to our newsletter!"
    };

    await client.SendAsync(MimeMessage.CreateFromMailMessage(message));
});

app.MapPost("/unsubscribe",
    async (MailKitClientFactory factory, string email) =>
{
    ISmtpClient client = await factory.GetSmtpClientAsync();

    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 client.SendAsync(MimeMessage.CreateFromMailMessage(message));
});

app.Run();

Najbardziej istotne zmiany w poprzednim kodzie to:

  • Zaktualizowane instrukcje using zawierające przestrzenie nazw MailKit.Client, MailKit.Net.Smtpi MimeKit.
  • Zastąpienie rejestracji oficjalnej .NETSmtpClient przez wywołanie metody rozszerzenia AddMailKitClient.
  • Zastąpienie zarówno wywołań post mapowań /subscribe i /unsubscribe poprzez wstrzyknięcie MailKitClientFactory oraz użycie instancji ISmtpClient do wysłania wiadomości e-mail.

Uruchamianie przykładu

Teraz, gdy utworzyłeś integrację MailKit client i zaktualizowałeś usługę Newsletter, aby ją używać, możesz uruchomić przykład. W środowisku IDE wybierz pozycję F5 lub uruchom dotnet run z katalogu głównego rozwiązania, aby uruchomić aplikację — powinien zostać wyświetlony pulpit nawigacyjny .NET.NET Aspire:

Panel sterowania .NET Aspire: zasoby MailDev i biuletynu uruchomione.

Po uruchomieniu aplikacji przejdź do interfejsu użytkownika Swagger w https://localhost:7251/swagger i przetestuj punkty końcowe /subscribe i /unsubscribe. Wybierz strzałkę w dół, aby rozwinąć punkt końcowy:

Interfejs Swagger UI: subskrybuj punkt końcowy.

Następnie wybierz przycisk Try it out. Wprowadź adres e-mail, a następnie wybierz przycisk Execute.

Swagger UI: Subskrypcja punktu końcowego za pomocą adresu e-mail.

Powtórz to kilka razy, aby dodać wiele adresów e-mail. Powinna zostać wyświetlona wiadomość e-mail wysłana do skrzynki odbiorczej MailDev:

MailDev skrzynka odbiorcza z wieloma e-mailami.

Zatrzymaj aplikację, wybierając Ctrl+C w oknie terminalu, w którym aplikacja jest uruchomiona, lub wybierając przycisk Zatrzymaj w środowisku IDE.

Wyświetlanie telemetrii zestawu MailKit

Biblioteka client MailKit uwidacznia dane telemetryczne, które można wyświetlić na pulpicie nawigacyjnym .NET Aspire. Aby wyświetlić dane telemetryczne, przejdź do pulpitu nawigacyjnego .NET.NET Aspire pod adresem https://localhost:7251. Wybierz zasób newsletter, aby wyświetlić dane telemetryczne na stronie Metrics:

.NET.NET Aspire pulpit nawigacyjny: telemetria MailKit.

Otwórz ponownie interfejs Swagger UI i wykonaj kilka żądań do punktów końcowych /subscribe i /unsubscribe. Następnie wróć do pulpitu nawigacyjnego .NET.NET Aspire i wybierz zasób newsletter. Wybierz metrykę w węźle mailkit.net.smtp, na przykład mailkit.net.smtp.client.operation.count. Powinny zostać wyświetlone dane telemetryczne zestawu MailKit client:

.NET.NET Aspire pulpicie nawigacyjnym: telemetria MailKit dla liczby operacji.

Streszczenie

W tym artykule przedstawiono sposób tworzenia integracji .NET.NET Aspire, która używa biblioteki MailKit do wysyłania wiadomości e-mail. Pokazano również, jak zintegrować tę integrację z utworzoną wcześniej aplikacją Biuletyn. Poznaliśmy podstawowe zasady integracji .NET Aspire, takie jak uwidacznianie podstawowej biblioteki client użytkownikom za pomocą wstrzykiwania zależności oraz sposób dodawania kontroli kondycji i telemetrii do integracji. Pokazano również, jak zaktualizować usługę Biuletyn w celu korzystania z zestawu MailKit client.

Przejdź dalej i utwórz własne integracje .NET.NET Aspire. Jeśli uważasz, że integracja, którą tworzysz, ma wystarczającą wartość dla społeczności, rozważ opublikowanie jej jako pakiet NuGet dla innych użytkowników. Ponadto rozważ przesłanie pull requesta do repozytorium .NET AspireGitHub, aby został on uwzględniony w oficjalnych integracjach .NET.NET Aspire.

Następne kroki