From 3b3fb207ba23c1ced6d8c44efea70c041eea6731 Mon Sep 17 00:00:00 2001
From: David Fowler <95136+davidfowl@users.noreply.github.com>
Date: Tue, 13 Oct 2026 06:34:06 +0000
Subject: [PATCH 1/2] docs: document package-based AppHost SDK migration
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---
src/frontend/config/sidebar/docs.topics.ts | 4 +
.../config/sidebar/reference.topics.ts | 3 +-
.../content/docs/app-host/configuration.mdx | 18 ++-
.../content/docs/diagnostics/aspire007.mdx | 4 +-
.../content/docs/diagnostics/aspire009.mdx | 4 +-
.../content/docs/diagnostics/aspire010.mdx | 27 ++--
.../content/docs/diagnostics/aspire012.mdx | 39 +++++
.../src/content/docs/diagnostics/overview.mdx | 3 +-
.../content/docs/get-started/aspire-sdk.mdx | 34 +++--
.../docs/get-started/migrate-apphost-sdk.mdx | 138 ++++++++++++++++++
.../src/content/docs/whats-new/aspire-17.mdx | 14 ++
.../content/docs/whats-new/upgrade-aspire.mdx | 8 +
12 files changed, 255 insertions(+), 41 deletions(-)
create mode 100644 src/frontend/src/content/docs/diagnostics/aspire012.mdx
create mode 100644 src/frontend/src/content/docs/get-started/migrate-apphost-sdk.mdx
diff --git a/src/frontend/config/sidebar/docs.topics.ts b/src/frontend/config/sidebar/docs.topics.ts
index 61f7b4c138..580ca28f75 100644
--- a/src/frontend/config/sidebar/docs.topics.ts
+++ b/src/frontend/config/sidebar/docs.topics.ts
@@ -995,6 +995,10 @@ export const docsTopics = {
label: 'Aspire SDK',
slug: 'get-started/aspire-sdk',
},
+ {
+ label: 'Migrate from the AppHost SDK',
+ slug: 'get-started/migrate-apphost-sdk',
+ },
{
label: 'Aspire templates',
slug: 'get-started/aspire-sdk-templates',
diff --git a/src/frontend/config/sidebar/reference.topics.ts b/src/frontend/config/sidebar/reference.topics.ts
index 5b692b24fb..25760024a7 100644
--- a/src/frontend/config/sidebar/reference.topics.ts
+++ b/src/frontend/config/sidebar/reference.topics.ts
@@ -627,7 +627,7 @@ export const referenceTopics: StarlightSidebarTopicsUserConfig[number] = {
{ label: 'ASPIRE002', link: '/diagnostics/aspire002' },
{ label: 'ASPIRE003', link: '/diagnostics/aspire003' },
{ label: 'ASPIRE004', link: '/diagnostics/aspire004' },
- { label: 'ASPIRE010', link: '/diagnostics/aspire010' },
+ { label: 'ASPIRE012', link: '/diagnostics/aspire012' },
{
label: 'ASPIREEXPORT005',
link: '/diagnostics/aspireexport005',
@@ -786,6 +786,7 @@ export const referenceTopics: StarlightSidebarTopicsUserConfig[number] = {
{ label: 'ASPIRE007', link: '/diagnostics/aspire007' },
{ label: 'ASPIRE008', link: '/diagnostics/aspire008' },
{ label: 'ASPIRE009', link: '/diagnostics/aspire009' },
+ { label: 'ASPIRE010', link: '/diagnostics/aspire010' },
{ label: 'ASPIRE011', link: '/diagnostics/aspire011' },
{
label: 'ASPIREACADOMAIN001',
diff --git a/src/frontend/src/content/docs/app-host/configuration.mdx b/src/frontend/src/content/docs/app-host/configuration.mdx
index c395a3e6f7..53a518e7a9 100644
--- a/src/frontend/src/content/docs/app-host/configuration.mdx
+++ b/src/frontend/src/content/docs/app-host/configuration.mdx
@@ -138,7 +138,13 @@ The version check runs only when:
- The check hasn't been disabled via the `ASPIRE_VERSION_CHECK_DISABLED` configuration setting.
- The app is not running in publish mode.
-Updates are manual. You need to edit your project file to upgrade the Aspire SDK and package versions.
+Use [`aspire update`](/reference/cli/commands/aspire-update/) or edit package versions manually. In Aspire 17.0, the default C# AppHost uses `Microsoft.NET.Sdk` and explicit `Aspire.Hosting.AppHost` and `Aspire.Hosting.Dotnet` packages. See [Migrate from the AppHost SDK](/get-started/migrate-apphost-sdk/) for existing SDK-based AppHosts.
+
+## CLI bundle configuration
+
+C# AppHosts in Aspire 17.0 require the Aspire CLI bundle. `AspireUseCliBundle` defaults to `true`; setting it to `false` produces error [ASPIRE010](/diagnostics/aspire010/) and can't be made valid with `NoWarn`. The bundle supplies the dashboard and DCP, including when the obsolete AppHost SDK is retained.
+
+`AspireCliPath` selects an executable; `AspireCliBundlePath` identifies an unpacked bundle layout. Invalid explicit paths remain authoritative and can produce [ASPIRE009](/diagnostics/aspire009/). For automatic discovery and DNX invocation modes, see [Use the Aspire CLI bundle](/get-started/aspire-sdk/#use-the-aspire-cli-bundle-for-orchestration-dependencies).
## Resource service
@@ -195,11 +201,11 @@ The `DcpCliPath` property specifies the path to the **Developer Control Plane (D
#### How it works
-When you use the [Aspire SDK](/get-started/aspire-sdk/), the build system automatically:
+With the required [Aspire CLI bundle](/get-started/aspire-sdk/#use-the-aspire-cli-bundle-for-orchestration-dependencies), the AppHost targets automatically:
-1. Imports the platform-specific `Aspire.Hosting.Orchestration` NuGet package (for example, `Aspire.Hosting.Orchestration.win-x64`).
-2. Sets `DcpCliPath` to point to the `dcp` executable within that package.
-3. Embeds this path as assembly metadata in your compiled AppHost.
+1. Resolve DCP from the selected Aspire CLI bundle.
+2. Set `DcpCliPath` to point to the `dcp` executable within that bundle.
+3. Embed this path as assembly metadata in your compiled AppHost.
At runtime, the AppHost reads this metadata to locate and start the DCP process, which then orchestrates your application's resources.
@@ -222,5 +228,5 @@ You might override `DcpCliPath` in these scenarios:
- **Troubleshooting**: Temporarily pointing to a specific DCP version to diagnose issues.
diff --git a/src/frontend/src/content/docs/diagnostics/aspire007.mdx b/src/frontend/src/content/docs/diagnostics/aspire007.mdx
index d6a6a1eb28..c0cefb6b02 100644
--- a/src/frontend/src/content/docs/diagnostics/aspire007.mdx
+++ b/src/frontend/src/content/docs/diagnostics/aspire007.mdx
@@ -15,7 +15,9 @@ import { Badge } from '@astrojs/starlight/components';
> The project is missing a required Aspire.AppHost.Sdk with a version of at least 9.0.0. Please add the following line after the Project declaration ``.
-The Aspire AppHost package references require Aspire SDK version 9.0.0 or greater. The SDK reference is either being omitted or is using a version older than 9.0.0.
+This diagnostic applies to the SDK requirement introduced with Aspire 9.0. With those package versions, the SDK reference is either omitted or uses a version older than 9.0.0. Aspire 17.0 still reports it for retained SDKs older than 9.0.0 or an invalid retained SDK reference. The legacy correction below is for SDK-based projects.
+
+Starting in Aspire 17.0, package-based AppHosts no longer require `Aspire.AppHost.Sdk`. Use `Microsoft.NET.Sdk` with explicit AppHost and Dotnet packages instead; see [Migrate from the AppHost SDK](/get-started/migrate-apphost-sdk/). Don't reintroduce the obsolete SDK into a package-based 17.0 AppHost to follow the legacy example.
## To correct this error
diff --git a/src/frontend/src/content/docs/diagnostics/aspire009.mdx b/src/frontend/src/content/docs/diagnostics/aspire009.mdx
index d8c46fa66f..e9c7ac4d2d 100644
--- a/src/frontend/src/content/docs/diagnostics/aspire009.mdx
+++ b/src/frontend/src/content/docs/diagnostics/aspire009.mdx
@@ -15,7 +15,7 @@ import { Badge } from '@astrojs/starlight/components';
> '[ProjectName]' is configured to use the Aspire CLI bundle, but the bundle could not be resolved.
-This diagnostic error is reported when an AppHost project opts in to the Aspire CLI bundle (`AspireUseCliBundle=true`) but the SDK can't resolve a usable bundle layout for the developer control plane (DCP) and the Aspire Dashboard.
+This diagnostic error is reported when an AppHost project uses the Aspire CLI bundle (`AspireUseCliBundle=true`) but the AppHost targets can't resolve a usable bundle layout for the developer control plane (DCP) and the Aspire Dashboard. The bundle is enabled by default and required for C# AppHosts in Aspire 17.0.
When neither `AspireCliPath` nor `AspireCliBundlePath` is set, a usable `dnx` host can resolve or prepare the required bundle layout through the selected Aspire CLI package. Therefore, a missing `aspire` command alone doesn't cause `ASPIRE009`. Explicit paths are authoritative: an invalid `AspireCliPath` or `AspireCliBundlePath` causes `ASPIRE009` even when `dnx` is available.
@@ -48,6 +48,6 @@ When no explicit path is set, either [install the Aspire CLI](https://get.aspire
If `Dnx` or `DnxPinned` mode can't find `dnx`, the run preflight reports [`ASPIRE011`](/diagnostics/aspire011/). A missing `dnx` command isn't itself an `ASPIRE009` condition, although a separate bundle-resolution failure can still produce `ASPIRE009`.
-Alternatively, set `AspireUseCliBundle` to `false` to restore orchestration dependencies from NuGet packages. Doing so reports [`ASPIRE010`](/diagnostics/aspire010/) because some Aspire features require the CLI bundle.
+In Aspire 17.0, setting `AspireUseCliBundle` to `false` isn't a workaround: it produces error [`ASPIRE010`](/diagnostics/aspire010/), which can't be suppressed to disable the bundle. Correct the installation or invalid path instead.
For more information, see [Use the Aspire CLI bundle for orchestration dependencies](/get-started/aspire-sdk/#use-the-aspire-cli-bundle-for-orchestration-dependencies).
diff --git a/src/frontend/src/content/docs/diagnostics/aspire010.mdx b/src/frontend/src/content/docs/diagnostics/aspire010.mdx
index f99552d710..be93094ab0 100644
--- a/src/frontend/src/content/docs/diagnostics/aspire010.mdx
+++ b/src/frontend/src/content/docs/diagnostics/aspire010.mdx
@@ -1,7 +1,7 @@
---
-title: Compiler Warning ASPIRE010
-seoTitle: 'ASPIRE010: Aspire CLI bundle opt-out warning · Aspire'
-description: Learn what causes Aspire compiler warning ASPIRE010 — the AppHost has opted out of the Aspire CLI bundle — and how to enable or suppress it.
+title: Compiler Error ASPIRE010
+seoTitle: 'ASPIRE010: The Aspire CLI bundle is required'
+description: Learn why disabling the required Aspire CLI bundle produces error ASPIRE010 in Aspire 17.0 and how to correct it.
---
import { Badge } from '@astrojs/starlight/components';
@@ -13,9 +13,9 @@ import { Badge } from '@astrojs/starlight/components';
class:list={'mb-1'}
/>
-> '[ProjectName]' is configured with AspireUseCliBundle=false. Some Aspire features require the Aspire CLI bundle. Set AspireUseCliBundle=true to enable those features, or suppress ASPIRE010 to continue without the bundle. See https://aka.ms/aspire/diagnostics/aspire010 for more information.
+> [ProjectName] requires the Aspire CLI bundle. Remove AspireUseCliBundle or set it to true, and install the matching Aspire CLI from https://get.aspire.dev. ASPIRE010 cannot be suppressed to disable the bundle. See https://aka.ms/aspire/diagnostics/aspire010 for more information.
-This diagnostic warning is reported when an AppHost project has `AspireUseCliBundle` set to `false` (the default). Launching the AppHost directly with `dotnet run` or an IDE continues to work without the Aspire CLI, but features that depend on the CLI bundle — such as resolving DCP and the Aspire Dashboard from the installed Aspire CLI instead of NuGet packages — remain unavailable.
+Introduced as a warning in Aspire 13.5, this diagnostic is an **error in Aspire 17.0** when a C# AppHost disables the required CLI bundle. `AspireUseCliBundle` now defaults to `true`. This applies both to package-based AppHosts and projects retaining `Aspire.AppHost.Sdk`.
## Example
@@ -27,11 +27,11 @@ The following configuration produces `ASPIRE010`:
```
-`ASPIRE010` is also reported when `AspireUseCliBundle` isn't set at all, because `false` is the default.
+Leaving `AspireUseCliBundle` unset uses the enabled default and doesn't produce this error.
-## To correct this warning
+## To correct this error
-Set `AspireUseCliBundle` to `true` to opt in to CLI bundle delegation:
+Remove the `false` setting or set `AspireUseCliBundle` to `true`, and [install a compatible Aspire CLI](/get-started/install-cli/):
```xml title="MyApp.AppHost.csproj"
@@ -39,17 +39,10 @@ Set `AspireUseCliBundle` to `true` to opt in to CLI bundle delegation:
```
-When you opt in, an explicit `AspireCliPath` is authoritative. Otherwise, the default `Path` invocation mode selects a compatible `aspire` on `PATH`, with the SDK-paired Aspire CLI package through DNX as a fallback. Setting `AspireCliInvocationMode=Dnx` selects the unversioned package through DNX so a tool manifest can apply, while `DnxPinned` selects the version paired with the AppHost SDK. `AspireCliBundlePath` is a bundle-layout input, not an executable invocation candidate.
+An explicit `AspireCliPath` is authoritative. Otherwise, the default `Path` invocation mode selects a compatible `aspire` on `PATH`, with the CLI package paired with `Aspire.Hosting.AppHost` through DNX as a fallback. `AspireCliInvocationMode=Dnx` selects the unversioned package through DNX so a tool manifest can apply, while `DnxPinned` selects the AppHost-package-paired version. `AspireCliBundlePath` is a bundle-layout input, not an executable invocation candidate.
An unresolved bundle layout reports [`ASPIRE009`](/diagnostics/aspire009/). [`ASPIRE011`](/diagnostics/aspire011/) is limited to the run preflight when `Dnx` or `DnxPinned` mode can't find `dnx`; it doesn't represent every CLI resolution failure.
-If you intend to keep using NuGet-restored orchestration dependencies, suppress `ASPIRE010`:
-
-```xml title="MyApp.AppHost.csproj"
-
- false
- $(NoWarn);ASPIRE010
-
-```
+`NoWarn=ASPIRE010` doesn't suppress this error or make a bundle opt-out valid. Earlier versions' warning suppression guidance doesn't apply to Aspire 17.0.
For more information, see [Use the Aspire CLI bundle for orchestration dependencies](/get-started/aspire-sdk/#use-the-aspire-cli-bundle-for-orchestration-dependencies).
diff --git a/src/frontend/src/content/docs/diagnostics/aspire012.mdx b/src/frontend/src/content/docs/diagnostics/aspire012.mdx
new file mode 100644
index 0000000000..3d6ab2fe0c
--- /dev/null
+++ b/src/frontend/src/content/docs/diagnostics/aspire012.mdx
@@ -0,0 +1,39 @@
+---
+title: Compiler Warning ASPIRE012
+seoTitle: 'ASPIRE012: Aspire.AppHost.Sdk is obsolete'
+description: Learn why Aspire.AppHost.Sdk reports ASPIRE012, how to migrate to explicit packages, and how to suppress the warning during staged migration.
+---
+
+import { Badge } from '@astrojs/starlight/components';
+
+
+
+> [ProjectName] uses the Aspire.AppHost.Sdk, which is obsolete but remains available for staged migration. Switch the project's Sdk attribute to Microsoft.NET.Sdk, add explicit PackageReference items for Aspire.Hosting.AppHost and Aspire.Hosting.Dotnet, and migrate C# resource ProjectReference items to AddDotnetProject calls. See https://aka.ms/aspire/diagnostics/aspire012 for migration guidance.
+
+This warning is reported when a project uses `Aspire.AppHost.Sdk`. The SDK remains functional, including original `ProjectReference` and `AddProject` resources. No removal date has been agreed, and this warning doesn't deprecate `AddProject`.
+
+## To correct this warning
+
+Follow [Migrate from the AppHost SDK](/get-started/migrate-apphost-sdk/): use `Microsoft.NET.Sdk`, explicitly reference `Aspire.Hosting.AppHost` and `Aspire.Hosting.Dotnet`, and use `AddDotnetProject` for path-based resources. Keep the required CLI bundle enabled.
+
+For staged migration, retained `AddProject` resources require `IsAspireProjectResource="true"` and `ReferenceOutputAssembly="false"` on their project references after removing the SDK.
+
+## Suppress the warning temporarily
+
+While you retain the obsolete SDK, set:
+
+```xml
+
+ true
+
+```
+
+Alternatively, append `ASPIRE012` to `NoWarn`:
+
+```xml
+
+ $(NoWarn);ASPIRE012
+
+```
+
+Suppression doesn't change resource declarations or bundle requirements. Unlike this warning, [ASPIRE010](/diagnostics/aspire010/) is an error in Aspire 17.0 and can't be suppressed to disable the bundle.
diff --git a/src/frontend/src/content/docs/diagnostics/overview.mdx b/src/frontend/src/content/docs/diagnostics/overview.mdx
index 9e0b41b8ed..535912db37 100644
--- a/src/frontend/src/content/docs/diagnostics/overview.mdx
+++ b/src/frontend/src/content/docs/diagnostics/overview.mdx
@@ -16,8 +16,9 @@ The following table lists the possible MSBuild and analyzer warnings and errors
| [ASPIRE007](/diagnostics/aspire007/) | Error | 'Project' requires a reference to "Aspire.AppHost.Sdk" with version "9.0.0" or greater to work correctly. |
| [ASPIRE008](/diagnostics/aspire008/) | Error | 'Project' requires GenerateAssemblyInfo to be enabled for the AppHost to function correctly. |
| [ASPIRE009](/diagnostics/aspire009/) | Error | 'Project' is configured to use the Aspire CLI bundle, but the bundle could not be resolved. |
-| [ASPIRE010](/diagnostics/aspire010/) | Warning | 'Project' is configured with AspireUseCliBundle=false. Some Aspire features require the Aspire CLI bundle. |
+| [ASPIRE010](/diagnostics/aspire010/) | Error (17.0 onward) | The C# AppHost requires the Aspire CLI bundle. Remove AspireUseCliBundle or set it to true; warning suppression doesn't permit opting out. |
| [ASPIRE011](/diagnostics/aspire011/) | Error | 'Project' is configured to invoke the Aspire CLI through DNX, but the dnx command could not be found on PATH. |
+| [ASPIRE012](/diagnostics/aspire012/) | Warning | Aspire.AppHost.Sdk is obsolete but remains functional for staged migration. Use Microsoft.NET.Sdk and explicit AppHost and Dotnet packages. |
| [ASPIREACADOMAINS001](/diagnostics/aspireacadomains001/) | (Experimental) Error | `ConfigureCustomDomain` is for evaluation purposes only and is subject to change or removal in future updates. |
| [ASPIREACAEXPRESS001](/diagnostics/aspireacaexpress001/) | (Experimental) Error | `AsExpress` is for evaluation purposes only and is subject to change or removal in future updates. |
| [ASPIREACANAMING001](/diagnostics/aspireacanaming001/) | (Experimental) Warning | `WithCompactResourceNaming` is for evaluation purposes only and is subject to change or removal in future updates. |
diff --git a/src/frontend/src/content/docs/get-started/aspire-sdk.mdx b/src/frontend/src/content/docs/get-started/aspire-sdk.mdx
index 063e0ed3cb..0014a05baa 100644
--- a/src/frontend/src/content/docs/get-started/aspire-sdk.mdx
+++ b/src/frontend/src/content/docs/get-started/aspire-sdk.mdx
@@ -1,12 +1,18 @@
---
title: Aspire SDK for distributed apps
-description: Learn how the Aspire SDK simplifies orchestrating Aspire applications — packaging, project references, source generators, and how the SDK plugs into AppHost projects.
+description: Learn about package-based C# AppHosts, migrating from the obsolete Aspire SDK, and the required Aspire CLI bundle.
---
import { Tabs, TabItem } from '@astrojs/starlight/components';
import LearnMore from '@components/LearnMore.astro';
-The Aspire SDK is intended for [AppHost projects](/get-started/app-host/), which serve as the orchestrator for Aspire applications. These projects are designated by their usage of the `Aspire.AppHost.Sdk` in the project file. The SDK provides features that simplify the development of Aspire apps.
+Starting in Aspire 17.0, the default C# [AppHost project](/get-started/app-host/) uses `Microsoft.NET.Sdk` with explicit `Aspire.Hosting.AppHost` and `Aspire.Hosting.Dotnet` package references. The AppHost package identifies the project as an AppHost and supplies build targets. Declare services with `builder.AddDotnetProject("myservice", "../MyService/")`; the Dotnet package provides this API.
+
+:::caution[The AppHost SDK is obsolete]
+`Aspire.AppHost.Sdk` reports [ASPIRE012](/diagnostics/aspire012/) but remains functional for staged migration. It doesn't deprecate `AddProject`. Follow [Migrate from the AppHost SDK](/get-started/migrate-apphost-sdk/) to change packages, resources, and solution/CI build inputs.
+:::
+
+The SDK examples and project-reference defaults below describe existing projects that retain the obsolete SDK, not the default configuration for new AppHosts.
The [📦 Aspire.AppHost.Sdk](https://www.nuget.org/packages/Aspire.AppHost.Sdk) is used for building Aspire apps.
@@ -92,28 +98,28 @@ var microservice1 = builder.AddProject("micro1");
var microservice2 = builder.AddProject("micro2");
```
-### Orchestrator dependencies
+### Historical orchestrator dependencies
-The Aspire SDK dynamically adds references to the [Aspire Dashboard](/dashboard/overview/) and other AppHost dependencies, such as the developer control plane (DCP) packages. These dependencies are specific to the platform that the AppHost is built on.
+Before the required CLI bundle, the Aspire SDK dynamically added platform-specific references to the [Aspire Dashboard](/dashboard/overview/) and developer control plane (DCP) packages. Aspire 17.0 uses the CLI bundle instead.
When the AppHost project runs, the orchestrator relies on these dependencies to provide the necessary functionality to the AppHost. For more information, see [Aspire orchestration overview](/get-started/app-host/).
### Use the Aspire CLI bundle for orchestration dependencies
-The Aspire SDK can source the binaries for these dependencies from platform-specific NuGet packages or from the installed **Aspire CLI bundle**. When it uses NuGet packages, the versions that run with your AppHost are tied to package restore.
+In Aspire 17.0, C# AppHosts require the **Aspire CLI bundle** for these binaries. This applies to both package-based AppHosts and projects retaining the obsolete SDK.
-When it uses the Aspire CLI bundle, those binaries update when you update the Aspire CLI through [`aspire update --self`](/reference/cli/commands/aspire-update/). Without the bundle, the Aspire SDK version used by the AppHost determines the binaries by adding implicit references to the RID-specific `Aspire.Hosting.Orchestration.*` and `Aspire.Dashboard.Sdk.*` packages.
+Bundle binaries update when you update the selected Aspire CLI through [`aspire update --self`](/reference/cli/commands/aspire-update/).
-New C# AppHost projects created with `aspire new` or `dotnet new`, and new single-file AppHosts created with `aspire init`, set `AspireUseCliBundle` to `true` automatically. For existing AppHosts, set `AspireUseCliBundle` to `true` to enable the CLI bundle. We recommend enabling it now because the CLI bundle will become the only supported source for orchestration dependencies in an upcoming Aspire release. The SDK property currently defaults to `false`, so launching a C# AppHost with `dotnet run` or an IDE continues to work without requiring the Aspire CLI. Leaving it unset (or explicitly `false`) reports warning [`ASPIRE010`](/diagnostics/aspire010/) as a reminder that some Aspire features require the bundle; suppress it if you intend to keep using NuGet-restored orchestration dependencies.
+`AspireUseCliBundle` defaults to `true` for C# project and file-based AppHosts. Remove an existing `false` setting or change it to `true`. Disabling the bundle reports error [`ASPIRE010`](/diagnostics/aspire010/); `NoWarn=ASPIRE010` doesn't permit opting out. An unresolved bundle reports [`ASPIRE009`](/diagnostics/aspire009/).
When `AspireUseCliBundle` is `true`:
-- `Aspire.AppHost.Sdk` still sets AppHost properties and adds the implicit `Aspire.Hosting.AppHost` package.
+- Package-based AppHosts explicitly reference `Aspire.Hosting.AppHost`; projects retaining the obsolete SDK can still receive its implicit reference.
- Your AppHost uses the DCP and Dashboard versions installed with the Aspire CLI.
- The SDK selects the executable used to launch the AppHost as follows:
1. An explicit `AspireCliPath` is always authoritative.
2. When `AspireCliInvocationMode` is set to `Dnx` or `DnxPinned`, the SDK selects a usable `dnx` host.
- 3. Otherwise, the default `Path` mode selects a compatible `aspire` on `PATH`, then falls back to the SDK-paired Aspire CLI package through DNX.
+ 3. Otherwise, the default `Path` mode selects a compatible `aspire` on `PATH`, then falls back to the Aspire CLI package paired with `Aspire.Hosting.AppHost` through DNX.
- `AspireCliBundlePath` isn't an executable candidate. It explicitly identifies a bundle layout for DCP and Dashboard resolution.
- If the resolved Aspire CLI has a bundle that hasn't been extracted yet, the build runs `aspire setup` through the selected `aspire` or paired DNX invocation to extract it, then resolves the bundle again. This lets an AppHost build and launch from an IDE even when the CLI installation didn't run the release install scripts.
- If a required bundle layout can't be resolved, the build emits error [`ASPIRE009`](/diagnostics/aspire009/). Invalid explicit `AspireCliPath` and `AspireCliBundlePath` values remain authoritative and can produce this error.
@@ -121,6 +127,8 @@ When `AspireUseCliBundle` is `true`:
#### Enable the CLI bundle
+The following setting is optional because `true` is the default:
+
Set `AspireUseCliBundle` in your AppHost `.csproj`:
```xml title="MyApp.AppHost.csproj"
@@ -151,15 +159,15 @@ Most apps don't need to set either path. `AspireCliPath` selects an explicit `as
#### Running with aspire run or aspire start
-When you start an opted-in AppHost using `aspire run` or `aspire start`, the CLI automatically passes the resolved bundle paths through the `ASPIRE_DCP_PATH` and `ASPIRE_DASHBOARD_PATH` environment variables.
+When you start an AppHost using `aspire run` or `aspire start`, the CLI automatically passes the resolved bundle paths through the `ASPIRE_DCP_PATH` and `ASPIRE_DASHBOARD_PATH` environment variables.
#### Running with dotnet run
-When `AspireUseCliBundle` is `true` and you start the AppHost with `dotnet run` instead of `aspire run`, the SDK resolves and invokes the Aspire CLI itself. Set `AspireCliInvocationMode` to control how that invocation happens:
+When you start the AppHost with `dotnet run` instead of `aspire run`, the AppHost package targets resolve and invoke the Aspire CLI. Set `AspireCliInvocationMode` to control how that invocation happens:
-- **`Path`** (default) — resolves a compatible `aspire` command from `AspireCliPath` (if set) or `PATH`. If no compatible command is found, it falls back to invoking the `Aspire.Cli` version paired with `Aspire.AppHost.Sdk` through [`dnx`](https://learn.microsoft.com/dotnet/core/tools/dotnet-tool-exec).
+- **`Path`** (default) — resolves a compatible `aspire` command from `AspireCliPath` (if set) or `PATH`. If no compatible command is found, it falls back to invoking the `Aspire.Cli` version paired with `Aspire.Hosting.AppHost` through [`dnx`](https://learn.microsoft.com/dotnet/core/tools/dotnet-tool-exec).
- **`Dnx`** — always invokes the Aspire CLI through `dnx`, using the unversioned `Aspire.Cli` package. This honors an in-scope [.NET local tool manifest](https://learn.microsoft.com/dotnet/core/tools/local-tools-how-to-use#create-a-manifest-file) (`.config/dotnet-tools.json`) if one pins `Aspire.Cli`, or resolves the latest published package when no manifest applies.
-- **`DnxPinned`** — always invokes the Aspire CLI through `dnx`, using `Aspire.Cli@` pinned to the exact `Aspire.Cli` version paired with `Aspire.AppHost.Sdk`. Use this when the CLI must match the AppHost SDK version exactly, ignoring any local tool manifest.
+- **`DnxPinned`** — always invokes the Aspire CLI through `dnx`, using `Aspire.Cli@` pinned to the exact `Aspire.Cli` version paired with `Aspire.Hosting.AppHost`, independently of an older retained SDK and ignoring any local tool manifest.
Set `AspireCliInvocationMode` in your AppHost `.csproj`:
diff --git a/src/frontend/src/content/docs/get-started/migrate-apphost-sdk.mdx b/src/frontend/src/content/docs/get-started/migrate-apphost-sdk.mdx
new file mode 100644
index 0000000000..f7453d7e42
--- /dev/null
+++ b/src/frontend/src/content/docs/get-started/migrate-apphost-sdk.mdx
@@ -0,0 +1,138 @@
+---
+title: Migrate from the AppHost SDK
+description: Migrate a C# AppHost to Microsoft.NET.Sdk, explicit Aspire packages, AddDotnetProject resources, and the required Aspire CLI bundle.
+---
+
+Starting in Aspire 17.0, `Aspire.AppHost.Sdk` is obsolete and reports warning [ASPIRE012](/diagnostics/aspire012/). It remains functional for staged migration, including existing `ProjectReference` and `AddProject` resources. No removal date has been agreed. SDK obsoletion does **not** deprecate `AddProject`.
+
+The default C# experience uses `Microsoft.NET.Sdk`, explicit `Aspire.Hosting.AppHost` and `Aspire.Hosting.Dotnet` packages, and `AddDotnetProject`. The AppHost package supplies the AppHost build targets; the Dotnet package supplies `AddDotnetProject`. The required Aspire CLI bundle supplies the dashboard and developer control plane (DCP).
+
+## Change the project SDK and packages
+
+Replace the `Aspire.AppHost.Sdk` SDK attribute (or nested `` element) with `Microsoft.NET.Sdk`. Add explicit references to both packages at compatible versions from a release supporting `AddDotnetProject`:
+
+```xml title="MyApp.AppHost.csproj"
+
+
+ Exe
+ net10.0
+ enable
+ enable
+
+
+
+
+
+
+```
+
+Keep your existing target framework, user secrets, launch settings, and other integration packages unless they separately need updating. `Aspire.Hosting.AppHost` sets `IsAspireHost`; an SDK reference is no longer required.
+
+### Central Package Management
+
+If `ManagePackageVersionsCentrally` is enabled, omit `Version` from the AppHost's `PackageReference` items and declare matching `PackageVersion` items in `Directory.Packages.props`. Keep the explicit AppHost package reference.
+
+```xml title="Directory.Packages.props (inside Project)"
+
+
+
+
+```
+
+```xml title="MyApp.AppHost.csproj (inside Project)"
+
+
+
+
+```
+
+Templates that emit inline package versions require this manual adjustment when created under a central package management root. Otherwise restore reports `NU1008`, even if the central versions already exist. Review service projects and optional integrations for inline versions too; don't assume creating or updating an AppHost automatically centralizes them.
+
+## Migrate project resources
+
+Replace each generated-metadata resource declaration with a path-based declaration:
+
+```csharp title="Before"
+var service = builder.AddProject("myservice");
+```
+
+```csharp title="After"
+var service = builder.AddDotnetProject("myservice", "../MyService/");
+```
+
+Use a trailing slash for a project directory containing a single project. An explicit project-file path, such as `"../MyService/MyService.csproj"`, remains supported when you need to select a particular project. Preserve resource names and chained endpoint settings, health checks, references, and waits. Review launch-profile options and excluded endpoints individually rather than mechanically replacing every overload.
+
+Remove the service's `ProjectReference` from the AppHost after converting its resource declaration. `AddDotnetProject` discovers and builds the service when starting it; it doesn't require an AppHost project reference.
+
+:::caution[Keep services in solution and CI builds]
+After removing service project references, building the AppHost alone no longer builds those services. Keep service projects in the solution and in CI build and publish inputs. Build the solution separately; successful AppHost compilation isn't evidence that all service projects compile.
+:::
+
+### Retain AddProject during staged migration
+
+You can remove the obsolete SDK without converting every `AddProject` resource at once. Under `Microsoft.NET.Sdk`, ordinary project references aren't automatically Aspire resources. Explicitly mark retained resources and prevent their output assemblies from becoming AppHost assembly references:
+
+```xml title="MyApp.AppHost.csproj (inside Project)"
+
+
+
+```
+
+This keeps the generated `Projects.MyService` metadata available for `AddProject`. An unannotated reference doesn't generate that resource metadata and can cause `CS0234` for the missing `Projects` type. Preserve any custom `AspireProjectMetadataTypeName` metadata.
+
+Keep genuine shared-library references as ordinary `ProjectReference` items. If you retain the obsolete SDK, set `IsAspireProjectResource="false"` on references that aren't orchestrated resources.
+
+## Use the required CLI bundle
+
+[Install a compatible Aspire CLI](/get-started/install-cli/). `AspireUseCliBundle` defaults to `true` for C# AppHosts, so you can omit it or set it explicitly:
+
+```xml
+
+ true
+
+```
+
+In Aspire 17.0, setting it to `false` produces error [ASPIRE010](/diagnostics/aspire010/). `NoWarn=ASPIRE010` doesn't make opting out valid. An unresolved or invalid bundle produces [ASPIRE009](/diagnostics/aspire009/); correct the installation or explicit paths instead of disabling the bundle.
+
+See [CLI bundle resolution and invocation modes](/get-started/aspire-sdk/#use-the-aspire-cli-bundle-for-orchestration-dependencies). Pinned DNX invocation uses the CLI version paired with `Aspire.Hosting.AppHost`, independently of an older SDK retained during staged migration.
+
+## Migrate a file-based AppHost
+
+Replace the obsolete `#:sdk Aspire.AppHost.Sdk@...` directive with explicit package directives:
+
+```csharp title="apphost.cs"
+#:package Aspire.Hosting.AppHost@%ASPIRE_VERSION%
+#:package Aspire.Hosting.Dotnet@%ASPIRE_VERSION%
+
+var builder = DistributedApplication.CreateBuilder(args);
+builder.AddDotnetProject("myservice", "../MyService/");
+builder.Build().Run();
+```
+
+Retain run configuration, user secrets, and other package directives. The CLI bundle is enabled by default; an explicit `#:property AspireUseCliBundle=true` is optional. The AppHost package sets `PublishAot=false` for file-based AppHosts, preserving the former SDK behavior. This doesn't change Native AOT settings for your service projects.
+
+## Verify the migration
+
+Restore and build the AppHost and the solution, then start the AppHost with the matching Aspire CLI. Verify that the dashboard starts, resource names and endpoints are unchanged, services return expected responses, and Restart/Rebuild work. Check service-to-service references and waits, not just AppHost compilation. Review IDE behavior separately; successful command-line builds don't qualify Visual Studio behavior.
+
+## Temporarily suppress ASPIRE012
+
+If you keep the functional obsolete SDK while migrating, either suppression is supported:
+
+```xml
+
+ true
+
+```
+
+Or append the diagnostic to the existing warning list:
+
+```xml
+
+ $(NoWarn);ASPIRE012
+
+```
+
+Suppression doesn't migrate resources or remove the requirement for a working CLI bundle.
diff --git a/src/frontend/src/content/docs/whats-new/aspire-17.mdx b/src/frontend/src/content/docs/whats-new/aspire-17.mdx
index 4c5cbc2c5e..da572493d7 100644
--- a/src/frontend/src/content/docs/whats-new/aspire-17.mdx
+++ b/src/frontend/src/content/docs/whats-new/aspire-17.mdx
@@ -55,6 +55,20 @@ Once Aspire 17.0 is available on the stable channel, use the [`aspire update` co
+#### AppHost SDK is obsolete and the CLI bundle is required
+
+The default C# AppHost now uses `Microsoft.NET.Sdk` with explicit `Aspire.Hosting.AppHost` and `Aspire.Hosting.Dotnet` package references. Declare project resources with `AddDotnetProject` using a project directory with a trailing slash:
+
+```csharp
+builder.AddDotnetProject("apiservice", "../MyApp.ApiService/");
+```
+
+`Aspire.AppHost.Sdk` reports warning [ASPIRE012](/diagnostics/aspire012/) but remains functional for staged migration, including original `ProjectReference` and `AddProject` resources. No removal date has been agreed; SDK obsoletion doesn't deprecate `AddProject`. After removing the SDK, retained `AddProject` resource references need explicit `IsAspireProjectResource="true"` and `ReferenceOutputAssembly="false"` metadata.
+
+C# AppHosts require the CLI bundle, enabled by default. Disabling it produces error [ASPIRE010](/diagnostics/aspire010/), not a suppressible warning. Fix an unresolved bundle using [ASPIRE009 guidance](/diagnostics/aspire009/) rather than opting out.
+
+Follow [Migrate from the AppHost SDK](/get-started/migrate-apphost-sdk/) for project and file-based AppHosts, central package management, and verification. Removing service project references means AppHost-only builds no longer build those services; keep solution and CI service builds. See [microsoft/aspire#20867](https://github.com/microsoft/aspire/pull/20867) for the source change.
+
#### Legacy RabbitMQ and MongoDB client packages removed
Starting in Aspire 17.0, new releases no longer include `Aspire.RabbitMQ.Client.v6` or `Aspire.MongoDB.Driver.v2`. Previously published versions of these packages remain available on NuGet.
diff --git a/src/frontend/src/content/docs/whats-new/upgrade-aspire.mdx b/src/frontend/src/content/docs/whats-new/upgrade-aspire.mdx
index e156111304..1ef9640577 100644
--- a/src/frontend/src/content/docs/whats-new/upgrade-aspire.mdx
+++ b/src/frontend/src/content/docs/whats-new/upgrade-aspire.mdx
@@ -43,6 +43,14 @@ If you're new to Aspire, there's no reason to upgrade anything. See [prerequisit
For more information, see [`aspire update` command reference](/reference/cli/commands/aspire-update/).
+## Migrate C# AppHosts for Aspire 17.0
+
+Updating package versions isn't the same as migrating AppHost resources. In Aspire 17.0, the default C# AppHost uses `Microsoft.NET.Sdk` with explicit `Aspire.Hosting.AppHost` and `Aspire.Hosting.Dotnet` references and `AddDotnetProject` declarations.
+
+Follow [Migrate from the AppHost SDK](/get-started/migrate-apphost-sdk/) to replace the obsolete SDK and service project references while preserving resource configuration. `Aspire.AppHost.Sdk` remains functional for staged migration; `AddProject` isn't deprecated by this SDK change. Retained `AddProject` references need explicit resource metadata after SDK removal.
+
+The CLI bundle is required and enabled by default. Remove `AspireUseCliBundle=false`: [ASPIRE010](/diagnostics/aspire010/) is now an error, and warning suppression doesn't permit opting out. Keep service projects in solution/CI builds after removing their AppHost project references. If you use central package management, move inline package versions to `Directory.Packages.props` manually to avoid `NU1008`.
+
## Update standalone dashboard container references
If you manage the standalone dashboard as a container, its stable image repository is now `mcr.microsoft.com/aspire/dashboard`; nightly images use `mcr.microsoft.com/aspire/nightly/dashboard`. Updating the Aspire CLI or packages doesn't rewrite image references in your own Docker commands, Compose files, or Kubernetes manifests.
From 830285d00e88d7c628aa15bdb1910a8594597551 Mon Sep 17 00:00:00 2001
From: David Fowler <95136+davidfowl@users.noreply.github.com>
Date: Tue, 13 Oct 2026 06:44:45 +0000
Subject: [PATCH 2/2] docs: make upcoming migration package versions explicit
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---
.../docs/get-started/migrate-apphost-sdk.mdx | 14 ++++++++------
1 file changed, 8 insertions(+), 6 deletions(-)
diff --git a/src/frontend/src/content/docs/get-started/migrate-apphost-sdk.mdx b/src/frontend/src/content/docs/get-started/migrate-apphost-sdk.mdx
index f7453d7e42..96c9347af6 100644
--- a/src/frontend/src/content/docs/get-started/migrate-apphost-sdk.mdx
+++ b/src/frontend/src/content/docs/get-started/migrate-apphost-sdk.mdx
@@ -11,6 +11,8 @@ The default C# experience uses `Microsoft.NET.Sdk`, explicit `Aspire.Hosting.App
Replace the `Aspire.AppHost.Sdk` SDK attribute (or nested `` element) with `Microsoft.NET.Sdk`. Add explicit references to both packages at compatible versions from a release supporting `AddDotnetProject`:
+This guide describes Aspire 17.0, which is upcoming. Replace `17.x.x` in the examples with an available compatible version from that release or its prerelease channel; `17.x.x` isn't a literal package version. Don't use the site's current stable 13.6 version for this SDK-removal migration.
+
```xml title="MyApp.AppHost.csproj"
@@ -20,8 +22,8 @@ Replace the `Aspire.AppHost.Sdk` SDK attribute (or nested `
-
+
+
```
@@ -34,8 +36,8 @@ If `ManagePackageVersionsCentrally` is enabled, omit `Version` from the AppHost'
```xml title="Directory.Packages.props (inside Project)"
-
-
+
+
```
@@ -103,8 +105,8 @@ See [CLI bundle resolution and invocation modes](/get-started/aspire-sdk/#use-th
Replace the obsolete `#:sdk Aspire.AppHost.Sdk@...` directive with explicit package directives:
```csharp title="apphost.cs"
-#:package Aspire.Hosting.AppHost@%ASPIRE_VERSION%
-#:package Aspire.Hosting.Dotnet@%ASPIRE_VERSION%
+#:package Aspire.Hosting.AppHost@17.x.x
+#:package Aspire.Hosting.Dotnet@17.x.x
var builder = DistributedApplication.CreateBuilder(args);
builder.AddDotnetProject("myservice", "../MyService/");