Skip to content
Docs Try Aspire

WPF and Windows Forms with Aspire

.NET logo

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.

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.

In your AppHost .csproj, add a project reference to your WPF or Windows Forms app:

XML — AppHost.csproj
<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”
C# — AppHost.cs
var builder = DistributedApplication.CreateBuilder(args);
var api = builder.AddProject<Projects.ApiService>("api");
// Start the WPF or WinForms app as a resource in local development
var 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:

C# — App.xaml.cs (WPF)
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();
}
}

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:

C# — AppHost.cs
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();
  • 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 deploy does 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.
FeatureWPF / WinForms.NET MAUI
First-class Aspire supportFrom the AddProject method (manual)From the Aspire.Hosting.Maui package
Cross-platformWindows onlyWindows, macOS, iOS, Android
Dev Tunnels supportNot applicableBuilt-in for iOS/Android
Production deployment with AspireNot supportedNot supported

For cross-platform desktop and mobile scenarios, consider .NET MAUI integration.