Introduction
When developers build distributed applications, the AppHost usually takes care of starting services, connecting resources, and making the local development environment easier to manage.
But real applications often need more than that.
Sometimes a developer needs to upload a configuration file, confirm a destructive operation, enter a value, see progress while a long-running operation is executing, or receive a useful message when something goes wrong.
This is where the Interaction Service in .NET Aspire 13.5 becomes interesting.
Aspire 13.5 expands the AppHost interaction capabilities with file inputs, progress dialogs, command arguments, and other interaction features. The result is that the AppHost can behave less like a simple application launcher and more like an interactive development experience.
For developers working with distributed .NET applications, this can make setup, import, debugging, and development workflows much easier to build into the application itself.
What Is the Aspire Interaction Service?
The Interaction Service is exposed through IInteractionService and allows an Aspire application to interact with the developer.
Depending on how the application is running, the interaction can appear in the Aspire dashboard or through the CLI.
For example:
Aspire AppHost
|
v
Interaction Service
|
+------> Dashboard Dialog
|
+------> Dashboard Notification
|
+------> User Input
|
+------> CLI Input
|
v
Application Continues
The service can be used to:
Ask the developer for input
Request confirmation
Display notifications
Display message boxes
Support command-driven workflows
Collect files
Report progress for longer operations
Microsoft's documentation describes the interaction service as a way to prompt users for input, request confirmation, and display messages in Aspire applications.
Why Interactive AppHosts Matter
Consider a common local development scenario.
A developer clones a distributed application and needs to import some configuration before starting work.
Without an interactive AppHost, the instructions might look like this:
1. Download configuration.json
2. Copy it into a specific folder
3. Rename the file
4. Run a setup script
5. Start Aspire
6. Check whether the import succeeded
This works, but the developer has to understand several implementation details before they can even start the application.
With an interactive resource command, the workflow can become:
1. Start Aspire
2. Click "Import Configuration"
3. Select configuration.json
4. Aspire validates the file
5. Import starts
6. Progress is displayed
7. Result is shown
The important difference is that the workflow becomes part of the application's development experience.
Getting the Interaction Service
The service can be resolved from dependency injection.
A simplified example looks like this:
var interactionService =
serviceProvider.GetRequiredService<IInteractionService>();
if (interactionService.IsAvailable)
{
var result = await interactionService.PromptInputAsync(
title: "Environment Configuration",
message: "Enter the environment name.");
var environment = result.Data;
}
The IsAvailable check is important.
The interaction service is not available in every execution context. Microsoft specifically recommends checking IInteractionService.IsAvailable before using dashboard-only interactions because attempting to use an unavailable interaction can result in an exception.
Dashboard and CLI Behavior
One of the useful parts of the Interaction Service is that Aspire understands different execution environments.
There are two important contexts:
| Context | Typical Usage | Interaction |
|---|---|---|
| Aspire Dashboard | Local development | Dialogs, notifications, forms |
| Aspire CLI | Publish/deploy workflows | Text-based input |
For example, input prompts can work in both environments:
Dashboard:
+------------------------------+
| Environment Name |
| |
| [ Development ] |
| |
| [ Continue ] |
+------------------------------+
While the CLI can provide an equivalent text prompt.
However, not every interaction is available in the CLI. According to the current documentation, PromptInputAsync and PromptInputsAsync are supported for CLI operations such as aspire publish and aspire deploy, while message boxes, notifications, and confirmation dialogs are dashboard-only.
This distinction is important when designing reusable AppHost workflows.
Asking for User Input
The Interaction Service supports different input types.
Examples include:
Text
Secret text
Choice
Boolean
Number
A simple example is asking for a service URL:
var result = await interactionService.PromptInputAsync(
title: "External Service",
message: "Enter the external service URL.");
var serviceUrl = result.Data;
For multiple inputs, you can collect several values together.
For example:
Application Name
[ Orders API ]
Environment
[ Development ]
Port
[ 5001 ]
This is much cleaner than requiring developers to manually edit configuration files.
Each interaction input has a programmatic Name and a user-facing Label. The name is used to retrieve the value programmatically, while the label is displayed to the developer.
Using Confirmation Dialogs
Confirmation prompts are particularly useful for operations that could cause data loss.
Imagine an Aspire resource command that resets a local database.
Instead of immediately executing the operation:
await ResetDatabaseAsync();
the workflow can first ask for confirmation:
var confirmation =
await interactionService.PromptConfirmationAsync(
title: "Reset Database",
message: "Are you sure you want to reset the development database?");
if (confirmation.Data)
{
await ResetDatabaseAsync();
}
This creates a simple safety boundary.
User clicks "Reset"
|
v
Confirmation Dialog
|
+---- Cancel ----> Stop
|
+---- Confirm ---> Reset Database
This pattern is especially useful for destructive developer operations.
Microsoft recommends confirmation prompts for operations that cannot easily be undone.
Adding Interactions to Resource Commands
The Interaction Service becomes especially useful when combined with custom resource commands.
Imagine an Aspire application with a database resource:
Resources
Orders API
Inventory API
PostgreSQL
Redis
PostgreSQL
[Reset Database]
When the developer selects Reset Database, the command can ask for confirmation before performing the operation.
A simplified AppHost structure might look like:
var builder = DistributedApplication.CreateBuilder(args);
var postgres = builder.AddPostgres("postgres");
var database = postgres.AddDatabase("ordersdb");
// Resource command logic can use the interaction service
// to collect input or confirm an operation.
var app = builder.AddProject<Projects.OrdersApi>("orders-api")
.WithReference(database);
builder.Build().Run();
The exact command registration depends on the resource and Aspire APIs being used, but the architectural idea is straightforward: the AppHost can expose developer operations directly through the Aspire dashboard.
File Inputs in Aspire 13.5
One of the more practical additions in Aspire 13.5 is file input support for resource commands.
Before this capability, a developer might need to place a file into a predefined directory before running a setup operation.
Now an interactive command can request the file directly.
For example:
Resource: Orders API
Command:
Import Configuration
Select configuration file:
[ config.json ]
File type:
JSON / YAML
[ Import ]
The AppHost can then receive the uploaded file and process it.
This is particularly useful for:
Configuration imports
Local data imports
Certificates
Development fixtures
Test data
Environment-specific setup
Microsoft's 13.5 release notes specifically describe a file-import workflow where a resource command can open a file picker, restrict accepted file types, enforce a size limit, and provide the file as a stream to the AppHost.
Join the conversation! Your thoughts help the community grow.