Distributed applications are powerful, but also complex to stitch together. Between service discovery, configuration, observability, and deployment, developers spend more time wiring up infrastructure than building features. Enter Aspire!
This demo project is organized into seven parts:
| Part | Topic | Files |
|---|---|---|
| Part 1 | Official Aspire Integrations | 1-OfficialIntegrations.cs |
| Part 2 | Multi-Language App Support | 2-MultiLanguage.cs |
| Part 3 | Custom Integration Creation | 3-ItTools.cs |
| Part 4 | MailPit Email Demo | 4-MailPit.cs |
| Part 5 | Advanced Integration Patterns | 5-AdvancedIntegrations.cs |
| Part 6 | AI Integration with GitHub Models | 6-AI.cs |
| Part 7 | Fun Demos | 7-Fun.cs |
AspireAllTheThings/
โโโ AspireAllTheThings.AppHost/
โ โโโ AppHost.cs โ Main entry point (uncomment demos here)
โ โโโ 1-OfficialIntegrations.cs โ Part 1: Redis, Postgres, SQL, Azure
โ โโโ 2-MultiLanguage.cs โ Part 2: .NET, Python, Node.js, Java
โ โโโ 3-ItTools.cs โ Part 3: Simple Docker container
โ โโโ 4-MailPit.cs โ Part 4: MailPit Email Demo
โ โโโ 5-AdvancedIntegrations.cs โ Part 5: Discord Notifier (eventing)
โ โโโ 6-AI.cs โ Part 6: GitHub Models AI Chat
โ โโโ 7-Fun.cs โ Part 7: Minecraft (Bonus!)
โโโ AspireAllTheThings.WebApi/ โ Sample ASP.NET Core API
โโโ python-api/ โ Sample Python Flask API
โโโ node-api/ โ Sample Node.js Express API
โโโ java-api/ โ Sample Java Spring Boot API
These integrations are published and maintained by the .NET Aspire team. They provide first-class support for databases, caches, and Azure services.
var redis = builder.AddRedis("cache")
.WithRedisInsight(); // Adds Redis Insight UI for debuggingvar postgres = builder.AddPostgres("postgres")
.WithPgAdmin() // Adds pgAdmin UI for database management
.AddDatabase("catalogdb");var sqlserver = builder.AddSqlServer("sql")
.AddDatabase("ordersdb");var serviceBus = builder.AddAzureServiceBus("messaging")
.RunAsEmulator(); // Use emulator for local dev
serviceBus.AddServiceBusQueue("orders");
serviceBus.AddServiceBusTopic("events", "audit");var cosmos = builder.AddAzureCosmosDB("cosmos")
.RunAsEmulator()
.AddCosmosDatabase("appdata");var storage = builder.AddAzureStorage("storage")
.RunAsEmulator(); // Uses Azurite emulator
storage.AddBlobs("blobs");
storage.AddQueues("queues");
storage.AddTables("tables");- Official integrations provide first-class support for popular services with minimal configuration (Redis, PostgreSQL, SQL Server)
- Emulators (
RunAsEmulator()) enable local development without cloud dependencies (Azure Service Bus, Cosmos DB, Storage) - Management UI extensions like
WithRedisInsight()andWithPgAdmin()add visual tools for debugging - Chained configuration allows composing integrations (e.g., adding databases to a Postgres server, queues to Service Bus)
- Aspire's resource model abstracts infrastructure differences โ same code for local emulators or cloud services (Resource Model)
Aspire isn't just for .NET! It can orchestrate applications written in any language.
builder.AddProject<Projects.AspireAllTheThings_WebApi>("webapi")
.WithExternalHttpEndpoints();builder.AddPythonApp("python-api", "../python-api", "app.py")
.WithHttpEndpoint(targetPort: 5000, name: "http")
.WithExternalHttpEndpoints();Setup: cd python-api && pip install -r requirements.txt
builder.AddJavaScriptApp("node-api", "../node-api", runScriptName: "start")
.WithHttpEndpoint(port: 3000, env: "PORT")
.WithExternalHttpEndpoints();Setup: cd node-api && npm install
builder.AddJavaApp("java-api", "../java-api", new JavaAppExecutableResourceOptions
{
ApplicationName = "target/java-api-0.0.1-SNAPSHOT.jar",
OtelAgentPath = "agents/opentelemetry-javaagent.jar",
Port = 8080
})
.WithHttpEndpoint(port: 8080, name: "http", isProxied: false)
.WithExternalHttpEndpoints();Setup:
- Install Java 21+:
winget install Microsoft.OpenJDK.21 - Install Maven: Download from Apache Maven
- Build the JAR:
cd java-api && mvn package -DskipTests - Import Aspire dev cert into Java truststore (for OpenTelemetry):
dotnet dev-certs https --export-path "$env:TEMP\aspire-dev-cert.crt" --format PEM --no-password # Run as Administrator: keytool -importcert -trustcacerts -cacerts -storepass changeit -noprompt -alias aspire-dev-cert -file "$env:TEMP\aspire-dev-cert.crt"
- Multi-language orchestration โ Aspire isn't just for .NET! It coordinates Python, Node.js, Java, and any executable (What's New in Aspire 13)
- Language-specific builders like
AddPythonApp(),AddJavaScriptApp(), andAddJavaApp()handle each runtime's unique patterns - OpenTelemetry integration works across languages โ even Java apps report telemetry to the Aspire dashboard with the OTel agent
- Unified developer experience โ all apps appear in the same dashboard with logs, metrics, and traces regardless of language
WithExternalHttpEndpoints()exposes services outside the container network for browser access
Build your own integrations with Docker containers!
Image: corentinth/it-tools
The simplest way to add ANY Docker container to Aspire.
var itTools = builder.AddContainer("it-tools", "corentinth/it-tools")
.WithHttpEndpoint(targetPort: 80, name: "http")
.WithExternalHttpEndpoints();Key Concepts:
AddContainer()- Add ANY Docker imageWithHttpEndpoint()- Expose HTTP portsWithExternalHttpEndpoints()- Make accessible from the dashboard
AddContainer()is the universal adapter โ any Docker image works in Aspire without a dedicated integration (Custom Resources)- Port mapping via
WithHttpEndpoint()exposes container services to the Aspire dashboard and other resources - Creating custom integrations is straightforward โ wrap
AddContainer()in extension methods for reusability - Deployment manifest automatically includes container-based resources for production deployment (Deployment Manifest)
Package: CommunityToolkit.Aspire.Hosting.Mailpit
One line of code instead of manual container configuration! Demonstrate email functionality in a local development environment using MailPit with an ASP.NET Core website.
var mailpit = builder.AddMailPit("mailpit");This demo shows how to wire up an ASP.NET Core application to send emails through MailPit, a local email testing tool.
var mailpit = builder.AddMailPit("mailpit");
builder.AddProject<Projects.AspireAllTheThings_MailDemo>("maildemo")
.WithReference(mailpit);Key Concepts:
AddMailPit()- Adds the MailPit container for local email testingWithReference()- Connects the ASP.NET app to MailPit for SMTP configuration- No real email server needed during development!
How It Works:
- MailPit runs as a container with SMTP and web UI endpoints
- The ASP.NET app receives SMTP connection details automatically
- Emails sent by the app are captured and viewable in MailPit's web UI
Learn More: Aspire Community Toolkit
- Community Toolkit integrations provide production-ready wrappers for popular tools like MailPit (Get Started with MailPit)
WithReference()automatically wires connection strings and configuration between resources- Local email testing without real SMTP servers โ MailPit captures all emails in a web UI (MailPit Hosting Reference)
- One-line integration replaces complex Docker Compose configuration and environment variable setup
Learn how to build CUSTOM Aspire integrations with proper eventing patterns and interactive parameter prompts.
โ ๏ธ Important Framing: This is DEV-TIME tooling! The AppHost (and its eventing) doesn't run in production. In production, you'd use Azure Monitor, Prometheus, etc. But the patterns you learn here ARE production-relevant for database seeding, migrations, and integration testing.
A custom integration that posts to Discord whenever resources change state. This demo also showcases Aspire's interactive parameter prompts โ the dashboard asks for configuration values at startup, with rich Markdown help text.
- Create a Discord webhook: Server Settings โ Integrations โ Webhooks โ New Webhook
- Option A โ Pre-fill via user secrets (no prompt at startup):
cd AspireAllTheThings.AppHost
dotnet user-secrets set "Parameters:discordWebhookUrl" "https://discord.com/api/webhooks/YOUR_ID/YOUR_TOKEN"
dotnet user-secrets set "Parameters:discordChannel" "aspire-demo"Option B โ Leave unconfigured and enter values in the Aspire dashboard's interactive parameter prompt at startup (recommended for demos โ it shows off the feature!).
// Interactive parameter prompts with rich Markdown descriptions
builder.AddParameter("discordWebhookUrl", secret: true)
.WithDescription("**Discord Webhook URL**\n\nFormat: `https://discord.com/api/webhooks/{id}/{token}`",
enableMarkdown: true);
builder.AddParameter("discordChannel")
.WithDescription("**Discord Channel Name**\n\nThe channel name to display in notifications.",
enableMarkdown: true);
builder.AddDiscordNotifier("discord-alerts")
.NotifyOnStartup() // ๐ "Aspire is starting up!"
.NotifyOnShutdown() // ๐ "Aspire is shutting down!"
.WatchAllResources(); // โ
"cache is ready!" for each resource| Concept | What It Shows |
|---|---|
| Custom Resource Type | DiscordNotifierResource - non-container resource |
| AddParameter(secret: true) | Dashboard prompts with a masked password field |
| AddParameter() | Dashboard prompts with a standard text field |
| WithDescription(enableMarkdown: true) | Rich Markdown help text rendered in the prompt dialog |
| BeforeStartEvent | Global event before any resources start |
| ResourceReadyEvent | Per-resource event when healthy |
| ResourceStoppedEvent | Per-resource event when stopped |
| ExcludeFromManifest() | Dev-only resource, won't deploy |
| Builder Pattern | Add* and With* extension methods |
| Step | What Happens | Discord Shows |
|---|---|---|
| 1 | Run dotnet run |
Dashboard shows parameter prompts (webhook URL + channel) |
| 2 | Enter values and submit | ๐ "Aspire is starting up! Launching X resources..." |
| 3 | Resources start | โ "cache is ready!" (with channel name in messages) |
| 4 | Stop Redis in dashboard | ๐ "cache stopped!" |
| 5 | Restart Redis | โ "cache is ready!" |
| 6 | Ctrl+C | ๐ "Aspire is shutting down!" |
This section demonstrates the most advanced Aspire patterns โ essential for production-grade integrations:
- Custom resource types don't have to be containers โ they can represent any logical component like notifiers, validators, or configuration managers (Custom Resources)
- The
Resourcebase class is the foundation for all Aspire resources, providing identity and lifecycle hooks (Resource Model) IResourceWithWaitSupportenables other resources to useWaitFor()to express dependencies- Global eventing APIs like
BeforeStartEventandAfterResourcesCreatedEventcoordinate application-wide initialization (AppHost Eventing APIs) - Resource-specific eventing (
ResourceReadyEvent,ResourceStoppedEvent) allows reacting to individual resource lifecycle changes (App Lifecycle Guide) IDistributedApplicationEventing.Subscribe()is the pattern for hooking into Aspire's event system โ both globally and per-resource- Extension method conventions (
Add*creates resources,With*configures them) provide a fluent, discoverable API surface ExcludeFromManifest()marks resources as dev-only โ they won't appear in production deployment manifests- Interactive parameters with
AddParameter(secret: true)prompt users in the Aspire dashboard at startup, eliminating hardcoded secrets (Interaction Service) - Rich Markdown prompts via
WithDescription(enableMarkdown: true)provide contextual help and formatting in parameter dialogs - Builder pattern and method chaining enable readable, composable configuration (e.g.,
.NotifyOnStartup().WatchAllResources()) - CancellationToken patterns for graceful shutdown โ register callbacks with
ct.Register()to clean up when the app stops
GitHub Models provides easy access to AI models (like GPT-4o-mini) through GitHub's inference API. This demo showcases the GenAI Visualizer in the Aspire dashboard, which automatically displays AI telemetry (token usage, latency, prompts and completions) when OpenTelemetry is flowing.
Package: Aspire.Hosting.GitHub.Models (AppHost), Aspire.Azure.AI.Inference (Client)
var apiKey = builder.AddParameter("githubApiKey", secret: true);
var chat = builder.AddGitHubModel("chat", "openai/gpt-4o-mini")
.WithApiKey(apiKey);
builder.AddProject<Projects.AspireAllTheThings_WebApi>("webapi")
.WithExternalHttpEndpoints()
.WithReference(chat);- Create a GitHub Personal Access Token with the models: read permission
- Store the token in user secrets:
cd AspireAllTheThings.AppHost
dotnet user-secrets set "Parameters:githubApiKey" "github_pat_YOUR_TOKEN"Or simply enter the token in the Aspire dashboard's interactive parameter prompt at startup!
| Concept | What It Shows |
|---|---|
| AddParameter(secret: true) | Dashboard prompts for the API key interactively |
| AddGitHubModel() | Registers a GitHub Model resource |
| WithApiKey() | Wires secret parameter to the model |
| GenAI Visualizer | Dashboard shows AI telemetry automatically via OpenTelemetry |
| IChatClient | Microsoft.Extensions.AI abstraction for provider-agnostic AI |
After starting the AppHost, open the chat UI in your browser:
http://localhost:{port}/chat.html
The chat page provides a dark-themed interface where you can type messages and see AI responses in real time. Watch the Aspire dashboard's GenAI Visualizer light up with token usage and latency data as you chat!
- GitHub Models integration provides easy access to AI models (GPT-4o-mini, Llama, etc.) through GitHub's inference API (AI Integrations Matrix)
AddParameter(secret: true)securely prompts for API keys in the dashboard, avoiding hardcoded credentials- GenAI Visualizer in the Aspire dashboard automatically visualizes AI telemetry (token usage, latency, prompts) via OpenTelemetry
- Microsoft.Extensions.AI (
IChatClient) abstracts AI providers, making it easy to swap models without changing application code - Interactive parameter prompts eliminate the need for complex secrets management during development
Because Aspire isn't just for web apps and databases!
Image: itzg/minecraft-server
Shows environment configuration, volumes, and non-HTTP endpoints.
var minecraft = builder.AddContainer("minecraft", "itzg/minecraft-server")
.WithEnvironment("EULA", "TRUE")
.WithEnvironment("MODE", "creative")
.WithEnvironment("MOTD", "CodeStock 2026 - Aspire All The Things!")
.WithEndpoint(targetPort: 25565, port: 25565, name: "minecraft", scheme: "tcp")
.WithVolume("minecraft-data", "/data")
.ExcludeFromManifest(); // Dev-only, don't publishConnect: localhost:25565
- Aspire orchestrates more than web apps โ game servers, databases, message queues, and any containerized workload
- Environment variables via
WithEnvironment()configure container behavior without rebuilding images - Volume mounting with
WithVolume()persists data across container restarts - Non-HTTP endpoints like TCP (
WithEndpoint(..., scheme: "tcp")) work seamlessly in Aspire's networking model - Custom resources can represent fun, creative use cases โ Aspire's flexibility extends to any Docker-based workload (Custom Resources)
- .NET 10 SDK
- Docker Desktop (or compatible container runtime)
- Aspire workload installed
- Python (for Part 2)
- Node.js (for Part 2)
- Java 21+ and Maven (for Part 2 - Java demo)
cd AspireAllTheThings.AppHost
dotnet runEdit AppHost.cs and uncomment the demos you want to run:
// ---- PART 1: Official Integrations ----
builder.AddRedisDemo();
builder.AddPostgresDemo();
// ---- PART 2: Multi-Language Apps ----
builder.AddAspNetApiDemo();
builder.AddJavaApiDemo(); // Requires Java 21+ and Maven
// ---- PART 3: Custom Integration Creation ----
builder.AddItToolsDemo();
// ---- PART 4: MailPit Email Demo ----
builder.AddMailPitDemo();
// ---- PART 5: Advanced Integration Patterns ----
builder.AddDiscordNotifierDemo(); // Dashboard prompts for webhook URL + channel
// ---- PART 6: AI Integration ----
builder.AddGitHubModelDemo(); // Requires GitHub PAT with models:read
// ---- PART 7: Fun Demos (BONUS) ----
builder.AddMinecraftDemo();- Aspire simplifies distributed development - No more complex Docker Compose files
- Official integrations - First-class support for databases and Azure services
- Multi-language support - .NET, Python, Node.js, Java, and more
- Add ANY container - If it runs in Docker, it runs in Aspire
- Community Toolkit - Don't reinvent the wheel, leverage community integrations
- Beyond web apps - Aspire is a general-purpose orchestrator
- AI integration - GitHub Models with GenAI dashboard visualization
- Aspire Documentation
- Aspire Community Toolkit
- IT-Tools
- MailPit
- Minecraft Server Docker Image
- Discord Webhooks Documentation
- GitHub Models
Speaker: Jeffrey T. Fritz