What's new in Aspire 9.5
Table of contents
Section titled “Table of contents”- Upgrade to Aspire 9.5
- CLI improvements
- Dashboard enhancements
- Integration changes and additions
- App model enhancements
- Azure
📢 Aspire 9.5 is the next minor version release of Aspire. It supports:
- .NET 8.0 Long Term Support (LTS)
- .NET 9.0 Standard Term Support (STS)
- .NET 10.0 Preview 6
If you have feedback, questions, or want to contribute to Aspire, collaborate with us on GitHub or join us on our new Discord to chat with the team and other community members.
It’s important to note that Aspire releases out-of-band from .NET releases. While major versions of Aspire align with major .NET versions, minor versions are released more frequently. For more information on .NET and Aspire version support, see:
- .NET support policy: Definitions for LTS and STS.
- Aspire support policy: Important unique product lifecycle details.
⬆️ Upgrade to Aspire 9.5
Section titled “⬆️ Upgrade to Aspire 9.5”Moving between minor releases of Aspire is simple:
-
In your AppHost project file (that is, MyApp.AppHost.csproj), update the 📦 Aspire.AppHost.Sdk NuGet package to version
9.5.0
:<Sdk Name="Aspire.AppHost.Sdk" Version="9.5.0" />For more information, see Aspire SDK.
-
Check for any NuGet package updates, either using the NuGet Package Manager in Visual Studio or the Update NuGet Package command from C# Dev Kit in VS Code.
-
Update to the latest Aspire templates by running the following .NET command line:
dotnet new install Aspire.ProjectTemplates
If your AppHost project file doesn’t have the Aspire.AppHost.Sdk
reference, you might still be using Aspire 8. To upgrade to 9, follow the upgrade guide.
🚀 CLI improvements
Section titled “🚀 CLI improvements”🧪 aspire exec
enhancements
Section titled “🧪 aspire exec enhancements”Introduced in 9.4 (behind a feature flag), aspire exec
in 9.5 adds --workdir
support plus improved help text and argument validation:
# Show environment info for an app containeraspire exec --resource api-container -- dotnet --info
# Run a command from a specific working directory (new in 9.5)aspire exec --resource worker --workdir /app/tools -- dotnet run -- --seed
🧷 Robust orphan detection
Section titled “🧷 Robust orphan detection”Resilient to PID reuse via ASPIRE_CLI_STARTED
timestamp + PID verification:
Detected orphaned prior AppHost process (PID reused). Cleaning up...
📦 Package channel & templating enhancements
Section titled “📦 Package channel & templating enhancements”New packaging channel infrastructure lets aspire add
and templating flows surface stable vs pre-release channels with localized UI.
📝 Rich markdown rendering
Section titled “📝 Rich markdown rendering”Extended markdown coverage in CLI prompts/output including code fences, emphasis, and safe escaping.
🧵 Improved cancellation & CTRL-C UX
Section titled “🧵 Improved cancellation & CTRL-C UX”- CTRL-C guidance message
- Fix for stall on interrupt
🎨 Dashboard enhancements
Section titled “🎨 Dashboard enhancements”🔗 Deep-linked telemetry navigation
Section titled “🔗 Deep-linked telemetry navigation”Trace IDs, span IDs, resource names, and log levels become interactive buttons in property grids for one-click navigation between telemetry views (#10648).
📊 Multi-resource console logs
Section titled “📊 Multi-resource console logs”New “All” option streams logs from every running resource simultaneously with deterministic colored name prefixes and a separate timestamp preference to reduce noise in aggregate view (#10981):
[api INF] Hosting started[postgres INF] database system is ready[redis INF] Ready to accept connections
🎭 Custom resource icons
Section titled “🎭 Custom resource icons”Resources can specify custom icons via WithIconName()
for better visual identification in dashboard views (#10760).
🌐 Reverse proxy support
Section titled “🌐 Reverse proxy support”Dashboard now explicitly maps forwarded Host & Proto headers when ASPIRE_DASHBOARD_FORWARDEDHEADERS_ENABLED=true
, fixing OpenID auth redirects and URL generation behind reverse proxies like YARP (#10388). Only these two headers are allowed to limit spoofing surface:
- Enable with
ASPIRE_DASHBOARD_FORWARDEDHEADERS_ENABLED=true
- Fixes OpenID authentication redirect issues with proxy scenarios
📱 Improved mobile experience
Section titled “📱 Improved mobile experience”Mobile and desktop toolbars redesigned for better usability across all dashboard pages with improved responsive layouts (#10407).
🔧 Enhanced resource management
Section titled “🔧 Enhanced resource management”- Resource action menus reorganized into sub-menus to prevent overflow (#10869)
- LaunchProfile property added to project details for easier debugging (#10906)
- Better resource navigation and selection handling (#10848)
🚨 Container runtime notifications
Section titled “🚨 Container runtime notifications”Smart notifications appear when Docker/Podman is installed but unhealthy, with automatic dismissal when runtime recovers (#11008).
✨ UI improvements
Section titled “✨ UI improvements”- Error spans use consistent error styling (#10742)
- Better default icons for parameters and services (#10762)
- Improved navigation reliability (#10848)
- Enhanced port parsing (#10884)
- Message truncation for long log entries (#10882)
- Optional log line wrapping (#10271)
- Improved text visualizer dialog (#10964)
📊 Trace performance & integration
Section titled “📊 Trace performance & integration”- Optimized trace detail page rendering (#10308)
- Embedded log entries within trace spans (#10281)
- Better span timing calculations (#10310)
🌍 Localization & deployment
Section titled “🌍 Localization & deployment”- Comprehensive dashboard localization with consolidated resource files
- Launch profile support with localized display names (#10906)
- Forwarded headers support for proxy/container scenarios (#10388)
Integration changes and additions
Section titled “Integration changes and additions”OpenAI hosting integration
Section titled “OpenAI hosting integration”New AddOpenAI
integration for self-hosted or compatible OpenAI endpoints with child model resources:
var openai = builder.AddOpenAI("openai") .WithApiKey(builder.AddParameter("OPENAI__API_KEY", secret: true)) .WithEndpoint("http://localhost:9000");
var chat = openai.AddModel("chat", "gpt-4o-mini");
builder.AddProject<Projects.Api>("api") .WithReference(chat);
🖥️ App model enhancements
Section titled “🖥️ App model enhancements”Telemetry configuration APIs
Section titled “Telemetry configuration APIs”Enhanced OTLP telemetry configuration with protocol selection:
// New OtlpProtocol enum with Grpc and HttpProtobuf optionspublic enum OtlpProtocol{ Grpc = 0, HttpProtobuf = 1}
// Configure OTLP telemetry with specific protocolvar api = builder.AddProject<Projects.Api>("api") .WithOtlpExporter(OtlpProtocol.HttpProtobuf);
// Or use default protocolvar worker = builder.AddProject<Projects.Worker>("worker") \ .WithOtlpExporter();
Resource waiting patterns
Section titled “Resource waiting patterns”Enhanced waiting with new WaitForStart
options (issue #7532, implemented in PR #10948). WaitForStart
waits for a dependency to reach the Running state without blocking on health checks—useful when initialization code (migrations, seeding, registry bootstrap) must run before the service can become “healthy”. Compared to WaitFor
:
WaitFor
= Running + passes health checks.WaitForStart
= Running only (ignores health checks, faster in dev / init flows).
This mirrors Docker Compose’s service_started
vs service_healthy
conditions and supports both existing WaitBehavior
modes.
var postgres = builder.AddPostgres("postgres");var redis = builder.AddRedis("redis");
var api = builder.AddProject<Projects.Api>("api") .WaitForStart(postgres) // New: Wait only for startup, not health .WaitFor(redis) // Existing: Wait for healthy .WithReference(postgres) .WithReference(redis);
ExternalService WaitFor behavior change
Section titled “ExternalService WaitFor behavior change”Breaking change: WaitFor
now properly honors ExternalService
health checks so dependent resources defer start until the external service reports healthy (issue #10827). Previously, dependents would start even if the external target failed its readiness probe. This improves correctness and aligns ExternalService
with other resource types.
If you relied on the old lenient behavior (e.g., starting a frontend while an external API was still warming up), you can temporarily remove the WaitFor
call or switch to WaitForStart
if only startup is required.
var externalApi = builder.AddExternalService("backend-api", "http://localhost:5082") .WithHttpHealthCheck("/health/ready");
builder.AddProject<Projects.Frontend>("frontend") .WaitFor(externalApi);
Context-based endpoint resolution
Section titled “Context-based endpoint resolution”Breaking change: Endpoint resolution in WithEnvironment
now correctly resolves container hostnames instead of always using “localhost” (#8574):
var redis = builder.AddRedis("redis");
builder.AddRabbitMQ("rabbitmq") .WithEnvironment(context => { var endpoint = redis.GetEndpoint("tcp"); var redisHost = endpoint.Property(EndpointProperty.Host); var redisPort = endpoint.Property(EndpointProperty.Port);
context.EnvironmentVariables["REDIS_HOST"] = redisHost; context.EnvironmentVariables["REDIS_PORT"] = redisPort; });
Resource lifetime behavior
Section titled “Resource lifetime behavior”Breaking change: Several resources now support WaitFor
operations that were previously not supported (#10851, #10842):
var connectionString = builder.AddConnectionString("db");var apiKey = builder.AddParameter("api-key", secret: true);
builder.AddProject<Projects.Api>("api") .WaitFor(connectionString) .WaitFor(apiKey);
Resources like ParameterResource
, ConnectionStringResource
, and GitHub Models no longer implement IResourceWithoutLifetime
. They now show as “Running” and can be used with WaitFor
operations.
InteractionInput API changes
Section titled “InteractionInput API changes”Breaking change: The InteractionInput
API now requires Name
and makes Label
optional (#10835):
var input = new InteractionInput{ Name = "username", Label = "Username", InputType = InputType.Text};
All InteractionInput
instances must now specify a Name
. The Label
property is optional and will default to the Name
if not provided.
Custom resource icons
Section titled “Custom resource icons”Resources can specify custom icon names for better visual identification:
var postgres = builder.AddPostgres("postgres") .WithIconName("database");
var api = builder.AddProject<Projects.Api>("api") .WithIconName("web-app", ApplicationModel.IconVariant.Regular);
MySQL password improvements
Section titled “MySQL password improvements”Consistent password handling across database resources:
var mysql = builder.AddMySql("mysql") .WithPassword(builder.AddParameter("mysql-password", secret: true));
// Password can be modified during configurationmysql.Resource.PasswordParameter = builder.AddParameter("new-password", secret: true);
Remote & debugging experience
Section titled “Remote & debugging experience”🔄 SSH remote auto port forwarding
Section titled “🔄 SSH remote auto port forwarding”VS Code SSH sessions now get automatic port forwarding configuration just like Dev Containers and Codespaces:
Remote SSH environment detected – configuring forwarded ports (dashboard, api, postgres).
🐞 AppHost debugging in VS Code
Section titled “🐞 AppHost debugging in VS Code”The extension offers Run vs Debug for the AppHost. If the C# extension is present it launches under the debugger; otherwise a terminal with dotnet watch
is used.
🧩 Extension modernization
Section titled “🧩 Extension modernization”Package upgrades and localization support plus groundwork for richer debugging scenarios.
Azure AI Foundry enhancements
Section titled “Azure AI Foundry enhancements”9.5 adds a generated, strongly-typed model catalog (AIFoundryModel
) for IntelliSense + ref safety when creating deployments (PR #10986) and a daily automation that refreshes the catalog as new models appear in Azure AI Foundry (PR #11040). Sample apps and end-to-end tests now use these constants (PR #11039) instead of raw strings. The original Foundry hosting integration and local runtime support were introduced earlier (issue #9568); this release focuses on developer ergonomics and keeping model metadata current.
Strongly-typed model catalog with IntelliSense support:
var aiFoundry = builder.AddAzureAIFoundry("ai-foundry");
// Strongly-typed model referencesvar gpt4 = aiFoundry.AddDeployment("gpt-4", AIFoundryModel.OpenAI.Gpt4);var mistral = aiFoundry.AddDeployment("mistral", AIFoundryModel.MistralAi.MistralLarge2411);
// Local on-device modevar localFoundry = builder.AddAzureAIFoundry("local-ai") .RunAsFoundryLocal();
Azure App Configuration emulator
Section titled “Azure App Configuration emulator”Run emulators locally with full configuration support:
var appConfig = builder.AddAzureAppConfiguration("config") .RunAsEmulator(emulator => emulator .WithDataVolume("config-data") .WithHostPort(8080));
Broader Azure resource capability surfacing
Section titled “Broader Azure resource capability surfacing”Several Azure hosting resource types now implement IResourceWithEndpoints
enabling uniform endpoint discovery and waiting semantics:
AzureAIFoundryResource
AzureAppConfigurationResource
AzureKeyVaultResource
AzurePostgresFlexibleServerResource
AzureRedisCacheResource