跳转到内容

What is the AppHost?

此内容尚不支持你的语言。

Aspire’s AppHost is the code-first place where you declare your application’s services and their relationships. Instead of managing scattered configuration files, you describe the architecture in code. Aspire then handles local orchestration so you can focus on building features.

Consider a simple three-tier architecture where the frontend talks to an API, and the API talks to a database:

architecture-beta

  service db(logos:postgresql)[PostgreSQL]
  service api(logos:dotnet)[API Service]
  service frontend(logos:react)[React Frontend]

  api:R --> L:db
  frontend:R --> L:api

You can represent that architecture in an AppHost like this:

C# — AppHost.cs
var builder = DistributedApplication.CreateBuilder(args);
// Add database resource
var postgres = builder.AddPostgres("db")
.AddDatabase("appdata")
.WithDataVolume();
// Add API service and reference the database
var api = builder.AddProject<Projects.Api>("api")
.WithReference(postgres)
.WaitFor(postgres);
// Add frontend service and reference the API
builder.AddViteApp("frontend", "../frontend")
.WithNpmPackageInstallation()
.WithHttpEndpoint(env: "PORT")
.WithReference(api);
builder.Build().Run();

Aspire presents the same, consistent model regardless of the language or framework used: services, resources, and the connections between them.

Below we highlight the key parts of a typical AppHost to explain what each step does.

C# — AppHost.cs
var builder = DistributedApplication.CreateBuilder(args);
15 collapsed lines
// Add database resource
var postgres = builder.AddPostgres("db")
.AddDatabase("appdata")
.WithDataVolume();
// Add API service and reference the database
var api = builder.AddProject<Projects.Api>("api")
.WithReference(postgres)
.WaitFor(postgres);
// Add frontend service and reference the API
builder.AddViteApp("frontend", "../frontend")
.WithNpmPackageInstallation()
.WithHttpEndpoint(env: "PORT")
.WithReference(api);
builder.Build().Run();

In the non-collapsed lines you:

  1. Create the distributed application builder with DistributedApplication.CreateBuilder(args).
  2. Call Build() to materialize the configuration into a runnable AppHost.
  3. Call Run() to start orchestration; services launch in dependency order.

The AppHost is the blueprint for your distributed application—Aspire manages the rest.

With the builder ready, define resources and services. The snippet below shows how to add a PostgreSQL server and a database:

C# — AppHost.cs
var builder = DistributedApplication.CreateBuilder(args);
// Add database resource
var postgres = builder.AddPostgres("db")
.AddDatabase("appdata")
.WithDataVolume();
12 collapsed lines
// Add API service and reference the database
var api = builder.AddProject<Projects.Api>("api")
.WithReference(postgres)
.WaitFor(postgres);
// Add frontend service and reference the API
builder.AddViteApp("frontend", "../frontend")
.WithNpmPackageInstallation()
.WithHttpEndpoint(env: "PORT")
.WithReference(api);
builder.Build().Run();

How this works:

  • AddPostgres("db") registers a PostgreSQL container named db.
    • This returns an IResourceBuilder<PostgresServerResource> so you can chain configuration fluent-style.
  • .AddDatabase("appdata") creates a database named appdata on that server.
  • .WithDataVolume() provisions a volume so data persists across container restarts.

Learn more about the official PostgreSQL integration.

Adding an API resource and declaring a dependency

Section titled “Adding an API resource and declaring a dependency”

Next, register the API service and wire it to the PostgreSQL resource:

C# — AppHost.cs
6 collapsed lines
var builder = DistributedApplication.CreateBuilder(args);
// Add database resource
var postgres = builder.AddPostgres("db")
.AddDatabase("appdata")
.WithDataVolume();
// Add API service and reference the database
var api = builder.AddProject<Projects.Api>("api")
.WithReference(postgres)
.WaitFor(postgres);
7 collapsed lines
// Add frontend service and reference the API
builder.AddViteApp("frontend", "../frontend")
.WithNpmPackageInstallation()
.WithHttpEndpoint(env: "PORT")
.WithReference(api);
builder.Build().Run();

