Partager via


Commandes de ressources personnalisées dans .NET.NET Aspire

Chaque ressource du modèle d’application .NET.NET Aspire est représentée sous la forme d’un IResource et lorsqu’elle est ajoutée au générateur d’applications distribué , il s’agit du paramètre de type générique de l’interface IResourceBuilder<T>. Vous utilisez le générateur de ressources API pour chaîner des appels, configurer la ressource sous-jacente et, dans certains cas, vous souhaiterez peut-être ajouter des commandes personnalisées à la ressource. Certains scénarios courants de création d’une commande personnalisée peuvent exécuter des migrations de base de données ou l’amorçage/réinitialisation d’une base de données. Dans cet article, vous allez apprendre à ajouter une commande personnalisée à une ressource Redis qui efface le cache.

Important

Ces .NET.NET Aspire tableau de bord commandes sont disponibles uniquement lors de l’exécution du tableau de bord localement. Ils ne sont pas disponibles lorsque vous utilisez le tableau de bord dans Azure Container Apps.

Ajouter des commandes personnalisées à une ressource

Commencez par créer une application de démarrage .NET.NET Aspire à partir des modèles disponibles . Pour créer la solution à partir de ce modèle, suivez le guide de démarrage rapide : Créez votre première solution .NET.NET Aspire. Après avoir créé cette solution, ajoutez une nouvelle classe nommée RedisResourceBuilderExtensions.cs au projet hôte d’application . Remplacez le contenu du fichier par le code suivant :

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Diagnostics.HealthChecks;
using Microsoft.Extensions.Logging;
using StackExchange.Redis;

namespace Aspire.Hosting;

internal static class RedisResourceBuilderExtensions
{
    public static IResourceBuilder<RedisResource> WithClearCommand(
        this IResourceBuilder<RedisResource> builder)
    {
        builder.WithCommand(
            name: "clear-cache",
            displayName: "Clear Cache",
            executeCommand: context => OnRunClearCacheCommandAsync(builder, context),
            updateState: OnUpdateResourceState,
            iconName: "AnimalRabbitOff",
            iconVariant: IconVariant.Filled);

        return builder;
    }

    private static async Task<ExecuteCommandResult> OnRunClearCacheCommandAsync(
        IResourceBuilder<RedisResource> builder,
        ExecuteCommandContext context)
    {
        var connectionString = await builder.Resource.GetConnectionStringAsync() ??
            throw new InvalidOperationException(
                $"Unable to get the '{context.ResourceName}' connection string.");

        await using var connection = ConnectionMultiplexer.Connect(connectionString);

        var database = connection.GetDatabase();

        await database.ExecuteAsync("FLUSHALL");

        return CommandResults.Success();
    }

    private static ResourceCommandState OnUpdateResourceState(
        UpdateCommandStateContext context)
    {
        var logger = context.ServiceProvider.GetRequiredService<ILogger<Program>>();

        if (logger.IsEnabled(LogLevel.Information))
        {
            logger.LogInformation(
                "Updating resource state: {ResourceSnapshot}",
                context.ResourceSnapshot);
        }

        return context.ResourceSnapshot.HealthStatus is HealthStatus.Healthy
            ? ResourceCommandState.Enabled
            : ResourceCommandState.Disabled;
    }
}

Code précédent :

  • Partage l’espace de noms Aspire.Hosting afin qu’il soit visible pour le projet hôte de l’application.
  • Est une static class afin qu’elle puisse contenir des méthodes d’extension.
  • Il définit une méthode d’extension unique nommée WithClearCommand, étendant l’interface IResourceBuilder<RedisResource>.
  • La méthode WithClearCommand inscrit une commande nommée clear-cache qui efface le cache de la ressource Redis.
  • La méthode WithClearCommand retourne l’instance IResourceBuilder<RedisResource> pour autoriser le chaînage.

L’API WithCommand ajoute les annotations appropriées à la ressource, qui sont consommées dans le tableau de bord .NET.NET Aspire. Le tableau de bord utilise ces annotations pour afficher la commande dans l’interface utilisateur. Avant d’entrer trop loin dans ces détails, nous allons vous assurer que vous comprenez d’abord les paramètres de la méthode WithCommand :

  • name: nom de la commande à appeler.
  • displayName: nom de la commande à afficher dans le tableau de bord.
  • executeCommand: Func<ExecuteCommandContext, Task<ExecuteCommandResult>> à exécuter lorsque la commande est appelée, c’est-à-dire l’emplacement où la logique de commande est implémentée.
  • updateState: le rappel Func<UpdateCommandStateContext, ResourceCommandState> est appelé pour déterminer l’état « activé » de la commande, qui est utilisé pour activer ou désactiver la commande dans le tableau de bord.
  • iconName: nom de l’icône à afficher dans le tableau de bord. L’icône est facultative, mais lorsque vous le fournissez, il doit s’agir d’un nom d’icône Fluent UI Blazor valide.
  • iconVariant: la variante de l’icône à afficher dans le tableau de bord, les options valides sont Regular (par défaut) ou Filled.

