From 41e8dac715c8d4f437d60e9c3edaa61c083cec87 Mon Sep 17 00:00:00 2001 From: wigodbe Date: Tue, 7 Apr 2026 10:54:41 -0700 Subject: [PATCH 01/12] Enable runtime-async for SharedFx-only libraries --- Directory.Build.targets | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/Directory.Build.targets b/Directory.Build.targets index 1e1a4d93b26a..8aa751d1d74b 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -138,6 +138,23 @@ $(BuildDependsOn);_CopySymbolsToArtifacts + + + $(Features);runtime-async=on + + + + + $(Features);runtime-async=on + + true From 6f8f5dcd1aef636dd081c2fce32efbcf6e16fa59 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 7 Apr 2026 18:10:43 +0000 Subject: [PATCH 02/12] Fix wasm exclusion: add RuntimeIdentifier check and fix comment Agent-Logs-Url: https://github.com/dotnet/aspnetcore/sessions/41a0b51b-1b8a-49be-99b9-41c10b7cb732 Co-authored-by: wtgodbe <14283640+wtgodbe@users.noreply.github.com> --- Directory.Build.targets | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Directory.Build.targets b/Directory.Build.targets index 8aa751d1d74b..280ce496a0d6 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -138,12 +138,13 @@ $(BuildDependsOn);_CopySymbolsToArtifacts - + + '$(TargetOS)' != 'browser' AND + !$(RuntimeIdentifier.StartsWith('browser-'))"> $(Features);runtime-async=on @@ -151,7 +152,8 @@ + '$(TargetOS)' != 'browser' AND + !$(RuntimeIdentifier.StartsWith('browser-'))"> $(Features);runtime-async=on From 64eaed6662a8c3985c8de8ad25e3cf3ce64cc483 Mon Sep 17 00:00:00 2001 From: wigodbe Date: Tue, 7 Apr 2026 12:19:45 -0700 Subject: [PATCH 03/12] Fix tests --- ...osoft.AspNetCore.Mvc.Core.WarningSuppressions.xml | 12 ++++++------ .../csharp/Client/test/FunctionalTests/Hubs.cs | 3 +++ 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/Mvc/Mvc.Core/src/Microsoft.AspNetCore.Mvc.Core.WarningSuppressions.xml b/src/Mvc/Mvc.Core/src/Microsoft.AspNetCore.Mvc.Core.WarningSuppressions.xml index e179ca1a04b3..91235bbf293d 100644 --- a/src/Mvc/Mvc.Core/src/Microsoft.AspNetCore.Mvc.Core.WarningSuppressions.xml +++ b/src/Mvc/Mvc.Core/src/Microsoft.AspNetCore.Mvc.Core.WarningSuppressions.xml @@ -83,13 +83,13 @@ ILLink IL2026 member - M:Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonInputFormatter.<ReadRequestBodyAsync>d__9.MoveNext + M:Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonInputFormatter.ReadRequestBodyAsync(Microsoft.AspNetCore.Mvc.Formatters.InputFormatterContext,System.Text.Encoding) ILLink IL2026 member - M:Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonOutputFormatter.<WriteResponseBodyAsync>d__5.MoveNext + M:Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonOutputFormatter.WriteResponseBodyAsync(Microsoft.AspNetCore.Mvc.Formatters.OutputFormatterWriteContext,System.Text.Encoding) ILLink @@ -101,7 +101,7 @@ ILLink IL2026 member - M:Microsoft.AspNetCore.Mvc.Infrastructure.SystemTextJsonResultExecutor.<ExecuteAsync>d__4.MoveNext + M:Microsoft.AspNetCore.Mvc.Infrastructure.SystemTextJsonResultExecutor.ExecuteAsync(Microsoft.AspNetCore.Mvc.ActionContext,Microsoft.AspNetCore.Mvc.JsonResult) ILLink @@ -113,13 +113,13 @@ ILLink IL2026 member - M:Microsoft.AspNetCore.Mvc.ModelBinding.Binders.CollectionModelBinder`1.<BindComplexCollectionFromIndexes>d__22.MoveNext + M:Microsoft.AspNetCore.Mvc.ModelBinding.Binders.CollectionModelBinder`1.BindComplexCollectionFromIndexes(Microsoft.AspNetCore.Mvc.ModelBinding.ModelBindingContext,System.Collections.Generic.IEnumerable{System.String}) ILLink IL2026 member - M:Microsoft.AspNetCore.Mvc.ModelBinding.Binders.ComplexObjectModelBinder.<BindPropertyAsync>d__15.MoveNext + M:Microsoft.AspNetCore.Mvc.ModelBinding.Binders.ComplexObjectModelBinder.BindPropertyAsync(Microsoft.AspNetCore.Mvc.ModelBinding.ModelBindingContext,Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata,Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinder,System.String,System.String) ILLink @@ -131,7 +131,7 @@ ILLink IL2026 member - M:Microsoft.AspNetCore.Mvc.ModelBinding.Binders.ComplexTypeModelBinder.<BindProperty>d__11.MoveNext + M:Microsoft.AspNetCore.Mvc.ModelBinding.Binders.ComplexTypeModelBinder.BindProperty(Microsoft.AspNetCore.Mvc.ModelBinding.ModelBindingContext,Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata,System.String,System.String) ILLink diff --git a/src/SignalR/clients/csharp/Client/test/FunctionalTests/Hubs.cs b/src/SignalR/clients/csharp/Client/test/FunctionalTests/Hubs.cs index 17d09d87818c..f22b370075cc 100644 --- a/src/SignalR/clients/csharp/Client/test/FunctionalTests/Hubs.cs +++ b/src/SignalR/clients/csharp/Client/test/FunctionalTests/Hubs.cs @@ -6,6 +6,7 @@ using System.Linq; using System.Reactive.Linq; using System.Threading.Channels; +using System.Runtime.CompilerServices; using System.Threading.Tasks; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Authorization; @@ -150,11 +151,13 @@ public class DynamicTestHub : DynamicHub public ChannelReader StreamBroken() => TestHubMethodsImpl.StreamBroken(); + [RuntimeAsyncMethodGeneration(false)] public async Task CallEcho(string message) { await Clients.Client(Context.ConnectionId).Echo(message); } + [RuntimeAsyncMethodGeneration(false)] public async Task CallHandlerThatDoesntExist() { await Clients.Client(Context.ConnectionId).NoClientHandler(); From a2eae5b097bf25a1aaeb361e5774e3bbdf6d70f0 Mon Sep 17 00:00:00 2001 From: wigodbe Date: Tue, 7 Apr 2026 13:18:10 -0700 Subject: [PATCH 04/12] Polyfill --- .../clients/csharp/Client/test/FunctionalTests/Hubs.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/SignalR/clients/csharp/Client/test/FunctionalTests/Hubs.cs b/src/SignalR/clients/csharp/Client/test/FunctionalTests/Hubs.cs index f22b370075cc..9efed2fee739 100644 --- a/src/SignalR/clients/csharp/Client/test/FunctionalTests/Hubs.cs +++ b/src/SignalR/clients/csharp/Client/test/FunctionalTests/Hubs.cs @@ -15,6 +15,16 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests; +// Polyfill: RuntimeAsyncMethodGenerationAttribute is not yet public API +namespace System.Runtime.CompilerServices +{ + [AttributeUsage(AttributeTargets.Method)] + internal sealed class RuntimeAsyncMethodGenerationAttribute(bool runtimeAsync) : Attribute + { + public bool RuntimeAsync { get; } = runtimeAsync; + } +} + public class TestHub : Hub { public string HelloWorld() => TestHubMethodsImpl.HelloWorld(); From afc8d1c9cb05a561b282cd5cb93c45f15b887e36 Mon Sep 17 00:00:00 2001 From: wigodbe Date: Tue, 7 Apr 2026 13:34:25 -0700 Subject: [PATCH 05/12] Fixup --- .../clients/csharp/Client/test/FunctionalTests/Hubs.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/SignalR/clients/csharp/Client/test/FunctionalTests/Hubs.cs b/src/SignalR/clients/csharp/Client/test/FunctionalTests/Hubs.cs index 9efed2fee739..6805bc24678d 100644 --- a/src/SignalR/clients/csharp/Client/test/FunctionalTests/Hubs.cs +++ b/src/SignalR/clients/csharp/Client/test/FunctionalTests/Hubs.cs @@ -13,8 +13,6 @@ using Microsoft.AspNetCore.Http.Connections.Features; using Microsoft.AspNetCore.Http.Features; -namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests; - // Polyfill: RuntimeAsyncMethodGenerationAttribute is not yet public API namespace System.Runtime.CompilerServices { @@ -25,6 +23,8 @@ internal sealed class RuntimeAsyncMethodGenerationAttribute(bool runtimeAsync) : } } +namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests; + public class TestHub : Hub { public string HelloWorld() => TestHubMethodsImpl.HelloWorld(); From 93f7b575c67c6f5bde4b533ba01f04e2c2023290 Mon Sep 17 00:00:00 2001 From: wigodbe Date: Tue, 7 Apr 2026 14:36:53 -0700 Subject: [PATCH 06/12] Own file --- .../clients/csharp/Client/test/FunctionalTests/Hubs.cs | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/SignalR/clients/csharp/Client/test/FunctionalTests/Hubs.cs b/src/SignalR/clients/csharp/Client/test/FunctionalTests/Hubs.cs index 6805bc24678d..f22b370075cc 100644 --- a/src/SignalR/clients/csharp/Client/test/FunctionalTests/Hubs.cs +++ b/src/SignalR/clients/csharp/Client/test/FunctionalTests/Hubs.cs @@ -13,16 +13,6 @@ using Microsoft.AspNetCore.Http.Connections.Features; using Microsoft.AspNetCore.Http.Features; -// Polyfill: RuntimeAsyncMethodGenerationAttribute is not yet public API -namespace System.Runtime.CompilerServices -{ - [AttributeUsage(AttributeTargets.Method)] - internal sealed class RuntimeAsyncMethodGenerationAttribute(bool runtimeAsync) : Attribute - { - public bool RuntimeAsync { get; } = runtimeAsync; - } -} - namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests; public class TestHub : Hub From 2342ba34d47e38f512405645317e6e06c738a01c Mon Sep 17 00:00:00 2001 From: wigodbe Date: Tue, 7 Apr 2026 15:08:07 -0700 Subject: [PATCH 07/12] Whoops --- .../RuntimeAsyncMethodGenerationAttribute.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 src/SignalR/clients/csharp/Client/test/FunctionalTests/RuntimeAsyncMethodGenerationAttribute.cs diff --git a/src/SignalR/clients/csharp/Client/test/FunctionalTests/RuntimeAsyncMethodGenerationAttribute.cs b/src/SignalR/clients/csharp/Client/test/FunctionalTests/RuntimeAsyncMethodGenerationAttribute.cs new file mode 100644 index 000000000000..137d30feae90 --- /dev/null +++ b/src/SignalR/clients/csharp/Client/test/FunctionalTests/RuntimeAsyncMethodGenerationAttribute.cs @@ -0,0 +1,11 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +// Polyfill: RuntimeAsyncMethodGenerationAttribute is not yet public API +namespace System.Runtime.CompilerServices; + +[AttributeUsage(AttributeTargets.Method)] +internal sealed class RuntimeAsyncMethodGenerationAttribute(bool runtimeAsync) : Attribute +{ + public bool RuntimeAsync { get; } = runtimeAsync; +} From f619ff74a4aa53f866e379e96449504775169558 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 13 Apr 2026 23:20:54 +0000 Subject: [PATCH 08/12] Quarantine CriticalErrorLoggedIfApplicationDoesntComplete test Agent-Logs-Url: https://github.com/dotnet/aspnetcore/sessions/ee6acbab-717b-438e-a17d-9b6c48506040 Co-authored-by: wtgodbe <14283640+wtgodbe@users.noreply.github.com> --- .../test/InMemory.FunctionalTests/HttpConnectionManagerTests.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Servers/Kestrel/test/InMemory.FunctionalTests/HttpConnectionManagerTests.cs b/src/Servers/Kestrel/test/InMemory.FunctionalTests/HttpConnectionManagerTests.cs index 053c7340f3a7..da38bd2c5bd9 100644 --- a/src/Servers/Kestrel/test/InMemory.FunctionalTests/HttpConnectionManagerTests.cs +++ b/src/Servers/Kestrel/test/InMemory.FunctionalTests/HttpConnectionManagerTests.cs @@ -21,6 +21,7 @@ public class HttpConnectionManagerTests : LoggedTest #if !DEBUG [ConditionalFact] [NoDebuggerCondition] + [QuarantinedTest("https://github.com/dotnet/runtime/issues/126735")] public async Task CriticalErrorLoggedIfApplicationDoesntComplete() { //////////////////////////////////////////////////////////////////////////////////////// From 852b983fc4995c69ef71ef4d7aed6752ab93ef93 Mon Sep 17 00:00:00 2001 From: wigodbe Date: Mon, 20 Apr 2026 18:15:29 -0700 Subject: [PATCH 09/12] Add --blame-hang to E2E tests to identify hanging tests Add blame-hang diagnostics with 5m per-test timeout to identify which specific tests hang with runtime-async enabled. Increase pipeline timeout to 180m to allow the run to complete. Fix script to preserve post-processing after nonzero test exit. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .azure/pipelines/components-e2e-tests.yml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/.azure/pipelines/components-e2e-tests.yml b/.azure/pipelines/components-e2e-tests.yml index b0f344f98ac4..a6fa2c06e7f8 100644 --- a/.azure/pipelines/components-e2e-tests.yml +++ b/.azure/pipelines/components-e2e-tests.yml @@ -57,7 +57,7 @@ jobs: use1ESUbuntu: true isAzDOTestingJob: true enablePublishTestResults: false - timeoutInMinutes: 120 + timeoutInMinutes: 180 steps: - script: git submodule update --init displayName: Update submodules @@ -70,17 +70,19 @@ jobs: - script: .dotnet/dotnet build ./src/Components/test/E2ETest -c $(BuildConfiguration) --no-restore displayName: Build - script: | - set -eo pipefail + set -o pipefail .dotnet/dotnet test ./src/Components/test/E2ETest \ -c $(BuildConfiguration) \ --no-build \ --filter 'Quarantined!=true|Quarantined=false' \ -p:VsTestUseMSBuildOutput=false \ + --blame-hang --blame-hang-timeout 5m --blame-hang-dump-type none \ --logger:"trx%3BLogFileName=Microsoft.AspNetCore.Components.E2ETests.trx" \ --logger:"html%3BLogFileName=Microsoft.AspNetCore.Components.E2ETests.html" \ --results-directory $(Build.SourcesDirectory)/artifacts/TestResults/$(BuildConfiguration)/Unquarantined \ | tee e2e-test-output.log + test_exit=${PIPESTATUS[0]} if grep -q "No test matches the given testcase filter" e2e-test-output.log then @@ -98,9 +100,12 @@ jobs: echo "##vso[task.logissue type=error] Insufficient total test count: $total. We expect at least $min_total tests to run." exit 1 fi + + exit $test_exit displayName: Run E2E tests - script: .dotnet/dotnet test ./src/Components/test/E2ETest -c $(BuildConfiguration) --no-build --filter 'Quarantined=true' -p:RunQuarantinedTests=true -p:VsTestUseMSBuildOutput=false + --blame-hang --blame-hang-timeout 5m --blame-hang-dump-type none --logger:"trx%3BLogFileName=Microsoft.AspNetCore.Components.E2ETests.trx" --logger:"html%3BLogFileName=Microsoft.AspNetCore.Components.E2ETests.html" --results-directory $(Build.SourcesDirectory)/artifacts/TestResults/$(BuildConfiguration)/Quarantined From 7a1c8e3836f0af861036ba62dc341a3d4bd36d74 Mon Sep 17 00:00:00 2001 From: wigodbe Date: Wed, 22 Apr 2026 16:55:17 -0700 Subject: [PATCH 10/12] Skip InputTextAreaWorksWithMutatingSetter under runtime-async This test hangs indefinitely with runtime-async enabled due to a runtime bug with async continuation rooting. Without runtime-async the test fails cleanly via WaitAssert timeout. See https://github.com/dotnet/runtime/issues/126735 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- src/Components/test/E2ETest/Tests/FormsTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Components/test/E2ETest/Tests/FormsTest.cs b/src/Components/test/E2ETest/Tests/FormsTest.cs index 304ea1721abc..43430cc37936 100644 --- a/src/Components/test/E2ETest/Tests/FormsTest.cs +++ b/src/Components/test/E2ETest/Tests/FormsTest.cs @@ -780,7 +780,7 @@ public void InputTextWorksWithMutatingSetter() Browser.Equal("24:00:00", () => input.GetDomProperty("value")); } - [Fact] + [Fact(Skip = "Hangs with runtime-async enabled: https://github.com/dotnet/runtime/issues/126735")] public void InputTextAreaWorksWithMutatingSetter() { // Repro for https://github.com/dotnet/aspnetcore/issues/40097 From 02eb5628edb8a5333c9d12fb29374aa5e74c4bb9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 23 Apr 2026 18:48:44 +0000 Subject: [PATCH 11/12] Remove IsTestAssetProject from runtime-async; revert components-e2e-tests.yml Agent-Logs-Url: https://github.com/dotnet/aspnetcore/sessions/c3cca376-481c-4186-a887-d43d9ab31f9e Co-authored-by: wtgodbe <14283640+wtgodbe@users.noreply.github.com> --- .azure/pipelines/components-e2e-tests.yml | 9 ++------- Directory.Build.targets | 2 +- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/.azure/pipelines/components-e2e-tests.yml b/.azure/pipelines/components-e2e-tests.yml index a6fa2c06e7f8..b0f344f98ac4 100644 --- a/.azure/pipelines/components-e2e-tests.yml +++ b/.azure/pipelines/components-e2e-tests.yml @@ -57,7 +57,7 @@ jobs: use1ESUbuntu: true isAzDOTestingJob: true enablePublishTestResults: false - timeoutInMinutes: 180 + timeoutInMinutes: 120 steps: - script: git submodule update --init displayName: Update submodules @@ -70,19 +70,17 @@ jobs: - script: .dotnet/dotnet build ./src/Components/test/E2ETest -c $(BuildConfiguration) --no-restore displayName: Build - script: | - set -o pipefail + set -eo pipefail .dotnet/dotnet test ./src/Components/test/E2ETest \ -c $(BuildConfiguration) \ --no-build \ --filter 'Quarantined!=true|Quarantined=false' \ -p:VsTestUseMSBuildOutput=false \ - --blame-hang --blame-hang-timeout 5m --blame-hang-dump-type none \ --logger:"trx%3BLogFileName=Microsoft.AspNetCore.Components.E2ETests.trx" \ --logger:"html%3BLogFileName=Microsoft.AspNetCore.Components.E2ETests.html" \ --results-directory $(Build.SourcesDirectory)/artifacts/TestResults/$(BuildConfiguration)/Unquarantined \ | tee e2e-test-output.log - test_exit=${PIPESTATUS[0]} if grep -q "No test matches the given testcase filter" e2e-test-output.log then @@ -100,12 +98,9 @@ jobs: echo "##vso[task.logissue type=error] Insufficient total test count: $total. We expect at least $min_total tests to run." exit 1 fi - - exit $test_exit displayName: Run E2E tests - script: .dotnet/dotnet test ./src/Components/test/E2ETest -c $(BuildConfiguration) --no-build --filter 'Quarantined=true' -p:RunQuarantinedTests=true -p:VsTestUseMSBuildOutput=false - --blame-hang --blame-hang-timeout 5m --blame-hang-dump-type none --logger:"trx%3BLogFileName=Microsoft.AspNetCore.Components.E2ETests.trx" --logger:"html%3BLogFileName=Microsoft.AspNetCore.Components.E2ETests.html" --results-directory $(Build.SourcesDirectory)/artifacts/TestResults/$(BuildConfiguration)/Quarantined diff --git a/Directory.Build.targets b/Directory.Build.targets index 280ce496a0d6..4712f2352485 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -149,7 +149,7 @@ - Date: Thu, 23 Apr 2026 14:29:19 -0700 Subject: [PATCH 12/12] Enable InputTextAreaWorksWithMutatingSetter test --- src/Components/test/E2ETest/Tests/FormsTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Components/test/E2ETest/Tests/FormsTest.cs b/src/Components/test/E2ETest/Tests/FormsTest.cs index 43430cc37936..304ea1721abc 100644 --- a/src/Components/test/E2ETest/Tests/FormsTest.cs +++ b/src/Components/test/E2ETest/Tests/FormsTest.cs @@ -780,7 +780,7 @@ public void InputTextWorksWithMutatingSetter() Browser.Equal("24:00:00", () => input.GetDomProperty("value")); } - [Fact(Skip = "Hangs with runtime-async enabled: https://github.com/dotnet/runtime/issues/126735")] + [Fact] public void InputTextAreaWorksWithMutatingSetter() { // Repro for https://github.com/dotnet/aspnetcore/issues/40097