What this does:

  • AddProject<Projects.Api>("api") registers the API project as a service named api.
  • WithReference(postgres) injects connection details (host, port, credentials, connection string) into the API configuration.
  • WaitFor(postgres) delays the API startup until PostgreSQL is healthy, avoiding brittle startup timing issues.

Now that the api service is defined, you can attach the frontend.

Register the frontend project, declare its dependency on the API, and let the AppHost provide the API address automatically.

C# — AppHost.cs
11 collapsed lines
var builder = DistributedApplication.CreateBuilder(args);
// Add database resource
var postgres = builder.AddPostgres("db")
.AddDatabase("appdata")
.WithDataVolume();
// Add API service and reference the database
var api = builder.AddProject<Projects.Api>("api")
.WithReference(postgres)
.WaitFor(postgres);
// Add frontend service and reference the API
builder.AddViteApp("frontend", "../frontend")
.WithNpmPackageInstallation()
.WithHttpEndpoint(env: "PORT")
.WithReference(api);
builder.Build().Run();

Key points:

  • .AddNpmApp("frontend", "../frontend") registers the frontend project as a service named frontend.
  • .WithHttpEndpoint(env: "PORT", targetPort: 3000) exposes the app on port 3000; the PORT environment variable can override it.
  • .WithNpmPackageInstallation() runs npm install before start so dependencies are present.
  • .WithReference(api) injects the API base address into the frontend configuration.

In short: define the backend first (DB → API), then point the UI at the API. The AppHost captures the dependency graph, connection flows, and startup order.

These dependencies and connections are automatically managed by Aspire. The AppHost generates configuration values like connection strings and endpoints, injecting them into services as needed. in the AppHost when you add resources, you name them (e.g., db, api, frontend); Aspire uses these names for DNS resolution, so services can communicate using predictable addresses. Consuming services also rely on these names for configuration injection.

architecture-beta

  service db(logos:postgresql)[pg]
  service epr(iconoir:server-connection)[Endpoint Reference]
  service api(logos:dotnet)[api]
  service ctr(iconoir:server-connection)[Connection String Reference]
  service frontend(logos:react)[frontend]

  db:L <-- R:ctr
  ctr:L <-- R:api
  api:L <-- R:epr
  epr:L <-- R:frontend

How these resources communicate

  1. pg publishes a ConnectionStringReference (host, port, database, user, password)—a strongly typed bundle Aspire understands.
  2. api declares a dependency on that reference; Aspire injects the connection string into its config with a unique configuration-flow process that injects settings values, including secrets, parameters, and connection strings for both local runs and deployments.
  3. api then publishes an EndpointReference (its base URL) after its HTTP endpoint is allocated.
  4. frontend depends on that endpoint; Aspire injects the API base URL so no hard-coded addresses are needed.

When you run the AppHost, Aspire performs these core responsibilities:

  1. Service discovery: Aspire discovers services and resources declared in the AppHost.
  2. Dependency resolution: Services start in the correct order based on declared dependencies.
  3. Configuration injection: Connection strings, endpoints, and other config values are injected automatically.
  4. Health monitoring: Aspire observes service health and can restart services when necessary.

Dive deeper into Aspire’s orchestration and the Resource Model.

The template AppHost project contains the following:

  • 文件夹AspireApp.AppHost
    • 文件夹Properties
      • launchSettings.json
    • appsettings.Development.json
    • appsettings.json
    • AspireApp.AppHost.csproj
    • AppHost.cs

You can hook into lifecycle events to run custom logic during startup and resource allocation.

  1. BeforeStartEvent: Raised before the AppHost begins starting services.
  2. AfterEndpointsAllocatedEvent: Raised after endpoints are allocated for services.
  3. AfterResourcesCreatedEvent: Raised after all resources are created.

For finer-grained lifecycle control, see the well-known lifecycle events.

  • Keep the AppHost minimal to start; add complexity only as required.
  • Define explicit dependencies with .WithReference(...) to make wiring obvious.
  • Use separate configurations for development, testing, and production.
  • Pick clear, descriptive names for resources to make debugging and logging easier.

最近更新:

问 & 答 协作 社区 讨论 观看