Skip to content

Latest commit

ย 

History

30 Commits

Folders and files

NameName
Last commit message
Last commit date
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

Hooking Up All The Things - Making Your Distributed Developer's Life Easier

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!

Session Overview

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

Project Structure

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

Part 1: Official Aspire Integrations

These integrations are published and maintained by the .NET Aspire team. They provide first-class support for databases, caches, and Azure services.

Redis Cache

var redis = builder.AddRedis("cache")
    .WithRedisInsight();  // Adds Redis Insight UI for debugging

PostgreSQL

var postgres = builder.AddPostgres("postgres")
    .WithPgAdmin()  // Adds pgAdmin UI for database management
    .AddDatabase("catalogdb");

SQL Server

var sqlserver = builder.AddSqlServer("sql")
    .AddDatabase("ordersdb");

Azure Service Bus (with Emulator)

var serviceBus = builder.AddAzureServiceBus("messaging")
    .RunAsEmulator();  // Use emulator for local dev
serviceBus.AddServiceBusQueue("orders");
serviceBus.AddServiceBusTopic("events", "audit");

Azure Cosmos DB (with Emulator)

var cosmos = builder.AddAzureCosmosDB("cosmos")
    .RunAsEmulator()
    .AddCosmosDatabase("appdata");

Azure Storage (Blobs, Queues, Tables)

var storage = builder.AddAzureStorage("storage")
    .RunAsEmulator();  // Uses Azurite emulator
storage.AddBlobs("blobs");
storage.AddQueues("queues");
storage.AddTables("tables");

๐Ÿ“š What We Learned

  • 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() and WithPgAdmin() 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)

Part 2: Multi-Language Application Support

Aspire isn't just for .NET! It can orchestrate applications written in any language.

ASP.NET Core Web API

builder.AddProject<Projects.AspireAllTheThings_WebApi>("webapi")
    .WithExternalHttpEndpoints();

Python Flask API

builder.AddPythonApp("python-api", "../python-api", "app.py")
    .WithHttpEndpoint(targetPort: 5000, name: "http")
    .WithExternalHttpEndpoints();

Setup: cd python-api && pip install -r requirements.txt

Node.js Express API

builder.AddJavaScriptApp("node-api", "../node-api", runScriptName: "start")
    .WithHttpEndpoint(port: 3000, env: "PORT")
    .WithExternalHttpEndpoints();

Setup: cd node-api && npm install

Java Spring Boot API

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:

  1. Install Java 21+: winget install Microsoft.OpenJDK.21
  2. Install Maven: Download from Apache Maven
  3. Build the JAR: cd java-api && mvn package -DskipTests
  4. 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"

๐Ÿ“š What We Learned

  • 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(), and AddJavaApp() 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

Part 3: Custom Integration Creation

Build your own integrations with Docker containers!

Demo: IT-Tools (Simple Docker Container)

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 image
  • WithHttpEndpoint() - Expose HTTP ports
  • WithExternalHttpEndpoints() - Make accessible from the dashboard

๐Ÿ“š What We Learned

  • 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)

Part 4: MailPit Email Demo

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.

Demo: MailPit (Community Toolkit)

var mailpit = builder.AddMailPit("mailpit");

Demo: Email Sending with 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 testing
  • WithReference() - Connects the ASP.NET app to MailPit for SMTP configuration
  • No real email server needed during development!

How It Works:

  1. MailPit runs as a container with SMTP and web UI endpoints
  2. The ASP.NET app receives SMTP connection details automatically
  3. Emails sent by the app are captured and viewable in MailPit's web UI

Learn More: Aspire Community Toolkit

๐Ÿ“š What We Learned

  • 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

Part 5: Advanced Integration Patterns

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.

Demo: Discord Notifier ๐Ÿ””

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.

Setup

  1. Create a Discord webhook: Server Settings โ†’ Integrations โ†’ Webhooks โ†’ New Webhook
  2. 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!).

Usage

// 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

Key Concepts Demonstrated

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

Live Demo Flow

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!"

๐Ÿ“š What We Learned

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 Resource base class is the foundation for all Aspire resources, providing identity and lifecycle hooks (Resource Model)
  • IResourceWithWaitSupport enables other resources to use WaitFor() to express dependencies
  • Global eventing APIs like BeforeStartEvent and AfterResourcesCreatedEvent coordinate 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

Part 6: AI Integration with GitHub Models

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.

Demo: GitHub Models Chat ๐Ÿค–

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);

Setup

  1. Create a GitHub Personal Access Token with the models: read permission
  2. 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!

Key Concepts

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

Try It

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!

๐Ÿ“š What We Learned

  • 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

Part 7: Fun Demos

Because Aspire isn't just for web apps and databases!

Demo: Minecraft Server ๐ŸŽฎ

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 publish

Connect: localhost:25565

๐Ÿ“š What We Learned

  • 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)

Running the Demos

Prerequisites

  • .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)

Run the AppHost

cd AspireAllTheThings.AppHost
dotnet run

Enable Demos

Edit 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();

Key Takeaways

  1. Aspire simplifies distributed development - No more complex Docker Compose files
  2. Official integrations - First-class support for databases and Azure services
  3. Multi-language support - .NET, Python, Node.js, Java, and more
  4. Add ANY container - If it runs in Docker, it runs in Aspire
  5. Community Toolkit - Don't reinvent the wheel, leverage community integrations
  6. Beyond web apps - Aspire is a general-purpose orchestrator
  7. AI integration - GitHub Models with GenAI dashboard visualization

Resources


Speaker: Jeffrey T. Fritz

About

Introducing all the ways that Aspire can work with your applications, systems, and existing technology stack

Resources

Stars

9 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages