Procedura per far girare un'applicazione .NET fatta di due servizi, vederli nel pannello di Aspire con log, tracce e metriche, e aggiungere una cache in un container cambiando due righe. Gira tutto sul computer: non serve un account cloud.

Occorre: .NET 10 sul computer, un browser, e Docker Desktop (o Podman) dal nono passo in poi. Durata: circa quindici minuti. Costo: nessuno.

Il pannello è tradotto in dodici lingue e segue quella del browser. Le schermate qui sono in inglese: i nomi dei comandi sono riportati come appaiono a schermo.

Preparare l'applicazione

1. Installa l'interfaccia a riga di comando

dotnet tool install --global aspire.cli

Se è già installata, dotnet tool update --global aspire.cli. Controlla la versione:

aspire --version
13.6.4+c89352703f78ae46de90fbf751ed8b52b77b89bf

2. Crea l'applicazione

aspire new aspire-starter --name HelloAspire --suppress-agent-init

Il comando chiede Use *.dev.localhost URLs [y/N]:; premendo Invio risponde di no e i servizi restano su localhost con una porta ciascuno, come nelle schermate che seguono.

Searching for available project template versions...
🧊 Getting templates...
📦 Using project templates version: 13.6.4
🚀 Creating new Aspire project...
✅ Project created successfully in D:\_guide-aspire\HelloAspire.

Senza --suppress-agent-init il comando cerca gli assistenti di programmazione installati e scrive nella loro configurazione un aggancio di telemetria, dicendolo in una riga sola: Installed Aspire agent telemetry hooks for: GitHub Copilot CLI, Claude Code. L'aggancio resta lì anche dopo aver cancellato il progetto, e va tolto a mano dal file di configurazione dell'assistente.

Scritto senza argomenti, aspire new fa scegliere il modello da un elenco: ASP.NET Core con Blazor, ASP.NET Core con React, Express con React, FastAPI con React, o un AppHost vuoto.

Il modello crea quattro progetti:

  • HelloAspire.AppHost: descrive l'applicazione, cioè di quali pezzi è fatta e come si collegano;
  • HelloAspire.ServiceDefaults: telemetria, controlli di salute e tentativi ripetuti, condivisi dagli altri progetti;
  • HelloAspire.ApiService: un'API che restituisce cinque previsioni del tempo;
  • HelloAspire.Web: un sito Blazor che chiama l'API.

3. Leggi l'AppHost

HelloAspire.AppHost/AppHost.cs è il file che descrive l'applicazione, ed è lungo undici righe:

var builder = DistributedApplication.CreateBuilder(args);

var apiService = builder.AddProject<Projects.HelloAspire_ApiService>("apiservice")
    .WithHttpHealthCheck("/health");

builder.AddProject<Projects.HelloAspire_Web>("webfrontend")
    .WithExternalHttpEndpoints()
    .WithHttpHealthCheck("/health")
    .WithReference(apiService)
    .WaitFor(apiService);

builder.Build().Run();

AddProject registra un progetto come risorsa e gli dà un nome. WithReference(apiService) passa al sito l'indirizzo dell'API, WaitFor(apiService) fa partire il sito solo dopo. Nel codice del sito l'indirizzo dell'API non compare: c'è il nome.

client.BaseAddress = new("https+http://apiservice");

4. Avvia

Dalla cartella HelloAspire:

aspire run
Building AppHost... HelloAspire.AppHost\HelloAspire.AppHost.csproj
Connecting to AppHost...
Starting dashboard...

  AppHost:  HelloAspire.AppHost\HelloAspire.AppHost.csproj
Dashboard:  https://localhost:17058/login?t=918beb4a438b514c63a14f799859fe68
     Logs:  C:\Users\lauri\.aspire\logs\cli_20261106T073344_de6c3600.log

Press CTRL+C to stop the AppHost and exit.

L'indirizzo del pannello finisce con un codice: senza quello il pannello non si apre, e il codice cambia a ogni avvio. Aprendolo si vedono le due risorse.

L'elenco delle risorse nel pannello di Aspire

Per ogni risorsa ci sono lo stato, l'ora di avvio, il progetto di origine e gli indirizzi: due per servizio, uno in HTTPS e uno in HTTP.

5. Apri l'applicazione

Premi l'indirizzo di webfrontend, https://localhost:7212, e nel menu a sinistra scegli Weather.

La pagina Weather del sito, con la tabella delle previsioni

