WPF and Windows Forms with Aspire
WPF (Windows Presentation Foundation) and Windows Forms are .NET desktop user interface (UI) frameworks for building Windows desktop applications. While Aspire’s primary focus is on cloud-native and web workloads, you can use WPF and Windows Forms applications alongside Aspire for development-time orchestration of backend services.
Add a WPF or Windows Forms app to Aspire
Section titled “Add a WPF or Windows Forms app to Aspire”Because WPF and Windows Forms projects are standard .NET projects, you can reference them directly from your AppHost using AddProject. This starts the desktop app alongside your backend services when you run the AppHost.
Step 1: Add a project reference
Section titled “Step 1: Add a project reference”In your AppHost .csproj, add a project reference to your WPF or Windows Forms app:
<ItemGroup> <ProjectReference Include="..\MyWpfApp\MyWpfApp.csproj" /></ItemGroup>Step 2: Register the project in the Aspire AppHost
Section titled “Step 2: Register the project in the Aspire AppHost”var builder = DistributedApplication.CreateBuilder(args);
var api = builder.AddProject<Projects.ApiService>("api");
// Start the WPF or WinForms app as a resource in local developmentvar desktop = builder.AddProject<Projects.MyWpfApp>("desktop") .WithReference(api);
// After adding all resources, run the app...builder.Build().Run();When you run the AppHost, the WPF or Windows Forms application starts automatically as a process resource.
Step 3: Consume service URLs in the desktop app
Section titled “Step 3: Consume service URLs in the desktop app”Add the Aspire.ServiceDefaults (or Microsoft.Extensions.ServiceDiscovery) package to your desktop project to enable service discovery:
public partial class App : Application{ public IServiceProvider Services { get; private set; } = default!;
protected override void OnStartup(StartupEventArgs e) { base.OnStartup(e);
var host = Host.CreateDefaultBuilder() .ConfigureServices(services => { services.AddServiceDiscovery(); services.AddHttpClient<ApiClient>(client => { // Ensure that the service name in the URI matches the name in AppHost client.BaseAddress = new Uri("https+http://api"); }).AddServiceDiscovery(); }) .Build();
Services = host.Services; host.Start(); }}Dev-only resources
Section titled “Dev-only resources”A common pattern is to start certain resources, such as databases, mock services, or dev tools, only during local development and skip them in production. Use builder.Environment.IsDevelopment() to add resources conditionally:
var builder = DistributedApplication.CreateBuilder(args);
var postgres = builder.AddPostgres("postgres") .AddDatabase("mydb");
var api = builder.AddProject<Projects.ApiService>("api") .WithReference(postgres);
if (builder.Environment.IsDevelopment()){ // Only launch the desktop app during local development builder.AddProject<Projects.MyWpfApp>("desktop") .WithReference(api);}
// After adding all resources, run the app...builder.Build().Run();Limitations
Section titled “Limitations”- Windows only: WPF and Windows Forms require Windows. If your team develops on macOS or Linux, the desktop resource will fail to start on non-Windows machines.
- No deployment support:
aspire deploydoes not produce deployment artifacts for desktop apps. They are treated as local-only resources. - No auto-launch from dashboard: Desktop apps registered with Aspire start automatically when the AppHost runs—they cannot be manually started or stopped from the Aspire dashboard the same way containerized services can be.
Comparison with .NET MAUI
Section titled “Comparison with .NET MAUI”| Feature | WPF / WinForms | .NET MAUI |
|---|---|---|
| First-class Aspire support | From the AddProject method (manual) | From the Aspire.Hosting.Maui package |
| Cross-platform | Windows only | Windows, macOS, iOS, Android |
| Dev Tunnels support | Not applicable | Built-in for iOS/Android |
| Production deployment with Aspire | Not supported | Not supported |
For cross-platform desktop and mobile scenarios, consider .NET MAUI integration.