Exécuter une logique de commande

Le délégué executeCommand est l’emplacement où la logique de commande est implémentée. Ce paramètre est défini en tant que Func<ExecuteCommandContext, Task<ExecuteCommandResult>>. La ExecuteCommandContext fournit les propriétés suivantes :

  • ExecuteCommandContext.ServiceProvider: instance IServiceProvider utilisée pour résoudre les services.
  • ExecuteCommandContext.ResourceName: nom de l’instance de ressource sur laquelle la commande est exécutée.
  • ExecuteCommandContext.CancellationToken: CancellationToken utilisée pour annuler l’exécution de la commande.

Dans l’exemple précédent, le délégué executeCommand est implémenté en tant que méthode async qui efface le cache de la ressource Redis. Il délègue à une fonction privée définie au niveau de la classe nommée OnRunClearCacheCommandAsync pour effacer le cache. Considérez le code suivant :

private static async Task<ExecuteCommandResult> OnRunClearCacheCommandAsync(
    IResourceBuilder<RedisResource> builder,
    ExecuteCommandContext context)
{
    var connectionString = await builder.Resource.GetConnectionStringAsync() ??
        throw new InvalidOperationException(
            $"Unable to get the '{context.ResourceName}' connection string.");

    await using var connection = ConnectionMultiplexer.Connect(connectionString);

    var database = connection.GetDatabase();

    await database.ExecuteAsync("FLUSHALL");

    return CommandResults.Success();
}

Code précédent :

  • Récupère la chaîne de connexion à partir de la ressource Redis.
  • Se connecte à l’instance Redis.
  • Obtient l’instance de base de données.
  • Exécute la commande FLUSHALL pour effacer le cache.
  • Retourne une instance CommandResults.Success() pour indiquer que la commande a réussi.

Mettre à jour la logique d’état de commande

Le délégué updateState est le lieu où l'état de la commande est déterminé. Ce paramètre est défini en tant que Func<UpdateCommandStateContext, ResourceCommandState>. La UpdateCommandStateContext fournit les propriétés suivantes :

  • UpdateCommandStateContext.ServiceProvider: instance IServiceProvider utilisée pour résoudre les services.
  • UpdateCommandStateContext.ResourceSnapshot: instantané de l’instance de ressource sur laquelle la commande est exécutée.

L’instantané immuable est une instance de CustomResourceSnapshot, qui expose toutes sortes de détails précieux sur l’instance de ressource. Considérez le code suivant :

private static ResourceCommandState OnUpdateResourceState(
    UpdateCommandStateContext context)
{
    var logger = context.ServiceProvider.GetRequiredService<ILogger<Program>>();

    if (logger.IsEnabled(LogLevel.Information))
    {
        logger.LogInformation(
            "Updating resource state: {ResourceSnapshot}",
            context.ResourceSnapshot);
    }

    return context.ResourceSnapshot.HealthStatus is HealthStatus.Healthy
        ? ResourceCommandState.Enabled
        : ResourceCommandState.Disabled;
}

Code précédent :

  • Récupère l'instance du logger depuis le fournisseur de services.
  • Enregistre les détails de l’instantané de ressource.
  • Retourne ResourceCommandState.Enabled si la ressource est saine ; sinon, elle retourne ResourceCommandState.Disabled.

Tester la commande personnalisée

Pour tester la commande personnalisée, mettez à jour le fichier Program.cs du projet hôte d’application pour inclure le code suivant :

var builder = DistributedApplication.CreateBuilder(args);

var cache = builder.AddRedis("cache")
                   .WithClearCommand();

var apiService = builder.AddProject<Projects.AspireApp_ApiService>("apiservice");

builder.AddProject<Projects.AspireApp_Web>("webfrontend")
    .WithExternalHttpEndpoints()
    .WithReference(cache)
    .WaitFor(cache)
    .WithReference(apiService)
    .WaitFor(apiService);

builder.Build().Run();

Le code précédent appelle la méthode d’extension WithClearCommand pour ajouter la commande personnalisée à la ressource Redis. Exécutez l’application et accédez au tableau de bord .NET.NET Aspire. Vous devez voir la commande personnalisée répertoriée sous la ressource Redis. Dans la page Resources du tableau de bord, sélectionnez le bouton de sélection sous la colonne Actions :

.NET Aspire tableau de bord : Redis ressource de cache avec une commande personnalisée affichée.

L’image précédente montre la commande Effacer le cache qui a été ajoutée à la ressource Redis. L’icône s’affiche sous la forme d’un lapin pour indiquer que la vitesse de la ressource dépendante est effacée.

Sélectionnez la commande Effacer le cache pour effacer le cache de la ressource Redis. La commande doit s’exécuter correctement et le cache doit être effacé :

.NET Aspire tableau de bord : Redis ressource de cache avec une commande personnalisée exécutée.

Voir aussi