-
Notifications
You must be signed in to change notification settings - Fork 1
Working with Aspire
This guide explains how to use the generated API with .NET Aspire for local development orchestration.
.NET Aspire provides a development-time orchestrator that manages service startup, health monitoring, environment variable injection, and service discovery. When combined with the source generator, you get a fully orchestrated stack from a single dotnet run.
A typical Aspire-orchestrated solution:
MyApi/
βββ MyApi.Aspire/ # Aspire AppHost (orchestrator)
β βββ Program.cs
β βββ MyApi.Aspire.csproj
βββ MyApi.Api/ # ASP.NET Core API
β βββ Program.cs
βββ MyApi.Api.Contracts/ # Generated code (source generator)
β βββ .atc-rest-api-server
β βββ MyApi.yaml
βββ MyApi.Api.Domain/ # Handler implementations
β βββ Handlers/
βββ MyApi.ClientApp/ # Console/test client (optional)
β βββ .atc-rest-api-client
βββ MyApi.BlazorApp/ # Blazor frontend (optional)
# Using the CLI scaffolding
atc-rest-api-gen generate server \
-s api.yaml \
-o src/ \
--aspire
# Or manually add the project
dotnet new aspire-apphost -n MyApi.Aspirevar builder = DistributedApplication.CreateBuilder(args);
// Add the API project
var api = builder
.AddProject<Projects.MyApi_Api>("api");
// Add a console client that references the API
builder
.AddProject<Projects.MyApi_ClientApp>("client")
.WithReference(api.GetEndpoint("http"))
.WaitFor(api);
// Add a Blazor frontend
builder
.AddProject<Projects.MyApi_BlazorApp>("blazor")
.WithReference(api.GetEndpoint("http"))
.WaitFor(api)
.WithExternalHttpEndpoints();
await builder.Build().RunAsync();<Project Sdk="Aspire.AppHost.Sdk/13.1.2">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\MyApi.Api\MyApi.Api.csproj" />
<ProjectReference Include="..\MyApi.ClientApp\MyApi.ClientApp.csproj" />
<ProjectReference Include="..\MyApi.BlazorApp\MyApi.BlazorApp.csproj" />
</ItemGroup>
</Project>Aspire injects service URLs via environment variables. Use them in your client projects:
var builder = Host.CreateApplicationBuilder(args);
// Aspire injects the API URL as an environment variable
var apiBaseUrl = builder.Configuration["services:api:http:0"]
?? "https://localhost:5001";
builder.Services.AddHttpClient<MyApiClient>(client =>
{
client.BaseAddress = new Uri(apiBaseUrl);
});var builder = WebAssemblyHostBuilder.CreateDefault(args);
// The API URL is injected by Aspire's WithReference()
var apiBaseUrl = builder.Configuration["services:api:http:0"]
?? builder.HostEnvironment.BaseAddress;
builder.Services.AddHttpClient<MyApiClient>(client =>
{
client.BaseAddress = new Uri(apiBaseUrl);
});For JavaScript frontends, Aspire can inject environment variables via AddViteApp:
// In AppHost Program.cs
builder
.AddViteApp("react-app", "../MyApi.ReactApp")
.WithEnvironment("VITE_API_BASE_URL", api.GetEndpoint("http"))
.WaitFor(api)
.WithExternalHttpEndpoints();Then in your React app:
import { ApiProvider } from './api/hooks/ApiProvider';
const apiBaseUrl = import.meta.env.VITE_API_BASE_URL ?? 'http://localhost:5000';
function App() {
return (
<ApiProvider baseUrl={apiBaseUrl}>
<YourApp />
</ApiProvider>
);
}When using EndpointPerOperation mode, the generated Constants.HttpClientName integrates with Aspire's service discovery:
// In your client project's Program.cs
builder.Services
.AddHttpClient(
MyApi.Generated.Constants.HttpClientName,
client =>
{
client.BaseAddress = new Uri(apiBaseUrl);
});# Start everything with Aspire
cd MyApi.Aspire
dotnet run
# The Aspire dashboard opens at https://localhost:15888
# - API: https://localhost:{dynamic-port}
# - Client: runs and calls API
# - Blazor: https://localhost:{dynamic-port}The Aspire dashboard shows:
- Service health and status
- Distributed traces across services
- Structured logs from all projects
- Environment variables and endpoints
Use WaitFor() to ensure services start in the correct order:
// Client waits for API to be healthy before starting
builder
.AddProject<Projects.MyApi_ClientApp>("client")
.WithReference(api.GetEndpoint("http"))
.WaitFor(api);This prevents the client from failing on startup because the API isn't ready yet.
The repository includes two Aspire-enabled samples:
| Sample | Description |
|---|---|
| Showcase | Full-featured: API + Blazor + Console client + React app with Aspire orchestration |
| PetStoreFull | Simple: API + Aspire AppHost for basic orchestration |
Run the Showcase sample:
cd sample/Showcase/Showcase.Aspire
dotnet run- Use
WithExternalHttpEndpoints()for browser-accessible services (Blazor, React) - Aspire assigns dynamic ports β always use service discovery, not hardcoded URLs
- Add
launchSettings.jsonwith"ASPIRE_ALLOW_UNSECURED_TRANSPORT": "true"for HTTP-only development - The
--aspireflag in the CLI scaffolding creates the AppHost project automatically
- Getting Started with Basic β Create your first generated API
- Getting Started with CLI β Full CLI scaffolding options
- Working with Resilience β Add retry policies to HTTP clients
- Working with Security β Configure authentication
π Home
- πΌ FAQ Business Value
- π Getting Started with Basic
- π οΈ Getting Started with CLI
- π Migration Guide
- β¬οΈ Upgrading to v2
- π Working with OpenAPI
- π³οΈ Working with Nullability
- π οΈ Working with CLI
- π How-To Guides
- π Working with Security
- π¦ Working with Rate Limiting
- π Working with Resilience
- ποΈ Working with Caching
- π’ Working with Versioning
- β Working with Validations
- π Working with Webhooks
- βοΈ Working with Aspire
- π£οΈ Working with Endpoint Definitions
- π Working with Multi-Part Specs
- π§ͺ Working with Code Coverage
- π Working with C# Client
- π§ͺ Working with C# Client Testing
- π¦ Working with TypeScript Client
- πͺ Showcase Demo
- π§ͺ Working with E2E Testing
- βοΈ Working with Configuration
- π Marker Files
- π API Reference
- π Analyzer Rules
- β FAQ and Troubleshooting
- πΊοΈ Roadmap
- π§ Development Notes
- π¦ GitHub Repository
- π₯ NuGet Package
- π Report Issues