La tabella non è nel sito: è la risposta dell'API, chiesta a https+http://apiservice.

6. Guarda i log

Nel pannello, seconda icona della colonna a sinistra: Console logs.

I log delle risorse, con l'etichetta di chi ha scritto ogni riga

Ogni riga porta l'etichetta della risorsa che l'ha scritta. Fra quelle di webfrontend si legge la chiamata appena fatta, prima con il nome e poi con l'indirizzo vero:

Start processing HTTP request GET https+http://apiservice/weatherforecast
Sending HTTP request GET https://localhost:7331/weatherforecast
Received HTTP response headers after 35.0304ms - 200

7. Guarda le tracce

Quarta icona: Traces.

L'elenco delle tracce, con gli spezzoni per risorsa

La riga webfrontend: GET /weather è l'unica con due colori: webfrontend (2) e apiservice (1). Premila.

Il dettaglio della traccia, con i tre spezzoni in ordine

La richiesta ha attraversato due risorse e tre spezzoni: la pagina del sito, la chiamata HTTP verso l'API (33,83 ms) e il lavoro dell'API (5,73 ms). Nessuna riga di codice è stata scritta per ottenerlo: la telemetria arriva da ServiceDefaults, che tutti i progetti richiamano.

8. Guarda le metriche

Quinta icona: Metrics. In Resource scegli apiservice, poi http.server.request.duration.

Il grafico della durata delle richieste dell'API

Il grafico riporta la mediana, il novantesimo e il novantanovesimo percentile, più i punti delle singole richieste campionate.

Aggiungere una cache

9. Aggiungi Redis all'AppHost

Ferma l'applicazione con Ctrl+C e, dalla cartella HelloAspire:

aspire add redis
Searching for Aspire integrations...
Adding Aspire hosting integration...
✅ The package Aspire.Hosting.Redis::13.6.4 was added successfully.

In AppHost.cs aggiungi la riga della cache e passala al sito:

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

var apiService = builder.AddProject<Projects.HelloAspire_ApiService>("apiservice")
    .WithHttpHealthCheck("/health");

builder.AddProject<Projects.HelloAspire_Web>("webfrontend")
    .WithExternalHttpEndpoints()
    .WithHttpHealthCheck("/health")
    .WithReference(cache)
    .WaitFor(cache)
    .WithReference(apiService)
    .WaitFor(apiService);

10. Usa la cache nel sito

cd HelloAspire.Web
dotnet add package Aspire.StackExchange.Redis.OutputCaching
cd ..

In HelloAspire.Web/Program.cs c'è una cache tenuta in memoria:

builder.Services.AddOutputCache();

Sostituiscila con la cache su Redis:

builder.AddRedisOutputCache("cache");

Il resto non si tocca: app.UseOutputCache() è già nel file, e la pagina Weather porta già l'attributo @attribute [OutputCache(Duration = 5)]. Nel codice del sito non compaiono né l'indirizzo né la password di Redis: arrivano dal nome cache.

11. Riavvia e controlla

aspire run

Le tre risorse, con il container della cache in cima

Le risorse sono tre. cache non è un progetto: è il container docker.io/library/redis:8.6, avviato con una password generata al momento. Se l'immagine non c'è, viene scaricata al primo avvio.

Il bottone Graph, in alto, mostra chi parla con chi.

Il grafo delle tre risorse e dei collegamenti

Per vedere la cache al lavoro, apri https://localhost:7212/weather due volte a meno di cinque secondi di distanza, poi torna in Traces e scrivi GET /weather nel filtro.

Le due richieste a confronto: con l'API e dalla cache

La prima richiesta è durata 0,16 secondi e ha toccato apiservice. La seconda 3,54 millisecondi, senza apiservice: la risposta è uscita dalla cache.

Pulire

12. Ferma tutto

Ctrl+C nel terminale dove gira aspire run: si fermano i due progetti e il container viene rimosso da solo, tanto che docker ps -a non lo trova più.

Fermando invece l'applicazione da un altro terminale con aspire stop, i progetti si chiudono ma il container resta acceso. In quel caso va tolto a mano:

docker ps --filter name=cache- --format "{{.Names}}"
docker rm -f <nome del container>

Comandi, schermate e tempi rilevati il 6 novembre 2026 su Windows 11 con .NET 10.0.401, interfaccia a riga di comando di Aspire 13.6.4 e Docker 29.7.2.