Delen via


Aangepaste resource-opdrachten in .NET.NET Aspire

Elke resource in het .NET.NET Aspireapp-model wordt weergegeven als een IResource en wanneer deze wordt toegevoegd aan de gedistribueerde toepassingsbouwer, is dit de algemene parameter van de IResourceBuilder<T>-interface. U gebruikt de hulpbronbouwer API om aanroepen te koppelen, de onderliggende hulpbron te configureren, en in sommige situaties wilt u misschien aangepaste opdrachten toevoegen aan de hulpbron. Sommige veelvoorkomende scenario's voor het maken van een aangepaste opdracht kunnen databasemigraties uitvoeren of een database seeden/opnieuw instellen. In dit artikel leert u hoe u een aangepaste opdracht toevoegt aan een Redis resource waarmee de cache wordt gewist.

Belangrijk

Deze .NET.NET Aspire dashboard opdrachten zijn alleen beschikbaar wanneer het dashboard lokaal wordt uitgevoerd. Ze zijn niet beschikbaar bij het uitvoeren van het dashboard in Azure Container Apps.

Aangepaste opdrachten toevoegen aan een resource

Begin met het maken van een nieuwe .NET.NET Aspire Starter-app op basis van de beschikbare sjablonen. Als u de oplossing op basis van deze sjabloon wilt maken, volgt u de Quickstart: Uw eerste .NET.NET Aspire-oplossing bouwen. Nadat u deze oplossing hebt gemaakt, voegt u een nieuwe klasse met de naam RedisResourceBuilderExtensions.cs toe aan het app-hostproject. Vervang de inhoud van het bestand door de volgende code:

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

De voorgaande code:

  • Deelt de Aspire.Hosting naamruimte zodat deze zichtbaar is voor het app-hostproject.
  • Is een static class zodat hij uitbreidingsmethoden kan bevatten.
  • Hiermee definieert u één extensiemethode met de naam WithClearCommand, waarmee de IResourceBuilder<RedisResource>-interface wordt uitgebreid.
  • De methode WithClearCommand registreert een opdracht met de naam clear-cache waarmee de cache van de Redis-resource wordt gewist.
  • De methode WithClearCommand geeft het IResourceBuilder<RedisResource> exemplaar terug, waardoor methodenketting mogelijk is.

De WithCommand-API voegt de juiste aantekeningen toe aan de resource, die worden gebruikt in het .NET.NET Aspire dashboard. Het dashboard gebruikt deze aantekeningen om de opdracht weer te geven in de gebruikersinterface. Voordat u deze details te ver gaat, moet u ervoor zorgen dat u eerst de parameters van de methode WithCommand begrijpt:

  • name: de naam van de opdracht die moet worden aangeroepen.
  • displayName: de naam van de opdracht die moet worden weergegeven in het dashboard.
  • executeCommand: de Func<ExecuteCommandContext, Task<ExecuteCommandResult>> die moet worden uitgevoerd wanneer de opdracht wordt aangeroepen, waar de opdrachtlogica wordt geïmplementeerd.
  • updateState: de Func<UpdateCommandStateContext, ResourceCommandState> callback wordt aangeroepen om de status Ingeschakeld van de opdracht te bepalen, die wordt gebruikt om de opdracht in of uit te schakelen in het dashboard.
  • iconName: de naam van het pictogram dat moet worden weergegeven in het dashboard. Het pictogram is optioneel, maar wanneer u het opgeeft, moet het een geldige Fluent UI zijn Blazor pictogramnaam.
  • iconVariant: de variant van het pictogram dat in het dashboard moet worden weergegeven, zijn geldige opties Regular (standaard) of Filled.

Opdrachtlogica uitvoeren

De executeCommand delegate is waar de commando-logica wordt geïmplementeerd. Deze parameter wordt gedefinieerd als een Func<ExecuteCommandContext, Task<ExecuteCommandResult>>. De ExecuteCommandContext biedt de volgende eigenschappen:

  • ExecuteCommandContext.ServiceProvider: het IServiceProvider exemplaar dat wordt gebruikt om services op te lossen.
  • ExecuteCommandContext.ResourceName: de naam van het resource-exemplaar waarop de opdracht wordt uitgevoerd.
  • ExecuteCommandContext.CancellationToken: de CancellationToken die wordt gebruikt om de uitvoering van de opdracht te annuleren.

In het vorige voorbeeld wordt de executeCommand delegate geïmplementeerd als een async methode waarmee de cache van de Redis bron wordt gewist. Het delegeert naar een privé-functie binnen de klasse met de naam OnRunClearCacheCommandAsync om de werkelijke cache-opruiming uit te voeren. Houd rekening met de volgende code:

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

De voorgaande code:

  • Haalt de verbindingsreeks op uit de Redis resource.
  • Maakt verbinding met het Redis-exemplaar.
  • Hiermee haalt u het database-exemplaar op.
  • Hiermee wordt de opdracht FLUSHALL uitgevoerd om de cache te wissen.
  • Retourneert een CommandResults.Success() exemplaar om aan te geven dat de opdracht is geslaagd.

Opdrachtstatuslogica bijwerken

De updateState-delegaat is de plaats waar de opdrachtstatus wordt bepaald. Deze parameter wordt gedefinieerd als een Func<UpdateCommandStateContext, ResourceCommandState>. De UpdateCommandStateContext biedt de volgende eigenschappen:

  • UpdateCommandStateContext.ServiceProvider: het IServiceProvider exemplaar dat wordt gebruikt om services op te lossen.
  • UpdateCommandStateContext.ResourceSnapshot: de momentopname van het resource-exemplaar waarop de opdracht wordt uitgevoerd.

De onveranderbare momentopname is een exemplaar van CustomResourceSnapshot, waarmee allerlei waardevolle details over het resource-exemplaar worden weergegeven. Houd rekening met de volgende code:

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

De voorgaande code:

  • Haalt de logger-instantie van de serviceprovider op.
  • Registreert de details van de momentopname van de resource.
  • Retourneert ResourceCommandState.Enabled als de resource in orde is; anders wordt ResourceCommandState.Disabledgeretourneerd.

De aangepaste opdracht testen

Als u de aangepaste opdracht wilt testen, werkt u het Program.cs-bestand van uw app-hostproject bij met de volgende code:

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

Met de voorgaande code wordt de WithClearCommand-extensiemethode aangeroepen om de aangepaste opdracht toe te voegen aan de Redis resource. Voer de app uit en navigeer naar het .NET.NET Aspire dashboard. De aangepaste opdracht wordt weergegeven onder de Redis resource. Selecteer op de pagina Resources van het dashboard het beletselteken onder de kolom Acties:

.NET Aspire dashboard: Redis cacheresource met aangepaste opdracht weergegeven.

In de voorgaande afbeelding ziet u de opdracht Cache wissen die is toegevoegd aan de Redis-resource. Het pictogram toont een doorgekruist konijn, wat aangeeft dat de snelheid van de afhankelijke bron wordt gewist.

Selecteer de opdracht Cache wissen om de cache van het Redis hulpmiddel te wissen. De opdracht moet worden uitgevoerd en de cache moet worden gewist:

.NET Aspire dashboard: Redis cacheresource met aangepaste opdracht uitgevoerd.

Zie ook