Since K2 2.9.3, aspire run starts the whole Kladde. Since then the AppHost has grown piece by piece: Azure SQL instead of SQL Server in 3.2.5, Azurite in 3.6.3, the Service Bus emulator in 3.5.2, a topic in 3.5.3, the fetch as a resource of its own in 3.5.7. Every lesson wrote a few lines into it, and each one was right on its own. As a whole, nobody has read it anymore.

This module takes Aspire seriously as what it has become for the Kladde: the one place where it is written down what the application consists of, how the parts fit together, how you test them and how they are delivered.

Lesson What comes out of it h
3.14.1 The app model a tidied AppHost with a parameter and a command of its own in the dashboard 3
3.14.2 Integrations: hosting and client emulators locally, Azure when rolling out, an integration of its own for the TED stub 3
3.14.3 Dashboard and service defaults adapted service defaults that repeat no POST, with a test 3
3.14.4 Testing with Aspire a "booking to notification" test against the started AppHost, in the pipeline 3
3.14.5 Delivering: azd, aspire publish, aspire deploy the decision on the delivery path 2

The module works with Aspire 13.6.5 (packages, SDK and CLI). Since K2, the Kladde has had 13.6.4; raise all Aspire.* packages, the SDK in the AppHost's project file (Aspire.AppHost.Sdk/13.6.5) and the CLI (dotnet tool update --global Aspire.Cli --version 13.6.5) together, in one pull request. Mixed versions often build anyway, but then your tests check a combination that nobody has ever shipped.

A model, not a startup script

AppHost.cs looks like a program that starts things. That's deceptive. Every line with Add… only puts a resource in a model, every line with With… or WaitFor… attaches a detail to it, in Aspire's code an annotation. Things are started only at builder.Build().Run(), and not in the order of the lines but in the one that follows from the dependencies.

The Kladde's resources belong to a few kinds:

Kind Example in the Kladde What Aspire does locally
Project web, worker, migrations, import builds the project and starts it with dotnet
Container sql, the emulators starts an image in Docker or Podman
Azure resource sql, storage, messaging a service in Azure; locally a container if RunAsContainer or RunAsEmulator says so
Child resource kladde (database), tender-import (queue), tenders-raw (blob container) belongs to its parent resource and lives with it
Parameter ted-cpv (new in this lesson) reads a value from the configuration or asks for it

The dashboard shows this model on the Resources page, as a table or as a graph. The CLI delivers the same list. With aspire describe you get it as a table; the version with --format json can be processed further in PowerShell. The first line of the output is a message from the CLI, so the JSON begins only at the first {:

PowerShell
$json = aspire describe --format json | Out-String
($json.Substring($json.IndexOf('{')) | ConvertFrom-Json).resources | Sort-Object displayName | Format-Table displayName, resourceType, state, healthStatus

This is what it looks like for the tidied AppHost at the end of this lesson:

displayName     resourceType                        state      healthStatus
-----------     ------------                        -----      ------------
assessment      AzureServiceBusSubscriptionResource Running    Healthy
blobs           AzureBlobStorageResource            Running    Healthy
contact-import  AzureServiceBusQueueResource        Running    Healthy
import          Project                             NotStarted 
kladde          SqlServerDatabaseResource           Running    Healthy
messaging       AzureServiceBusResource             Running    Healthy
messaging-mssql Container                           Running    Healthy
migrations      Project                             Finished   
notification    AzureServiceBusSubscriptionResource Running    Healthy
offers          AzureBlobStorageContainerResource   Running    Healthy
sql             Container                           Running    Healthy
storage         AzureStorageResource                Running    Healthy
ted-cpv         Parameter                           Running    Healthy
tender-events   AzureServiceBusTopicResource        Running    Healthy
tender-import   AzureServiceBusQueueResource        Running    Healthy
tenders-raw     AzureBlobStorageContainerResource   Running    Healthy
web             Project                             Running    Healthy
worker          Project                             Running    Healthy

Three things stand out. messaging-mssql appears in no line of the AppHost: The Service Bus emulator needs a SQL Server as its storage (3.5.2), and RunAsEmulator creates it as a resource of its own. import is NotStarted, because WithExplicitStart from 3.5.7 says it runs only at the push of a button. And cae, the Container Apps environment from 3.2.5, is missing entirely: It exists only when publishing.