From 2a6252fc33fb31860c6aff167e96c157b1495fb2 Mon Sep 17 00:00:00 2001 From: Adam Ratzman Date: Thu, 12 Mar 2026 01:23:30 -0400 Subject: [PATCH 1/4] always build file-based apps to prevent using cached version --- extension/src/debugger/languages/dotnet.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/extension/src/debugger/languages/dotnet.ts b/extension/src/debugger/languages/dotnet.ts index 2009733dfcb..2135b172368 100644 --- a/extension/src/debugger/languages/dotnet.ts +++ b/extension/src/debugger/languages/dotnet.ts @@ -325,10 +325,9 @@ export function createProjectDebuggerExtension(dotNetServiceProducer: (debugSess const runApiOutput = await dotNetService.getDotNetRunApiOutput(projectPath); const runApiConfig = getRunApiConfigFromOutput(runApiOutput); - // Build if the executable doesn't exist or forceBuild is requested - if ((!(await doesFileExist(runApiConfig.executablePath)) || launchOptions.forceBuild)) { - await dotNetService.buildDotNetProject(projectPath); - } + // There may be an older cached version of the file-based app, so we + // should force a build. + await dotNetService.buildDotNetProject(projectPath); debugConfiguration.program = runApiConfig.executablePath; From 7d58964fb496d2884e48cac5aea8920059ecf274 Mon Sep 17 00:00:00 2001 From: Adam Ratzman Date: Thu, 12 Mar 2026 01:39:27 -0400 Subject: [PATCH 2/4] respect KnownConfigNames.DebugSessionRunMode in project resources --- src/Aspire.Hosting/Dcp/DcpExecutor.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Aspire.Hosting/Dcp/DcpExecutor.cs b/src/Aspire.Hosting/Dcp/DcpExecutor.cs index e82734ab6b4..090726cb53e 100644 --- a/src/Aspire.Hosting/Dcp/DcpExecutor.cs +++ b/src/Aspire.Hosting/Dcp/DcpExecutor.cs @@ -1383,6 +1383,8 @@ private void PrepareProjectExecutables() { var projectLaunchConfiguration = new ProjectLaunchConfiguration(); projectLaunchConfiguration.ProjectPath = projectMetadata.ProjectPath; + projectLaunchConfiguration.Mode = _configuration[KnownConfigNames.DebugSessionRunMode] + ?? (Debugger.IsAttached ? ExecutableLaunchMode.Debug : ExecutableLaunchMode.NoDebug); projectLaunchConfiguration.DisableLaunchProfile = project.TryGetLastAnnotation(out _); // Use the effective launch profile which has fallback logic From 6b8e075e910dd0bdf7e0513ca92a6b0761a1be30 Mon Sep 17 00:00:00 2001 From: Adam Ratzman Date: Thu, 12 Mar 2026 01:47:35 -0400 Subject: [PATCH 3/4] dont use c# dev kit at all for builds --- extension/src/debugger/languages/dotnet.ts | 54 ---------------------- 1 file changed, 54 deletions(-) diff --git a/extension/src/debugger/languages/dotnet.ts b/extension/src/debugger/languages/dotnet.ts index 2135b172368..4bcf7da8f57 100644 --- a/extension/src/debugger/languages/dotnet.ts +++ b/extension/src/debugger/languages/dotnet.ts @@ -56,60 +56,6 @@ class DotNetService implements IDotNetService { } async buildDotNetProject(projectFile: string): Promise { - const isDevKitEnabled = await this.getAndActivateDevKit(); - if (isDevKitEnabled) { - this.writeToDebugConsole(lookingForDevkitBuildTask, 'stdout', true); - - const tasks = await vscode.tasks.fetchTasks(); - const buildTask = tasks.find(t => t.source === "dotnet" && t.name?.includes('build')); - - // The build task may not be registered if there are is no solution in the workspace or if there are no C# projects - // with .csproj files. - if (buildTask) { - // Modify the task to target the specific project - const projectName = path.basename(projectFile, '.csproj'); - - // Create a modified task definition with just the project file - const modifiedDefinition = { - ...buildTask.definition, - file: projectFile // This will make it build the specific project directly - }; - - // Create a new task with the modified definition - const modifiedTask = new vscode.Task( - modifiedDefinition, - buildTask.scope || vscode.TaskScope.Workspace, - `build ${projectName}`, - buildTask.source, - buildTask.execution, - buildTask.problemMatchers - ); - - extensionLogOutputChannel.info(`Executing build task: ${modifiedTask.name} for project: ${projectFile}`); - await vscode.tasks.executeTask(modifiedTask); - - let disposable: vscode.Disposable = { dispose: () => {} }; - return new Promise((resolve, reject) => { - disposable = vscode.tasks.onDidEndTaskProcess(async e => { - if (e.execution.task === modifiedTask) { - if (e.exitCode !== 0) { - reject(new Error(buildFailedWithExitCode(e.exitCode ?? 'unknown'))); - } - else { - return resolve(); - } - } - }); - }).finally(() => disposable.dispose()); - } - else { - this.writeToDebugConsole(noCsharpBuildTask, 'stdout', true); - } - } - else { - this.writeToDebugConsole(csharpDevKitNotInstalled, 'stdout', true); - } - return new Promise((resolve, reject) => { extensionLogOutputChannel.info(`Building .NET project: ${projectFile} using dotnet CLI`); From 449745b02a64288381fe4d8ab58dc7ba1e508dfc Mon Sep 17 00:00:00 2001 From: Adam Ratzman Date: Thu, 12 Mar 2026 09:39:32 -0400 Subject: [PATCH 4/4] Add test for DebugSessionRunMode on project resources --- .../Dcp/DcpExecutorTests.cs | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/tests/Aspire.Hosting.Tests/Dcp/DcpExecutorTests.cs b/tests/Aspire.Hosting.Tests/Dcp/DcpExecutorTests.cs index 1bfaee947fa..0fd59219924 100644 --- a/tests/Aspire.Hosting.Tests/Dcp/DcpExecutorTests.cs +++ b/tests/Aspire.Hosting.Tests/Dcp/DcpExecutorTests.cs @@ -1421,6 +1421,39 @@ public async Task ProjectLaunchConfiguration_Populated_WhenLaunchProfileSpecifie Assert.Equal("http", plc.LaunchProfile); } + [Theory] + [InlineData("Debug", ExecutableLaunchMode.Debug)] + [InlineData("NoDebug", ExecutableLaunchMode.NoDebug)] + public async Task ProjectLaunchConfiguration_RespectsDebugSessionRunMode(string runMode, string expectedMode) + { + var builder = DistributedApplication.CreateBuilder(); + builder.AddProject("proj", launchProfileName: "http"); + + using var app = builder.Build(); + var model = app.Services.GetRequiredService(); + + var kubernetes = new TestKubernetesService(); + var configBuilder = new ConfigurationBuilder(); + configBuilder.AddInMemoryCollection(new Dictionary + { + [KnownConfigNames.DashboardOtlpGrpcEndpointUrl] = "http://localhost", + ["AppHost:BrowserToken"] = "token", + ["AppHost:OtlpApiKey"] = "otlp-key", + [DcpExecutor.DebugSessionPortVar] = "12345", + [KnownConfigNames.DebugSessionRunMode] = runMode + }); + var configuration = configBuilder.Build(); + + var executor = CreateAppExecutor(model, configuration: configuration, kubernetesService: kubernetes); + + await executor.RunApplicationAsync(); + + var exe = Assert.Single(kubernetes.CreatedResources.OfType()); + Assert.True(exe.TryGetProjectLaunchConfiguration(out var plc)); + Assert.NotNull(plc); + Assert.Equal(expectedMode, plc!.Mode); + } + [Fact] public async Task ProjectLaunchConfiguration_Disabled_WhenLaunchProfileExcluded_InDebugSession() {