.NET Aspire 13.1 : orchestration cloud-native avec sucre C#
Quand une application moderne grandit, elle se fragmente : une API REST, une base PostgreSQL, un cache Redis, une file de messages RabbitMQ, un worker en arrière-plan, un frontend SPA, peut-être un service Python pour le ML. Faire tourner tout ça localement devient un casse-tête de docker-compose, scripts bash et fichiers .env. .NET Aspire est la réponse de Microsoft à ce chaos. Sorti en GA en mai 2024, il atteint en décembre 2025 la version 13.1, dont les notes officielles publiées sur aspire.dev confirment la dépendance au SDK .NET 10 et l’intégration native d’outils MCP (Model Context Protocol) pour les assistants IA.
Cette série pratique vous fait construire une application multi-services depuis une page blanche : un projet AppHost, une API ASP.NET Core, une base PostgreSQL, un cache Redis, et un dashboard de télémétrie unifié. Chaque étape vous montre concrètement pourquoi Aspire change la productivité d’une équipe backend par rapport à l’approche docker-compose manuelle.
Étape 1 : Installer le SDK .NET 10 et le template Aspire
Le préalable absolu est le SDK .NET 10. Vérifiez :
dotnet --version # doit afficher 10.0.x
Installez ensuite les templates Aspire :
dotnet new install Aspire.ProjectTemplates
Aspire requiert également un runtime de conteneur compatible OCI : Docker Desktop, Podman, ou Rancher Desktop. Sur Linux, Docker Engine suffit. Vérifiez avec docker info qu’un démon écoute. La CLI aspire, séparée du SDK depuis Aspire 9, s’installe via :
dotnet tool install --global Aspire.Cli
Signal de réussite : aspire --version retourne 13.1.x et dotnet new list aspire liste les templates aspire-starter, aspire-apphost, aspire-servicedefaults, et aspire-ts-cs-starter (nouveau en 13.1 pour les frontends TypeScript/React).
Étape 2 : Générer une solution Aspire complète
Créez un projet de démarrage prêt à l’emploi :
dotnet new aspire-starter -n CommerceApp
cd CommerceApp
dotnet run --project CommerceApp.AppHost
Le template crée quatre projets dans une seule solution. Le projet CommerceApp.AppHost est l’orchestrateur — c’est lui qui décrit la topologie en code C#. Le projet CommerceApp.ServiceDefaults contient les configurations partagées : OpenTelemetry, health checks, service discovery. Le projet CommerceApp.ApiService est une Minimal API d’exemple. Le projet CommerceApp.Web est un frontend Blazor qui consomme l’API. Au démarrage, Aspire ouvre automatiquement le navigateur sur le dashboard, généralement à l’adresse https://localhost:17040. Signal de réussite : le dashboard affiche les quatre ressources avec un statut « Running » vert et des logs en temps réel.
Étape 3 : Comprendre le rôle de l’AppHost
Ouvrez CommerceApp.AppHost/Program.cs. Le code typique est :
var builder = DistributedApplication.CreateBuilder(args);
var apiService = builder.AddProject<Projects.CommerceApp_ApiService>("apiservice");
builder.AddProject<Projects.CommerceApp_Web>("webfrontend")
.WithExternalHttpEndpoints()
.WithReference(apiService);
builder.Build().Run();
Ce fichier C# est l’unique source de vérité de votre topologie. La méthode AddProject enregistre un projet .NET comme ressource. WithReference propage les informations de service discovery : à l’exécution, l’API frontend reçoit dans son IConfiguration l’URL effective de l’API service (par exemple http://localhost:5443). Plus de configuration en dur, plus de .env qui dérive. Si vous renommez le projet, IntelliSense corrige automatiquement. Signal de réussite : le projet web peut appeler builder.Services.AddHttpClient<ApiClient>(c => c.BaseAddress = new Uri("http+https://apiservice")) sans aucune URL en dur, et l’appel fonctionne immédiatement.
Étape 4 : Ajouter une base PostgreSQL avec Aspire
Installez l’intégration PostgreSQL dans le projet AppHost :
dotnet add CommerceApp.AppHost package Aspire.Hosting.PostgreSQL
Modifiez l’AppHost pour ajouter la ressource :
var postgres = builder.AddPostgres("postgres")
.WithDataVolume()
.WithPgAdmin();
var commerceDb = postgres.AddDatabase("commercedb");
var apiService = builder.AddProject<Projects.CommerceApp_ApiService>("apiservice")
.WithReference(commerceDb);
L’appel AddPostgres télécharge l’image officielle PostgreSQL à la première exécution et la lance dans un conteneur. WithDataVolume attache un volume persistant pour conserver les données entre redémarrages. WithPgAdmin ajoute un conteneur supplémentaire avec l’interface d’administration pgAdmin, accessible depuis le dashboard Aspire. La chaîne de connexion est injectée automatiquement dans l’API service via builder.AddNpgsqlDataSource("commercedb") dans son Program.cs. Signal de réussite : le dashboard affiche deux nouvelles ressources (postgres, pgadmin) avec leurs logs, et l’API peut exécuter SELECT now() sans aucune configuration manuelle.
Étape 5 : Ajouter Redis pour le cache de session
Même approche :
dotnet add CommerceApp.AppHost package Aspire.Hosting.Redis
var redis = builder.AddRedis("cache").WithRedisCommander();
var apiService = builder.AddProject<Projects.CommerceApp_ApiService>("apiservice")
.WithReference(commerceDb)
.WithReference(redis);
WithRedisCommander lance le UI web Redis Commander dans un conteneur additionnel. Côté API, dans CommerceApp.ApiService/Program.cs, ajoutez :
builder.AddRedisDistributedCache("cache");
Désormais IDistributedCache est injectable partout dans l’API et écrit vers Redis transparente. Signal de réussite : visualiser dans Redis Commander les clés écrites par l’API en temps réel, par exemple un cache.SetString("session:abc", "...") apparaît immédiatement dans l’UI.
Étape 6 : Le dashboard, votre console d’observabilité unifiée
Le dashboard Aspire est l’aspect le plus visible et le plus apprécié du framework. Il regroupe en une seule interface : logs structurés de chaque ressource (avec recherche et filtre par niveau), traces OpenTelemetry distribuées (un span par appel HTTP, base, file de messages), métriques exposées par Prometheus instrumentées par les ServiceDefaults, et console interactive pour redémarrer une ressource. Aspire 13.1 ajoute un onglet « Parameters » dédié à la configuration des ressources et un « GenAI visualizer » qui affiche les invocations d’API LLM avec multimedia preview.
Cliquez sur une trace dans l’onglet Traces : vous voyez le flow complet d’une requête, depuis le clic dans le navigateur jusqu’à la requête SQL effective, avec les durées de chaque étape. Sur un bug de latence en production, c’est l’outil qui détecte en quelques secondes la requête N+1 qui sature la base. Signal de réussite : provoquer un appel API depuis le frontend, le retrouver dans l’onglet Traces en moins de cinq secondes, et identifier le span correspondant à la requête PostgreSQL avec sa durée exacte.
Étape 7 : Service Discovery et HTTP+HTTPS
Aspire introduit le pseudo-schéma http+https://nom-ressource compris par HttpClient. Au moment d’envoyer la requête, Aspire résout dynamiquement l’URL réelle en fonction de l’environnement et préfère HTTPS si disponible :
builder.Services.AddHttpClient<ProduitsClient>(client =>
{
client.BaseAddress = new Uri("http+https://apiservice");
});
En développement local, la résolution pointe vers https://localhost:7080 ou similaire ; en déploiement Kubernetes via la cible aspire-publish, elle pointe vers le DNS interne du Service. Aucun changement de code requis. Cette indirection élimine la classique appsettings.Production.json avec ses URLs en dur. Signal de réussite : exporter votre déploiement en YAML Kubernetes (aspire publish --publisher kubernetes) génère automatiquement des objets Service et Deployment correctement reliés.
Étape 8 : Déployer en production sur Kubernetes ou Azure
Aspire 13.1 sait générer plusieurs cibles de déploiement. Pour Azure Container Apps :
aspire publish --publisher azure
La commande produit un manifeste aspire-manifest.json consommable par les outils Azure (Bicep, Azure Developer CLI). Pour Kubernetes générique :
aspire publish --publisher kubernetes -o ./k8s
Le dossier ./k8s contient un ensemble de manifestes YAML : Deployments, Services, Secrets, ConfigMaps. Vous pouvez les appliquer tels quels avec kubectl apply -f ./k8s, ou les intégrer dans votre pipeline GitOps (ArgoCD, FluxCD). Aspire 13.1 stabilise par ailleurs le support DevTunnels qui exposait précédemment vos services locaux à internet pour debugging — utile pour tester un webhook Stripe sans déployer. Signal de réussite : kubectl get pods sur le cluster cible montre tous les pods Running dans les deux minutes suivant le kubectl apply.
Étape 9 : Intégration des assistants IA via MCP
La nouveauté la plus stratégique d’Aspire 13.1 est la commande aspire agent init et l’exposition d’outils MCP (Model Context Protocol). MCP est un standard ouvert, soutenu par Anthropic et Microsoft, qui permet à un assistant IA (Claude, Copilot, Cursor) de découvrir et d’invoquer des outils d’une application. Initialisez :
aspire agent init
La commande génère une configuration dans .aspire/agent.json et expose les ressources Aspire comme des outils MCP. Un assistant IA branché peut alors : « lister les ressources actives », « relancer le service Redis », « interroger les dernières traces du service web ». Pour les équipes qui automatisent leur workflow de développement, c’est un gain de productivité significatif. Signal de réussite : Claude Desktop configuré avec votre fichier MCP voit apparaître les ressources Aspire dans son sélecteur d’outils, et peut répondre à « combien de requêtes a traité l’API au cours de la dernière minute ? » en interrogeant les métriques OpenTelemetry exposées.
Pourquoi Aspire change la donne pour les équipes
Aspire ne réinvente pas Docker Compose ; il l’enveloppe dans du C# fortement typé, ajoute un dashboard d’observabilité partagé, et industrialise le service discovery et la configuration. L’effet net pour une équipe : un nouveau développeur clone le repo, lance dotnet run --project AppHost, et son poste a une stack complète opérationnelle en moins de cinq minutes — sans tâches manuelles d’export de variables, copie de docker-compose ou ouverture de ports. La courbe d’adoption en startup est rapide ; en grande entreprise, l’argument décisif est la traçabilité OpenTelemetry de bout en bout. Si vous bâtissez aujourd’hui une nouvelle application backend en .NET 10 et qu’elle dépasse trois processus, Aspire vous fera gagner des jours sur la durée d’un projet.