diff --git a/NuGet.config b/NuGet.config
index ecf11c3e4032..5a4f8306a391 100644
--- a/NuGet.config
+++ b/NuGet.config
@@ -4,8 +4,10 @@
+
+
@@ -24,8 +26,10 @@
+
+
diff --git a/eng/Baseline.Designer.props b/eng/Baseline.Designer.props
index 61d7f2813e8c..b03207e20d0c 100644
--- a/eng/Baseline.Designer.props
+++ b/eng/Baseline.Designer.props
@@ -2,28 +2,28 @@
$(MSBuildAllProjects);$(MSBuildThisFileFullPath)
- 7.0.12
+ 7.0.14
- 7.0.12
+ 7.0.14
- 7.0.12
+ 7.0.14
- 7.0.12
+ 7.0.14
- 7.0.12
+ 7.0.14
-
-
-
+
+
+
@@ -35,105 +35,105 @@
- 7.0.12
+ 7.0.14
- 7.0.12
+ 7.0.14
- 7.0.12
+ 7.0.14
- 7.0.12
+ 7.0.14
- 7.0.12
+ 7.0.14
- 7.0.12
+ 7.0.14
- 7.0.12
+ 7.0.14
- 7.0.12
+ 7.0.14
- 7.0.12
+ 7.0.14
- 7.0.12
+ 7.0.14
- 7.0.12
+ 7.0.14
- 7.0.12
+ 7.0.14
- 7.0.12
+ 7.0.14
- 7.0.12
+ 7.0.14
- 7.0.12
+ 7.0.14
- 7.0.12
+ 7.0.14
- 7.0.12
+ 7.0.14
- 7.0.12
+ 7.0.14
- 7.0.12
+ 7.0.14
-
+
- 7.0.12
+ 7.0.14
- 7.0.12
+ 7.0.14
- 7.0.12
+ 7.0.14
@@ -141,121 +141,121 @@
- 7.0.12
+ 7.0.14
-
+
-
+
-
+
- 7.0.12
+ 7.0.14
-
+
- 7.0.12
+ 7.0.14
- 7.0.12
+ 7.0.14
-
+
- 7.0.12
+ 7.0.14
-
-
+
+
- 7.0.12
+ 7.0.14
- 7.0.12
+ 7.0.14
-
-
+
+
- 7.0.12
+ 7.0.14
-
+
- 7.0.12
+ 7.0.14
-
+
- 7.0.12
+ 7.0.14
-
-
-
+
+
+
- 7.0.12
+ 7.0.14
-
-
+
+
- 7.0.12
+ 7.0.14
-
-
+
+
- 7.0.12
+ 7.0.14
- 7.0.12
+ 7.0.14
- 7.0.12
+ 7.0.14
-
-
+
+
@@ -263,7 +263,7 @@
- 7.0.12
+ 7.0.14
@@ -272,50 +272,50 @@
- 7.0.12
+ 7.0.14
-
+
-
+
-
+
-
+
- 7.0.12
+ 7.0.14
- 7.0.12
+ 7.0.14
-
+
-
+
-
+
- 7.0.12
+ 7.0.14
-
-
+
+
@@ -325,8 +325,8 @@
-
-
+
+
@@ -334,8 +334,8 @@
-
-
+
+
@@ -346,58 +346,58 @@
- 7.0.12
+ 7.0.14
- 7.0.12
+ 7.0.14
-
-
+
+
- 7.0.12
+ 7.0.14
-
+
-
+
-
+
- 7.0.12
+ 7.0.14
-
+
-
+
-
+
- 7.0.12
+ 7.0.14
-
+
- 7.0.12
+ 7.0.14
@@ -414,7 +414,7 @@
- 7.0.12
+ 7.0.14
@@ -422,71 +422,71 @@
- 7.0.12
+ 7.0.14
- 7.0.12
+ 7.0.14
-
+
-
+
-
+
-
+
- 7.0.12
+ 7.0.14
-
-
+
+
-
+
-
-
+
+
- 7.0.12
+ 7.0.14
-
-
+
+
- 7.0.12
+ 7.0.14
-
-
+
+
- 7.0.12
+ 7.0.14
@@ -502,27 +502,27 @@
- 7.0.12
+ 7.0.14
- 7.0.12
+ 7.0.14
- 7.0.12
+ 7.0.14
-
+
- 7.0.12
+ 7.0.14
@@ -531,151 +531,151 @@
- 7.0.12
+ 7.0.14
-
+
- 7.0.12
+ 7.0.14
- 7.0.12
+ 7.0.14
- 7.0.12
+ 7.0.14
-
-
+
+
-
-
+
+
-
-
+
+
- 7.0.12
+ 7.0.14
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
- 7.0.12
+ 7.0.14
-
+
-
+
-
+
-
+
-
+
- 7.0.12
+ 7.0.14
-
+
-
+
-
+
- 7.0.12
+ 7.0.14
-
+
-
+
-
+
- 7.0.12
+ 7.0.14
-
+
-
+
-
+
- 7.0.12
+ 7.0.14
-
-
-
-
+
+
+
+
- 7.0.12
+ 7.0.14
@@ -684,60 +684,60 @@
- 7.0.12
+ 7.0.14
- 7.0.12
+ 7.0.14
- 7.0.12
+ 7.0.14
- 7.0.12
+ 7.0.14
-
+
- 7.0.12
+ 7.0.14
- 7.0.12
+ 7.0.14
- 7.0.12
+ 7.0.14
- 7.0.12
+ 7.0.14
- 7.0.12
+ 7.0.14
- 7.0.12
+ 7.0.14
- 7.0.12
+ 7.0.14
- 7.0.12
+ 7.0.14
@@ -756,7 +756,7 @@
- 7.0.12
+ 7.0.14
@@ -778,7 +778,7 @@
- 7.0.12
+ 7.0.14
@@ -794,46 +794,46 @@
- 7.0.12
+ 7.0.14
-
+
-
+
-
+
- 7.0.12
+ 7.0.14
- 7.0.12
+ 7.0.14
-
-
-
+
+
+
- 7.0.12
+ 7.0.14
- 7.0.12
+ 7.0.14
@@ -843,7 +843,7 @@
- 7.0.12
+ 7.0.14
@@ -852,73 +852,73 @@
- 7.0.12
+ 7.0.14
-
+
-
+
-
+
- 7.0.12
+ 7.0.14
-
+
-
+
-
+
- 7.0.12
+ 7.0.14
-
+
-
+
-
+
- 7.0.12
+ 7.0.14
- 7.0.12
+ 7.0.14
@@ -947,11 +947,11 @@
- 7.0.12
+ 7.0.14
- 7.0.12
+ 7.0.14
@@ -969,13 +969,13 @@
- 7.0.12
+ 7.0.14
- 7.0.12
+ 7.0.14
-
+
\ No newline at end of file
diff --git a/eng/Baseline.xml b/eng/Baseline.xml
index 55daaf5598e6..c6150314843e 100644
--- a/eng/Baseline.xml
+++ b/eng/Baseline.xml
@@ -4,109 +4,109 @@ This file contains a list of all the packages and their versions which were rele
Update this list when preparing for a new patch.
-->
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml
index f92be2b86c1d..5bf37fb721e5 100644
--- a/eng/Version.Details.xml
+++ b/eng/Version.Details.xml
@@ -9,37 +9,37 @@
-->
-
+
https://dev.azure.com/dnceng/internal/_git/dotnet-efcore
- c20ecc79b7df3657e186ac52e7fc050beea36c92
+ 31662b30f1a4497db482b3aed8ed4c4aa6de801b
-
+
https://dev.azure.com/dnceng/internal/_git/dotnet-efcore
- c20ecc79b7df3657e186ac52e7fc050beea36c92
+ 31662b30f1a4497db482b3aed8ed4c4aa6de801b
-
+
https://dev.azure.com/dnceng/internal/_git/dotnet-efcore
- c20ecc79b7df3657e186ac52e7fc050beea36c92
+ 31662b30f1a4497db482b3aed8ed4c4aa6de801b
-
+
https://dev.azure.com/dnceng/internal/_git/dotnet-efcore
- c20ecc79b7df3657e186ac52e7fc050beea36c92
+ 31662b30f1a4497db482b3aed8ed4c4aa6de801b
-
+
https://dev.azure.com/dnceng/internal/_git/dotnet-efcore
- c20ecc79b7df3657e186ac52e7fc050beea36c92
+ 31662b30f1a4497db482b3aed8ed4c4aa6de801b
-
+
https://dev.azure.com/dnceng/internal/_git/dotnet-efcore
- c20ecc79b7df3657e186ac52e7fc050beea36c92
+ 31662b30f1a4497db482b3aed8ed4c4aa6de801b
-
+
https://dev.azure.com/dnceng/internal/_git/dotnet-efcore
- c20ecc79b7df3657e186ac52e7fc050beea36c92
+ 31662b30f1a4497db482b3aed8ed4c4aa6de801b
-
+
https://dev.azure.com/dnceng/internal/_git/dotnet-efcore
- c20ecc79b7df3657e186ac52e7fc050beea36c92
+ 31662b30f1a4497db482b3aed8ed4c4aa6de801b
https://dev.azure.com/dnceng/internal/_git/dotnet-runtime
@@ -177,9 +177,9 @@
https://dev.azure.com/dnceng/internal/_git/dotnet-runtime
d099f075e45d2aa6007a22b71b45a08758559f80
-
+
https://dev.azure.com/dnceng/internal/_git/dotnet-runtime
- 4a824ef37caa51072221584c64cbf15455f406ca
+ 808851b07acfa1c5c94b0d4f9fb50debedb2df70
https://github.com/dotnet/source-build-externals
@@ -242,9 +242,9 @@
https://dev.azure.com/dnceng/internal/_git/dotnet-runtime
d099f075e45d2aa6007a22b71b45a08758559f80
-
+
https://dev.azure.com/dnceng/internal/_git/dotnet-runtime
- 5b20af47d99620150c53eaf5db8636fdf730b126
+ 808851b07acfa1c5c94b0d4f9fb50debedb2df70
https://dev.azure.com/dnceng/internal/_git/dotnet-runtime
@@ -262,33 +262,33 @@
https://dev.azure.com/dnceng/internal/_git/dotnet-runtime
d099f075e45d2aa6007a22b71b45a08758559f80
-
+
https://dev.azure.com/dnceng/internal/_git/dotnet-runtime
- 4a824ef37caa51072221584c64cbf15455f406ca
+ 808851b07acfa1c5c94b0d4f9fb50debedb2df70
-
+
https://dev.azure.com/dnceng/internal/_git/dotnet-runtime
- 4a824ef37caa51072221584c64cbf15455f406ca
+ 808851b07acfa1c5c94b0d4f9fb50debedb2df70
-
+
https://dev.azure.com/dnceng/internal/_git/dotnet-runtime
- 4a824ef37caa51072221584c64cbf15455f406ca
+ 808851b07acfa1c5c94b0d4f9fb50debedb2df70
-
+
https://dev.azure.com/dnceng/internal/_git/dotnet-runtime
- 4a824ef37caa51072221584c64cbf15455f406ca
+ 808851b07acfa1c5c94b0d4f9fb50debedb2df70
-
+
https://dev.azure.com/dnceng/internal/_git/dotnet-runtime
- 4a824ef37caa51072221584c64cbf15455f406ca
+ 808851b07acfa1c5c94b0d4f9fb50debedb2df70
-
+
https://dev.azure.com/dnceng/internal/_git/dotnet-runtime
- 4a824ef37caa51072221584c64cbf15455f406ca
+ 808851b07acfa1c5c94b0d4f9fb50debedb2df70
https://github.com/dotnet/xdt
diff --git a/eng/Versions.props b/eng/Versions.props
index eb4eb924977d..853e4681b6dd 100644
--- a/eng/Versions.props
+++ b/eng/Versions.props
@@ -9,7 +9,7 @@
7
0
15
- false
+ true
@@ -63,12 +63,12 @@
7.0.0
- 7.0.12
- 7.0.12
- 7.0.12
- 7.0.12
- 7.0.12
- 7.0.12-servicing.23477.20
+ 7.0.14
+ 7.0.14
+ 7.0.14
+ 7.0.14
+ 7.0.14
+ 7.0.14-servicing.23519.10
7.0.0
7.0.0
7.0.0
@@ -103,7 +103,7 @@
7.0.0
7.0.1
7.0.0
- 7.0.12-servicing.23477.20
+ 7.0.14-servicing.23519.10
7.0.0
7.0.2
7.0.0
@@ -118,21 +118,21 @@
7.0.0
7.0.1
7.0.0
- 7.0.3
+ 7.0.4
7.0.1
7.0.0
7.0.1
7.0.4
- 7.0.12
- 7.0.12
- 7.0.12
- 7.0.12
- 7.0.12
- 7.0.12
- 7.0.12
- 7.0.12
+ 7.0.14
+ 7.0.14
+ 7.0.14
+ 7.0.14
+ 7.0.14
+ 7.0.14
+ 7.0.14
+ 7.0.14
7.0.0-beta.23556.6
7.0.0-beta.23556.6
@@ -238,7 +238,7 @@
5.0.17-servicing-22215-7
$(MicrosoftAspNetCoreAzureAppServicesSiteExtension50Version)
$(MicrosoftAspNetCoreAzureAppServicesSiteExtension50Version)
- 6.0.22-servicing-23424-15
+ 6.0.25-servicing-23523-15
$(MicrosoftAspNetCoreAzureAppServicesSiteExtension60Version)
$(MicrosoftAspNetCoreAzureAppServicesSiteExtension60Version)
diff --git a/eng/helix/content/runtests.cmd b/eng/helix/content/runtests.cmd
index 8fd9e85596ce..bbdac7d80453 100644
--- a/eng/helix/content/runtests.cmd
+++ b/eng/helix/content/runtests.cmd
@@ -9,6 +9,7 @@ set $arch=%4
set $quarantined=%5
set $helixTimeout=%6
set $installPlaywright=%7
+set $dotnetEfVersion=%8
REM Batch only supports up to 9 arguments using the %# syntax, need to shift to get more
set DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1
@@ -24,8 +25,8 @@ echo.
set exit_code=0
-echo "Running tests: dotnet %HELIX_CORRELATION_PAYLOAD%/HelixTestRunner/HelixTestRunner.dll --target %$target% --runtime %$aspRuntimeVersion% --queue %$queue% --arch %$arch% --quarantined %$quarantined% --helixTimeout %$helixTimeout% --playwright %$installPlaywright%"
-dotnet %HELIX_CORRELATION_PAYLOAD%/HelixTestRunner/HelixTestRunner.dll --target %$target% --runtime %$aspRuntimeVersion% --queue %$queue% --arch %$arch% --quarantined %$quarantined% --helixTimeout %$helixTimeout% --playwright %$installPlaywright%
+echo "Running tests: dotnet %HELIX_CORRELATION_PAYLOAD%/HelixTestRunner/HelixTestRunner.dll --target %$target% --runtime %$aspRuntimeVersion% --queue %$queue% --arch %$arch% --quarantined %$quarantined% --helixTimeout %$helixTimeout% --playwright %$installPlaywright% --dotnetEf %$dotnetEfVersion%"
+dotnet %HELIX_CORRELATION_PAYLOAD%/HelixTestRunner/HelixTestRunner.dll --target %$target% --runtime %$aspRuntimeVersion% --queue %$queue% --arch %$arch% --quarantined %$quarantined% --helixTimeout %$helixTimeout% --playwright %$installPlaywright% --dotnetEf %$dotnetEfVersion%
if not errorlevel 0 (
set exit_code=%errorlevel%
)
diff --git a/eng/helix/content/runtests.sh b/eng/helix/content/runtests.sh
index ba9ce79418ef..23f4229c2175 100644
--- a/eng/helix/content/runtests.sh
+++ b/eng/helix/content/runtests.sh
@@ -78,8 +78,8 @@ sync
exit_code=0
-echo "Running tests: dotnet $HELIX_CORRELATION_PAYLOAD/HelixTestRunner/HelixTestRunner.dll --target $1 --runtime $2 --queue $helixQueue --arch $4 --quarantined $5 --helixTimeout $6 --playwright $installPlaywright"
-dotnet $HELIX_CORRELATION_PAYLOAD/HelixTestRunner/HelixTestRunner.dll --target $1 --runtime $2 --queue $helixQueue --arch $4 --quarantined $5 --helixTimeout $6 --playwright $installPlaywright
+echo "Running tests: dotnet $HELIX_CORRELATION_PAYLOAD/HelixTestRunner/HelixTestRunner.dll --target $1 --runtime $2 --queue $helixQueue --arch $4 --quarantined $5 --helixTimeout $6 --playwright $installPlaywright --dotnetEf $8"
+dotnet $HELIX_CORRELATION_PAYLOAD/HelixTestRunner/HelixTestRunner.dll --target $1 --runtime $2 --queue $helixQueue --arch $4 --quarantined $5 --helixTimeout $6 --playwright $installPlaywright --dotnetEf $8
exit_code=$?
echo "Finished tests...exit_code=$exit_code"
diff --git a/eng/targets/Helix.targets b/eng/targets/Helix.targets
index 84eaa3bba42c..f189c471caa5 100644
--- a/eng/targets/Helix.targets
+++ b/eng/targets/Helix.targets
@@ -221,8 +221,8 @@
When the targeting pack builds, it has exactly the same version as the shared framework. Passing
SharedFxVersion because that's needed even when the targeting pack isn't building.
-->
- call runtests.cmd $(TargetFileName) $(SharedFxVersion) $(_HelixFriendlyNameTargetQueue) $(_TestingArchitecture) $(RunQuarantinedTests) $(HelixTimeout) $(TestDependsOnPlaywright)
- ./runtests.sh $(TargetFileName) $(SharedFxVersion) $(_HelixFriendlyNameTargetQueue) $(_TestingArchitecture) $(RunQuarantinedTests) $(HelixTimeout) $(TestDependsOnPlaywright)
+ call runtests.cmd $(TargetFileName) $(SharedFxVersion) $(_HelixFriendlyNameTargetQueue) $(_TestingArchitecture) $(RunQuarantinedTests) $(HelixTimeout) $(TestDependsOnPlaywright) $(DotnetEfVersion)
+ ./runtests.sh $(TargetFileName) $(SharedFxVersion) $(_HelixFriendlyNameTargetQueue) $(_TestingArchitecture) $(RunQuarantinedTests) $(HelixTimeout) $(TestDependsOnPlaywright) $(DotnetEfVersion)
$(HelixCommand)
$(HelixTimeout)
diff --git a/eng/tools/HelixTestRunner/HelixTestRunnerOptions.cs b/eng/tools/HelixTestRunner/HelixTestRunnerOptions.cs
index 13d483d64caf..3de5d928c725 100644
--- a/eng/tools/HelixTestRunner/HelixTestRunnerOptions.cs
+++ b/eng/tools/HelixTestRunner/HelixTestRunnerOptions.cs
@@ -55,11 +55,17 @@ public static HelixTestRunnerOptions Parse(string[] args)
new Option(
aliases: new string[] { "--source" },
description: "The restore sources to use during testing")
- { Argument = new Argument() { Arity = ArgumentArity.ZeroOrMore }, Required = true }
+ { Argument = new Argument() { Arity = ArgumentArity.ZeroOrMore }, Required = true },
+
+ new Option(
+ aliases: new string[] { "--dotnetEf" },
+ description: "The version of the dotnet-ef tool being installed and used")
+ { Argument = new Argument(), Required = true }
};
var parseResult = command.Parse(args);
var sharedFxVersion = parseResult.ValueForOption("--runtime");
+ var dotnetEfVersion = parseResult.ValueForOption("--dotnetEf");
var options = new HelixTestRunnerOptions
{
Architecture = parseResult.ValueForOption("--arch"),
@@ -67,6 +73,7 @@ public static HelixTestRunnerOptions Parse(string[] args)
InstallPlaywright = parseResult.ValueForOption("--playwright"),
Quarantined = parseResult.ValueForOption("--quarantined"),
RuntimeVersion = sharedFxVersion,
+ DotnetEfVersion = dotnetEfVersion,
Target = parseResult.ValueForOption("--target"),
Timeout = TimeSpan.Parse(parseResult.ValueForOption("--helixTimeout"), CultureInfo.InvariantCulture),
@@ -87,6 +94,7 @@ public static HelixTestRunnerOptions Parse(string[] args)
public bool InstallPlaywright { get; private set; }
public bool Quarantined { get; private set; }
public string RuntimeVersion { get; private set; }
+ public string DotnetEfVersion { get; private set; }
public string Target { get; private set; }
public TimeSpan Timeout { get; private set; }
diff --git a/eng/tools/HelixTestRunner/TestRunner.cs b/eng/tools/HelixTestRunner/TestRunner.cs
index 30285e90ee1e..2202ec79606b 100644
--- a/eng/tools/HelixTestRunner/TestRunner.cs
+++ b/eng/tools/HelixTestRunner/TestRunner.cs
@@ -134,7 +134,7 @@ await ProcessUtil.RunAsync($"{Options.DotnetRoot}/dotnet",
cancellationToken: new CancellationTokenSource(TimeSpan.FromMinutes(2)).Token);
await ProcessUtil.RunAsync($"{Options.DotnetRoot}/dotnet",
- $"tool install dotnet-ef --tool-path {Options.HELIX_WORKITEM_ROOT} --add-source {correlationPayload}",
+ $"tool install dotnet-ef --tool-path {Options.HELIX_WORKITEM_ROOT} --add-source {correlationPayload} --version {Options.DotnetEfVersion}",
environmentVariables: EnvironmentVariables,
outputDataReceived: ProcessUtil.PrintMessage,
errorDataReceived: ProcessUtil.PrintErrorMessage,
diff --git a/global.json b/global.json
index e35b08d604e5..d28f803d7fac 100644
--- a/global.json
+++ b/global.json
@@ -1,9 +1,9 @@
{
"sdk": {
- "version": "7.0.112"
+ "version": "7.0.114"
},
"tools": {
- "dotnet": "7.0.112",
+ "dotnet": "7.0.114",
"runtimes": {
"dotnet/x86": [
"$(MicrosoftNETCoreBrowserDebugHostTransportVersion)"
diff --git a/src/Components/Components/src/ComponentBase.cs b/src/Components/Components/src/ComponentBase.cs
index 1c172a30f54c..a4738625053a 100644
--- a/src/Components/Components/src/ComponentBase.cs
+++ b/src/Components/Components/src/ComponentBase.cs
@@ -326,4 +326,7 @@ Task IHandleAfterRender.OnAfterRenderAsync()
// have to use "async void" and do their own exception handling in
// the case where they want to start an async task.
}
+
+ // Exists for 6.0/7.0 patch only. A different solution is used from .NET 8 onwards.
+ internal bool IsComponentDisposed() => _renderHandle.IsComponentDisposed();
}
diff --git a/src/Components/Components/src/RenderHandle.cs b/src/Components/Components/src/RenderHandle.cs
index 62edaab1d7a2..285ee7d06f56 100644
--- a/src/Components/Components/src/RenderHandle.cs
+++ b/src/Components/Components/src/RenderHandle.cs
@@ -70,4 +70,7 @@ private static void ThrowNotInitialized()
{
throw new InvalidOperationException("The render handle is not yet assigned.");
}
+
+ // Exists for 6.0/7.0 patch only. A different solution is used from .NET 8 onwards.
+ internal bool IsComponentDisposed() => _renderer?.IsComponentDisposed(_componentId) ?? false;
}
diff --git a/src/Components/Components/src/RenderTree/Renderer.cs b/src/Components/Components/src/RenderTree/Renderer.cs
index 51550c2b9957..3c91a368f0b8 100644
--- a/src/Components/Components/src/RenderTree/Renderer.cs
+++ b/src/Components/Components/src/RenderTree/Renderer.cs
@@ -1119,4 +1119,8 @@ public async ValueTask DisposeAsync()
}
}
}
+
+ // Exists for 6.0/7.0 patch only. A different solution is used from .NET 8 onwards.
+ internal bool IsComponentDisposed(int componentId)
+ => !_componentStateById.ContainsKey(componentId);
}
diff --git a/src/Components/Web/src/Forms/EditForm.cs b/src/Components/Web/src/Forms/EditForm.cs
index b2f3186daa3b..9b95a45aede3 100644
--- a/src/Components/Web/src/Forms/EditForm.cs
+++ b/src/Components/Web/src/Forms/EditForm.cs
@@ -136,6 +136,12 @@ private async Task HandleSubmitAsync()
{
Debug.Assert(_editContext != null);
+ // Exists for 6.0/7.0 patch only. A different solution is used from .NET 8 onwards.
+ if (IsComponentDisposed())
+ {
+ return;
+ }
+
if (OnSubmit.HasDelegate)
{
// When using OnSubmit, the developer takes control of the validation lifecycle
diff --git a/src/Components/test/E2ETest/Tests/FormsTest.cs b/src/Components/test/E2ETest/Tests/FormsTest.cs
index 2770ab4ee556..f14bd5cf1c09 100644
--- a/src/Components/test/E2ETest/Tests/FormsTest.cs
+++ b/src/Components/test/E2ETest/Tests/FormsTest.cs
@@ -809,6 +809,39 @@ public void CanHaveModelLevelValidationErrors()
Browser.Collection(logEntries, x => Assert.Equal("OnValidSubmit", x));
}
+ [Fact]
+ public async Task CannotSubmitEditFormSynchronouslyAfterItWasRemoved()
+ {
+ var appElement = MountSimpleValidationComponent();
+
+ var submitButtonFinder = By.CssSelector("button[type=submit]");
+ Browser.Exists(submitButtonFinder);
+
+ // Remove the form then immediately also submit it, so the server receives both
+ // the 'remove' and 'submit' commands (in that order) before it updates the UI
+ appElement.FindElement(By.Id("remove-form")).Click();
+
+ try
+ {
+ appElement.FindElement(submitButtonFinder).Click();
+ }
+ catch (NoSuchElementException)
+ {
+ // This should happen on WebAssembly because the form will be removed synchronously
+ // That means the test has passed
+ return;
+ }
+
+ // Wait for the removal to complete, which is intentionally delayed to ensure
+ // this test can submit a second instruction before the first is processed. Then
+ // wait a bit more to be really sure the second instruction was processed.
+ Browser.DoesNotExist(submitButtonFinder);
+ await Task.Delay(1000);
+
+ // Verify that the form submit event was not processed
+ Browser.DoesNotExist(By.Id("last-callback"));
+ }
+
private Func CreateValidationMessagesAccessor(IWebElement appElement, string messageSelector = ".validation-message")
{
return () => appElement.FindElements(By.CssSelector(messageSelector))
diff --git a/src/Components/test/testassets/BasicTestApp/FormsTest/SimpleValidationComponent.razor b/src/Components/test/testassets/BasicTestApp/FormsTest/SimpleValidationComponent.razor
index 8bceb63f5b71..0428e7baa1d1 100644
--- a/src/Components/test/testassets/BasicTestApp/FormsTest/SimpleValidationComponent.razor
+++ b/src/Components/test/testassets/BasicTestApp/FormsTest/SimpleValidationComponent.razor
@@ -1,6 +1,8 @@
@using System.ComponentModel.DataAnnotations
@using Microsoft.AspNetCore.Components.Forms
+@if (!removeForm)
+{
@@ -22,16 +24,20 @@
+}
@if (lastCallback != null)
{
@lastCallback
}
+
+
@code {
protected virtual bool UseExperimentalValidator => false;
string lastCallback;
+ bool removeForm;
[Required(ErrorMessage = "Please choose a username")]
public string UserName { get; set; }
@@ -49,4 +55,10 @@
{
lastCallback = "OnInvalidSubmit";
}
+
+ void RemoveForm()
+ {
+ removeForm = true;
+ Thread.Sleep(1000); // To ensure we can dispatch another event before this completes
+ }
}