diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index d9677ceaa6..5e84dbbf0b 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -13,288 +13,288 @@ https://github.com/dotnet/blazor cc449601d638ffaab58ae9487f0fd010bb178a12 - + https://github.com/dotnet/efcore - dbb4ec7b7b94df404b32d592c658bf5df2dbba55 + e4884bbaf11c3b75fe4021c49ac1da5dfa0f293a - + https://github.com/dotnet/efcore - dbb4ec7b7b94df404b32d592c658bf5df2dbba55 + e4884bbaf11c3b75fe4021c49ac1da5dfa0f293a - + https://github.com/dotnet/efcore - dbb4ec7b7b94df404b32d592c658bf5df2dbba55 + e4884bbaf11c3b75fe4021c49ac1da5dfa0f293a - + https://github.com/dotnet/efcore - dbb4ec7b7b94df404b32d592c658bf5df2dbba55 + e4884bbaf11c3b75fe4021c49ac1da5dfa0f293a - + https://github.com/dotnet/efcore - dbb4ec7b7b94df404b32d592c658bf5df2dbba55 + e4884bbaf11c3b75fe4021c49ac1da5dfa0f293a - + https://github.com/dotnet/efcore - dbb4ec7b7b94df404b32d592c658bf5df2dbba55 + e4884bbaf11c3b75fe4021c49ac1da5dfa0f293a - + https://github.com/dotnet/efcore - dbb4ec7b7b94df404b32d592c658bf5df2dbba55 + e4884bbaf11c3b75fe4021c49ac1da5dfa0f293a - + https://github.com/dotnet/runtime - 17df0b885273d0f4d22794fd830361d28bf3b663 + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 17df0b885273d0f4d22794fd830361d28bf3b663 + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 17df0b885273d0f4d22794fd830361d28bf3b663 + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 17df0b885273d0f4d22794fd830361d28bf3b663 + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 17df0b885273d0f4d22794fd830361d28bf3b663 + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 17df0b885273d0f4d22794fd830361d28bf3b663 + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 17df0b885273d0f4d22794fd830361d28bf3b663 + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 17df0b885273d0f4d22794fd830361d28bf3b663 + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 17df0b885273d0f4d22794fd830361d28bf3b663 + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 17df0b885273d0f4d22794fd830361d28bf3b663 + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 17df0b885273d0f4d22794fd830361d28bf3b663 + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 17df0b885273d0f4d22794fd830361d28bf3b663 + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 17df0b885273d0f4d22794fd830361d28bf3b663 + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 17df0b885273d0f4d22794fd830361d28bf3b663 + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 17df0b885273d0f4d22794fd830361d28bf3b663 + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 17df0b885273d0f4d22794fd830361d28bf3b663 + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 17df0b885273d0f4d22794fd830361d28bf3b663 + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 17df0b885273d0f4d22794fd830361d28bf3b663 + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 17df0b885273d0f4d22794fd830361d28bf3b663 + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 17df0b885273d0f4d22794fd830361d28bf3b663 + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 17df0b885273d0f4d22794fd830361d28bf3b663 + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 17df0b885273d0f4d22794fd830361d28bf3b663 + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 17df0b885273d0f4d22794fd830361d28bf3b663 + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 17df0b885273d0f4d22794fd830361d28bf3b663 + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 17df0b885273d0f4d22794fd830361d28bf3b663 + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 17df0b885273d0f4d22794fd830361d28bf3b663 + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 17df0b885273d0f4d22794fd830361d28bf3b663 + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 17df0b885273d0f4d22794fd830361d28bf3b663 + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 17df0b885273d0f4d22794fd830361d28bf3b663 + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 17df0b885273d0f4d22794fd830361d28bf3b663 + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 17df0b885273d0f4d22794fd830361d28bf3b663 + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 17df0b885273d0f4d22794fd830361d28bf3b663 + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 17df0b885273d0f4d22794fd830361d28bf3b663 + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 17df0b885273d0f4d22794fd830361d28bf3b663 + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 17df0b885273d0f4d22794fd830361d28bf3b663 + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 17df0b885273d0f4d22794fd830361d28bf3b663 + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 17df0b885273d0f4d22794fd830361d28bf3b663 + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 17df0b885273d0f4d22794fd830361d28bf3b663 + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 17df0b885273d0f4d22794fd830361d28bf3b663 + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 17df0b885273d0f4d22794fd830361d28bf3b663 + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 17df0b885273d0f4d22794fd830361d28bf3b663 + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 17df0b885273d0f4d22794fd830361d28bf3b663 + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 17df0b885273d0f4d22794fd830361d28bf3b663 + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 17df0b885273d0f4d22794fd830361d28bf3b663 + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 17df0b885273d0f4d22794fd830361d28bf3b663 + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 17df0b885273d0f4d22794fd830361d28bf3b663 + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 17df0b885273d0f4d22794fd830361d28bf3b663 + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 17df0b885273d0f4d22794fd830361d28bf3b663 + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 17df0b885273d0f4d22794fd830361d28bf3b663 + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 17df0b885273d0f4d22794fd830361d28bf3b663 + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 17df0b885273d0f4d22794fd830361d28bf3b663 + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 17df0b885273d0f4d22794fd830361d28bf3b663 + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 17df0b885273d0f4d22794fd830361d28bf3b663 + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 17df0b885273d0f4d22794fd830361d28bf3b663 + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 17df0b885273d0f4d22794fd830361d28bf3b663 + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 17df0b885273d0f4d22794fd830361d28bf3b663 + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 17df0b885273d0f4d22794fd830361d28bf3b663 + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 17df0b885273d0f4d22794fd830361d28bf3b663 + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 17df0b885273d0f4d22794fd830361d28bf3b663 + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 17df0b885273d0f4d22794fd830361d28bf3b663 + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 17df0b885273d0f4d22794fd830361d28bf3b663 + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 - + https://github.com/dotnet/runtime - 17df0b885273d0f4d22794fd830361d28bf3b663 + d6b8109177d0ba0eeafc8f7570c63cbc0b2f2562 https://github.com/dotnet/arcade diff --git a/eng/Versions.props b/eng/Versions.props index 93ddb85ac8..e8977a9bad 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -9,7 +9,7 @@ 5 0 0 - 7 + 8 @@ -66,79 +66,79 @@ 3.7.0-4.20319.6 - 5.0.0-preview.7.20323.4 - 5.0.0-preview.7.20323.4 - 5.0.0-preview.7.20323.4 - 5.0.0-preview.7.20323.4 - 5.0.0-preview.7.20323.4 - 5.0.0-preview.7.20323.4 - 5.0.0-preview.7.20323.4 - 5.0.0-preview.7.20323.4 - 5.0.0-preview.7.20323.4 - 5.0.0-preview.7.20323.4 - 5.0.0-preview.7.20323.4 - 5.0.0-preview.7.20323.4 - 5.0.0-preview.7.20323.4 - 5.0.0-preview.7.20323.4 - 5.0.0-preview.7.20323.4 - 5.0.0-preview.7.20323.4 - 5.0.0-preview.7.20323.4 - 5.0.0-preview.7.20323.4 - 5.0.0-preview.7.20323.4 - 5.0.0-preview.7.20323.4 - 5.0.0-preview.7.20323.4 - 5.0.0-preview.7.20323.4 - 5.0.0-preview.7.20323.4 - 5.0.0-preview.7.20323.4 - 5.0.0-preview.7.20323.4 - 5.0.0-preview.7.20323.4 - 5.0.0-preview.7.20323.4 - 5.0.0-preview.7.20323.4 - 5.0.0-preview.7.20323.4 - 5.0.0-preview.7.20323.4 - 5.0.0-preview.7.20323.4 - 5.0.0-preview.7.20323.4 - 5.0.0-preview.7.20323.4 - 5.0.0-preview.7.20323.4 - 5.0.0-preview.7.20323.4 - 5.0.0-preview.7.20323.4 - 5.0.0-preview.7.20323.4 - 5.0.0-preview.7.20323.4 - 5.0.0-preview.7.20323.4 - 5.0.0-preview.7.20323.4 - 5.0.0-preview.7.20323.4 - 5.0.0-preview.7.20323.4 - 5.0.0-preview.7.20323.4 - 5.0.0-preview.7.20323.4 - 5.0.0-preview.7.20323.4 - 5.0.0-preview.7.20323.4 - 5.0.0-preview.7.20323.4 - 5.0.0-preview.7.20323.4 - 5.0.0-preview.7.20323.4 - 5.0.0-preview.7.20323.4 - 5.0.0-preview.7.20323.4 - 5.0.0-preview.7.20323.4 - 5.0.0-preview.7.20323.4 - 5.0.0-preview.7.20323.4 - 5.0.0-preview.7.20323.4 - 5.0.0-preview.7.20323.4 - 5.0.0-preview.7.20323.4 - 5.0.0-preview.7.20323.4 - 5.0.0-preview.7.20323.4 - 5.0.0-preview.7.20323.4 - 5.0.0-preview.7.20323.4 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 + 5.0.0-preview.7.20322.7 - 5.0.0-preview.7.20323.4 + 5.0.0-preview.7.20322.7 3.2.0 - 5.0.0-preview.7.20322.5 - 5.0.0-preview.7.20322.5 - 5.0.0-preview.7.20322.5 - 5.0.0-preview.7.20322.5 - 5.0.0-preview.7.20322.5 - 5.0.0-preview.7.20322.5 - 5.0.0-preview.7.20322.5 + 5.0.0-preview.8.20323.2 + 5.0.0-preview.8.20323.2 + 5.0.0-preview.8.20323.2 + 5.0.0-preview.8.20323.2 + 5.0.0-preview.8.20323.2 + 5.0.0-preview.8.20323.2 + 5.0.0-preview.8.20323.2 diff --git a/src/Components/Components/test/Rendering/RendererSynchronizationContextTest.cs b/src/Components/Components/test/Rendering/RendererSynchronizationContextTest.cs index 77544baa77..b8908caff8 100644 --- a/src/Components/Components/test/Rendering/RendererSynchronizationContextTest.cs +++ b/src/Components/Components/test/Rendering/RendererSynchronizationContextTest.cs @@ -26,7 +26,7 @@ namespace Microsoft.AspNetCore.Components.Rendering Thread capturedThread = null; var e = new ManualResetEventSlim(); - + // Act context.Post((_) => { @@ -766,7 +766,6 @@ namespace Microsoft.AspNetCore.Components.Rendering } [Fact] - [QuarantinedTest] public async Task InvokeAsync_SyncWorkInAsyncTaskIsCompletedFirst() { // Simplified version of ServerComponentRenderingTest.CanDispatchAsyncWorkToSyncContext diff --git a/src/Hosting/Hosting/ref/Microsoft.AspNetCore.Hosting.csproj b/src/Hosting/Hosting/ref/Microsoft.AspNetCore.Hosting.csproj index 72e71d1c31..11eb4ad78e 100644 --- a/src/Hosting/Hosting/ref/Microsoft.AspNetCore.Hosting.csproj +++ b/src/Hosting/Hosting/ref/Microsoft.AspNetCore.Hosting.csproj @@ -16,7 +16,7 @@ - + diff --git a/src/Hosting/Hosting/src/Microsoft.AspNetCore.Hosting.csproj b/src/Hosting/Hosting/src/Microsoft.AspNetCore.Hosting.csproj index c78cef809d..c0e3e77284 100644 --- a/src/Hosting/Hosting/src/Microsoft.AspNetCore.Hosting.csproj +++ b/src/Hosting/Hosting/src/Microsoft.AspNetCore.Hosting.csproj @@ -1,4 +1,4 @@ - + ASP.NET Core hosting infrastructure and startup logic for web applications. @@ -26,7 +26,7 @@ - + diff --git a/src/Identity/Specification.Tests/src/UserManagerSpecificationTests.cs b/src/Identity/Specification.Tests/src/UserManagerSpecificationTests.cs index 4bc1a37559..f675482bfb 100644 --- a/src/Identity/Specification.Tests/src/UserManagerSpecificationTests.cs +++ b/src/Identity/Specification.Tests/src/UserManagerSpecificationTests.cs @@ -1450,7 +1450,6 @@ namespace Microsoft.AspNetCore.Identity.Test /// /// Task [Fact] - [QuarantinedTest] public async Task ChangePhoneNumberFailsWithWrongPhoneNumber() { var manager = CreateManager(); @@ -1471,7 +1470,6 @@ namespace Microsoft.AspNetCore.Identity.Test /// /// Task [Fact] - [QuarantinedTest] public async Task CanVerifyPhoneNumber() { var manager = CreateManager(); @@ -1519,7 +1517,6 @@ namespace Microsoft.AspNetCore.Identity.Test /// /// Task [Fact] - [QuarantinedTest] public async Task CanChangeEmailOnlyIfEmailSame() { var manager = CreateManager(); diff --git a/src/JSInterop/Microsoft.JSInterop.JS/src/package.json b/src/JSInterop/Microsoft.JSInterop.JS/src/package.json index b73521f14f..40db20ee63 100644 --- a/src/JSInterop/Microsoft.JSInterop.JS/src/package.json +++ b/src/JSInterop/Microsoft.JSInterop.JS/src/package.json @@ -18,9 +18,9 @@ "author": "Microsoft", "license": "Apache-2.0", "bugs": { - "url": "https://github.com/dotnet/extensions/issues" + "url": "https://github.com/dotnet/aspnetcore/issues" }, - "homepage": "https://github.com/dotnet/extensions/tree/master/src/JSInterop#readme", + "homepage": "https://github.com/dotnet/aspnetcore/tree/master/src/JSInterop", "files": [ "dist/**" ], diff --git a/src/Middleware/SpaServices.Extensions/src/Proxying/SpaProxy.cs b/src/Middleware/SpaServices.Extensions/src/Proxying/SpaProxy.cs index 04d7e697a1..20f516540d 100644 --- a/src/Middleware/SpaServices.Extensions/src/Proxying/SpaProxy.cs +++ b/src/Middleware/SpaServices.Extensions/src/Proxying/SpaProxy.cs @@ -27,7 +27,7 @@ namespace Microsoft.AspNetCore.SpaServices.Extensions.Proxy // Don't forward User-Agent/Accept because of https://github.com/aspnet/JavaScriptServices/issues/1469 // Others just aren't applicable in proxy scenarios - private static readonly string[] NotForwardedWebSocketHeaders = new[] { "Accept", "Connection", "Host", "User-Agent", "Upgrade", "Sec-WebSocket-Key", "Sec-WebSocket-Version" }; + private static readonly string[] NotForwardedWebSocketHeaders = new[] { "Accept", "Connection", "Host", "User-Agent", "Upgrade", "Sec-WebSocket-Key", "Sec-WebSocket-Protocol", "Sec-WebSocket-Version" }; public static HttpClient CreateHttpClientForProxy(TimeSpan requestTimeout) { @@ -209,6 +209,10 @@ namespace Microsoft.AspNetCore.SpaServices.Extensions.Proxy using (var client = new ClientWebSocket()) { + foreach (var protocol in context.WebSockets.WebSocketRequestedProtocols) + { + client.Options.AddSubProtocol(protocol); + } foreach (var headerEntry in context.Request.Headers) { if (!NotForwardedWebSocketHeaders.Contains(headerEntry.Key, StringComparer.OrdinalIgnoreCase)) diff --git a/src/Mvc/Mvc.Abstractions/ref/Microsoft.AspNetCore.Mvc.Abstractions.csproj b/src/Mvc/Mvc.Abstractions/ref/Microsoft.AspNetCore.Mvc.Abstractions.csproj index ce0671621e..2ae7b2695e 100644 --- a/src/Mvc/Mvc.Abstractions/ref/Microsoft.AspNetCore.Mvc.Abstractions.csproj +++ b/src/Mvc/Mvc.Abstractions/ref/Microsoft.AspNetCore.Mvc.Abstractions.csproj @@ -2,6 +2,7 @@ $(DefaultNetCoreTargetFramework) + annotations diff --git a/src/Mvc/Mvc.Abstractions/ref/Microsoft.AspNetCore.Mvc.Abstractions.netcoreapp.cs b/src/Mvc/Mvc.Abstractions/ref/Microsoft.AspNetCore.Mvc.Abstractions.netcoreapp.cs index 84ca15ad39..267c99ef8a 100644 --- a/src/Mvc/Mvc.Abstractions/ref/Microsoft.AspNetCore.Mvc.Abstractions.netcoreapp.cs +++ b/src/Mvc/Mvc.Abstractions/ref/Microsoft.AspNetCore.Mvc.Abstractions.netcoreapp.cs @@ -33,10 +33,10 @@ namespace Microsoft.AspNetCore.Mvc.Abstractions public partial class ActionDescriptor { public ActionDescriptor() { } - public System.Collections.Generic.IList ActionConstraints { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } - public Microsoft.AspNetCore.Mvc.Routing.AttributeRouteInfo AttributeRouteInfo { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } + public System.Collections.Generic.IList? ActionConstraints { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } + public Microsoft.AspNetCore.Mvc.Routing.AttributeRouteInfo? AttributeRouteInfo { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } public System.Collections.Generic.IList BoundProperties { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } - public virtual string DisplayName { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } + public virtual string? DisplayName { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } public System.Collections.Generic.IList EndpointMetadata { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } public System.Collections.Generic.IList FilterDescriptors { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } public string Id { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } @@ -58,7 +58,7 @@ namespace Microsoft.AspNetCore.Mvc.Abstractions { public ActionInvokerProviderContext(Microsoft.AspNetCore.Mvc.ActionContext actionContext) { } public Microsoft.AspNetCore.Mvc.ActionContext ActionContext { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } - public Microsoft.AspNetCore.Mvc.Abstractions.IActionInvoker Result { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } + public Microsoft.AspNetCore.Mvc.Abstractions.IActionInvoker? Result { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } } public partial interface IActionDescriptorProvider { @@ -143,8 +143,8 @@ namespace Microsoft.AspNetCore.Mvc.ApiExplorer { public ApiDescription() { } public Microsoft.AspNetCore.Mvc.Abstractions.ActionDescriptor ActionDescriptor { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } - public string GroupName { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } - public string HttpMethod { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } + public string? GroupName { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } + public string? HttpMethod { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } public System.Collections.Generic.IList ParameterDescriptions { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } public System.Collections.Generic.IDictionary Properties { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } public string RelativePath { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } @@ -160,21 +160,21 @@ namespace Microsoft.AspNetCore.Mvc.ApiExplorer public partial class ApiParameterDescription { public ApiParameterDescription() { } - public Microsoft.AspNetCore.Mvc.ModelBinding.BindingInfo BindingInfo { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } - public object DefaultValue { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } + public Microsoft.AspNetCore.Mvc.ModelBinding.BindingInfo? BindingInfo { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } + public object? DefaultValue { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } public bool IsRequired { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } public Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata ModelMetadata { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } public string Name { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } public Microsoft.AspNetCore.Mvc.Abstractions.ParameterDescriptor ParameterDescriptor { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } - public Microsoft.AspNetCore.Mvc.ApiExplorer.ApiParameterRouteInfo RouteInfo { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } + public Microsoft.AspNetCore.Mvc.ApiExplorer.ApiParameterRouteInfo? RouteInfo { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } public Microsoft.AspNetCore.Mvc.ModelBinding.BindingSource Source { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } public System.Type Type { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } } public partial class ApiParameterRouteInfo { public ApiParameterRouteInfo() { } - public System.Collections.Generic.IEnumerable Constraints { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } - public object DefaultValue { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } + public System.Collections.Generic.IEnumerable? Constraints { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } + public object? DefaultValue { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } public bool IsOptional { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } } public partial class ApiRequestFormat @@ -194,9 +194,9 @@ namespace Microsoft.AspNetCore.Mvc.ApiExplorer public ApiResponseType() { } public System.Collections.Generic.IList ApiResponseFormats { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } public bool IsDefaultResponse { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } - public Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata ModelMetadata { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } + public Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata? ModelMetadata { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } public int StatusCode { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } - public System.Type Type { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } + public System.Type? Type { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } } public partial interface IApiDescriptionProvider { @@ -218,8 +218,8 @@ namespace Microsoft.AspNetCore.Mvc.Filters public ActionExecutedContext(Microsoft.AspNetCore.Mvc.ActionContext actionContext, System.Collections.Generic.IList filters, object controller) : base (default(Microsoft.AspNetCore.Mvc.ActionContext), default(System.Collections.Generic.IList)) { } public virtual bool Canceled { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } public virtual object Controller { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } - public virtual System.Exception Exception { get { throw null; } set { } } - public virtual System.Runtime.ExceptionServices.ExceptionDispatchInfo ExceptionDispatchInfo { get { throw null; } set { } } + public virtual System.Exception? Exception { get { throw null; } set { } } + public virtual System.Runtime.ExceptionServices.ExceptionDispatchInfo? ExceptionDispatchInfo { get { throw null; } set { } } public virtual bool ExceptionHandled { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } public virtual Microsoft.AspNetCore.Mvc.IActionResult Result { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } } @@ -228,26 +228,27 @@ namespace Microsoft.AspNetCore.Mvc.Filters public ActionExecutingContext(Microsoft.AspNetCore.Mvc.ActionContext actionContext, System.Collections.Generic.IList filters, System.Collections.Generic.IDictionary actionArguments, object controller) : base (default(Microsoft.AspNetCore.Mvc.ActionContext), default(System.Collections.Generic.IList)) { } public virtual System.Collections.Generic.IDictionary ActionArguments { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } public virtual object Controller { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } - public virtual Microsoft.AspNetCore.Mvc.IActionResult Result { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } + public virtual Microsoft.AspNetCore.Mvc.IActionResult? Result { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } } public delegate System.Threading.Tasks.Task ActionExecutionDelegate(); public partial class AuthorizationFilterContext : Microsoft.AspNetCore.Mvc.Filters.FilterContext { public AuthorizationFilterContext(Microsoft.AspNetCore.Mvc.ActionContext actionContext, System.Collections.Generic.IList filters) : base (default(Microsoft.AspNetCore.Mvc.ActionContext), default(System.Collections.Generic.IList)) { } - public virtual Microsoft.AspNetCore.Mvc.IActionResult Result { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } + public virtual Microsoft.AspNetCore.Mvc.IActionResult? Result { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } } public partial class ExceptionContext : Microsoft.AspNetCore.Mvc.Filters.FilterContext { public ExceptionContext(Microsoft.AspNetCore.Mvc.ActionContext actionContext, System.Collections.Generic.IList filters) : base (default(Microsoft.AspNetCore.Mvc.ActionContext), default(System.Collections.Generic.IList)) { } public virtual System.Exception Exception { get { throw null; } set { } } - public virtual System.Runtime.ExceptionServices.ExceptionDispatchInfo ExceptionDispatchInfo { get { throw null; } set { } } + public virtual System.Runtime.ExceptionServices.ExceptionDispatchInfo? ExceptionDispatchInfo { get { throw null; } set { } } public virtual bool ExceptionHandled { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } - public virtual Microsoft.AspNetCore.Mvc.IActionResult Result { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } + public virtual Microsoft.AspNetCore.Mvc.IActionResult? Result { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } } public abstract partial class FilterContext : Microsoft.AspNetCore.Mvc.ActionContext { public FilterContext(Microsoft.AspNetCore.Mvc.ActionContext actionContext, System.Collections.Generic.IList filters) { } public virtual System.Collections.Generic.IList Filters { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } + [return: System.Diagnostics.CodeAnalysis.MaybeNullAttribute] public TMetadata FindEffectivePolicy() where TMetadata : Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata { throw null; } public bool IsEffectivePolicy(TMetadata policy) where TMetadata : Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata { throw null; } } @@ -349,15 +350,15 @@ namespace Microsoft.AspNetCore.Mvc.Filters { public ResourceExecutedContext(Microsoft.AspNetCore.Mvc.ActionContext actionContext, System.Collections.Generic.IList filters) : base (default(Microsoft.AspNetCore.Mvc.ActionContext), default(System.Collections.Generic.IList)) { } public virtual bool Canceled { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } - public virtual System.Exception Exception { get { throw null; } set { } } - public virtual System.Runtime.ExceptionServices.ExceptionDispatchInfo ExceptionDispatchInfo { get { throw null; } set { } } + public virtual System.Exception? Exception { get { throw null; } set { } } + public virtual System.Runtime.ExceptionServices.ExceptionDispatchInfo? ExceptionDispatchInfo { get { throw null; } set { } } public virtual bool ExceptionHandled { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } - public virtual Microsoft.AspNetCore.Mvc.IActionResult Result { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } + public virtual Microsoft.AspNetCore.Mvc.IActionResult? Result { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } } public partial class ResourceExecutingContext : Microsoft.AspNetCore.Mvc.Filters.FilterContext { public ResourceExecutingContext(Microsoft.AspNetCore.Mvc.ActionContext actionContext, System.Collections.Generic.IList filters, System.Collections.Generic.IList valueProviderFactories) : base (default(Microsoft.AspNetCore.Mvc.ActionContext), default(System.Collections.Generic.IList)) { } - public virtual Microsoft.AspNetCore.Mvc.IActionResult Result { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } + public virtual Microsoft.AspNetCore.Mvc.IActionResult? Result { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } public System.Collections.Generic.IList ValueProviderFactories { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } } public delegate System.Threading.Tasks.Task ResourceExecutionDelegate(); @@ -366,8 +367,8 @@ namespace Microsoft.AspNetCore.Mvc.Filters public ResultExecutedContext(Microsoft.AspNetCore.Mvc.ActionContext actionContext, System.Collections.Generic.IList filters, Microsoft.AspNetCore.Mvc.IActionResult result, object controller) : base (default(Microsoft.AspNetCore.Mvc.ActionContext), default(System.Collections.Generic.IList)) { } public virtual bool Canceled { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } public virtual object Controller { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } - public virtual System.Exception Exception { get { throw null; } set { } } - public virtual System.Runtime.ExceptionServices.ExceptionDispatchInfo ExceptionDispatchInfo { get { throw null; } set { } } + public virtual System.Exception? Exception { get { throw null; } set { } } + public virtual System.Runtime.ExceptionServices.ExceptionDispatchInfo? ExceptionDispatchInfo { get { throw null; } set { } } public virtual bool ExceptionHandled { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } public virtual Microsoft.AspNetCore.Mvc.IActionResult Result { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } } @@ -382,7 +383,7 @@ namespace Microsoft.AspNetCore.Mvc.Filters } namespace Microsoft.AspNetCore.Mvc.Formatters { - public partial class FormatterCollection : System.Collections.ObjectModel.Collection + public partial class FormatterCollection : System.Collections.ObjectModel.Collection where TFormatter : notnull { public FormatterCollection() { } public FormatterCollection(System.Collections.Generic.IList list) { } @@ -426,7 +427,7 @@ namespace Microsoft.AspNetCore.Mvc.Formatters internal InputFormatterResult() { } public bool HasError { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } public bool IsModelSet { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } - public object Model { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } + public object? Model { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } public static Microsoft.AspNetCore.Mvc.Formatters.InputFormatterResult Failure() { throw null; } public static System.Threading.Tasks.Task FailureAsync() { throw null; } public static Microsoft.AspNetCore.Mvc.Formatters.InputFormatterResult NoValue() { throw null; } @@ -445,8 +446,8 @@ namespace Microsoft.AspNetCore.Mvc.Formatters public virtual Microsoft.Extensions.Primitives.StringSegment ContentType { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } public virtual bool ContentTypeIsServerDefined { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } public virtual Microsoft.AspNetCore.Http.HttpContext HttpContext { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] protected set { } } - public virtual object Object { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] protected set { } } - public virtual System.Type ObjectType { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] protected set { } } + public virtual object? Object { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] protected set { } } + public virtual System.Type? ObjectType { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] protected set { } } } public partial class OutputFormatterWriteContext : Microsoft.AspNetCore.Mvc.Formatters.OutputFormatterCanWriteContext { @@ -460,18 +461,18 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding { public BindingInfo() { } public BindingInfo(Microsoft.AspNetCore.Mvc.ModelBinding.BindingInfo other) { } - public string BinderModelName { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } - public System.Type BinderType { get { throw null; } set { } } - public Microsoft.AspNetCore.Mvc.ModelBinding.BindingSource BindingSource { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } + public string? BinderModelName { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } + public System.Type? BinderType { get { throw null; } set { } } + public Microsoft.AspNetCore.Mvc.ModelBinding.BindingSource? BindingSource { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } public Microsoft.AspNetCore.Mvc.ModelBinding.EmptyBodyBehavior EmptyBodyBehavior { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } - public Microsoft.AspNetCore.Mvc.ModelBinding.IPropertyFilterProvider PropertyFilterProvider { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } - public System.Func RequestPredicate { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } - public static Microsoft.AspNetCore.Mvc.ModelBinding.BindingInfo GetBindingInfo(System.Collections.Generic.IEnumerable attributes) { throw null; } - public static Microsoft.AspNetCore.Mvc.ModelBinding.BindingInfo GetBindingInfo(System.Collections.Generic.IEnumerable attributes, Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata modelMetadata) { throw null; } + public Microsoft.AspNetCore.Mvc.ModelBinding.IPropertyFilterProvider? PropertyFilterProvider { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } + public System.Func? RequestPredicate { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } + public static Microsoft.AspNetCore.Mvc.ModelBinding.BindingInfo? GetBindingInfo(System.Collections.Generic.IEnumerable attributes) { throw null; } + public static Microsoft.AspNetCore.Mvc.ModelBinding.BindingInfo? GetBindingInfo(System.Collections.Generic.IEnumerable attributes, Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata modelMetadata) { throw null; } public bool TryApplyBindingInfo(Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata modelMetadata) { throw null; } } [System.Diagnostics.DebuggerDisplayAttribute("Source: {DisplayName}")] - public partial class BindingSource : System.IEquatable + public partial class BindingSource : System.IEquatable { public static readonly Microsoft.AspNetCore.Mvc.ModelBinding.BindingSource Body; public static readonly Microsoft.AspNetCore.Mvc.ModelBinding.BindingSource Custom; @@ -489,11 +490,11 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding public bool IsFromRequest { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } public bool IsGreedy { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } public virtual bool CanAcceptDataFrom(Microsoft.AspNetCore.Mvc.ModelBinding.BindingSource bindingSource) { throw null; } - public bool Equals(Microsoft.AspNetCore.Mvc.ModelBinding.BindingSource other) { throw null; } - public override bool Equals(object obj) { throw null; } + public bool Equals(Microsoft.AspNetCore.Mvc.ModelBinding.BindingSource? other) { throw null; } + public override bool Equals(object? obj) { throw null; } public override int GetHashCode() { throw null; } - public static bool operator ==(Microsoft.AspNetCore.Mvc.ModelBinding.BindingSource s1, Microsoft.AspNetCore.Mvc.ModelBinding.BindingSource s2) { throw null; } - public static bool operator !=(Microsoft.AspNetCore.Mvc.ModelBinding.BindingSource s1, Microsoft.AspNetCore.Mvc.ModelBinding.BindingSource s2) { throw null; } + public static bool operator ==(Microsoft.AspNetCore.Mvc.ModelBinding.BindingSource? s1, Microsoft.AspNetCore.Mvc.ModelBinding.BindingSource? s2) { throw null; } + public static bool operator !=(Microsoft.AspNetCore.Mvc.ModelBinding.BindingSource? s1, Microsoft.AspNetCore.Mvc.ModelBinding.BindingSource? s2) { throw null; } } public partial class CompositeBindingSource : Microsoft.AspNetCore.Mvc.ModelBinding.BindingSource { @@ -524,7 +525,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding } public partial interface IBindingSourceMetadata { - Microsoft.AspNetCore.Mvc.ModelBinding.BindingSource BindingSource { get; } + Microsoft.AspNetCore.Mvc.ModelBinding.BindingSource? BindingSource { get; } } public partial interface IModelBinder { @@ -607,9 +608,9 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding private readonly object _dummy; private readonly int _dummyPrimitive; public bool IsModelSet { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } - public object Model { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } + public object? Model { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } public bool Equals(Microsoft.AspNetCore.Mvc.ModelBinding.ModelBindingResult other) { throw null; } - public override bool Equals(object obj) { throw null; } + public override bool Equals(object? obj) { throw null; } public static Microsoft.AspNetCore.Mvc.ModelBinding.ModelBindingResult Failed() { throw null; } public override int GetHashCode() { throw null; } public static bool operator ==(Microsoft.AspNetCore.Mvc.ModelBinding.ModelBindingResult x, Microsoft.AspNetCore.Mvc.ModelBinding.ModelBindingResult y) { throw null; } @@ -620,10 +621,10 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding public partial class ModelError { public ModelError(System.Exception exception) { } - public ModelError(System.Exception exception, string errorMessage) { } - public ModelError(string errorMessage) { } + public ModelError(System.Exception exception, string? errorMessage) { } + public ModelError(string? errorMessage) { } public string ErrorMessage { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } - public System.Exception Exception { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } + public System.Exception? Exception { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } } public partial class ModelErrorCollection : System.Collections.ObjectModel.Collection { @@ -632,7 +633,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding public void Add(string errorMessage) { } } [System.Diagnostics.DebuggerDisplayAttribute("{DebuggerToString(),nq}")] - public abstract partial class ModelMetadata : Microsoft.AspNetCore.Mvc.ModelBinding.IModelMetadataProvider, System.IEquatable + public abstract partial class ModelMetadata : Microsoft.AspNetCore.Mvc.ModelBinding.IModelMetadataProvider, System.IEquatable { public static readonly int DefaultOrder; protected ModelMetadata(Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.ModelMetadataIdentity identity) { } @@ -641,15 +642,15 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding public abstract System.Type BinderType { get; } public abstract Microsoft.AspNetCore.Mvc.ModelBinding.BindingSource BindingSource { get; } public virtual Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata ContainerMetadata { get { throw null; } } - public System.Type ContainerType { get { throw null; } } + public System.Type? ContainerType { get { throw null; } } public abstract bool ConvertEmptyStringToNull { get; } public abstract string DataTypeName { get; } public abstract string Description { get; } public abstract string DisplayFormatString { get; } public abstract string DisplayName { get; } public abstract string EditFormatString { get; } - public abstract Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata ElementMetadata { get; } - public System.Type ElementType { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } + public abstract Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata? ElementMetadata { get; } + public System.Type? ElementType { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } public abstract System.Collections.Generic.IEnumerable> EnumGroupedDisplayNamesAndValues { get; } public abstract System.Collections.Generic.IReadOnlyDictionary EnumNamesAndValues { get; } public abstract bool HasNonDefaultEditFormat { get; } @@ -671,17 +672,17 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding public Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.ModelMetadataKind MetadataKind { get { throw null; } } public abstract Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.ModelBindingMessageProvider ModelBindingMessageProvider { get; } public System.Type ModelType { get { throw null; } } - public string Name { get { throw null; } } + public string? Name { get { throw null; } } public abstract string NullDisplayText { get; } public abstract int Order { get; } - public string ParameterName { get { throw null; } } + public string? ParameterName { get { throw null; } } public abstract string Placeholder { get; } public abstract Microsoft.AspNetCore.Mvc.ModelBinding.ModelPropertyCollection Properties { get; } public abstract Microsoft.AspNetCore.Mvc.ModelBinding.IPropertyFilterProvider PropertyFilterProvider { get; } public abstract System.Func PropertyGetter { get; } - public string PropertyName { get { throw null; } } + public string? PropertyName { get { throw null; } } public abstract System.Action PropertySetter { get; } - public virtual Microsoft.AspNetCore.Mvc.ModelBinding.Validation.IPropertyValidationFilter PropertyValidationFilter { get { throw null; } } + public virtual Microsoft.AspNetCore.Mvc.ModelBinding.Validation.IPropertyValidationFilter? PropertyValidationFilter { get { throw null; } } public abstract bool ShowForDisplay { get; } public abstract bool ShowForEdit { get; } public abstract string SimpleDisplayProperty { get; } @@ -689,8 +690,8 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding public System.Type UnderlyingOrModelType { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } public abstract bool ValidateChildren { get; } public abstract System.Collections.Generic.IReadOnlyList ValidatorMetadata { get; } - public bool Equals(Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata other) { throw null; } - public override bool Equals(object obj) { throw null; } + public bool Equals(Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata? other) { throw null; } + public override bool Equals(object? obj) { throw null; } public string GetDisplayName() { throw null; } public override int GetHashCode() { throw null; } public virtual System.Collections.Generic.IEnumerable GetMetadataForProperties(System.Type modelType) { throw null; } @@ -708,7 +709,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding public partial class ModelPropertyCollection : System.Collections.ObjectModel.ReadOnlyCollection { public ModelPropertyCollection(System.Collections.Generic.IEnumerable properties) : base (default(System.Collections.Generic.IList)) { } - public Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata this[string propertyName] { get { throw null; } } + public Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata? this[string propertyName] { get { throw null; } } } public partial class ModelStateDictionary : System.Collections.Generic.IEnumerable>, System.Collections.Generic.IReadOnlyCollection>, System.Collections.Generic.IReadOnlyDictionary, System.Collections.IEnumerable { @@ -724,8 +725,8 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding public Microsoft.AspNetCore.Mvc.ModelBinding.ModelStateDictionary.KeyEnumerable Keys { get { throw null; } } public int MaxAllowedErrors { get { throw null; } set { } } public Microsoft.AspNetCore.Mvc.ModelBinding.ModelStateEntry Root { get { throw null; } } - System.Collections.Generic.IEnumerable System.Collections.Generic.IReadOnlyDictionary.Keys { get { throw null; } } - System.Collections.Generic.IEnumerable System.Collections.Generic.IReadOnlyDictionary.Values { get { throw null; } } + System.Collections.Generic.IEnumerable System.Collections.Generic.IReadOnlyDictionary.Keys { get { throw null; } } + System.Collections.Generic.IEnumerable System.Collections.Generic.IReadOnlyDictionary.Values { get { throw null; } } public Microsoft.AspNetCore.Mvc.ModelBinding.ModelValidationState ValidationState { get { throw null; } } public Microsoft.AspNetCore.Mvc.ModelBinding.ModelStateDictionary.ValueEnumerable Values { get { throw null; } } public void AddModelError(string key, System.Exception exception, Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata metadata) { } @@ -742,14 +743,14 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding public void Merge(Microsoft.AspNetCore.Mvc.ModelBinding.ModelStateDictionary dictionary) { } public bool Remove(string key) { throw null; } public void SetModelValue(string key, Microsoft.AspNetCore.Mvc.ModelBinding.ValueProviderResult valueProviderResult) { } - public void SetModelValue(string key, object rawValue, string attemptedValue) { } + public void SetModelValue(string key, object? rawValue, string attemptedValue) { } public static bool StartsWithPrefix(string prefix, string key) { throw null; } - System.Collections.Generic.IEnumerator> System.Collections.Generic.IEnumerable>.GetEnumerator() { throw null; } + System.Collections.Generic.IEnumerator> System.Collections.Generic.IEnumerable>.GetEnumerator() { throw null; } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { throw null; } public bool TryAddModelError(string key, System.Exception exception, Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata metadata) { throw null; } public bool TryAddModelError(string key, string errorMessage) { throw null; } public bool TryAddModelException(string key, System.Exception exception) { throw null; } - public bool TryGetValue(string key, out Microsoft.AspNetCore.Mvc.ModelBinding.ModelStateEntry value) { throw null; } + public bool TryGetValue(string key, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out Microsoft.AspNetCore.Mvc.ModelBinding.ModelStateEntry? value) { throw null; } [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] public partial struct Enumerator : System.Collections.Generic.IEnumerator>, System.Collections.IEnumerator, System.IDisposable { @@ -769,7 +770,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding private readonly int _dummyPrimitive; public KeyEnumerable(Microsoft.AspNetCore.Mvc.ModelBinding.ModelStateDictionary dictionary) { throw null; } public Microsoft.AspNetCore.Mvc.ModelBinding.ModelStateDictionary.KeyEnumerator GetEnumerator() { throw null; } - System.Collections.Generic.IEnumerator System.Collections.Generic.IEnumerable.GetEnumerator() { throw null; } + System.Collections.Generic.IEnumerator System.Collections.Generic.IEnumerable.GetEnumerator() { throw null; } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { throw null; } } [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] @@ -791,7 +792,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding private readonly int _dummyPrimitive; public PrefixEnumerable(Microsoft.AspNetCore.Mvc.ModelBinding.ModelStateDictionary dictionary, string prefix) { throw null; } public Microsoft.AspNetCore.Mvc.ModelBinding.ModelStateDictionary.Enumerator GetEnumerator() { throw null; } - System.Collections.Generic.IEnumerator> System.Collections.Generic.IEnumerable>.GetEnumerator() { throw null; } + System.Collections.Generic.IEnumerator> System.Collections.Generic.IEnumerable>.GetEnumerator() { throw null; } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { throw null; } } [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] @@ -820,13 +821,13 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding public abstract partial class ModelStateEntry { protected ModelStateEntry() { } - public string AttemptedValue { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } - public abstract System.Collections.Generic.IReadOnlyList Children { get; } + public string? AttemptedValue { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } + public abstract System.Collections.Generic.IReadOnlyList? Children { get; } public Microsoft.AspNetCore.Mvc.ModelBinding.ModelErrorCollection Errors { get { throw null; } } public abstract bool IsContainerNode { get; } - public object RawValue { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } + public object? RawValue { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } public Microsoft.AspNetCore.Mvc.ModelBinding.ModelValidationState ValidationState { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } - public abstract Microsoft.AspNetCore.Mvc.ModelBinding.ModelStateEntry GetModelStateForProperty(string propertyName); + public abstract Microsoft.AspNetCore.Mvc.ModelBinding.ModelStateEntry? GetModelStateForProperty(string propertyName); } public enum ModelValidationState { @@ -859,11 +860,11 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding public ValueProviderResult(Microsoft.Extensions.Primitives.StringValues values) { throw null; } public ValueProviderResult(Microsoft.Extensions.Primitives.StringValues values, System.Globalization.CultureInfo culture) { throw null; } public System.Globalization.CultureInfo Culture { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } - public string FirstValue { get { throw null; } } + public string? FirstValue { get { throw null; } } public int Length { get { throw null; } } public Microsoft.Extensions.Primitives.StringValues Values { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } public bool Equals(Microsoft.AspNetCore.Mvc.ModelBinding.ValueProviderResult other) { throw null; } - public override bool Equals(object obj) { throw null; } + public override bool Equals(object? obj) { throw null; } public System.Collections.Generic.IEnumerator GetEnumerator() { throw null; } public override int GetHashCode() { throw null; } public static bool operator ==(Microsoft.AspNetCore.Mvc.ModelBinding.ValueProviderResult x, Microsoft.AspNetCore.Mvc.ModelBinding.ValueProviderResult y) { throw null; } @@ -896,14 +897,14 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Metadata { private readonly object _dummy; private readonly int _dummyPrimitive; - public System.Type ContainerType { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } + public System.Type? ContainerType { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } public Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.ModelMetadataKind MetadataKind { get { throw null; } } public System.Type ModelType { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } - public string Name { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } - public System.Reflection.ParameterInfo ParameterInfo { get { throw null; } } - public System.Reflection.PropertyInfo PropertyInfo { get { throw null; } } + public string? Name { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } + public System.Reflection.ParameterInfo? ParameterInfo { get { throw null; } } + public System.Reflection.PropertyInfo? PropertyInfo { get { throw null; } } public bool Equals(Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.ModelMetadataIdentity other) { throw null; } - public override bool Equals(object obj) { throw null; } + public override bool Equals(object? obj) { throw null; } public static Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.ModelMetadataIdentity ForParameter(System.Reflection.ParameterInfo parameter) { throw null; } public static Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.ModelMetadataIdentity ForParameter(System.Reflection.ParameterInfo parameter, System.Type modelType) { throw null; } public static Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.ModelMetadataIdentity ForProperty(System.Reflection.PropertyInfo propertyInfo, System.Type modelType, System.Type containerType) { throw null; } @@ -1000,17 +1001,19 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Validation public ValidationEntry(Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata metadata, string key, object model) { throw null; } public string Key { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } public Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata Metadata { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } - public object Model { get { throw null; } } + public object? Model { get { throw null; } } } public partial class ValidationStateDictionary : System.Collections.Generic.ICollection>, System.Collections.Generic.IDictionary, System.Collections.Generic.IEnumerable>, System.Collections.Generic.IReadOnlyCollection>, System.Collections.Generic.IReadOnlyDictionary, System.Collections.IEnumerable { public ValidationStateDictionary() { } public int Count { get { throw null; } } public bool IsReadOnly { get { throw null; } } - public Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ValidationStateEntry this[object key] { get { throw null; } set { } } + public Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ValidationStateEntry? this[object key] { get { throw null; } set { } } public System.Collections.Generic.ICollection Keys { get { throw null; } } - System.Collections.Generic.IEnumerable System.Collections.Generic.IReadOnlyDictionary.Keys { get { throw null; } } - System.Collections.Generic.IEnumerable System.Collections.Generic.IReadOnlyDictionary.Values { get { throw null; } } + Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ValidationStateEntry System.Collections.Generic.IDictionary.this[object key] { get { throw null; } set { } } + Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ValidationStateEntry System.Collections.Generic.IReadOnlyDictionary.this[object key] { get { throw null; } } + System.Collections.Generic.IEnumerable System.Collections.Generic.IReadOnlyDictionary.Keys { get { throw null; } } + System.Collections.Generic.IEnumerable System.Collections.Generic.IReadOnlyDictionary.Values { get { throw null; } } public System.Collections.Generic.ICollection Values { get { throw null; } } public void Add(System.Collections.Generic.KeyValuePair item) { } public void Add(object key, Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ValidationStateEntry value) { } @@ -1022,7 +1025,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Validation public bool Remove(System.Collections.Generic.KeyValuePair item) { throw null; } public bool Remove(object key) { throw null; } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { throw null; } - public bool TryGetValue(object key, out Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ValidationStateEntry value) { throw null; } + public bool TryGetValue(object key, [System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ValidationStateEntry value) { throw null; } } public partial class ValidationStateEntry { @@ -1050,25 +1053,25 @@ namespace Microsoft.AspNetCore.Mvc.Routing public int Order { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } public bool SuppressLinkGeneration { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } public bool SuppressPathMatching { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } - public string Template { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } + public string? Template { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } } public partial class UrlActionContext { public UrlActionContext() { } - public string Action { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } - public string Controller { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } - public string Fragment { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } - public string Host { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } - public string Protocol { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } - public object Values { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } + public string? Action { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } + public string? Controller { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } + public string? Fragment { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } + public string? Host { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } + public string? Protocol { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } + public object? Values { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } } public partial class UrlRouteContext { public UrlRouteContext() { } - public string Fragment { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } - public string Host { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } - public string Protocol { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } - public string RouteName { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } - public object Values { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } + public string? Fragment { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } + public string? Host { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } + public string? Protocol { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } + public string? RouteName { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } + public object? Values { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } } } diff --git a/src/Mvc/Mvc.Abstractions/src/Abstractions/ActionDescriptor.cs b/src/Mvc/Mvc.Abstractions/src/Abstractions/ActionDescriptor.cs index c6200ba6ee..fe6130f382 100644 --- a/src/Mvc/Mvc.Abstractions/src/Abstractions/ActionDescriptor.cs +++ b/src/Mvc/Mvc.Abstractions/src/Abstractions/ActionDescriptor.cs @@ -38,42 +38,42 @@ namespace Microsoft.AspNetCore.Mvc.Abstractions /// /// Gets or sets the . /// - public AttributeRouteInfo AttributeRouteInfo { get; set; } + public AttributeRouteInfo? AttributeRouteInfo { get; set; } /// /// The set of constraints for this action. Must all be satisfied for the action to be selected. /// - public IList ActionConstraints { get; set; } + public IList? ActionConstraints { get; set; } /// /// Gets or sets the endpoint metadata for this action. /// This API is meant for infrastructure and should not be used by application code. /// - public IList EndpointMetadata { get; set; } + public IList EndpointMetadata { get; set; } = Array.Empty(); /// /// The set of parameters associated with this action. /// - public IList Parameters { get; set; } + public IList Parameters { get; set; } = Array.Empty(); /// /// The set of properties which are model bound. /// - public IList BoundProperties { get; set; } + public IList BoundProperties { get; set; } = Array.Empty(); /// /// The set of filters associated with this action. /// - public IList FilterDescriptors { get; set; } + public IList FilterDescriptors { get; set; } = Array.Empty(); /// /// A friendly name for this action. /// - public virtual string DisplayName { get; set; } + public virtual string? DisplayName { get; set; } /// /// Stores arbitrary metadata properties associated with the . /// - public IDictionary Properties { get; set; } + public IDictionary Properties { get; set; } = default!; } } diff --git a/src/Mvc/Mvc.Abstractions/src/Abstractions/ActionDescriptorExtensions.cs b/src/Mvc/Mvc.Abstractions/src/Abstractions/ActionDescriptorExtensions.cs index 3cd94db1f1..e683080af6 100644 --- a/src/Mvc/Mvc.Abstractions/src/Abstractions/ActionDescriptorExtensions.cs +++ b/src/Mvc/Mvc.Abstractions/src/Abstractions/ActionDescriptorExtensions.cs @@ -24,14 +24,13 @@ namespace Microsoft.AspNetCore.Mvc.Abstractions throw new ArgumentNullException(nameof(actionDescriptor)); } - object value; - if (actionDescriptor.Properties.TryGetValue(typeof(T), out value)) + if (actionDescriptor.Properties.TryGetValue(typeof(T), out var value)) { return (T)value; } else { - return default(T); + return default!; } } diff --git a/src/Mvc/Mvc.Abstractions/src/Abstractions/ActionInvokerProviderContext.cs b/src/Mvc/Mvc.Abstractions/src/Abstractions/ActionInvokerProviderContext.cs index 1356b02ea4..ccb5af263c 100644 --- a/src/Mvc/Mvc.Abstractions/src/Abstractions/ActionInvokerProviderContext.cs +++ b/src/Mvc/Mvc.Abstractions/src/Abstractions/ActionInvokerProviderContext.cs @@ -32,6 +32,6 @@ namespace Microsoft.AspNetCore.Mvc.Abstractions /// /// Gets or sets the that will be used to invoke /// - public IActionInvoker Result { get; set; } + public IActionInvoker? Result { get; set; } } } diff --git a/src/Mvc/Mvc.Abstractions/src/Abstractions/ParameterDescriptor.cs b/src/Mvc/Mvc.Abstractions/src/Abstractions/ParameterDescriptor.cs index 33e3824a0b..4414affe32 100644 --- a/src/Mvc/Mvc.Abstractions/src/Abstractions/ParameterDescriptor.cs +++ b/src/Mvc/Mvc.Abstractions/src/Abstractions/ParameterDescriptor.cs @@ -14,16 +14,16 @@ namespace Microsoft.AspNetCore.Mvc.Abstractions /// /// Gets or sets the parameter name. /// - public string Name { get; set; } + public string Name { get; set; } = default!; /// /// Gets or sets the type of the parameter. /// - public Type ParameterType { get; set; } + public Type ParameterType { get; set; } = default!; /// /// Gets or sets the for the parameter. /// - public BindingInfo BindingInfo { get; set; } + public BindingInfo BindingInfo { get; set; } = default!; } } diff --git a/src/Mvc/Mvc.Abstractions/src/ActionConstraints/ActionConstraintContext.cs b/src/Mvc/Mvc.Abstractions/src/ActionConstraints/ActionConstraintContext.cs index 68ee228d0e..c475f0a634 100644 --- a/src/Mvc/Mvc.Abstractions/src/ActionConstraints/ActionConstraintContext.cs +++ b/src/Mvc/Mvc.Abstractions/src/ActionConstraints/ActionConstraintContext.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using System.Collections.Generic; using Microsoft.AspNetCore.Routing; @@ -15,16 +16,16 @@ namespace Microsoft.AspNetCore.Mvc.ActionConstraints /// The list of . This includes all actions that are valid for the current /// request, as well as their constraints. /// - public IReadOnlyList Candidates { get; set; } + public IReadOnlyList Candidates { get; set; } = Array.Empty(); /// /// The current . /// - public ActionSelectorCandidate CurrentCandidate { get; set; } + public ActionSelectorCandidate CurrentCandidate { get; set; } = default!; /// /// The . /// - public RouteContext RouteContext { get; set; } + public RouteContext RouteContext { get; set; } = default!; } } \ No newline at end of file diff --git a/src/Mvc/Mvc.Abstractions/src/ActionConstraints/ActionConstraintItem.cs b/src/Mvc/Mvc.Abstractions/src/ActionConstraints/ActionConstraintItem.cs index 7022a8f283..8868005a57 100644 --- a/src/Mvc/Mvc.Abstractions/src/ActionConstraints/ActionConstraintItem.cs +++ b/src/Mvc/Mvc.Abstractions/src/ActionConstraints/ActionConstraintItem.cs @@ -28,7 +28,7 @@ namespace Microsoft.AspNetCore.Mvc.ActionConstraints /// /// The associated with . /// - public IActionConstraint Constraint { get; set; } + public IActionConstraint Constraint { get; set; } = default!; /// /// The instance. diff --git a/src/Mvc/Mvc.Abstractions/src/ActionContext.cs b/src/Mvc/Mvc.Abstractions/src/ActionContext.cs index 744a439dc7..000e55558c 100644 --- a/src/Mvc/Mvc.Abstractions/src/ActionContext.cs +++ b/src/Mvc/Mvc.Abstractions/src/ActionContext.cs @@ -31,10 +31,10 @@ namespace Microsoft.AspNetCore.Mvc /// The to copy. public ActionContext(ActionContext actionContext) : this( - actionContext?.HttpContext, - actionContext?.RouteData, - actionContext?.ActionDescriptor, - actionContext?.ModelState) + actionContext.HttpContext, + actionContext.RouteData, + actionContext.ActionDescriptor, + actionContext.ModelState) { } @@ -97,10 +97,7 @@ namespace Microsoft.AspNetCore.Mvc /// /// The property setter is provided for unit test purposes only. /// - public ActionDescriptor ActionDescriptor - { - get; set; - } + public ActionDescriptor ActionDescriptor { get; set; } = default!; /// /// Gets or sets the for the current request. @@ -108,18 +105,12 @@ namespace Microsoft.AspNetCore.Mvc /// /// The property setter is provided for unit test purposes only. /// - public HttpContext HttpContext - { - get; set; - } + public HttpContext HttpContext { get; set; } = default!; /// /// Gets the . /// - public ModelStateDictionary ModelState - { - get; - } + public ModelStateDictionary ModelState { get; } = default!; /// /// Gets or sets the for the current request. @@ -127,9 +118,6 @@ namespace Microsoft.AspNetCore.Mvc /// /// The property setter is provided for unit test purposes only. /// - public RouteData RouteData - { - get; set; - } + public RouteData RouteData { get; set; } = default!; } } diff --git a/src/Mvc/Mvc.Abstractions/src/ApiExplorer/ApiDescription.cs b/src/Mvc/Mvc.Abstractions/src/ApiExplorer/ApiDescription.cs index 827712f1bc..f20437ce0d 100644 --- a/src/Mvc/Mvc.Abstractions/src/ApiExplorer/ApiDescription.cs +++ b/src/Mvc/Mvc.Abstractions/src/ApiExplorer/ApiDescription.cs @@ -16,17 +16,17 @@ namespace Microsoft.AspNetCore.Mvc.ApiExplorer /// /// Gets or sets for this api. /// - public ActionDescriptor ActionDescriptor { get; set; } + public ActionDescriptor ActionDescriptor { get; set; } = default!; /// /// Gets or sets group name for this api. /// - public string GroupName { get; set; } + public string? GroupName { get; set; } /// /// Gets or sets the supported HTTP method for this api, or null if all HTTP methods are supported. /// - public string HttpMethod { get; set; } + public string? HttpMethod { get; set; } /// /// Gets a list of for this api. @@ -41,7 +41,7 @@ namespace Microsoft.AspNetCore.Mvc.ApiExplorer /// /// Gets or sets relative url path template (relative to application root) for this api. /// - public string RelativePath { get; set; } + public string RelativePath { get; set; } = default!; /// /// Gets the list of possible formats for a request. diff --git a/src/Mvc/Mvc.Abstractions/src/ApiExplorer/ApiParameterDescription.cs b/src/Mvc/Mvc.Abstractions/src/ApiExplorer/ApiParameterDescription.cs index 17f499c1f0..7b6d8f548a 100644 --- a/src/Mvc/Mvc.Abstractions/src/ApiExplorer/ApiParameterDescription.cs +++ b/src/Mvc/Mvc.Abstractions/src/ApiExplorer/ApiParameterDescription.cs @@ -15,37 +15,37 @@ namespace Microsoft.AspNetCore.Mvc.ApiExplorer /// /// Gets or sets the . /// - public ModelMetadata ModelMetadata { get; set; } + public ModelMetadata ModelMetadata { get; set; } = default!; /// /// Gets or sets the name. /// - public string Name { get; set; } + public string Name { get; set; } = default!; /// /// Gets or sets the . /// - public ApiParameterRouteInfo RouteInfo { get; set; } + public ApiParameterRouteInfo? RouteInfo { get; set; } /// /// Gets or sets the . /// - public BindingSource Source { get; set; } + public BindingSource Source { get; set; } = default!; /// /// Gets or sets the . /// - public BindingInfo BindingInfo { get; set; } + public BindingInfo? BindingInfo { get; set; } /// /// Gets or sets the parameter type. /// - public Type Type { get; set; } + public Type Type { get; set; } = default!; /// /// Gets or sets the parameter descriptor. /// - public ParameterDescriptor ParameterDescriptor { get; set; } + public ParameterDescriptor ParameterDescriptor { get; set; } = default!; /// /// Gets or sets a value that determines if the parameter is required. @@ -63,6 +63,6 @@ namespace Microsoft.AspNetCore.Mvc.ApiExplorer /// /// Gets or sets the default value for a parameter. /// - public object DefaultValue { get; set; } + public object? DefaultValue { get; set; } } } \ No newline at end of file diff --git a/src/Mvc/Mvc.Abstractions/src/ApiExplorer/ApiParameterRouteInfo.cs b/src/Mvc/Mvc.Abstractions/src/ApiExplorer/ApiParameterRouteInfo.cs index 6e5cbfc494..fbb79452d4 100644 --- a/src/Mvc/Mvc.Abstractions/src/ApiExplorer/ApiParameterRouteInfo.cs +++ b/src/Mvc/Mvc.Abstractions/src/ApiExplorer/ApiParameterRouteInfo.cs @@ -18,12 +18,12 @@ namespace Microsoft.AspNetCore.Mvc.ApiExplorer /// Route constraints are only applied when a value is bound from a URL's path. See /// for the data source considered. /// - public IEnumerable Constraints { get; set; } + public IEnumerable? Constraints { get; set; } /// /// Gets or sets the default value for the parameter. /// - public object DefaultValue { get; set; } + public object? DefaultValue { get; set; } /// /// Gets a value indicating whether not a parameter is considered optional by routing. diff --git a/src/Mvc/Mvc.Abstractions/src/ApiExplorer/ApiRequestFormat.cs b/src/Mvc/Mvc.Abstractions/src/ApiExplorer/ApiRequestFormat.cs index 8d93cc65b3..3e063da212 100644 --- a/src/Mvc/Mvc.Abstractions/src/ApiExplorer/ApiRequestFormat.cs +++ b/src/Mvc/Mvc.Abstractions/src/ApiExplorer/ApiRequestFormat.cs @@ -13,11 +13,11 @@ namespace Microsoft.AspNetCore.Mvc.ApiExplorer /// /// The formatter used to read this request. /// - public IInputFormatter Formatter { get; set; } + public IInputFormatter Formatter { get; set; } = default!; /// /// The media type of the request. /// - public string MediaType { get; set; } + public string MediaType { get; set; } = default!; } } \ No newline at end of file diff --git a/src/Mvc/Mvc.Abstractions/src/ApiExplorer/ApiResponseFormat.cs b/src/Mvc/Mvc.Abstractions/src/ApiExplorer/ApiResponseFormat.cs index bf04db9da7..9830ef279a 100644 --- a/src/Mvc/Mvc.Abstractions/src/ApiExplorer/ApiResponseFormat.cs +++ b/src/Mvc/Mvc.Abstractions/src/ApiExplorer/ApiResponseFormat.cs @@ -13,11 +13,11 @@ namespace Microsoft.AspNetCore.Mvc.ApiExplorer /// /// Gets or sets the formatter used to output this response. /// - public IOutputFormatter Formatter { get; set; } + public IOutputFormatter Formatter { get; set; } = default!; /// /// Gets or sets the media type of the response. /// - public string MediaType { get; set; } + public string MediaType { get; set; } = default!; } } diff --git a/src/Mvc/Mvc.Abstractions/src/ApiExplorer/ApiResponseType.cs b/src/Mvc/Mvc.Abstractions/src/ApiExplorer/ApiResponseType.cs index 6ed9644931..1029ec3437 100644 --- a/src/Mvc/Mvc.Abstractions/src/ApiExplorer/ApiResponseType.cs +++ b/src/Mvc/Mvc.Abstractions/src/ApiExplorer/ApiResponseType.cs @@ -23,7 +23,7 @@ namespace Microsoft.AspNetCore.Mvc.ApiExplorer /// /// Will be null if is null or void. /// - public ModelMetadata ModelMetadata { get; set; } + public ModelMetadata? ModelMetadata { get; set; } /// /// Gets or sets the CLR data type of the response or null. @@ -33,7 +33,7 @@ namespace Microsoft.AspNetCore.Mvc.ApiExplorer /// Microsoft.AspNetCore.Mvc.ProducesAttribute or Microsoft.AspNetCore.Mvc.ProducesResponseTypeAttribute on an action method /// to specify a response type. /// - public Type Type { get; set; } + public Type? Type { get; set; } /// /// Gets or sets the HTTP response status code. diff --git a/src/Mvc/Mvc.Abstractions/src/Filters/ActionExecutedContext.cs b/src/Mvc/Mvc.Abstractions/src/Filters/ActionExecutedContext.cs index 68e0343f04..6440a27878 100644 --- a/src/Mvc/Mvc.Abstractions/src/Filters/ActionExecutedContext.cs +++ b/src/Mvc/Mvc.Abstractions/src/Filters/ActionExecutedContext.cs @@ -12,8 +12,8 @@ namespace Microsoft.AspNetCore.Mvc.Filters /// public class ActionExecutedContext : FilterContext { - private Exception _exception; - private ExceptionDispatchInfo _exceptionDispatchInfo; + private Exception? _exception; + private ExceptionDispatchInfo? _exceptionDispatchInfo; /// /// Instantiates a new instance. @@ -44,7 +44,7 @@ namespace Microsoft.AspNetCore.Mvc.Filters /// Gets or sets the caught while executing the action or action filters, if /// any. /// - public virtual Exception Exception + public virtual Exception? Exception { get { @@ -69,7 +69,7 @@ namespace Microsoft.AspNetCore.Mvc.Filters /// Gets or sets the for the /// , if an was caught and this information captured. /// - public virtual ExceptionDispatchInfo ExceptionDispatchInfo + public virtual ExceptionDispatchInfo? ExceptionDispatchInfo { get { @@ -91,6 +91,6 @@ namespace Microsoft.AspNetCore.Mvc.Filters /// /// Gets or sets the . /// - public virtual IActionResult Result { get; set; } + public virtual IActionResult Result { get; set; } = default!; } } diff --git a/src/Mvc/Mvc.Abstractions/src/Filters/ActionExecutingContext.cs b/src/Mvc/Mvc.Abstractions/src/Filters/ActionExecutingContext.cs index 65ade1e1c5..0bdd07c4a9 100644 --- a/src/Mvc/Mvc.Abstractions/src/Filters/ActionExecutingContext.cs +++ b/src/Mvc/Mvc.Abstractions/src/Filters/ActionExecutingContext.cs @@ -41,7 +41,7 @@ namespace Microsoft.AspNetCore.Mvc.Filters /// Gets or sets the to execute. Setting to a non-null /// value inside an action filter will short-circuit the action and any remaining action filters. /// - public virtual IActionResult Result { get; set; } + public virtual IActionResult? Result { get; set; } /// /// Gets the arguments to pass when invoking the action. Keys are parameter names. diff --git a/src/Mvc/Mvc.Abstractions/src/Filters/AuthorizationFilterContext.cs b/src/Mvc/Mvc.Abstractions/src/Filters/AuthorizationFilterContext.cs index a344d55432..0854a422d2 100644 --- a/src/Mvc/Mvc.Abstractions/src/Filters/AuthorizationFilterContext.cs +++ b/src/Mvc/Mvc.Abstractions/src/Filters/AuthorizationFilterContext.cs @@ -27,6 +27,6 @@ namespace Microsoft.AspNetCore.Mvc.Filters /// Gets or sets the result of the request. Setting to a non-null value inside /// an authorization filter will short-circuit the remainder of the filter pipeline. /// - public virtual IActionResult Result { get; set; } + public virtual IActionResult? Result { get; set; } } } diff --git a/src/Mvc/Mvc.Abstractions/src/Filters/ExceptionContext.cs b/src/Mvc/Mvc.Abstractions/src/Filters/ExceptionContext.cs index c0920f057b..d151134b8a 100644 --- a/src/Mvc/Mvc.Abstractions/src/Filters/ExceptionContext.cs +++ b/src/Mvc/Mvc.Abstractions/src/Filters/ExceptionContext.cs @@ -13,8 +13,8 @@ namespace Microsoft.AspNetCore.Mvc.Filters /// public class ExceptionContext : FilterContext { - private Exception _exception; - private ExceptionDispatchInfo _exceptionDispatchInfo; + private Exception? _exception; + private ExceptionDispatchInfo? _exceptionDispatchInfo; /// /// Instantiates a new instance. @@ -39,7 +39,7 @@ namespace Microsoft.AspNetCore.Mvc.Filters } else { - return _exception; + return _exception!; } } @@ -54,7 +54,7 @@ namespace Microsoft.AspNetCore.Mvc.Filters /// Gets or sets the for the /// , if this information was captured. /// - public virtual ExceptionDispatchInfo ExceptionDispatchInfo + public virtual ExceptionDispatchInfo? ExceptionDispatchInfo { get { @@ -76,6 +76,6 @@ namespace Microsoft.AspNetCore.Mvc.Filters /// /// Gets or sets the . /// - public virtual IActionResult Result { get; set; } + public virtual IActionResult? Result { get; set; } } } diff --git a/src/Mvc/Mvc.Abstractions/src/Filters/FilterContext.cs b/src/Mvc/Mvc.Abstractions/src/Filters/FilterContext.cs index 961e283399..97e0a294b6 100644 --- a/src/Mvc/Mvc.Abstractions/src/Filters/FilterContext.cs +++ b/src/Mvc/Mvc.Abstractions/src/Filters/FilterContext.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; namespace Microsoft.AspNetCore.Mvc.Filters { @@ -81,6 +82,7 @@ namespace Microsoft.AspNetCore.Mvc.Filters /// The implementation of applied to the action associated with /// the /// + [return: MaybeNull] public TMetadata FindEffectivePolicy() where TMetadata : IFilterMetadata { // The most specific policy is the one closest to the action (nearest the end of the list). @@ -93,7 +95,7 @@ namespace Microsoft.AspNetCore.Mvc.Filters } } - return default(TMetadata); + return default; } } } diff --git a/src/Mvc/Mvc.Abstractions/src/Filters/FilterItem.cs b/src/Mvc/Mvc.Abstractions/src/Filters/FilterItem.cs index 516acd7d24..fdf03752b7 100644 --- a/src/Mvc/Mvc.Abstractions/src/Filters/FilterItem.cs +++ b/src/Mvc/Mvc.Abstractions/src/Filters/FilterItem.cs @@ -48,12 +48,12 @@ namespace Microsoft.AspNetCore.Mvc.Filters /// /// Gets the containing the filter metadata. /// - public FilterDescriptor Descriptor { get; } + public FilterDescriptor Descriptor { get; } = default!; /// /// Gets or sets the executable associated with . /// - public IFilterMetadata Filter { get; set; } + public IFilterMetadata Filter { get; set; } = default!; /// /// Gets or sets a value indicating whether or not can be reused across requests. diff --git a/src/Mvc/Mvc.Abstractions/src/Filters/ResourceExecutedContext.cs b/src/Mvc/Mvc.Abstractions/src/Filters/ResourceExecutedContext.cs index 6a54d2c410..8dfe78bba6 100644 --- a/src/Mvc/Mvc.Abstractions/src/Filters/ResourceExecutedContext.cs +++ b/src/Mvc/Mvc.Abstractions/src/Filters/ResourceExecutedContext.cs @@ -12,8 +12,8 @@ namespace Microsoft.AspNetCore.Mvc.Filters /// public class ResourceExecutedContext : FilterContext { - private Exception _exception; - private ExceptionDispatchInfo _exceptionDispatchInfo; + private Exception? _exception; + private ExceptionDispatchInfo? _exceptionDispatchInfo; /// /// Creates a new . @@ -44,7 +44,7 @@ namespace Microsoft.AspNetCore.Mvc.Filters /// Setting to true will also mark the exception as handled. /// /// - public virtual Exception Exception + public virtual Exception? Exception { get { @@ -77,7 +77,7 @@ namespace Microsoft.AspNetCore.Mvc.Filters /// Setting to true will also mark the exception as handled. /// /// - public virtual ExceptionDispatchInfo ExceptionDispatchInfo + public virtual ExceptionDispatchInfo? ExceptionDispatchInfo { get { @@ -115,6 +115,6 @@ namespace Microsoft.AspNetCore.Mvc.Filters /// to resource filters. /// /// - public virtual IActionResult Result { get; set; } + public virtual IActionResult? Result { get; set; } } } \ No newline at end of file diff --git a/src/Mvc/Mvc.Abstractions/src/Filters/ResourceExecutingContext.cs b/src/Mvc/Mvc.Abstractions/src/Filters/ResourceExecutingContext.cs index 46378b3760..37985fc1af 100644 --- a/src/Mvc/Mvc.Abstractions/src/Filters/ResourceExecutingContext.cs +++ b/src/Mvc/Mvc.Abstractions/src/Filters/ResourceExecutingContext.cs @@ -40,7 +40,7 @@ namespace Microsoft.AspNetCore.Mvc.Filters /// Setting to a non-null value inside a resource filter will /// short-circuit execution of additional resource filters and the action itself. /// - public virtual IActionResult Result { get; set; } + public virtual IActionResult? Result { get; set; } /// /// Gets the list of instances used by model binding. diff --git a/src/Mvc/Mvc.Abstractions/src/Filters/ResultExecutedContext.cs b/src/Mvc/Mvc.Abstractions/src/Filters/ResultExecutedContext.cs index ae4947d8bf..01eae1d8cf 100644 --- a/src/Mvc/Mvc.Abstractions/src/Filters/ResultExecutedContext.cs +++ b/src/Mvc/Mvc.Abstractions/src/Filters/ResultExecutedContext.cs @@ -12,8 +12,8 @@ namespace Microsoft.AspNetCore.Mvc.Filters /// public class ResultExecutedContext : FilterContext { - private Exception _exception; - private ExceptionDispatchInfo _exceptionDispatchInfo; + private Exception? _exception; + private ExceptionDispatchInfo? _exceptionDispatchInfo; /// /// Instantiates a new instance. @@ -55,7 +55,7 @@ namespace Microsoft.AspNetCore.Mvc.Filters /// Gets or sets the caught while executing the result or result filters, if /// any. /// - public virtual Exception Exception + public virtual Exception? Exception { get { @@ -80,7 +80,7 @@ namespace Microsoft.AspNetCore.Mvc.Filters /// Gets or sets the for the /// , if an was caught and this information captured. /// - public virtual ExceptionDispatchInfo ExceptionDispatchInfo + public virtual ExceptionDispatchInfo? ExceptionDispatchInfo { get { diff --git a/src/Mvc/Mvc.Abstractions/src/Formatters/FormatterCollection.cs b/src/Mvc/Mvc.Abstractions/src/Formatters/FormatterCollection.cs index 401febb5cf..ad16757da4 100644 --- a/src/Mvc/Mvc.Abstractions/src/Formatters/FormatterCollection.cs +++ b/src/Mvc/Mvc.Abstractions/src/Formatters/FormatterCollection.cs @@ -11,7 +11,7 @@ namespace Microsoft.AspNetCore.Mvc.Formatters /// Represents a collection of formatters. /// /// The type of formatters in the collection. - public class FormatterCollection : Collection + public class FormatterCollection : Collection where TFormatter : notnull { /// /// Initializes a new instance of the class that is empty. diff --git a/src/Mvc/Mvc.Abstractions/src/Formatters/InputFormatterResult.cs b/src/Mvc/Mvc.Abstractions/src/Formatters/InputFormatterResult.cs index 2304cd5671..d83a5095d7 100644 --- a/src/Mvc/Mvc.Abstractions/src/Formatters/InputFormatterResult.cs +++ b/src/Mvc/Mvc.Abstractions/src/Formatters/InputFormatterResult.cs @@ -42,7 +42,7 @@ namespace Microsoft.AspNetCore.Mvc.Formatters /// /// null if is true. /// - public object Model { get; } + public object? Model { get; } /// /// Returns an indicating the diff --git a/src/Mvc/Mvc.Abstractions/src/Formatters/OutputFormatterCanWriteContext.cs b/src/Mvc/Mvc.Abstractions/src/Formatters/OutputFormatterCanWriteContext.cs index ae48a91b1e..daf10315f0 100644 --- a/src/Mvc/Mvc.Abstractions/src/Formatters/OutputFormatterCanWriteContext.cs +++ b/src/Mvc/Mvc.Abstractions/src/Formatters/OutputFormatterCanWriteContext.cs @@ -53,11 +53,11 @@ namespace Microsoft.AspNetCore.Mvc.Formatters /// /// Gets or sets the object to write to the response. /// - public virtual object Object { get; protected set; } + public virtual object? Object { get; protected set; } /// /// Gets or sets the of the object to write to the response. /// - public virtual Type ObjectType { get; protected set; } + public virtual Type? ObjectType { get; protected set; } } } diff --git a/src/Mvc/Mvc.Abstractions/src/Microsoft.AspNetCore.Mvc.Abstractions.csproj b/src/Mvc/Mvc.Abstractions/src/Microsoft.AspNetCore.Mvc.Abstractions.csproj index bc27d62e2c..b3e599ab25 100644 --- a/src/Mvc/Mvc.Abstractions/src/Microsoft.AspNetCore.Mvc.Abstractions.csproj +++ b/src/Mvc/Mvc.Abstractions/src/Microsoft.AspNetCore.Mvc.Abstractions.csproj @@ -9,6 +9,7 @@ Microsoft.AspNetCore.Mvc.IActionResult true aspnetcore;aspnetcoremvc false + enable @@ -20,8 +21,4 @@ Microsoft.AspNetCore.Mvc.IActionResult - - - - diff --git a/src/Mvc/Mvc.Abstractions/src/ModelBinding/BindingInfo.cs b/src/Mvc/Mvc.Abstractions/src/ModelBinding/BindingInfo.cs index 38fbc894a9..b7379ae4e0 100644 --- a/src/Mvc/Mvc.Abstractions/src/ModelBinding/BindingInfo.cs +++ b/src/Mvc/Mvc.Abstractions/src/ModelBinding/BindingInfo.cs @@ -13,7 +13,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding /// public class BindingInfo { - private Type _binderType; + private Type? _binderType; /// /// Creates a new . @@ -44,12 +44,12 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding /// /// Gets or sets the . /// - public BindingSource BindingSource { get; set; } + public BindingSource? BindingSource { get; set; } /// /// Gets or sets the binder model name. /// - public string BinderModelName { get; set; } + public string? BinderModelName { get; set; } /// /// Gets or sets the of the implementation used to bind the @@ -59,7 +59,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding /// Also set if the specified implementation does not /// use values from form data, route values or the query string. /// - public Type BinderType + public Type? BinderType { get => _binderType; set @@ -80,13 +80,13 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding /// /// Gets or sets the . /// - public IPropertyFilterProvider PropertyFilterProvider { get; set; } + public IPropertyFilterProvider? PropertyFilterProvider { get; set; } /// /// Gets or sets a predicate which determines whether or not the model should be bound based on state /// from the current request. /// - public Func RequestPredicate { get; set; } + public Func? RequestPredicate { get; set; } /// /// Gets or sets the value which decides if empty bodies are treated as valid inputs. @@ -104,7 +104,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding /// A collection of attributes which are used to construct /// /// A new instance of . - public static BindingInfo GetBindingInfo(IEnumerable attributes) + public static BindingInfo? GetBindingInfo(IEnumerable attributes) { var bindingInfo = new BindingInfo(); var isBindingInfoPresent = false; @@ -182,7 +182,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding /// A collection of attributes which are used to construct . /// The . /// A new instance of if any binding metadata was discovered; otherwise or . - public static BindingInfo GetBindingInfo(IEnumerable attributes, ModelMetadata modelMetadata) + public static BindingInfo? GetBindingInfo(IEnumerable attributes, ModelMetadata modelMetadata) { if (attributes == null) { diff --git a/src/Mvc/Mvc.Abstractions/src/ModelBinding/BindingSource.cs b/src/Mvc/Mvc.Abstractions/src/ModelBinding/BindingSource.cs index 97105efe3c..ea06036844 100644 --- a/src/Mvc/Mvc.Abstractions/src/ModelBinding/BindingSource.cs +++ b/src/Mvc/Mvc.Abstractions/src/ModelBinding/BindingSource.cs @@ -12,7 +12,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding /// A metadata object representing a source of data for model binding. /// [DebuggerDisplay("Source: {DisplayName}")] - public class BindingSource : IEquatable + public class BindingSource : IEquatable { /// /// A for the request body. @@ -210,13 +210,13 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding } /// - public bool Equals(BindingSource other) + public bool Equals(BindingSource? other) { return string.Equals(other?.Id, Id, StringComparison.Ordinal); } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) { return Equals(obj as BindingSource); } @@ -228,7 +228,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding } /// - public static bool operator ==(BindingSource s1, BindingSource s2) + public static bool operator ==(BindingSource? s1, BindingSource? s2) { if (s1 is null) { @@ -239,7 +239,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding } /// - public static bool operator !=(BindingSource s1, BindingSource s2) + public static bool operator !=(BindingSource? s1, BindingSource? s2) { return !(s1 == s2); } diff --git a/src/Mvc/Mvc.Abstractions/src/ModelBinding/CompositeBindingSource.cs b/src/Mvc/Mvc.Abstractions/src/ModelBinding/CompositeBindingSource.cs index 886deb9951..99044400b5 100644 --- a/src/Mvc/Mvc.Abstractions/src/ModelBinding/CompositeBindingSource.cs +++ b/src/Mvc/Mvc.Abstractions/src/ModelBinding/CompositeBindingSource.cs @@ -89,7 +89,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding /// public override bool CanAcceptDataFrom(BindingSource bindingSource) { - if (bindingSource == null) + if (bindingSource is null) { throw new ArgumentNullException(nameof(bindingSource)); } diff --git a/src/Mvc/Mvc.Abstractions/src/ModelBinding/IBindingSourceMetadata.cs b/src/Mvc/Mvc.Abstractions/src/ModelBinding/IBindingSourceMetadata.cs index 4a1ed31275..8639ce826e 100644 --- a/src/Mvc/Mvc.Abstractions/src/ModelBinding/IBindingSourceMetadata.cs +++ b/src/Mvc/Mvc.Abstractions/src/ModelBinding/IBindingSourceMetadata.cs @@ -15,6 +15,6 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding /// The is metadata which can be used to determine which data /// sources are valid for model binding of a property or parameter. /// - BindingSource BindingSource { get; } + BindingSource? BindingSource { get; } } } \ No newline at end of file diff --git a/src/Mvc/Mvc.Abstractions/src/ModelBinding/Metadata/ModelBindingMessageProvider.cs b/src/Mvc/Mvc.Abstractions/src/ModelBinding/Metadata/ModelBindingMessageProvider.cs index c91bfe4cb0..7992450f37 100644 --- a/src/Mvc/Mvc.Abstractions/src/ModelBinding/Metadata/ModelBindingMessageProvider.cs +++ b/src/Mvc/Mvc.Abstractions/src/ModelBinding/Metadata/ModelBindingMessageProvider.cs @@ -17,28 +17,28 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Metadata /// /// Default is "A value for the '{0}' parameter or property was not provided.". /// - public virtual Func MissingBindRequiredValueAccessor { get; } + public virtual Func MissingBindRequiredValueAccessor { get; } = default!; /// /// Error message the model binding system adds when either the key or the value of a /// is bound but not both. /// /// Default is "A value is required.". - public virtual Func MissingKeyOrValueAccessor { get; } + public virtual Func MissingKeyOrValueAccessor { get; } = default!; /// /// Error message the model binding system adds when no value is provided for the request body, /// but a value is required. /// /// Default is "A non-empty request body is required.". - public virtual Func MissingRequestBodyRequiredValueAccessor { get; } + public virtual Func MissingRequestBodyRequiredValueAccessor { get; } = default!; /// /// Error message the model binding system adds when a null value is bound to a /// non- property. /// /// Default is "The value '{0}' is invalid.". - public virtual Func ValueMustNotBeNullAccessor { get; } + public virtual Func ValueMustNotBeNullAccessor { get; } = default!; /// /// Error message the model binding system adds when is of type @@ -46,7 +46,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Metadata /// with a property. /// /// Default is "The value '{0}' is not valid for {1}.". - public virtual Func AttemptedValueIsInvalidAccessor { get; } + public virtual Func AttemptedValueIsInvalidAccessor { get; } = default!; /// /// Error message the model binding system adds when is of type @@ -54,7 +54,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Metadata /// with a collection element or action parameter. /// /// Default is "The value '{0}' is not valid.". - public virtual Func NonPropertyAttemptedValueIsInvalidAccessor { get; } + public virtual Func NonPropertyAttemptedValueIsInvalidAccessor { get; } = default!; /// /// Error message the model binding system adds when is of type @@ -62,7 +62,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Metadata /// with a property. /// /// Default is "The supplied value is invalid for {0}.". - public virtual Func UnknownValueIsInvalidAccessor { get; } + public virtual Func UnknownValueIsInvalidAccessor { get; } = default!; /// /// Error message the model binding system adds when is of type @@ -70,21 +70,21 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Metadata /// with a collection element or action parameter. /// /// Default is "The supplied value is invalid.". - public virtual Func NonPropertyUnknownValueIsInvalidAccessor { get; } + public virtual Func NonPropertyUnknownValueIsInvalidAccessor { get; } = default!; /// /// Fallback error message HTML and tag helpers display when a property is invalid but the /// s have null s. /// /// Default is "The value '{0}' is invalid.". - public virtual Func ValueIsInvalidAccessor { get; } + public virtual Func ValueIsInvalidAccessor { get; } = default!; /// /// Error message HTML and tag helpers add for client-side validation of numeric formats. Visible in the /// browser if the field for a float (for example) property does not have a correctly-formatted value. /// /// Default is "The field {0} must be a number.". - public virtual Func ValueMustBeANumberAccessor { get; } + public virtual Func ValueMustBeANumberAccessor { get; } = default!; /// /// Error message HTML and tag helpers add for client-side validation of numeric formats. Visible in the @@ -92,6 +92,6 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Metadata /// correctly-formatted value. /// /// Default is "The field must be a number.". - public virtual Func NonPropertyValueMustBeANumberAccessor { get; } + public virtual Func NonPropertyValueMustBeANumberAccessor { get; } = default!; } } diff --git a/src/Mvc/Mvc.Abstractions/src/ModelBinding/Metadata/ModelMetadataIdentity.cs b/src/Mvc/Mvc.Abstractions/src/ModelBinding/Metadata/ModelMetadataIdentity.cs index 9b1cf4fec2..5fff9bad3d 100644 --- a/src/Mvc/Mvc.Abstractions/src/ModelBinding/Metadata/ModelMetadataIdentity.cs +++ b/src/Mvc/Mvc.Abstractions/src/ModelBinding/Metadata/ModelMetadataIdentity.cs @@ -4,7 +4,6 @@ using System; using System.Reflection; using Microsoft.AspNetCore.Mvc.Abstractions; -using Microsoft.Extensions.Internal; namespace Microsoft.AspNetCore.Mvc.ModelBinding.Metadata { @@ -15,9 +14,9 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Metadata { private ModelMetadataIdentity( Type modelType, - string name = null, - Type containerType = null, - object fieldInfo = null) + string? name = null, + Type? containerType = null, + object? fieldInfo = null) { ModelType = modelType; Name = name; @@ -107,7 +106,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Metadata /// The . /// A . public static ModelMetadataIdentity ForParameter(ParameterInfo parameter) - => ForParameter(parameter, parameter?.ParameterType); + => ForParameter(parameter, parameter.ParameterType); /// /// Creates a for the provided parameter with the specified @@ -135,7 +134,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Metadata /// Gets the defining the model property represented by the current /// instance, or null if the current instance does not represent a property. /// - public Type ContainerType { get; } + public Type? ContainerType { get; } /// /// Gets the represented by the current instance. @@ -168,21 +167,21 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Metadata /// Gets the name of the current instance if it represents a parameter or property, or null if /// the current instance represents a type. /// - public string Name { get; } + public string? Name { get; } - private object FieldInfo { get; } + private object? FieldInfo { get; } /// /// Gets a descriptor for the parameter, or null if this instance /// does not represent a parameter. /// - public ParameterInfo ParameterInfo => FieldInfo as ParameterInfo; + public ParameterInfo? ParameterInfo => FieldInfo as ParameterInfo; /// /// Gets a descriptor for the property, or null if this instance /// does not represent a property. /// - public PropertyInfo PropertyInfo => FieldInfo as PropertyInfo; + public PropertyInfo? PropertyInfo => FieldInfo as PropertyInfo; /// public bool Equals(ModelMetadataIdentity other) @@ -196,7 +195,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Metadata } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) { var other = obj as ModelMetadataIdentity?; return other.HasValue && Equals(other.Value); @@ -205,13 +204,13 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Metadata /// public override int GetHashCode() { - var hash = new HashCodeCombiner(); + var hash = new HashCode(); hash.Add(ContainerType); hash.Add(ModelType); hash.Add(Name, StringComparer.Ordinal); hash.Add(ParameterInfo); hash.Add(PropertyInfo); - return hash; + return hash.ToHashCode(); } } } \ No newline at end of file diff --git a/src/Mvc/Mvc.Abstractions/src/ModelBinding/ModelBinderProviderContext.cs b/src/Mvc/Mvc.Abstractions/src/ModelBinding/ModelBinderProviderContext.cs index 6228923e70..c35c8c4814 100644 --- a/src/Mvc/Mvc.Abstractions/src/ModelBinding/ModelBinderProviderContext.cs +++ b/src/Mvc/Mvc.Abstractions/src/ModelBinding/ModelBinderProviderContext.cs @@ -48,6 +48,6 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding /// /// Gets the . /// - public virtual IServiceProvider Services { get; } + public virtual IServiceProvider Services { get; } = default!; } } \ No newline at end of file diff --git a/src/Mvc/Mvc.Abstractions/src/ModelBinding/ModelBindingContext.cs b/src/Mvc/Mvc.Abstractions/src/ModelBinding/ModelBindingContext.cs index 915ea38085..3dfd4790f3 100644 --- a/src/Mvc/Mvc.Abstractions/src/ModelBinding/ModelBindingContext.cs +++ b/src/Mvc/Mvc.Abstractions/src/ModelBinding/ModelBindingContext.cs @@ -39,7 +39,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding /// /// Gets the associated with this context. /// - public virtual HttpContext HttpContext => ActionContext?.HttpContext; + public virtual HttpContext HttpContext => ActionContext?.HttpContext!; /// /// Gets or sets an indication that the current binder is handling the top-level object. @@ -71,7 +71,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding /// Gets or sets the name of the top-level model. This is not reset to when value /// providers have no match for that model. /// - public string OriginalModelName { get; protected set; } + public string OriginalModelName { get; protected set; } = default!; /// /// Gets or sets the used to capture values diff --git a/src/Mvc/Mvc.Abstractions/src/ModelBinding/ModelBindingResult.cs b/src/Mvc/Mvc.Abstractions/src/ModelBinding/ModelBindingResult.cs index 2bfc3dd5fd..3ab9c0ba4f 100644 --- a/src/Mvc/Mvc.Abstractions/src/ModelBinding/ModelBindingResult.cs +++ b/src/Mvc/Mvc.Abstractions/src/ModelBinding/ModelBindingResult.cs @@ -2,7 +2,6 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; -using Microsoft.Extensions.Internal; namespace Microsoft.AspNetCore.Mvc.ModelBinding { @@ -19,7 +18,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding { return new ModelBindingResult(model: null, isModelSet: false); } - + /// /// Creates a representing a successful model binding operation. /// @@ -27,10 +26,10 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding /// A representing a successful model bind. public static ModelBindingResult Success(object model) { - return new ModelBindingResult( model, isModelSet: true); + return new ModelBindingResult(model, isModelSet: true); } - private ModelBindingResult(object model, bool isModelSet) + private ModelBindingResult(object? model, bool isModelSet) { Model = model; IsModelSet = isModelSet; @@ -39,7 +38,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding /// /// Gets the model associated with this context. /// - public object Model { get; } + public object? Model { get; } /// /// @@ -53,7 +52,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding public bool IsModelSet { get; } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) { var other = obj as ModelBindingResult?; if (other == null) @@ -69,11 +68,11 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding /// public override int GetHashCode() { - var hashCodeCombiner = HashCodeCombiner.Start(); + var hashCodeCombiner = new HashCode(); hashCodeCombiner.Add(IsModelSet); hashCodeCombiner.Add(Model); - return hashCodeCombiner.CombinedHash; + return hashCodeCombiner.ToHashCode(); } /// diff --git a/src/Mvc/Mvc.Abstractions/src/ModelBinding/ModelError.cs b/src/Mvc/Mvc.Abstractions/src/ModelBinding/ModelError.cs index 0473e20d5d..d30796e081 100644 --- a/src/Mvc/Mvc.Abstractions/src/ModelBinding/ModelError.cs +++ b/src/Mvc/Mvc.Abstractions/src/ModelBinding/ModelError.cs @@ -25,7 +25,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding /// /// The . /// The error message. - public ModelError(Exception exception, string errorMessage) + public ModelError(Exception exception, string? errorMessage) : this(errorMessage) { Exception = exception ?? throw new ArgumentNullException(nameof(exception)); @@ -35,7 +35,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding /// Initializes a new instance of with the specified . /// /// The error message. - public ModelError(string errorMessage) + public ModelError(string? errorMessage) { ErrorMessage = errorMessage ?? string.Empty; } @@ -43,7 +43,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding /// /// Gets the associated with this instance. /// - public Exception Exception { get; } + public Exception? Exception { get; } /// /// Gets the error message associated with this instance. diff --git a/src/Mvc/Mvc.Abstractions/src/ModelBinding/ModelMetadata.cs b/src/Mvc/Mvc.Abstractions/src/ModelBinding/ModelMetadata.cs index 4733f732cd..f04cac166e 100644 --- a/src/Mvc/Mvc.Abstractions/src/ModelBinding/ModelMetadata.cs +++ b/src/Mvc/Mvc.Abstractions/src/ModelBinding/ModelMetadata.cs @@ -17,7 +17,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding /// A metadata representation of a model type, property or parameter. /// [DebuggerDisplay("{DebuggerToString(),nq}")] - public abstract class ModelMetadata : IEquatable, IModelMetadataProvider + public abstract class ModelMetadata : IEquatable, IModelMetadataProvider { /// /// The default value of . @@ -40,7 +40,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding /// /// Gets the type containing the property if this metadata is for a property; otherwise. /// - public Type ContainerType => Identity.ContainerType; + public Type? ContainerType => Identity.ContainerType; /// /// Gets the metadata for if this metadata is for a property; @@ -68,17 +68,17 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding /// Gets the name of the parameter or property if this metadata is for a parameter or property; /// otherwise i.e. if this is the metadata for a type. /// - public string Name => Identity.Name; + public string? Name => Identity.Name; /// /// Gets the name of the parameter if this metadata is for a parameter; otherwise. /// - public string ParameterName => MetadataKind == ModelMetadataKind.Parameter ? Identity.Name : null; + public string? ParameterName => MetadataKind == ModelMetadataKind.Parameter ? Identity.Name : null; /// /// Gets the name of the property if this metadata is for a property; otherwise. /// - public string PropertyName => MetadataKind == ModelMetadataKind.Property ? Identity.Name : null; + public string? PropertyName => MetadataKind == ModelMetadataKind.Property ? Identity.Name : null; /// /// Gets the key for the current instance. @@ -155,7 +155,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding /// implements but not . null otherwise i.e. when /// is false. /// - public abstract ModelMetadata ElementMetadata { get; } + public abstract ModelMetadata? ElementMetadata { get; } /// /// Gets the ordered and grouped display names and values of all values in @@ -318,7 +318,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding /// validated. If null, properties with this are validated. /// /// Defaults to null. - public virtual IPropertyValidationFilter PropertyValidationFilter => null; + public virtual IPropertyValidationFilter? PropertyValidationFilter => null; /// /// Gets a value that indicates whether properties or elements of the model should be validated. @@ -343,7 +343,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding /// Gets the for elements of if that /// implements . /// - public Type ElementType { get; private set; } + public Type? ElementType { get; private set; } /// /// Gets a value indicating whether is a complex type. @@ -389,7 +389,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding /// /// Identical to unless is true. /// - public Type UnderlyingOrModelType { get; private set; } + public Type UnderlyingOrModelType { get; private set; } = default!; /// /// Gets a property getter delegate to get the property value from a model object. @@ -415,7 +415,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding } /// - public bool Equals(ModelMetadata other) + public bool Equals(ModelMetadata? other) { if (object.ReferenceEquals(this, other)) { @@ -433,7 +433,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) { return Equals(obj as ModelMetadata); } @@ -469,14 +469,14 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding else if (ModelType.IsArray) { IsEnumerableType = true; - ElementType = ModelType.GetElementType(); + ElementType = ModelType.GetElementType()!; } else { IsEnumerableType = true; var enumerableType = ClosedGenericMatcher.ExtractGenericInterface(ModelType, typeof(IEnumerable<>)); - ElementType = enumerableType?.GenericTypeArguments[0]; + ElementType = enumerableType?.GenericTypeArguments[0]!; if (ElementType == null) { @@ -497,7 +497,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding case ModelMetadataKind.Parameter: return $"ModelMetadata (Parameter: '{ParameterName}' Type: '{ModelType.Name}')"; case ModelMetadataKind.Property: - return $"ModelMetadata (Property: '{ContainerType.Name}.{PropertyName}' Type: '{ModelType.Name}')"; + return $"ModelMetadata (Property: '{ContainerType!.Name}.{PropertyName}' Type: '{ModelType.Name}')"; case ModelMetadataKind.Type: return $"ModelMetadata (Type: '{ModelType.Name}')"; default: diff --git a/src/Mvc/Mvc.Abstractions/src/ModelBinding/ModelPropertyCollection.cs b/src/Mvc/Mvc.Abstractions/src/ModelBinding/ModelPropertyCollection.cs index 733da709ba..797e1b9514 100644 --- a/src/Mvc/Mvc.Abstractions/src/ModelBinding/ModelPropertyCollection.cs +++ b/src/Mvc/Mvc.Abstractions/src/ModelBinding/ModelPropertyCollection.cs @@ -32,7 +32,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding /// The instance for the property specified by , or /// null if no match can be found. /// - public ModelMetadata this[string propertyName] + public ModelMetadata? this[string propertyName] { get { diff --git a/src/Mvc/Mvc.Abstractions/src/ModelBinding/ModelStateDictionary.cs b/src/Mvc/Mvc.Abstractions/src/ModelBinding/ModelStateDictionary.cs index 48b8b9ee3a..24581e0510 100644 --- a/src/Mvc/Mvc.Abstractions/src/ModelBinding/ModelStateDictionary.cs +++ b/src/Mvc/Mvc.Abstractions/src/ModelBinding/ModelStateDictionary.cs @@ -5,6 +5,7 @@ using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; using Microsoft.AspNetCore.Mvc.Abstractions; using Microsoft.AspNetCore.Mvc.Formatters; @@ -166,7 +167,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding } TryGetValue(key, out var entry); - return entry; + return entry!; } } @@ -305,15 +306,15 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding } else if (entry == null) { - errorMessage = messageProvider.UnknownValueIsInvalidAccessor(name); + errorMessage = messageProvider.UnknownValueIsInvalidAccessor(name!); } else if (name == null) { - errorMessage = messageProvider.NonPropertyAttemptedValueIsInvalidAccessor(entry.AttemptedValue); + errorMessage = messageProvider.NonPropertyAttemptedValueIsInvalidAccessor(entry.AttemptedValue!); } else { - errorMessage = messageProvider.AttemptedValueIsInvalidAccessor(entry.AttemptedValue, name); + errorMessage = messageProvider.AttemptedValueIsInvalidAccessor(entry.AttemptedValue!, name); } return TryAddModelError(key, errorMessage); @@ -511,7 +512,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding /// /// The values of in a comma-separated . /// - public void SetModelValue(string key, object rawValue, string attemptedValue) + public void SetModelValue(string key, object? rawValue, string attemptedValue) { if (key == null) { @@ -540,7 +541,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding } // Avoid creating a new array for rawValue if there's only one value. - object rawValue; + object? rawValue; if (valueProviderResult == ValueProviderResult.None) { rawValue = null; @@ -573,10 +574,8 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding } } - private ModelStateNode GetNode(string key) + private ModelStateNode? GetNode(string key) { - Debug.Assert(key != null); - var current = _root; if (key.Length > 0) { @@ -661,7 +660,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding return new StringSegment(key, keyStart, index - keyStart); } - private static ModelValidationState? GetValidity(ModelStateNode node) + private static ModelValidationState? GetValidity(ModelStateNode? node) { if (node == null) { @@ -774,7 +773,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding } /// - public bool TryGetValue(string key, out ModelStateEntry value) + public bool TryGetValue(string key, [NotNullWhen(true)] out ModelStateEntry? value) { if (key == null) { @@ -893,11 +892,11 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding SubKey = subKey; } - public List ChildNodes { get; set; } + public List? ChildNodes { get; set; } - public override IReadOnlyList Children => ChildNodes; + public override IReadOnlyList? Children => ChildNodes; - public string Key { get; set; } + public string Key { get; set; } = default!; public StringSegment SubKey { get; } @@ -931,9 +930,9 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ModelStateNode GetNode(StringSegment subKey) + public ModelStateNode? GetNode(StringSegment subKey) { - ModelStateNode modelStateNode = null; + ModelStateNode? modelStateNode = null; if (subKey.Length == 0) { modelStateNode = this; @@ -981,7 +980,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding return modelStateNode; } - public override ModelStateEntry GetModelStateForProperty(string propertyName) + public override ModelStateEntry? GetModelStateForProperty(string propertyName) => GetNode(new StringSegment(propertyName)); private int BinarySearch(StringSegment searchKey) @@ -1068,9 +1067,9 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding /// public struct Enumerator : IEnumerator> { - private readonly ModelStateNode _rootNode; + private readonly ModelStateNode? _rootNode; private ModelStateNode _modelStateNode; - private List _nodes; + private List? _nodes; private int _index; private bool _visitedRoot; @@ -1093,7 +1092,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding _index = -1; _rootNode = dictionary.GetNode(prefix); - _modelStateNode = null; + _modelStateNode = default!; _nodes = null; _visitedRoot = false; } @@ -1141,7 +1140,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding while (_nodes.Count > 0) { var node = _nodes[0]; - if (_index == node.ChildNodes.Count - 1) + if (_index == node.ChildNodes!.Count - 1) { // We've exhausted the current sublist. _nodes.RemoveAt(0); @@ -1173,9 +1172,9 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding public void Reset() { _index = -1; - _nodes.Clear(); + _nodes?.Clear(); _visitedRoot = false; - _modelStateNode = null; + _modelStateNode = default!; } } @@ -1218,7 +1217,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding public KeyEnumerator(ModelStateDictionary dictionary, string prefix) { _prefixEnumerator = new Enumerator(dictionary, prefix); - Current = null; + Current = default!; } /// @@ -1240,7 +1239,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding } else { - Current = null; + Current = default!; } return result; @@ -1250,7 +1249,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding public void Reset() { _prefixEnumerator.Reset(); - Current = null; + Current = default!; } } @@ -1293,7 +1292,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding public ValueEnumerator(ModelStateDictionary dictionary, string prefix) { _prefixEnumerator = new Enumerator(dictionary, prefix); - Current = null; + Current = default!; } /// @@ -1315,7 +1314,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding } else { - Current = null; + Current = default!; } return result; @@ -1325,7 +1324,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding public void Reset() { _prefixEnumerator.Reset(); - Current = null; + Current = default!; } } } diff --git a/src/Mvc/Mvc.Abstractions/src/ModelBinding/ModelStateEntry.cs b/src/Mvc/Mvc.Abstractions/src/ModelBinding/ModelStateEntry.cs index b73eab4f77..d56ef3dd81 100644 --- a/src/Mvc/Mvc.Abstractions/src/ModelBinding/ModelStateEntry.cs +++ b/src/Mvc/Mvc.Abstractions/src/ModelBinding/ModelStateEntry.cs @@ -10,17 +10,17 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding /// public abstract class ModelStateEntry { - private ModelErrorCollection _errors; + private ModelErrorCollection? _errors; /// /// Gets the raw value from the request associated with this entry. /// - public object RawValue { get; set; } + public object? RawValue { get; set; } /// /// Gets the set of values contained in , joined into a comma-separated string. /// - public string AttemptedValue { get; set; } + public string? AttemptedValue { get; set; } /// /// Gets the for this entry. @@ -61,7 +61,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding /// This method returns any existing entry, even those with with value /// . /// - public abstract ModelStateEntry GetModelStateForProperty(string propertyName); + public abstract ModelStateEntry? GetModelStateForProperty(string propertyName); /// /// Gets the values for sub-properties. @@ -70,6 +70,6 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding /// This property returns all existing entries, even those with with value /// . /// - public abstract IReadOnlyList Children { get; } + public abstract IReadOnlyList? Children { get; } } } diff --git a/src/Mvc/Mvc.Abstractions/src/ModelBinding/Validation/ClientValidatorItem.cs b/src/Mvc/Mvc.Abstractions/src/ModelBinding/Validation/ClientValidatorItem.cs index e346509701..be8552d8df 100644 --- a/src/Mvc/Mvc.Abstractions/src/ModelBinding/Validation/ClientValidatorItem.cs +++ b/src/Mvc/Mvc.Abstractions/src/ModelBinding/Validation/ClientValidatorItem.cs @@ -30,12 +30,12 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Validation /// /// Gets the metadata associated with the . /// - public object ValidatorMetadata { get; } + public object ValidatorMetadata { get; } = default!; /// /// Gets or sets the . /// - public IClientModelValidator Validator { get; set; } + public IClientModelValidator Validator { get; set; } = default!; /// /// Gets or sets a value indicating whether or not can be reused across requests. diff --git a/src/Mvc/Mvc.Abstractions/src/ModelBinding/Validation/ValidationEntry.cs b/src/Mvc/Mvc.Abstractions/src/ModelBinding/Validation/ValidationEntry.cs index a873273ca7..cedca096a4 100644 --- a/src/Mvc/Mvc.Abstractions/src/ModelBinding/Validation/ValidationEntry.cs +++ b/src/Mvc/Mvc.Abstractions/src/ModelBinding/Validation/ValidationEntry.cs @@ -10,8 +10,8 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Validation /// public struct ValidationEntry { - private object _model; - private Func _modelAccessor; + private object? _model; + private Func? _modelAccessor; /// /// Creates a new . @@ -79,7 +79,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Validation /// /// The model object. /// - public object Model + public object? Model { get { diff --git a/src/Mvc/Mvc.Abstractions/src/ModelBinding/Validation/ValidationStateDictionary.cs b/src/Mvc/Mvc.Abstractions/src/ModelBinding/Validation/ValidationStateDictionary.cs index 11179b014d..2d40811d5c 100644 --- a/src/Mvc/Mvc.Abstractions/src/ModelBinding/Validation/ValidationStateDictionary.cs +++ b/src/Mvc/Mvc.Abstractions/src/ModelBinding/Validation/ValidationStateDictionary.cs @@ -4,7 +4,7 @@ using System; using System.Collections; using System.Collections.Generic; -using System.Runtime.CompilerServices; +using System.Diagnostics.CodeAnalysis; namespace Microsoft.AspNetCore.Mvc.ModelBinding.Validation { @@ -25,8 +25,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Validation _inner = new Dictionary(ReferenceEqualityComparer.Instance); } - /// - public ValidationStateEntry this[object key] + public ValidationStateEntry? this[object key] { get { @@ -36,10 +35,19 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Validation set { - _inner[key] = value; + _inner[key] = value!; } } + /// + ValidationStateEntry IDictionary.this[object key] + { + get => this[key]!; + set => this[key] = value; + } + + ValidationStateEntry IReadOnlyDictionary.this[object key] => this[key]!; + /// public int Count => _inner.Count; @@ -115,7 +123,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Validation } /// - public bool TryGetValue(object key, out ValidationStateEntry value) + public bool TryGetValue(object key, [MaybeNullWhen(false)] out ValidationStateEntry value) { return _inner.TryGetValue(key, out value); } @@ -125,30 +133,5 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Validation { return ((IDictionary)_inner).GetEnumerator(); } - - private class ReferenceEqualityComparer : IEqualityComparer - { - private static readonly bool IsMono = Type.GetType("Mono.Runtime") != null; - - public static readonly ReferenceEqualityComparer Instance = new ReferenceEqualityComparer(); - - public new bool Equals(object x, object y) - { - return Object.ReferenceEquals(x, y); - } - - public int GetHashCode(object obj) - { - // RuntimeHelpers.GetHashCode sometimes crashes the runtime on Mono 4.0.4 - // See: https://github.com/aspnet/External/issues/45 - // The workaround here is to just not hash anything, and fall back to an equality check. - if (IsMono) - { - return 0; - } - - return RuntimeHelpers.GetHashCode(obj); - } - } } } \ No newline at end of file diff --git a/src/Mvc/Mvc.Abstractions/src/ModelBinding/Validation/ValidationStateEntry.cs b/src/Mvc/Mvc.Abstractions/src/ModelBinding/Validation/ValidationStateEntry.cs index 970cbb8dfa..ee94334283 100644 --- a/src/Mvc/Mvc.Abstractions/src/ModelBinding/Validation/ValidationStateEntry.cs +++ b/src/Mvc/Mvc.Abstractions/src/ModelBinding/Validation/ValidationStateEntry.cs @@ -12,12 +12,12 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Validation /// /// Gets or sets the model prefix associated with the entry. /// - public string Key { get; set; } + public string Key { get; set; } = default!; /// /// Gets or sets the associated with the entry. /// - public ModelMetadata Metadata { get; set; } + public ModelMetadata Metadata { get; set; } = default!; /// /// Gets or sets a value indicating whether the associated model object should be validated. @@ -28,6 +28,6 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Validation /// Gets or sets an for enumerating child entries of the associated /// model object. /// - public IValidationStrategy Strategy { get; set; } + public IValidationStrategy Strategy { get; set; } = default!; } } diff --git a/src/Mvc/Mvc.Abstractions/src/ModelBinding/Validation/ValidatorItem.cs b/src/Mvc/Mvc.Abstractions/src/ModelBinding/Validation/ValidatorItem.cs index 8592eeca71..ca8b291e1a 100644 --- a/src/Mvc/Mvc.Abstractions/src/ModelBinding/Validation/ValidatorItem.cs +++ b/src/Mvc/Mvc.Abstractions/src/ModelBinding/Validation/ValidatorItem.cs @@ -30,12 +30,12 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Validation /// /// Gets the metadata associated with the . /// - public object ValidatorMetadata { get; } + public object ValidatorMetadata { get; } = default!; /// /// Gets or sets the . /// - public IModelValidator Validator { get; set; } + public IModelValidator Validator { get; set; } = default!; /// /// Gets or sets a value indicating whether or not can be reused across requests. diff --git a/src/Mvc/Mvc.Abstractions/src/ModelBinding/ValueProviderResult.cs b/src/Mvc/Mvc.Abstractions/src/ModelBinding/ValueProviderResult.cs index 3a0b8e1fa8..e5b088b4a0 100644 --- a/src/Mvc/Mvc.Abstractions/src/ModelBinding/ValueProviderResult.cs +++ b/src/Mvc/Mvc.Abstractions/src/ModelBinding/ValueProviderResult.cs @@ -69,7 +69,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding /// to get a single value for processing regardless of whether a single or multiple values were provided /// in the request. /// - public string FirstValue + public string? FirstValue { get { @@ -87,7 +87,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding public int Length => Values.Count; /// - public override bool Equals(object obj) + public override bool Equals(object? obj) { var other = obj as ValueProviderResult?; return other.HasValue && Equals(other.Value); diff --git a/src/Mvc/Mvc.Abstractions/src/Routing/AttributeRouteInfo.cs b/src/Mvc/Mvc.Abstractions/src/Routing/AttributeRouteInfo.cs index f2fc4ea77b..1aae06847e 100644 --- a/src/Mvc/Mvc.Abstractions/src/Routing/AttributeRouteInfo.cs +++ b/src/Mvc/Mvc.Abstractions/src/Routing/AttributeRouteInfo.cs @@ -13,7 +13,7 @@ namespace Microsoft.AspNetCore.Mvc.Routing /// /// The route template. May be null if the action has no attribute routes. /// - public string Template { get; set; } + public string? Template { get; set; } /// /// Gets the order of the route associated with a given action. This property determines @@ -27,7 +27,7 @@ namespace Microsoft.AspNetCore.Mvc.Routing /// to generate a link by referring to the route by name instead of attempting to match a /// route by provided route data. /// - public string Name { get; set; } + public string Name { get; set; } = default!; /// /// Gets or sets a value that determines if the route entry associated with this model participates in link generation. diff --git a/src/Mvc/Mvc.Abstractions/src/Routing/UrlActionContext.cs b/src/Mvc/Mvc.Abstractions/src/Routing/UrlActionContext.cs index 8260b6b680..09853000d0 100644 --- a/src/Mvc/Mvc.Abstractions/src/Routing/UrlActionContext.cs +++ b/src/Mvc/Mvc.Abstractions/src/Routing/UrlActionContext.cs @@ -11,7 +11,7 @@ namespace Microsoft.AspNetCore.Mvc.Routing /// /// The name of the action method that uses to generate URLs. /// - public string Action + public string? Action { get; set; @@ -20,7 +20,7 @@ namespace Microsoft.AspNetCore.Mvc.Routing /// /// The name of the controller that uses to generate URLs. /// - public string Controller + public string? Controller { get; set; @@ -30,7 +30,7 @@ namespace Microsoft.AspNetCore.Mvc.Routing /// The object that contains the route values that /// uses to generate URLs. /// - public object Values + public object? Values { get; set; @@ -40,7 +40,7 @@ namespace Microsoft.AspNetCore.Mvc.Routing /// The protocol for the URLs that generates, /// such as "http" or "https" /// - public string Protocol + public string? Protocol { get; set; @@ -49,7 +49,7 @@ namespace Microsoft.AspNetCore.Mvc.Routing /// /// The host name for the URLs that generates. /// - public string Host + public string? Host { get; set; @@ -58,7 +58,7 @@ namespace Microsoft.AspNetCore.Mvc.Routing /// /// The fragment for the URLs that generates. /// - public string Fragment + public string? Fragment { get; set; diff --git a/src/Mvc/Mvc.Abstractions/src/Routing/UrlRouteContext.cs b/src/Mvc/Mvc.Abstractions/src/Routing/UrlRouteContext.cs index 706414f958..d713e69212 100644 --- a/src/Mvc/Mvc.Abstractions/src/Routing/UrlRouteContext.cs +++ b/src/Mvc/Mvc.Abstractions/src/Routing/UrlRouteContext.cs @@ -11,7 +11,7 @@ namespace Microsoft.AspNetCore.Mvc.Routing /// /// The name of the route that uses to generate URLs. /// - public string RouteName + public string? RouteName { get; set; @@ -21,7 +21,7 @@ namespace Microsoft.AspNetCore.Mvc.Routing /// The object that contains the route values that /// uses to generate URLs. /// - public object Values + public object? Values { get; set; @@ -31,7 +31,7 @@ namespace Microsoft.AspNetCore.Mvc.Routing /// The protocol for the URLs that generates, /// such as "http" or "https" /// - public string Protocol + public string? Protocol { get; set; @@ -40,7 +40,7 @@ namespace Microsoft.AspNetCore.Mvc.Routing /// /// The host name for the URLs that generates. /// - public string Host + public string? Host { get; set; @@ -49,7 +49,7 @@ namespace Microsoft.AspNetCore.Mvc.Routing /// /// The fragment for the URLs that generates. /// - public string Fragment + public string? Fragment { get; set; diff --git a/src/Mvc/Mvc.ApiExplorer/src/DefaultApiDescriptionProvider.cs b/src/Mvc/Mvc.ApiExplorer/src/DefaultApiDescriptionProvider.cs index bbc1f86ef1..73a4c35492 100644 --- a/src/Mvc/Mvc.ApiExplorer/src/DefaultApiDescriptionProvider.cs +++ b/src/Mvc/Mvc.ApiExplorer/src/DefaultApiDescriptionProvider.cs @@ -662,11 +662,11 @@ namespace Microsoft.AspNetCore.Mvc.ApiExplorer public int GetHashCode(PropertyKey obj) { - var hashCodeCombiner = HashCodeCombiner.Start(); + var hashCodeCombiner = new HashCode(); hashCodeCombiner.Add(obj.ContainerType); hashCodeCombiner.Add(obj.PropertyName); hashCodeCombiner.Add(obj.Source); - return hashCodeCombiner.CombinedHash; + return hashCodeCombiner.ToHashCode(); } } } diff --git a/src/Mvc/Mvc.Core/src/ModelBinding/ModelBinderFactory.cs b/src/Mvc/Mvc.Core/src/ModelBinding/ModelBinderFactory.cs index 1cd59d4c72..180fb433e1 100644 --- a/src/Mvc/Mvc.Core/src/ModelBinding/ModelBinderFactory.cs +++ b/src/Mvc/Mvc.Core/src/ModelBinding/ModelBinderFactory.cs @@ -319,10 +319,10 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding public override int GetHashCode() { - var hash = new HashCodeCombiner(); + var hash = new HashCode(); hash.Add(_metadata); hash.Add(RuntimeHelpers.GetHashCode(_token)); - return hash; + return hash.ToHashCode(); } public override string ToString() diff --git a/src/Mvc/Mvc.Core/src/Routing/AttributeRoute.cs b/src/Mvc/Mvc.Core/src/Routing/AttributeRoute.cs index da0fc4594e..185e77fb58 100644 --- a/src/Mvc/Mvc.Core/src/Routing/AttributeRoute.cs +++ b/src/Mvc/Mvc.Core/src/Routing/AttributeRoute.cs @@ -291,10 +291,10 @@ namespace Microsoft.AspNetCore.Mvc.Routing return 0; } - var hash = new HashCodeCombiner(); + var hash = new HashCode(); hash.Add(obj.Order); hash.Add(obj.RouteTemplate.TemplateText, StringComparer.OrdinalIgnoreCase); - return hash; + return hash.ToHashCode(); } } diff --git a/src/Mvc/Mvc.Razor/src/RazorPageActivator.cs b/src/Mvc/Mvc.Razor/src/RazorPageActivator.cs index 9acc858e5a..49eb5c05a9 100644 --- a/src/Mvc/Mvc.Razor/src/RazorPageActivator.cs +++ b/src/Mvc/Mvc.Razor/src/RazorPageActivator.cs @@ -123,14 +123,14 @@ namespace Microsoft.AspNetCore.Mvc.Razor public override int GetHashCode() { - var hashCodeCombiner = HashCodeCombiner.Start(); + var hashCodeCombiner = new HashCode(); hashCodeCombiner.Add(PageType); if (ProvidedModelType != null) { hashCodeCombiner.Add(ProvidedModelType); } - return hashCodeCombiner.CombinedHash; + return hashCodeCombiner.ToHashCode(); } } } diff --git a/src/Mvc/Mvc.Razor/src/ViewLocationCacheKey.cs b/src/Mvc/Mvc.Razor/src/ViewLocationCacheKey.cs index 2640110dd5..140b55ba9e 100644 --- a/src/Mvc/Mvc.Razor/src/ViewLocationCacheKey.cs +++ b/src/Mvc/Mvc.Razor/src/ViewLocationCacheKey.cs @@ -135,7 +135,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor /// public override int GetHashCode() { - var hashCodeCombiner = HashCodeCombiner.Start(); + var hashCodeCombiner = new HashCode(); hashCodeCombiner.Add(IsMainPage ? 1 : 0); hashCodeCombiner.Add(ViewName, StringComparer.Ordinal); hashCodeCombiner.Add(ControllerName, StringComparer.Ordinal); @@ -151,7 +151,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor } } - return hashCodeCombiner; + return hashCodeCombiner.ToHashCode(); } } } diff --git a/src/Mvc/Mvc.TagHelpers/src/Cache/CacheTagKey.cs b/src/Mvc/Mvc.TagHelpers/src/Cache/CacheTagKey.cs index bf327f30ca..f527f8f55f 100644 --- a/src/Mvc/Mvc.TagHelpers/src/Cache/CacheTagKey.cs +++ b/src/Mvc/Mvc.TagHelpers/src/Cache/CacheTagKey.cs @@ -247,7 +247,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers.Cache return _hashcode.Value; } - var hashCodeCombiner = new HashCodeCombiner(); + var hashCodeCombiner = new HashCode(); hashCodeCombiner.Add(Key, StringComparer.Ordinal); hashCodeCombiner.Add(_expiresAfter); @@ -258,12 +258,12 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers.Cache hashCodeCombiner.Add(_requestCulture); hashCodeCombiner.Add(_requestUICulture); - CombineCollectionHashCode(hashCodeCombiner, VaryByCookieName, _cookies); - CombineCollectionHashCode(hashCodeCombiner, VaryByHeaderName, _headers); - CombineCollectionHashCode(hashCodeCombiner, VaryByQueryName, _queries); - CombineCollectionHashCode(hashCodeCombiner, VaryByRouteName, _routeValues); + CombineCollectionHashCode(ref hashCodeCombiner, VaryByCookieName, _cookies); + CombineCollectionHashCode(ref hashCodeCombiner, VaryByHeaderName, _headers); + CombineCollectionHashCode(ref hashCodeCombiner, VaryByQueryName, _queries); + CombineCollectionHashCode(ref hashCodeCombiner, VaryByRouteName, _routeValues); - _hashcode = hashCodeCombiner.CombinedHash; + _hashcode = hashCodeCombiner.ToHashCode(); return _hashcode.Value; } @@ -331,7 +331,7 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers.Cache } private static void CombineCollectionHashCode( - HashCodeCombiner hashCodeCombiner, + ref HashCode hashCodeCombiner, string collectionName, IList> values) { diff --git a/src/Mvc/Mvc.TagHelpers/src/GlobbingUrlBuilder.cs b/src/Mvc/Mvc.TagHelpers/src/GlobbingUrlBuilder.cs index 82c176bc8b..e0a04a5374 100644 --- a/src/Mvc/Mvc.TagHelpers/src/GlobbingUrlBuilder.cs +++ b/src/Mvc/Mvc.TagHelpers/src/GlobbingUrlBuilder.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Security.Policy; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.FileProviders; @@ -373,11 +374,11 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers public override int GetHashCode() { - var hashCodeCombiner = HashCodeCombiner.Start(); + var hashCodeCombiner = new HashCode(); hashCodeCombiner.Add(Include); hashCodeCombiner.Add(Exclude); - return hashCodeCombiner.CombinedHash; + return hashCodeCombiner.ToHashCode(); } } } diff --git a/src/Mvc/Mvc.TagHelpers/test/CacheTagHelperTest.cs b/src/Mvc/Mvc.TagHelpers/test/CacheTagHelperTest.cs index 90313c0efa..525f1107f2 100644 --- a/src/Mvc/Mvc.TagHelpers/test/CacheTagHelperTest.cs +++ b/src/Mvc/Mvc.TagHelpers/test/CacheTagHelperTest.cs @@ -887,7 +887,6 @@ namespace Microsoft.AspNetCore.Mvc.TagHelpers } [Fact] - [QuarantinedTest] public async Task ProcessAsync_AwaitersUseTheResultOfExecutor() { // Arrange diff --git a/src/Mvc/Mvc.ViewFeatures/ref/Microsoft.AspNetCore.Mvc.ViewFeatures.netcoreapp.cs b/src/Mvc/Mvc.ViewFeatures/ref/Microsoft.AspNetCore.Mvc.ViewFeatures.netcoreapp.cs index 62cfeb38a0..b6c137cfea 100644 --- a/src/Mvc/Mvc.ViewFeatures/ref/Microsoft.AspNetCore.Mvc.ViewFeatures.netcoreapp.cs +++ b/src/Mvc/Mvc.ViewFeatures/ref/Microsoft.AspNetCore.Mvc.ViewFeatures.netcoreapp.cs @@ -652,6 +652,7 @@ namespace Microsoft.AspNetCore.Mvc.Rendering [System.Diagnostics.DebuggerDisplayAttribute("{DebuggerToString()}")] public partial class TagBuilder : Microsoft.AspNetCore.Html.IHtmlContent { + public TagBuilder(Microsoft.AspNetCore.Mvc.Rendering.TagBuilder tagBuilder) { } public TagBuilder(string tagName) { } public Microsoft.AspNetCore.Mvc.ViewFeatures.AttributeDictionary Attributes { get { throw null; } } public bool HasInnerHtml { get { throw null; } } diff --git a/src/Mvc/Mvc.ViewFeatures/src/LambdaExpressionComparer.cs b/src/Mvc/Mvc.ViewFeatures/src/LambdaExpressionComparer.cs index 1e0dcc7fe7..e3448c15c0 100644 --- a/src/Mvc/Mvc.ViewFeatures/src/LambdaExpressionComparer.cs +++ b/src/Mvc/Mvc.ViewFeatures/src/LambdaExpressionComparer.cs @@ -84,7 +84,7 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures public int GetHashCode(LambdaExpression lambdaExpression) { var expression = lambdaExpression.Body; - var hashCodeCombiner = HashCodeCombiner.Start(); + var hashCodeCombiner = new HashCode(); while (true) { @@ -107,7 +107,7 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures } } - return hashCodeCombiner.CombinedHash; + return hashCodeCombiner.ToHashCode(); } } } diff --git a/src/Mvc/Mvc.ViewFeatures/src/MemberExpressionCacheKeyComparer.cs b/src/Mvc/Mvc.ViewFeatures/src/MemberExpressionCacheKeyComparer.cs index 5911611c89..b1586e71ba 100644 --- a/src/Mvc/Mvc.ViewFeatures/src/MemberExpressionCacheKeyComparer.cs +++ b/src/Mvc/Mvc.ViewFeatures/src/MemberExpressionCacheKeyComparer.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using System.Collections.Generic; using Microsoft.Extensions.Internal; @@ -39,7 +40,7 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures public int GetHashCode(MemberExpressionCacheKey obj) { - var hashCodeCombiner = new HashCodeCombiner(); + var hashCodeCombiner = new HashCode(); hashCodeCombiner.Add(obj.ModelType); foreach (var member in obj) @@ -47,7 +48,7 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures hashCodeCombiner.Add(member); } - return hashCodeCombiner.CombinedHash; + return hashCodeCombiner.ToHashCode(); } } } diff --git a/src/Mvc/Mvc.ViewFeatures/src/Rendering/TagBuilder.cs b/src/Mvc/Mvc.ViewFeatures/src/Rendering/TagBuilder.cs index e3e4edfbb8..4b6d8b6fcb 100644 --- a/src/Mvc/Mvc.ViewFeatures/src/Rendering/TagBuilder.cs +++ b/src/Mvc/Mvc.ViewFeatures/src/Rendering/TagBuilder.cs @@ -37,6 +37,34 @@ namespace Microsoft.AspNetCore.Mvc.Rendering TagName = tagName; } + /// + /// Creates a copy of the HTML tag passed as . + /// + /// Tag to copy. + public TagBuilder(TagBuilder tagBuilder) + { + if (tagBuilder == null) + { + throw new ArgumentException(Resources.ArgumentCannotBeNullOrEmpty, nameof(tagBuilder)); + } + + if (tagBuilder._attributes != null) + { + foreach (var tag in tagBuilder._attributes) + { + Attributes.Add(tag); + } + } + + if (tagBuilder._innerHtml != null) + { + tagBuilder.InnerHtml.CopyTo(InnerHtml); + } + + TagName = tagBuilder.TagName; + TagRenderMode = tagBuilder.TagRenderMode; + } + /// /// Gets the set of attributes that will be written to the tag. /// diff --git a/src/Mvc/Mvc.ViewFeatures/test/Rendering/TagBuilderTest.cs b/src/Mvc/Mvc.ViewFeatures/test/Rendering/TagBuilderTest.cs index 0132887614..3ceaeef37b 100644 --- a/src/Mvc/Mvc.ViewFeatures/test/Rendering/TagBuilderTest.cs +++ b/src/Mvc/Mvc.ViewFeatures/test/Rendering/TagBuilderTest.cs @@ -253,5 +253,64 @@ namespace Microsoft.AspNetCore.Mvc.Core.Rendering // Assert Assert.Equal("Hello", HtmlContentUtilities.HtmlContentToString(tag)); } + + [Fact] + public void Constructor_Copy_CopiesTagRenderMode() + { + // Arrange + var originalTagBuilder = new TagBuilder("p"); + originalTagBuilder.TagRenderMode = TagRenderMode.SelfClosing; + + // Act + var clonedTagBuilder = new TagBuilder(originalTagBuilder); + + + // Assert + Assert.Equal(originalTagBuilder.TagRenderMode, clonedTagBuilder.TagRenderMode); + } + + [Fact] + public void Constructor_Copy_DoesShallowCopyOfInnerHtml() + { + // Arrange + var originalTagBuilder = new TagBuilder("p"); + originalTagBuilder.InnerHtml.AppendHtml("Hello"); + + // Act + var clonedTagBuilder = new TagBuilder(originalTagBuilder); + + // Assert + Assert.NotEqual(originalTagBuilder.InnerHtml, clonedTagBuilder.InnerHtml); + Assert.Equal(HtmlContentUtilities.HtmlContentToString(originalTagBuilder.RenderBody()), HtmlContentUtilities.HtmlContentToString(clonedTagBuilder.RenderBody())); + } + + [Fact] + public void Constructor_Copy_DoesShallowCopyOfAttributes() + { + // Arrange + var originalTagBuilder = new TagBuilder("p"); + originalTagBuilder.AddCssClass("class1"); + + // Act + var clonedTagBuilder = new TagBuilder(originalTagBuilder); + + // Assert + Assert.NotSame(originalTagBuilder.Attributes, clonedTagBuilder.Attributes); + Assert.Equal(originalTagBuilder.Attributes, clonedTagBuilder.Attributes); + } + + [Fact] + public void Constructor_Copy_CopiesTagName() + { + // Arrange + var originalTagBuilder = new TagBuilder("p"); + + // Act + + var clonedTagBuilder = new TagBuilder(originalTagBuilder); + + // Assert + Assert.Equal(originalTagBuilder.TagName, clonedTagBuilder.TagName); + } } } \ No newline at end of file diff --git a/src/Servers/IIS/IIS/test/Common.FunctionalTests/ClientCertificateTests.cs b/src/Servers/IIS/IIS/test/Common.FunctionalTests/ClientCertificateTests.cs index d61c6fa5da..f883d88f83 100644 --- a/src/Servers/IIS/IIS/test/Common.FunctionalTests/ClientCertificateTests.cs +++ b/src/Servers/IIS/IIS/test/Common.FunctionalTests/ClientCertificateTests.cs @@ -34,7 +34,6 @@ namespace Microsoft.AspNetCore.Server.IIS.FunctionalTests .WithAllHostingModels(); [ConditionalTheory] - [QuarantinedTest] [MemberData(nameof(TestVariants))] [MinimumOSVersion(OperatingSystems.Windows, WindowsVersions.Win8)] public Task HttpsNoClientCert_NoClientCert(TestVariant variant) diff --git a/src/Servers/Kestrel/Core/src/CoreStrings.resx b/src/Servers/Kestrel/Core/src/CoreStrings.resx index 96f6e49969..46f2e263a3 100644 --- a/src/Servers/Kestrel/Core/src/CoreStrings.resx +++ b/src/Servers/Kestrel/Core/src/CoreStrings.resx @@ -268,7 +268,7 @@ Overriding endpoints defined in UseKestrel() because {settingName} is set to true. Binding to address(es) '{addresses}' instead. - Unrecognized scheme in server address '{address}'. Only 'http://' is supported. + Unrecognized scheme in server address '{address}'. Only 'http://' and 'https://' are supported. Headers are read-only, response has already started. diff --git a/src/Servers/Kestrel/Core/src/Internal/Http2/HPackHeaderWriter.cs b/src/Servers/Kestrel/Core/src/Internal/Http2/HPackHeaderWriter.cs index 33c7b920f3..c914595bc9 100644 --- a/src/Servers/Kestrel/Core/src/Internal/Http2/HPackHeaderWriter.cs +++ b/src/Servers/Kestrel/Core/src/Internal/Http2/HPackHeaderWriter.cs @@ -83,7 +83,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2 case 404: case 500: // Status codes which exist in the HTTP/2 StaticTable. - return HPackEncoder.EncodeIndexedHeaderField(H2StaticTable.StatusIndex[statusCode], buffer, out length); + return HPackEncoder.EncodeIndexedHeaderField(H2StaticTable.GetStatusIndex(statusCode), buffer, out length); default: const string name = ":status"; var value = StatusCodes.ToStatusString(statusCode); diff --git a/src/Servers/Kestrel/perf/Kestrel.Performance/HPackDecoderBenchmark.cs b/src/Servers/Kestrel/perf/Kestrel.Performance/HPackDecoderBenchmark.cs new file mode 100644 index 0000000000..31382bbf5e --- /dev/null +++ b/src/Servers/Kestrel/perf/Kestrel.Performance/HPackDecoderBenchmark.cs @@ -0,0 +1,135 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Linq; +using System.Net.Http.HPack; +using System.Text; +using System.Threading.Tasks; +using BenchmarkDotNet.Attributes; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http; + +namespace Microsoft.AspNetCore.Server.Kestrel.Performance +{ + public class HPackDecoderBenchmark + { + // Indexed Header Field Representation - Dynamic Table - Index 62 (first index in dynamic table) + private static readonly byte[] _indexedHeaderDynamic = new byte[] { 0xbe }; + + private static readonly byte[] _literalHeaderFieldWithoutIndexingNewName = new byte[] { 0x00 }; + + private const string _headerNameString = "new-header"; + + private static readonly byte[] _headerNameBytes = Encoding.ASCII.GetBytes(_headerNameString); + + private static readonly byte[] _headerName = new byte[] { (byte)_headerNameBytes.Length } + .Concat(_headerNameBytes) + .ToArray(); + + private const string _headerValueString = "value"; + + private static readonly byte[] _headerValueBytes = Encoding.ASCII.GetBytes(_headerValueString); + + private static readonly byte[] _headerValue = new byte[] { (byte)_headerValueBytes.Length } + .Concat(_headerValueBytes) + .ToArray(); + + private static readonly byte[] _literalHeaderFieldNeverIndexed_NewName = _literalHeaderFieldWithoutIndexingNewName + .Concat(_headerName) + .Concat(_headerValue) + .ToArray(); + + private static readonly byte[] _literalHeaderFieldNeverIndexed_NewName_Large; + private static readonly byte[] _literalHeaderFieldNeverIndexed_NewName_Multiple; + private static readonly byte[] _indexedHeaderDynamic_Multiple; + + static HPackDecoderBenchmark() + { + string string8193 = new string('a', 8193); + + _literalHeaderFieldNeverIndexed_NewName_Large = _literalHeaderFieldWithoutIndexingNewName + .Concat(new byte[] { 0x7f, 0x82, 0x3f }) // 8193 encoded with 7-bit prefix, no Huffman encoding + .Concat(Encoding.ASCII.GetBytes(string8193)) + .Concat(new byte[] { 0x7f, 0x82, 0x3f }) // 8193 encoded with 7-bit prefix, no Huffman encoding + .Concat(Encoding.ASCII.GetBytes(string8193)) + .ToArray(); + + _literalHeaderFieldNeverIndexed_NewName_Multiple = _literalHeaderFieldNeverIndexed_NewName + .Concat(_literalHeaderFieldNeverIndexed_NewName) + .Concat(_literalHeaderFieldNeverIndexed_NewName) + .Concat(_literalHeaderFieldNeverIndexed_NewName) + .Concat(_literalHeaderFieldNeverIndexed_NewName) + .ToArray(); + + _indexedHeaderDynamic_Multiple = _indexedHeaderDynamic + .Concat(_indexedHeaderDynamic) + .Concat(_indexedHeaderDynamic) + .Concat(_indexedHeaderDynamic) + .Concat(_indexedHeaderDynamic) + .ToArray(); + } + + private HPackDecoder _decoder; + private TestHeadersHandler _testHeadersHandler; + private DynamicTable _dynamicTable; + + [GlobalSetup] + public void GlobalSetup() + { + _dynamicTable = new DynamicTable(maxSize: 4096); + _dynamicTable.Insert(_headerNameBytes, _headerValueBytes); + _decoder = new HPackDecoder(maxDynamicTableSize: 4096, maxHeadersLength: 65536, _dynamicTable); + _testHeadersHandler = new TestHeadersHandler(); + } + + [Benchmark] + public void DecodesLiteralHeaderFieldNeverIndexed_NewName() + { + _decoder.Decode(_literalHeaderFieldNeverIndexed_NewName, endHeaders: true, handler: _testHeadersHandler); + } + + [Benchmark] + public void DecodesLiteralHeaderFieldNeverIndexed_NewName_Large() + { + _decoder.Decode(_literalHeaderFieldNeverIndexed_NewName_Large, endHeaders: true, handler: _testHeadersHandler); + } + + [Benchmark] + public void DecodesLiteralHeaderFieldNeverIndexed_NewName_Multiple() + { + _decoder.Decode(_literalHeaderFieldNeverIndexed_NewName_Multiple, endHeaders: true, handler: _testHeadersHandler); + } + + [Benchmark] + public void DecodesIndexedHeaderField_DynamicTable() + { + _decoder.Decode(_indexedHeaderDynamic, endHeaders: true, handler: _testHeadersHandler); + } + + [Benchmark] + public void DecodesIndexedHeaderField_DynamicTable_Multiple() + { + _decoder.Decode(_indexedHeaderDynamic_Multiple, endHeaders: true, handler: _testHeadersHandler); + } + + private class TestHeadersHandler : IHttpHeadersHandler + { + public void OnHeader(ReadOnlySpan name, ReadOnlySpan value) + { + } + + public void OnHeadersComplete(bool endStream) + { + } + + public void OnStaticIndexedHeader(int index) + { + } + + public void OnStaticIndexedHeader(int index, ReadOnlySpan value) + { + } + } + } +} diff --git a/src/Servers/Kestrel/test/InMemory.FunctionalTests/Http2/Http2ConnectionTests.cs b/src/Servers/Kestrel/test/InMemory.FunctionalTests/Http2/Http2ConnectionTests.cs index 43a3f9d7a2..a1cf418fe3 100644 --- a/src/Servers/Kestrel/test/InMemory.FunctionalTests/Http2/Http2ConnectionTests.cs +++ b/src/Servers/Kestrel/test/InMemory.FunctionalTests/Http2/Http2ConnectionTests.cs @@ -300,7 +300,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests } [Fact] - [QuarantinedTest] public async Task StreamPool_MultipleStreamsInSequence_PooledStreamReused() { TaskCompletionSource appDelegateTcs = null; @@ -365,7 +364,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests } [Fact] - [QuarantinedTest] public async Task StreamPool_StreamIsInvalidState_DontReturnedToPool() { var serverTcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); @@ -4010,7 +4008,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests [Theory] [InlineData(true)] [InlineData(false)] - [QuarantinedTest] public async Task CONTINUATION_Received_WithTrailers_Available(bool sendData) { await InitializeConnectionAsync(_readTrailersApplication); diff --git a/src/Servers/Kestrel/test/InMemory.FunctionalTests/Http2/Http2TimeoutTests.cs b/src/Servers/Kestrel/test/InMemory.FunctionalTests/Http2/Http2TimeoutTests.cs index 99bbd21ea5..c433bb90be 100644 --- a/src/Servers/Kestrel/test/InMemory.FunctionalTests/Http2/Http2TimeoutTests.cs +++ b/src/Servers/Kestrel/test/InMemory.FunctionalTests/Http2/Http2TimeoutTests.cs @@ -371,7 +371,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests } [Fact] - [QuarantinedTest] public async Task DATA_Sent_TooSlowlyDueToFlowControlOnSmallWrite_AbortsConnectionAfterGracePeriod() { var mockSystemClock = _serviceContext.MockSystemClock; @@ -426,7 +425,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests } [Fact] - [QuarantinedTest] public async Task DATA_Sent_TooSlowlyDueToOutputFlowControlOnLargeWrite_AbortsConnectionAfterRateTimeout() { var mockSystemClock = _serviceContext.MockSystemClock; diff --git a/src/Servers/Kestrel/test/InMemory.FunctionalTests/HttpsTests.cs b/src/Servers/Kestrel/test/InMemory.FunctionalTests/HttpsTests.cs index 4849965c40..e36759544c 100644 --- a/src/Servers/Kestrel/test/InMemory.FunctionalTests/HttpsTests.cs +++ b/src/Servers/Kestrel/test/InMemory.FunctionalTests/HttpsTests.cs @@ -220,7 +220,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.InMemory.FunctionalTests [Fact] [Repeat(20)] - [QuarantinedTest] public async Task DoesNotThrowObjectDisposedExceptionFromWriteAsyncAfterConnectionIsAborted() { var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); diff --git a/src/Servers/Kestrel/test/InMemory.FunctionalTests/RequestHeaderLimitsTests.cs b/src/Servers/Kestrel/test/InMemory.FunctionalTests/RequestHeaderLimitsTests.cs index c5002a8c8c..5ab5b467e8 100644 --- a/src/Servers/Kestrel/test/InMemory.FunctionalTests/RequestHeaderLimitsTests.cs +++ b/src/Servers/Kestrel/test/InMemory.FunctionalTests/RequestHeaderLimitsTests.cs @@ -23,7 +23,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.InMemory.FunctionalTests [InlineData(5, 0)] [InlineData(5, 1)] [InlineData(5, 1337)] - [QuarantinedTest] public async Task ServerAcceptsRequestWithHeaderTotalSizeWithinLimit(int headerCount, int extraLimit) { var headers = MakeHeaders(headerCount); diff --git a/src/Servers/Kestrel/test/InMemory.FunctionalTests/RequestTests.cs b/src/Servers/Kestrel/test/InMemory.FunctionalTests/RequestTests.cs index 3ada9a09a6..0d1c028fe5 100644 --- a/src/Servers/Kestrel/test/InMemory.FunctionalTests/RequestTests.cs +++ b/src/Servers/Kestrel/test/InMemory.FunctionalTests/RequestTests.cs @@ -559,7 +559,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.InMemory.FunctionalTests } [Fact] - [QuarantinedTest] public async Task TraceIdentifierIsUnique() { const int identifierLength = 22; diff --git a/src/Shared/ClosedGenericMatcher/ClosedGenericMatcher.cs b/src/Shared/ClosedGenericMatcher/ClosedGenericMatcher.cs index f234c2edbc..fc41de2069 100644 --- a/src/Shared/ClosedGenericMatcher/ClosedGenericMatcher.cs +++ b/src/Shared/ClosedGenericMatcher/ClosedGenericMatcher.cs @@ -1,8 +1,9 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +#nullable enable + using System; -using System.Linq; using System.Reflection; namespace Microsoft.Extensions.Internal @@ -28,7 +29,7 @@ namespace Microsoft.Extensions.Internal /// typeof(KeyValuePair{,}), and is /// typeof(KeyValuePair{string, object}). /// - public static Type ExtractGenericInterface(Type queryType, Type interfaceType) + public static Type? ExtractGenericInterface(Type queryType, Type interfaceType) { if (queryType == null) { @@ -62,9 +63,9 @@ namespace Microsoft.Extensions.Internal candidate.GetGenericTypeDefinition() == interfaceType; } - private static Type GetGenericInstantiation(Type queryType, Type interfaceType) + private static Type? GetGenericInstantiation(Type queryType, Type interfaceType) { - Type bestMatch = null; + Type? bestMatch = null; var interfaces = queryType.GetInterfaces(); foreach (var @interface in interfaces) { @@ -103,4 +104,4 @@ namespace Microsoft.Extensions.Internal } } } -} \ No newline at end of file +} diff --git a/src/Shared/runtime/Http2/Hpack/DynamicTable.cs b/src/Shared/runtime/Http2/Hpack/DynamicTable.cs index 5a8fdf170f..9e93dca87c 100644 --- a/src/Shared/runtime/Http2/Hpack/DynamicTable.cs +++ b/src/Shared/runtime/Http2/Hpack/DynamicTable.cs @@ -25,7 +25,7 @@ namespace System.Net.Http.HPack public int MaxSize => _maxSize; - public HeaderField this[int index] + public ref readonly HeaderField this[int index] { get { @@ -42,7 +42,7 @@ namespace System.Net.Http.HPack index += _buffer.Length; } - return _buffer[index]; + return ref _buffer[index]; } } diff --git a/src/Shared/runtime/Http2/Hpack/H2StaticTable.cs b/src/Shared/runtime/Http2/Hpack/H2StaticTable.cs index 7f3b775582..c0f203fef4 100644 --- a/src/Shared/runtime/Http2/Hpack/H2StaticTable.cs +++ b/src/Shared/runtime/Http2/Hpack/H2StaticTable.cs @@ -9,23 +9,22 @@ namespace System.Net.Http.HPack { internal static class H2StaticTable { - // Index of status code into s_staticDecoderTable - private static readonly Dictionary s_statusIndex = new Dictionary - { - [200] = 8, - [204] = 9, - [206] = 10, - [304] = 11, - [400] = 12, - [404] = 13, - [500] = 14, - }; - public static int Count => s_staticDecoderTable.Length; - public static HeaderField Get(int index) => s_staticDecoderTable[index]; + public static ref readonly HeaderField Get(int index) => ref s_staticDecoderTable[index]; - public static IReadOnlyDictionary StatusIndex => s_statusIndex; + public static int GetStatusIndex(int status) => + status switch + { + 200 => 8, + 204 => 9, + 206 => 10, + 304 => 11, + 400 => 12, + 404 => 13, + 500 => 14, + _ => throw new ArgumentOutOfRangeException() + }; private static readonly HeaderField[] s_staticDecoderTable = new HeaderField[] { diff --git a/src/Shared/runtime/Http2/Hpack/HPackDecoder.cs b/src/Shared/runtime/Http2/Hpack/HPackDecoder.cs index 3fe3c86243..b07dc47d9a 100644 --- a/src/Shared/runtime/Http2/Hpack/HPackDecoder.cs +++ b/src/Shared/runtime/Http2/Hpack/HPackDecoder.cs @@ -5,6 +5,7 @@ #nullable enable using System.Buffers; using System.Diagnostics; +using System.Numerics; #if KESTREL using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http; #endif @@ -37,7 +38,6 @@ namespace System.Net.Http.HPack // | 1 | Index (7+) | // +---+---------------------------+ private const byte IndexedHeaderFieldMask = 0x80; - private const byte IndexedHeaderFieldRepresentation = 0x80; // http://httpwg.org/specs/rfc7541.html#rfc.section.6.2.1 // 0 1 2 3 4 5 6 7 @@ -45,7 +45,6 @@ namespace System.Net.Http.HPack // | 0 | 1 | Index (6+) | // +---+---+-----------------------+ private const byte LiteralHeaderFieldWithIncrementalIndexingMask = 0xc0; - private const byte LiteralHeaderFieldWithIncrementalIndexingRepresentation = 0x40; // http://httpwg.org/specs/rfc7541.html#rfc.section.6.2.2 // 0 1 2 3 4 5 6 7 @@ -53,7 +52,6 @@ namespace System.Net.Http.HPack // | 0 | 0 | 0 | 0 | Index (4+) | // +---+---+-----------------------+ private const byte LiteralHeaderFieldWithoutIndexingMask = 0xf0; - private const byte LiteralHeaderFieldWithoutIndexingRepresentation = 0x00; // http://httpwg.org/specs/rfc7541.html#rfc.section.6.2.3 // 0 1 2 3 4 5 6 7 @@ -61,7 +59,6 @@ namespace System.Net.Http.HPack // | 0 | 0 | 0 | 1 | Index (4+) | // +---+---+-----------------------+ private const byte LiteralHeaderFieldNeverIndexedMask = 0xf0; - private const byte LiteralHeaderFieldNeverIndexedRepresentation = 0x10; // http://httpwg.org/specs/rfc7541.html#rfc.section.6.3 // 0 1 2 3 4 5 6 7 @@ -69,7 +66,6 @@ namespace System.Net.Http.HPack // | 0 | 0 | 1 | Max size (5+) | // +---+---------------------------+ private const byte DynamicTableSizeUpdateMask = 0xe0; - private const byte DynamicTableSizeUpdateRepresentation = 0x20; // http://httpwg.org/specs/rfc7541.html#rfc.section.5.2 // 0 1 2 3 4 5 6 7 @@ -92,6 +88,8 @@ namespace System.Net.Http.HPack private byte[] _stringOctets; private byte[] _headerNameOctets; private byte[] _headerValueOctets; + private (int start, int length)? _headerNameRange; + private (int start, int length)? _headerValueRange; private State _state = State.Ready; private byte[]? _headerName; @@ -124,107 +122,247 @@ namespace System.Net.Http.HPack { foreach (ReadOnlyMemory segment in data) { - DecodeInternal(segment.Span, endHeaders, handler); + DecodeInternal(segment.Span, handler); } CheckIncompleteHeaderBlock(endHeaders); } - public void Decode(ReadOnlySpan data, bool endHeaders, IHttpHeadersHandler? handler) + public void Decode(ReadOnlySpan data, bool endHeaders, IHttpHeadersHandler handler) { - DecodeInternal(data, endHeaders, handler); + DecodeInternal(data, handler); CheckIncompleteHeaderBlock(endHeaders); } - private void DecodeInternal(ReadOnlySpan data, bool endHeaders, IHttpHeadersHandler? handler) + private void DecodeInternal(ReadOnlySpan data, IHttpHeadersHandler handler) { - int intResult; + int currentIndex = 0; - for (int i = 0; i < data.Length; i++) + do { - byte b = data[i]; switch (_state) { case State.Ready: - // TODO: Instead of masking and comparing each prefix value, - // consider doing a 16-way switch on the first four bits (which is the max prefix size). - // Look at this once we have more concrete perf data. - if ((b & IndexedHeaderFieldMask) == IndexedHeaderFieldRepresentation) + Parse(data, ref currentIndex, handler); + break; + case State.HeaderFieldIndex: + ParseHeaderFieldIndex(data, ref currentIndex, handler); + break; + case State.HeaderNameIndex: + ParseHeaderNameIndex(data, ref currentIndex, handler); + break; + case State.HeaderNameLength: + ParseHeaderNameLength(data, ref currentIndex, handler); + break; + case State.HeaderNameLengthContinue: + ParseHeaderNameLengthContinue(data, ref currentIndex, handler); + break; + case State.HeaderName: + ParseHeaderName(data, ref currentIndex, handler); + break; + case State.HeaderValueLength: + ParseHeaderValueLength(data, ref currentIndex, handler); + break; + case State.HeaderValueLengthContinue: + ParseHeaderValueLengthContinue(data, ref currentIndex, handler); + break; + case State.HeaderValue: + ParseHeaderValue(data, ref currentIndex, handler); + break; + case State.DynamicTableSizeUpdate: + ParseDynamicTableSizeUpdate(data, ref currentIndex); + break; + default: + // Can't happen + Debug.Fail("HPACK decoder reach an invalid state"); + throw new NotImplementedException(_state.ToString()); + } + } + // Parse methods each check the length. This check is to see whether there is still data available + // and to continue parsing. + while (currentIndex < data.Length); + + // If a header range was set, but the value was not in the data, then copy the range + // to the name buffer. Must copy because because the data will be replaced and the range + // will no longer be valid. + if (_headerNameRange != null) + { + EnsureStringCapacity(ref _headerNameOctets); + _headerName = _headerNameOctets; + + ReadOnlySpan headerBytes = data.Slice(_headerNameRange.GetValueOrDefault().start, _headerNameRange.GetValueOrDefault().length); + headerBytes.CopyTo(_headerName); + _headerNameLength = headerBytes.Length; + _headerNameRange = null; + } + } + + private void ParseDynamicTableSizeUpdate(ReadOnlySpan data, ref int currentIndex) + { + if (TryDecodeInteger(data, ref currentIndex, out int intResult)) + { + SetDynamicHeaderTableSize(intResult); + _state = State.Ready; + } + } + + private void ParseHeaderValueLength(ReadOnlySpan data, ref int currentIndex, IHttpHeadersHandler handler) + { + if (currentIndex < data.Length) + { + byte b = data[currentIndex++]; + + _huffman = IsHuffmanEncoded(b); + + if (_integerDecoder.BeginTryDecode((byte)(b & ~HuffmanMask), StringLengthPrefix, out int intResult)) + { + OnStringLength(intResult, nextState: State.HeaderValue); + + if (intResult == 0) + { + OnString(nextState: State.Ready); + ProcessHeaderValue(data, handler); + } + else + { + ParseHeaderValue(data, ref currentIndex, handler); + } + } + else + { + _state = State.HeaderValueLengthContinue; + ParseHeaderValueLengthContinue(data, ref currentIndex, handler); + } + } + } + + private void ParseHeaderNameLengthContinue(ReadOnlySpan data, ref int currentIndex, IHttpHeadersHandler handler) + { + if (TryDecodeInteger(data, ref currentIndex, out int intResult)) + { + // IntegerDecoder disallows overlong encodings, where an integer is encoded with more bytes than is strictly required. + // 0 should always be represented by a single byte, so we shouldn't need to check for it in the continuation case. + Debug.Assert(intResult != 0, "A header name length of 0 should never be encoded with a continuation byte."); + + OnStringLength(intResult, nextState: State.HeaderName); + ParseHeaderName(data, ref currentIndex, handler); + } + } + + private void ParseHeaderValueLengthContinue(ReadOnlySpan data, ref int currentIndex, IHttpHeadersHandler handler) + { + if (TryDecodeInteger(data, ref currentIndex, out int intResult)) + { + // 0 should always be represented by a single byte, so we shouldn't need to check for it in the continuation case. + Debug.Assert(intResult != 0, "A header value length of 0 should never be encoded with a continuation byte."); + + OnStringLength(intResult, nextState: State.HeaderValue); + ParseHeaderValue(data, ref currentIndex, handler); + } + } + + private void ParseHeaderFieldIndex(ReadOnlySpan data, ref int currentIndex, IHttpHeadersHandler handler) + { + if (TryDecodeInteger(data, ref currentIndex, out int intResult)) + { + OnIndexedHeaderField(intResult, handler); + } + } + + private void ParseHeaderNameIndex(ReadOnlySpan data, ref int currentIndex, IHttpHeadersHandler handler) + { + if (TryDecodeInteger(data, ref currentIndex, out int intResult)) + { + OnIndexedHeaderName(intResult); + ParseHeaderValueLength(data, ref currentIndex, handler); + } + } + + private void ParseHeaderNameLength(ReadOnlySpan data, ref int currentIndex, IHttpHeadersHandler handler) + { + if (currentIndex < data.Length) + { + byte b = data[currentIndex++]; + + _huffman = IsHuffmanEncoded(b); + + if (_integerDecoder.BeginTryDecode((byte)(b & ~HuffmanMask), StringLengthPrefix, out int intResult)) + { + if (intResult == 0) + { + throw new HPackDecodingException(SR.Format(SR.net_http_invalid_header_name, "")); + } + + OnStringLength(intResult, nextState: State.HeaderName); + ParseHeaderName(data, ref currentIndex, handler); + } + else + { + _state = State.HeaderNameLengthContinue; + ParseHeaderNameLengthContinue(data, ref currentIndex, handler); + } + } + } + + private void Parse(ReadOnlySpan data, ref int currentIndex, IHttpHeadersHandler handler) + { + if (currentIndex < data.Length) + { + Debug.Assert(_state == State.Ready, "Should be ready to parse a new header."); + + byte b = data[currentIndex++]; + + switch (BitOperations.LeadingZeroCount(b) - 24) // byte 'b' is extended to uint, so will have 24 extra 0s. + { + case 0: // Indexed Header Field { _headersObserved = true; int val = b & ~IndexedHeaderFieldMask; - if (_integerDecoder.BeginTryDecode((byte)val, IndexedHeaderFieldPrefix, out intResult)) + if (_integerDecoder.BeginTryDecode((byte)val, IndexedHeaderFieldPrefix, out int intResult)) { OnIndexedHeaderField(intResult, handler); } else { _state = State.HeaderFieldIndex; + ParseHeaderFieldIndex(data, ref currentIndex, handler); } + break; } - else if ((b & LiteralHeaderFieldWithIncrementalIndexingMask) == LiteralHeaderFieldWithIncrementalIndexingRepresentation) - { - _headersObserved = true; - - _index = true; - int val = b & ~LiteralHeaderFieldWithIncrementalIndexingMask; - - if (val == 0) - { - _state = State.HeaderNameLength; - } - else if (_integerDecoder.BeginTryDecode((byte)val, LiteralHeaderFieldWithIncrementalIndexingPrefix, out intResult)) - { - OnIndexedHeaderName(intResult); - } - else - { - _state = State.HeaderNameIndex; - } - } - else if ((b & LiteralHeaderFieldWithoutIndexingMask) == LiteralHeaderFieldWithoutIndexingRepresentation) - { - _headersObserved = true; - - _index = false; - int val = b & ~LiteralHeaderFieldWithoutIndexingMask; - - if (val == 0) - { - _state = State.HeaderNameLength; - } - else if (_integerDecoder.BeginTryDecode((byte)val, LiteralHeaderFieldWithoutIndexingPrefix, out intResult)) - { - OnIndexedHeaderName(intResult); - } - else - { - _state = State.HeaderNameIndex; - } - } - else if ((b & LiteralHeaderFieldNeverIndexedMask) == LiteralHeaderFieldNeverIndexedRepresentation) - { - _headersObserved = true; - - _index = false; - int val = b & ~LiteralHeaderFieldNeverIndexedMask; - - if (val == 0) - { - _state = State.HeaderNameLength; - } - else if (_integerDecoder.BeginTryDecode((byte)val, LiteralHeaderFieldNeverIndexedPrefix, out intResult)) - { - OnIndexedHeaderName(intResult); - } - else - { - _state = State.HeaderNameIndex; - } - } - else if ((b & DynamicTableSizeUpdateMask) == DynamicTableSizeUpdateRepresentation) + case 1: // Literal Header Field with Incremental Indexing + ParseLiteralHeaderField( + data, + ref currentIndex, + b, + LiteralHeaderFieldWithIncrementalIndexingMask, + LiteralHeaderFieldWithIncrementalIndexingPrefix, + index: true, + handler); + break; + case 4: + default: // Literal Header Field without Indexing + ParseLiteralHeaderField( + data, + ref currentIndex, + b, + LiteralHeaderFieldWithoutIndexingMask, + LiteralHeaderFieldWithoutIndexingPrefix, + index: false, + handler); + break; + case 3: // Literal Header Field Never Indexed + ParseLiteralHeaderField( + data, + ref currentIndex, + b, + LiteralHeaderFieldNeverIndexedMask, + LiteralHeaderFieldNeverIndexedPrefix, + index: false, + handler); + break; + case 2: // Dynamic Table Size Update { // https://tools.ietf.org/html/rfc7541#section-4.2 // This dynamic table size @@ -235,125 +373,107 @@ namespace System.Net.Http.HPack throw new HPackDecodingException(SR.net_http_hpack_late_dynamic_table_size_update); } - if (_integerDecoder.BeginTryDecode((byte)(b & ~DynamicTableSizeUpdateMask), DynamicTableSizeUpdatePrefix, out intResult)) + if (_integerDecoder.BeginTryDecode((byte)(b & ~DynamicTableSizeUpdateMask), DynamicTableSizeUpdatePrefix, out int intResult)) { SetDynamicHeaderTableSize(intResult); } else { _state = State.DynamicTableSizeUpdate; + ParseDynamicTableSizeUpdate(data, ref currentIndex); } + break; } - else - { - // Can't happen - Debug.Fail("Unreachable code"); - throw new InvalidOperationException("Unreachable code."); - } + } + } + } - break; - case State.HeaderFieldIndex: - if (_integerDecoder.TryDecode(b, out intResult)) - { - OnIndexedHeaderField(intResult, handler); - } + private void ParseLiteralHeaderField(ReadOnlySpan data, ref int currentIndex, byte b, byte mask, byte indexPrefix, bool index, IHttpHeadersHandler handler) + { + _headersObserved = true; - break; - case State.HeaderNameIndex: - if (_integerDecoder.TryDecode(b, out intResult)) - { - OnIndexedHeaderName(intResult); - } + _index = index; + int val = b & ~mask; - break; - case State.HeaderNameLength: - _huffman = (b & HuffmanMask) != 0; + if (val == 0) + { + _state = State.HeaderNameLength; + ParseHeaderNameLength(data, ref currentIndex, handler); + } + else + { + if (_integerDecoder.BeginTryDecode((byte)val, indexPrefix, out int intResult)) + { + OnIndexedHeaderName(intResult); + ParseHeaderValueLength(data, ref currentIndex, handler); + } + else + { + _state = State.HeaderNameIndex; + ParseHeaderNameIndex(data, ref currentIndex, handler); + } + } + } - if (_integerDecoder.BeginTryDecode((byte)(b & ~HuffmanMask), StringLengthPrefix, out intResult)) - { - if (intResult == 0) - { - throw new HPackDecodingException(SR.Format(SR.net_http_invalid_header_name, "")); - } + private void ParseHeaderName(ReadOnlySpan data, ref int currentIndex, IHttpHeadersHandler handler) + { + // Read remaining chars, up to the length of the current data + int count = Math.Min(_stringLength - _stringIndex, data.Length - currentIndex); - OnStringLength(intResult, nextState: State.HeaderName); - } - else - { - _state = State.HeaderNameLengthContinue; - } + // Check whether the whole string is available in the data and no decompression required. + // If string is good then mark its range. + // NOTE: it may need to be copied to buffer later the if value is not current data. + if (count == _stringLength && !_huffman) + { + // Fast path. Store the range rather than copying. + _headerNameRange = (start: currentIndex, count); + currentIndex += count; - break; - case State.HeaderNameLengthContinue: - if (_integerDecoder.TryDecode(b, out intResult)) - { - // IntegerDecoder disallows overlong encodings, where an integer is encoded with more bytes than is strictly required. - // 0 should always be represented by a single byte, so we shouldn't need to check for it in the continuation case. - Debug.Assert(intResult != 0, "A header name length of 0 should never be encoded with a continuation byte."); + _state = State.HeaderValueLength; + } + else + { + // Copy string to temporary buffer. + // _stringOctets was already + data.Slice(currentIndex, count).CopyTo(_stringOctets.AsSpan(_stringIndex)); + _stringIndex += count; + currentIndex += count; - OnStringLength(intResult, nextState: State.HeaderName); - } + if (_stringIndex == _stringLength) + { + OnString(nextState: State.HeaderValueLength); + ParseHeaderValueLength(data, ref currentIndex, handler); + } + } + } - break; - case State.HeaderName: - _stringOctets[_stringIndex++] = b; + private void ParseHeaderValue(ReadOnlySpan data, ref int currentIndex, IHttpHeadersHandler handler) + { + // Read remaining chars, up to the length of the current data + int count = Math.Min(_stringLength - _stringIndex, data.Length - currentIndex); - if (_stringIndex == _stringLength) - { - OnString(nextState: State.HeaderValueLength); - } + // Check whether the whole string is available in the data and no decompressed required. + // If string is good then mark its range. + if (count == _stringLength && !_huffman) + { + // Fast path. Store the range rather than copying. + _headerValueRange = (start: currentIndex, count); + currentIndex += count; - break; - case State.HeaderValueLength: - _huffman = (b & HuffmanMask) != 0; + _state = State.Ready; + ProcessHeaderValue(data, handler); + } + else + { + // Copy string to temporary buffer. + data.Slice(currentIndex, count).CopyTo(_stringOctets.AsSpan(_stringIndex)); + _stringIndex += count; + currentIndex += count; - if (_integerDecoder.BeginTryDecode((byte)(b & ~HuffmanMask), StringLengthPrefix, out intResult)) - { - OnStringLength(intResult, nextState: State.HeaderValue); - - if (intResult == 0) - { - ProcessHeaderValue(handler); - } - } - else - { - _state = State.HeaderValueLengthContinue; - } - - break; - case State.HeaderValueLengthContinue: - if (_integerDecoder.TryDecode(b, out intResult)) - { - // IntegerDecoder disallows overlong encodings where an integer is encoded with more bytes than is strictly required. - // 0 should always be represented by a single byte, so we shouldn't need to check for it in the continuation case. - Debug.Assert(intResult != 0, "A header value length of 0 should never be encoded with a continuation byte."); - - OnStringLength(intResult, nextState: State.HeaderValue); - } - - break; - case State.HeaderValue: - _stringOctets[_stringIndex++] = b; - - if (_stringIndex == _stringLength) - { - ProcessHeaderValue(handler); - } - - break; - case State.DynamicTableSizeUpdate: - if (_integerDecoder.TryDecode(b, out intResult)) - { - SetDynamicHeaderTableSize(intResult); - _state = State.Ready; - } - - break; - default: - // Can't happen - Debug.Fail("HPACK decoder reach an invalid state"); - throw new NotImplementedException(_state.ToString()); + if (_stringIndex == _stringLength) + { + OnString(nextState: State.Ready); + ProcessHeaderValue(data, handler); } } } @@ -371,14 +491,20 @@ namespace System.Net.Http.HPack } } - private void ProcessHeaderValue(IHttpHeadersHandler? handler) + private void ProcessHeaderValue(ReadOnlySpan data, IHttpHeadersHandler handler) { - OnString(nextState: State.Ready); + ReadOnlySpan headerNameSpan = _headerNameRange == null + ? new Span(_headerName, 0, _headerNameLength) + : data.Slice(_headerNameRange.GetValueOrDefault().start, _headerNameRange.GetValueOrDefault().length); - var headerNameSpan = new Span(_headerName, 0, _headerNameLength); - var headerValueSpan = new Span(_headerValueOctets, 0, _headerValueLength); + ReadOnlySpan headerValueSpan = _headerValueRange == null + ? new Span(_headerValueOctets, 0, _headerValueLength) + : data.Slice(_headerValueRange.GetValueOrDefault().start, _headerValueRange.GetValueOrDefault().length); - handler?.OnHeader(headerNameSpan, headerValueSpan); + handler.OnHeader(headerNameSpan, headerValueSpan); + + _headerNameRange = null; + _headerValueRange = null; if (_index) { @@ -395,18 +521,17 @@ namespace System.Net.Http.HPack } } - private void OnIndexedHeaderField(int index, IHttpHeadersHandler? handler) + private void OnIndexedHeaderField(int index, IHttpHeadersHandler handler) { - HeaderField header = GetHeader(index); - handler?.OnHeader(header.Name, header.Value); + ref readonly HeaderField header = ref GetHeader(index); + handler.OnHeader(header.Name, header.Value); _state = State.Ready; } private void OnIndexedHeaderName(int index) { - HeaderField header = GetHeader(index); - _headerName = header.Name; - _headerNameLength = header.Name.Length; + _headerName = GetHeader(index).Name; + _headerNameLength = _headerName.Length; _state = State.HeaderValueLength; } @@ -437,11 +562,7 @@ namespace System.Net.Http.HPack } else { - if (dst.Length < _stringLength) - { - dst = new byte[Math.Max(_stringLength, dst.Length * 2)]; - } - + EnsureStringCapacity(ref dst); Buffer.BlockCopy(_stringOctets, 0, dst, 0, _stringLength); return _stringLength; } @@ -467,13 +588,41 @@ namespace System.Net.Http.HPack _state = nextState; } - private HeaderField GetHeader(int index) + private void EnsureStringCapacity(ref byte[] dst) + { + if (dst.Length < _stringLength) + { + dst = new byte[Math.Max(_stringLength, dst.Length * 2)]; + } + } + + private bool TryDecodeInteger(ReadOnlySpan data, ref int currentIndex, out int result) + { + for (; currentIndex < data.Length; currentIndex++) + { + if (_integerDecoder.TryDecode(data[currentIndex], out result)) + { + currentIndex++; + return true; + } + } + + result = default; + return false; + } + + private static bool IsHuffmanEncoded(byte b) + { + return (b & HuffmanMask) != 0; + } + + private ref readonly HeaderField GetHeader(int index) { try { - return index <= H2StaticTable.Count - ? H2StaticTable.Get(index - 1) - : _dynamicTable[index - H2StaticTable.Count - 1]; + return ref index <= H2StaticTable.Count + ? ref H2StaticTable.Get(index - 1) + : ref _dynamicTable[index - H2StaticTable.Count - 1]; } catch (IndexOutOfRangeException) { diff --git a/src/Shared/runtime/Http2/Hpack/HPackEncoder.cs b/src/Shared/runtime/Http2/Hpack/HPackEncoder.cs index 97cdea1c50..4a8511e682 100644 --- a/src/Shared/runtime/Http2/Hpack/HPackEncoder.cs +++ b/src/Shared/runtime/Http2/Hpack/HPackEncoder.cs @@ -54,7 +54,7 @@ namespace System.Net.Http.HPack case 404: case 500: // Status codes which exist in the HTTP/2 StaticTable. - return EncodeIndexedHeaderField(H2StaticTable.StatusIndex[statusCode], destination, out bytesWritten); + return EncodeIndexedHeaderField(H2StaticTable.GetStatusIndex(statusCode), destination, out bytesWritten); default: // If the status code doesn't have a static index then we need to include the full value. // Write a status index and then the number bytes as a string literal. diff --git a/src/Shared/test/Shared.Tests/runtime/Http2/HPackDecoderTest.cs b/src/Shared/test/Shared.Tests/runtime/Http2/HPackDecoderTest.cs index 2afdb29901..d5d26ccb37 100644 --- a/src/Shared/test/Shared.Tests/runtime/Http2/HPackDecoderTest.cs +++ b/src/Shared/test/Shared.Tests/runtime/Http2/HPackDecoderTest.cs @@ -14,7 +14,7 @@ using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http; namespace System.Net.Http.Unit.Tests.HPack { - public class HPackDecoderTests : IHttpHeadersHandler + public class HPackDecoderTests { private const int DynamicTableInitialMaxSize = 4096; private const int MaxHeaderFieldSize = 8192; @@ -89,42 +89,26 @@ namespace System.Net.Http.Unit.Tests.HPack private readonly DynamicTable _dynamicTable; private readonly HPackDecoder _decoder; - - private readonly Dictionary _decodedHeaders = new Dictionary(); + private readonly TestHttpHeadersHandler _handler = new TestHttpHeadersHandler(); public HPackDecoderTests() { - _dynamicTable = new DynamicTable(DynamicTableInitialMaxSize); - _decoder = new HPackDecoder(DynamicTableInitialMaxSize, MaxHeaderFieldSize, _dynamicTable); + (_dynamicTable, _decoder) = CreateDecoderAndTable(); } - void IHttpHeadersHandler.OnHeader(ReadOnlySpan name, ReadOnlySpan value) + private static (DynamicTable, HPackDecoder) CreateDecoderAndTable() { - string headerName = Encoding.ASCII.GetString(name); - string headerValue = Encoding.ASCII.GetString(value); + var dynamicTable = new DynamicTable(DynamicTableInitialMaxSize); + var decoder = new HPackDecoder(DynamicTableInitialMaxSize, MaxHeaderFieldSize, dynamicTable); - _decodedHeaders[headerName] = headerValue; + return (dynamicTable, decoder); } - void IHttpHeadersHandler.OnStaticIndexedHeader(int index) - { - // Not yet implemented for HPACK. - throw new NotImplementedException(); - } - - void IHttpHeadersHandler.OnStaticIndexedHeader(int index, ReadOnlySpan value) - { - // Not yet implemented for HPACK. - throw new NotImplementedException(); - } - - void IHttpHeadersHandler.OnHeadersComplete(bool endStream) { } - [Fact] public void DecodesIndexedHeaderField_StaticTable() { - _decoder.Decode(_indexedHeaderStatic, endHeaders: true, handler: this); - Assert.Equal("GET", _decodedHeaders[":method"]); + _decoder.Decode(_indexedHeaderStatic, endHeaders: true, handler: _handler); + Assert.Equal("GET", _handler.DecodedHeaders[":method"]); } [Fact] @@ -134,17 +118,17 @@ namespace System.Net.Http.Unit.Tests.HPack _dynamicTable.Insert(_headerNameBytes, _headerValueBytes); // Index it - _decoder.Decode(_indexedHeaderDynamic, endHeaders: true, handler: this); - Assert.Equal(_headerValueString, _decodedHeaders[_headerNameString]); + _decoder.Decode(_indexedHeaderDynamic, endHeaders: true, handler: _handler); + Assert.Equal(_headerValueString, _handler.DecodedHeaders[_headerNameString]); } [Fact] public void DecodesIndexedHeaderField_OutOfRange_Error() { HPackDecodingException exception = Assert.Throws(() => - _decoder.Decode(_indexedHeaderDynamic, endHeaders: true, handler: this)); + _decoder.Decode(_indexedHeaderDynamic, endHeaders: true, handler: _handler)); Assert.Equal(SR.Format(SR.net_http_hpack_invalid_index, 62), exception.Message); - Assert.Empty(_decodedHeaders); + Assert.Empty(_handler.DecodedHeaders); } [Fact] @@ -218,9 +202,9 @@ namespace System.Net.Http.Unit.Tests.HPack // 11 1110 (Indexed Name - Index 62 encoded with 6-bit prefix - see http://httpwg.org/specs/rfc7541.html#integer.representation) // Index 62 is the first entry in the dynamic table. If there's nothing there, the decoder should throw. - HPackDecodingException exception = Assert.Throws(() => _decoder.Decode(new byte[] { 0x7e }, endHeaders: true, handler: this)); + HPackDecodingException exception = Assert.Throws(() => _decoder.Decode(new byte[] { 0x7e }, endHeaders: true, handler: _handler)); Assert.Equal(SR.Format(SR.net_http_hpack_invalid_index, 62), exception.Message); - Assert.Empty(_decodedHeaders); + Assert.Empty(_handler.DecodedHeaders); } [Fact] @@ -294,9 +278,9 @@ namespace System.Net.Http.Unit.Tests.HPack // 1111 0010 1111 (Indexed Name - Index 62 encoded with 4-bit prefix - see http://httpwg.org/specs/rfc7541.html#integer.representation) // Index 62 is the first entry in the dynamic table. If there's nothing there, the decoder should throw. - HPackDecodingException exception = Assert.Throws(() => _decoder.Decode(new byte[] { 0x0f, 0x2f }, endHeaders: true, handler: this)); + HPackDecodingException exception = Assert.Throws(() => _decoder.Decode(new byte[] { 0x0f, 0x2f }, endHeaders: true, handler: _handler)); Assert.Equal(SR.Format(SR.net_http_hpack_invalid_index, 62), exception.Message); - Assert.Empty(_decodedHeaders); + Assert.Empty(_handler.DecodedHeaders); } [Fact] @@ -310,6 +294,19 @@ namespace System.Net.Http.Unit.Tests.HPack TestDecodeWithoutIndexing(encoded, _headerNameString, _headerValueString); } + [Fact] + public void DecodesLiteralHeaderFieldNeverIndexed_NewName_Duplicated() + { + byte[] encoded = _literalHeaderFieldNeverIndexedNewName + .Concat(_headerName) + .Concat(_headerValue) + .ToArray(); + + encoded = encoded.Concat(encoded).ToArray(); + + TestDecodeWithoutIndexing(encoded, _headerNameString, _headerValueString); + } + [Fact] public void DecodesLiteralHeaderFieldNeverIndexed_NewName_HuffmanEncodedName() { @@ -376,9 +373,9 @@ namespace System.Net.Http.Unit.Tests.HPack // 1111 0010 1111 (Indexed Name - Index 62 encoded with 4-bit prefix - see http://httpwg.org/specs/rfc7541.html#integer.representation) // Index 62 is the first entry in the dynamic table. If there's nothing there, the decoder should throw. - HPackDecodingException exception = Assert.Throws(() => _decoder.Decode(new byte[] { 0x1f, 0x2f }, endHeaders: true, handler: this)); + HPackDecodingException exception = Assert.Throws(() => _decoder.Decode(new byte[] { 0x1f, 0x2f }, endHeaders: true, handler: _handler)); Assert.Equal(SR.Format(SR.net_http_hpack_invalid_index, 62), exception.Message); - Assert.Empty(_decodedHeaders); + Assert.Empty(_handler.DecodedHeaders); } [Fact] @@ -389,10 +386,10 @@ namespace System.Net.Http.Unit.Tests.HPack Assert.Equal(DynamicTableInitialMaxSize, _dynamicTable.MaxSize); - _decoder.Decode(new byte[] { 0x3e }, endHeaders: true, handler: this); + _decoder.Decode(new byte[] { 0x3e }, endHeaders: true, handler: _handler); Assert.Equal(30, _dynamicTable.MaxSize); - Assert.Empty(_decodedHeaders); + Assert.Empty(_handler.DecodedHeaders); } [Fact] @@ -404,7 +401,7 @@ namespace System.Net.Http.Unit.Tests.HPack Assert.Equal(DynamicTableInitialMaxSize, _dynamicTable.MaxSize); byte[] data = _indexedHeaderStatic.Concat(new byte[] { 0x3e }).ToArray(); - HPackDecodingException exception = Assert.Throws(() => _decoder.Decode(data, endHeaders: true, handler: this)); + HPackDecodingException exception = Assert.Throws(() => _decoder.Decode(data, endHeaders: true, handler: _handler)); Assert.Equal(SR.net_http_hpack_late_dynamic_table_size_update, exception.Message); } @@ -413,13 +410,13 @@ namespace System.Net.Http.Unit.Tests.HPack { Assert.Equal(DynamicTableInitialMaxSize, _dynamicTable.MaxSize); - _decoder.Decode(_indexedHeaderStatic, endHeaders: false, handler: this); - Assert.Equal("GET", _decodedHeaders[":method"]); + _decoder.Decode(_indexedHeaderStatic, endHeaders: false, handler: _handler); + Assert.Equal("GET", _handler.DecodedHeaders[":method"]); // 001 (Dynamic Table Size Update) // 11110 (30 encoded with 5-bit prefix - see http://httpwg.org/specs/rfc7541.html#integer.representation) byte[] data = new byte[] { 0x3e }; - HPackDecodingException exception = Assert.Throws(() => _decoder.Decode(data, endHeaders: true, handler: this)); + HPackDecodingException exception = Assert.Throws(() => _decoder.Decode(data, endHeaders: true, handler: _handler)); Assert.Equal(SR.net_http_hpack_late_dynamic_table_size_update, exception.Message); } @@ -428,12 +425,12 @@ namespace System.Net.Http.Unit.Tests.HPack { Assert.Equal(DynamicTableInitialMaxSize, _dynamicTable.MaxSize); - _decoder.Decode(_indexedHeaderStatic, endHeaders: true, handler: this); - Assert.Equal("GET", _decodedHeaders[":method"]); + _decoder.Decode(_indexedHeaderStatic, endHeaders: true, handler: _handler); + Assert.Equal("GET", _handler.DecodedHeaders[":method"]); // 001 (Dynamic Table Size Update) // 11110 (30 encoded with 5-bit prefix - see http://httpwg.org/specs/rfc7541.html#integer.representation) - _decoder.Decode(new byte[] { 0x3e }, endHeaders: true, handler: this); + _decoder.Decode(new byte[] { 0x3e }, endHeaders: true, handler: _handler); Assert.Equal(30, _dynamicTable.MaxSize); } @@ -447,9 +444,9 @@ namespace System.Net.Http.Unit.Tests.HPack Assert.Equal(DynamicTableInitialMaxSize, _dynamicTable.MaxSize); HPackDecodingException exception = Assert.Throws(() => - _decoder.Decode(new byte[] { 0x3f, 0xe2, 0x1f }, endHeaders: true, handler: this)); + _decoder.Decode(new byte[] { 0x3f, 0xe2, 0x1f }, endHeaders: true, handler: _handler)); Assert.Equal(SR.Format(SR.net_http_hpack_large_table_size_update, 4097, DynamicTableInitialMaxSize), exception.Message); - Assert.Empty(_decodedHeaders); + Assert.Empty(_handler.DecodedHeaders); } [Fact] @@ -459,9 +456,9 @@ namespace System.Net.Http.Unit.Tests.HPack .Concat(new byte[] { 0xff, 0x82, 0x3f }) // 8193 encoded with 7-bit prefix .ToArray(); - HPackDecodingException exception = Assert.Throws(() => _decoder.Decode(encoded, endHeaders: true, handler: this)); + HPackDecodingException exception = Assert.Throws(() => _decoder.Decode(encoded, endHeaders: true, handler: _handler)); Assert.Equal(SR.Format(SR.net_http_headers_exceeded_length, MaxHeaderFieldSize), exception.Message); - Assert.Empty(_decodedHeaders); + Assert.Empty(_handler.DecodedHeaders); } [Fact] @@ -477,9 +474,57 @@ namespace System.Net.Http.Unit.Tests.HPack .Concat(Encoding.ASCII.GetBytes(string8193)) .ToArray(); - decoder.Decode(encoded, endHeaders: true, handler: this); + decoder.Decode(encoded, endHeaders: true, handler: _handler); - Assert.Equal(string8193, _decodedHeaders[string8193]); + Assert.Equal(string8193, _handler.DecodedHeaders[string8193]); + } + + [Fact] + public void DecodesStringLength_IndividualBytes() + { + HPackDecoder decoder = new HPackDecoder(DynamicTableInitialMaxSize, MaxHeaderFieldSize + 1); + string string8193 = new string('a', MaxHeaderFieldSize + 1); + + byte[] encoded = _literalHeaderFieldWithoutIndexingNewName + .Concat(new byte[] { 0x7f, 0x82, 0x3f }) // 8193 encoded with 7-bit prefix, no Huffman encoding + .Concat(Encoding.ASCII.GetBytes(string8193)) + .Concat(new byte[] { 0x7f, 0x82, 0x3f }) // 8193 encoded with 7-bit prefix, no Huffman encoding + .Concat(Encoding.ASCII.GetBytes(string8193)) + .ToArray(); + + for (int i = 0; i < encoded.Length; i++) + { + bool end = i + 1 == encoded.Length; + + decoder.Decode(new byte[] { encoded[i] }, endHeaders: end, handler: _handler); + } + + Assert.Equal(string8193, _handler.DecodedHeaders[string8193]); + } + + [Fact] + public void DecodesHeaderNameAndValue_SeparateSegments() + { + HPackDecoder decoder = new HPackDecoder(DynamicTableInitialMaxSize, MaxHeaderFieldSize + 1); + string string8193 = new string('a', MaxHeaderFieldSize + 1); + + byte[][] segments = new byte[][] + { + _literalHeaderFieldWithoutIndexingNewName, + new byte[] { 0x7f, 0x82, 0x3f }, // 8193 encoded with 7-bit prefix, no Huffman encoding + Encoding.ASCII.GetBytes(string8193), + new byte[] { 0x7f, 0x82, 0x3f }, // 8193 encoded with 7-bit prefix, no Huffman encoding + Encoding.ASCII.GetBytes(string8193) + }; + + for (int i = 0; i < segments.Length; i++) + { + bool end = i + 1 == segments.Length; + + decoder.Decode(segments[i], endHeaders: end, handler: _handler); + } + + Assert.Equal(string8193, _handler.DecodedHeaders[string8193]); } public static readonly TheoryData _incompleteHeaderBlockData = new TheoryData @@ -567,9 +612,9 @@ namespace System.Net.Http.Unit.Tests.HPack [MemberData(nameof(_incompleteHeaderBlockData))] public void DecodesIncompleteHeaderBlock_Error(byte[] encoded) { - HPackDecodingException exception = Assert.Throws(() => _decoder.Decode(encoded, endHeaders: true, handler: this)); + HPackDecodingException exception = Assert.Throws(() => _decoder.Decode(encoded, endHeaders: true, handler: _handler)); Assert.Equal(SR.net_http_hpack_incomplete_header_block, exception.Message); - Assert.Empty(_decodedHeaders); + Assert.Empty(_handler.DecodedHeaders); } public static readonly TheoryData _huffmanDecodingErrorData = new TheoryData @@ -601,43 +646,89 @@ namespace System.Net.Http.Unit.Tests.HPack [MemberData(nameof(_huffmanDecodingErrorData))] public void WrapsHuffmanDecodingExceptionInHPackDecodingException(byte[] encoded) { - HPackDecodingException exception = Assert.Throws(() => _decoder.Decode(encoded, endHeaders: true, handler: this)); + HPackDecodingException exception = Assert.Throws(() => _decoder.Decode(encoded, endHeaders: true, handler: _handler)); Assert.Equal(SR.net_http_hpack_huffman_decode_failed, exception.Message); Assert.IsType(exception.InnerException); - Assert.Empty(_decodedHeaders); + Assert.Empty(_handler.DecodedHeaders); } - private void TestDecodeWithIndexing(byte[] encoded, string expectedHeaderName, string expectedHeaderValue) + private static void TestDecodeWithIndexing(byte[] encoded, string expectedHeaderName, string expectedHeaderValue) { - TestDecode(encoded, expectedHeaderName, expectedHeaderValue, expectDynamicTableEntry: true); + TestDecode(encoded, expectedHeaderName, expectedHeaderValue, expectDynamicTableEntry: true, byteAtATime: false); + TestDecode(encoded, expectedHeaderName, expectedHeaderValue, expectDynamicTableEntry: true, byteAtATime: true); } - private void TestDecodeWithoutIndexing(byte[] encoded, string expectedHeaderName, string expectedHeaderValue) + private static void TestDecodeWithoutIndexing(byte[] encoded, string expectedHeaderName, string expectedHeaderValue) { - TestDecode(encoded, expectedHeaderName, expectedHeaderValue, expectDynamicTableEntry: false); + TestDecode(encoded, expectedHeaderName, expectedHeaderValue, expectDynamicTableEntry: false, byteAtATime: false); + TestDecode(encoded, expectedHeaderName, expectedHeaderValue, expectDynamicTableEntry: false, byteAtATime: true); } - private void TestDecode(byte[] encoded, string expectedHeaderName, string expectedHeaderValue, bool expectDynamicTableEntry) + private static void TestDecode(byte[] encoded, string expectedHeaderName, string expectedHeaderValue, bool expectDynamicTableEntry, bool byteAtATime) { - Assert.Equal(0, _dynamicTable.Count); - Assert.Equal(0, _dynamicTable.Size); + var (dynamicTable, decoder) = CreateDecoderAndTable(); + var handler = new TestHttpHeadersHandler(); - _decoder.Decode(encoded, endHeaders: true, handler: this); + Assert.Equal(0, dynamicTable.Count); + Assert.Equal(0, dynamicTable.Size); - Assert.Equal(expectedHeaderValue, _decodedHeaders[expectedHeaderName]); - - if (expectDynamicTableEntry) + if (!byteAtATime) { - Assert.Equal(1, _dynamicTable.Count); - Assert.Equal(expectedHeaderName, Encoding.ASCII.GetString(_dynamicTable[0].Name)); - Assert.Equal(expectedHeaderValue, Encoding.ASCII.GetString(_dynamicTable[0].Value)); - Assert.Equal(expectedHeaderName.Length + expectedHeaderValue.Length + 32, _dynamicTable.Size); + decoder.Decode(encoded, endHeaders: true, handler: handler); } else { - Assert.Equal(0, _dynamicTable.Count); - Assert.Equal(0, _dynamicTable.Size); + // Parse data in 1 byte chunks, separated by empty chunks + for (int i = 0; i < encoded.Length; i++) + { + bool end = i + 1 == encoded.Length; + + decoder.Decode(Array.Empty(), endHeaders: false, handler: handler); + decoder.Decode(new byte[] { encoded[i] }, endHeaders: end, handler: handler); + } + } + + Assert.Equal(expectedHeaderValue, handler.DecodedHeaders[expectedHeaderName]); + + if (expectDynamicTableEntry) + { + Assert.Equal(1, dynamicTable.Count); + Assert.Equal(expectedHeaderName, Encoding.ASCII.GetString(dynamicTable[0].Name)); + Assert.Equal(expectedHeaderValue, Encoding.ASCII.GetString(dynamicTable[0].Value)); + Assert.Equal(expectedHeaderName.Length + expectedHeaderValue.Length + 32, dynamicTable.Size); + } + else + { + Assert.Equal(0, dynamicTable.Count); + Assert.Equal(0, dynamicTable.Size); } } } + + public class TestHttpHeadersHandler : IHttpHeadersHandler + { + public Dictionary DecodedHeaders { get; } = new Dictionary(); + + void IHttpHeadersHandler.OnHeader(ReadOnlySpan name, ReadOnlySpan value) + { + string headerName = Encoding.ASCII.GetString(name); + string headerValue = Encoding.ASCII.GetString(value); + + DecodedHeaders[headerName] = headerValue; + } + + void IHttpHeadersHandler.OnStaticIndexedHeader(int index) + { + // Not yet implemented for HPACK. + throw new NotImplementedException(); + } + + void IHttpHeadersHandler.OnStaticIndexedHeader(int index, ReadOnlySpan value) + { + // Not yet implemented for HPACK. + throw new NotImplementedException(); + } + + void IHttpHeadersHandler.OnHeadersComplete(bool endStream) { } + } } diff --git a/src/SignalR/clients/csharp/Client/test/FunctionalTests/HubConnectionTests.cs b/src/SignalR/clients/csharp/Client/test/FunctionalTests/HubConnectionTests.cs index 39f99f7ff0..1e1de9abe4 100644 --- a/src/SignalR/clients/csharp/Client/test/FunctionalTests/HubConnectionTests.cs +++ b/src/SignalR/clients/csharp/Client/test/FunctionalTests/HubConnectionTests.cs @@ -86,7 +86,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests public async Task CheckFixedMessage(string protocolName, HttpTransportType transportType, string path) { var protocol = HubProtocols[protocolName]; - using (var server = await StartServer()) + await using (var server = await StartServer()) { var connectionBuilder = new HubConnectionBuilder() .WithLoggerFactory(LoggerFactory) @@ -125,7 +125,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests } var protocol = HubProtocols["json"]; - using (var server = await StartServer(ExpectedError)) + await using (var server = await StartServer(ExpectedError)) { var connectionBuilder = new HubConnectionBuilder() .WithLoggerFactory(LoggerFactory) @@ -155,7 +155,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests public async Task ClientCanConnectToServerWithLowerMinimumProtocol() { var protocol = HubProtocols["json"]; - using (var server = await StartServer()) + await using (var server = await StartServer()) { var connectionBuilder = new HubConnectionBuilder() .WithLoggerFactory(LoggerFactory) @@ -185,7 +185,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests public async Task CanSendAndReceiveMessage(string protocolName, HttpTransportType transportType, string path) { var protocol = HubProtocols[protocolName]; - using (var server = await StartServer()) + await using (var server = await StartServer()) { const string originalMessage = "SignalR"; var connection = CreateHubConnection(server.Url, path, transportType, protocol, LoggerFactory); @@ -214,7 +214,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests public async Task CanSendNull(string protocolName) { var protocol = HubProtocols[protocolName]; - using (var server = await StartServer()) + await using (var server = await StartServer()) { var connection = CreateHubConnection(server.Url, "/default", HttpTransportType.LongPolling, protocol, LoggerFactory); try @@ -243,7 +243,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests public async Task CanStopAndStartConnection(string protocolName, HttpTransportType transportType, string path) { var protocol = HubProtocols[protocolName]; - using (var server = await StartServer()) + await using (var server = await StartServer()) { const string originalMessage = "SignalR"; var connection = CreateHubConnection(server.Url, path, transportType, protocol, LoggerFactory); @@ -275,7 +275,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests public async Task CanAccessConnectionIdFromHubConnection(string protocolName, HttpTransportType transportType, string path) { var protocol = HubProtocols[protocolName]; - using (var server = await StartServer()) + await using (var server = await StartServer()) { var connection = CreateHubConnection(server.Url, path, transportType, protocol, LoggerFactory); try @@ -310,7 +310,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests public async Task CanStartConnectionFromClosedEvent(string protocolName, HttpTransportType transportType, string path) { var protocol = HubProtocols[protocolName]; - using (var server = await StartServer()) + await using (var server = await StartServer()) { var logger = LoggerFactory.CreateLogger(); const string originalMessage = "SignalR"; @@ -372,7 +372,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests public async Task MethodsAreCaseInsensitive(string protocolName, HttpTransportType transportType, string path) { var protocol = HubProtocols[protocolName]; - using (var server = await StartServer()) + await using (var server = await StartServer()) { const string originalMessage = "SignalR"; var connection = CreateHubConnection(server.Url, path, transportType, protocol, LoggerFactory); @@ -402,7 +402,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests public async Task CanInvokeFromOnHandler(string protocolName, HttpTransportType transportType, string path) { var protocol = HubProtocols[protocolName]; - using (var server = await StartServer()) + await using (var server = await StartServer()) { const string originalMessage = "SignalR"; @@ -442,7 +442,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests public async Task StreamAsyncCoreTest(string protocolName, HttpTransportType transportType, string path) { var protocol = HubProtocols[protocolName]; - using (var server = await StartServer()) + await using (var server = await StartServer()) { var connection = CreateHubConnection(server.Url, path, transportType, protocol, LoggerFactory); try @@ -477,7 +477,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests public async Task CanStreamToHubWithIAsyncEnumerableMethodArg(string protocolName) { var protocol = HubProtocols[protocolName]; - using (var server = await StartServer()) + await using (var server = await StartServer()) { var connection = CreateHubConnection(server.Url, "/default", HttpTransportType.WebSockets, protocol, LoggerFactory); try @@ -523,7 +523,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests public async Task StreamAsyncTest(string protocolName, HttpTransportType transportType, string path) { var protocol = HubProtocols[protocolName]; - using (var server = await StartServer()) + await using (var server = await StartServer()) { var connection = CreateHubConnection(server.Url, path, transportType, protocol, LoggerFactory); try @@ -558,7 +558,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests public async Task StreamAsyncDoesNotStartIfTokenAlreadyCanceled(string protocolName, HttpTransportType transportType, string path) { var protocol = HubProtocols[protocolName]; - using (var server = await StartServer()) + await using (var server = await StartServer()) { var connection = CreateHubConnection(server.Url, path, transportType, protocol, LoggerFactory); try @@ -595,7 +595,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests public async Task StreamAsyncCanBeCanceled(string protocolName, HttpTransportType transportType, string path) { var protocol = HubProtocols[protocolName]; - using (var server = await StartServer()) + await using (var server = await StartServer()) { var connection = CreateHubConnection(server.Url, path, transportType, protocol, LoggerFactory); try @@ -643,7 +643,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests } var protocol = HubProtocols[protocolName]; - using (var server = await StartServer(ExpectedErrors)) + await using (var server = await StartServer(ExpectedErrors)) { var connection = CreateHubConnection(server.Url, path, transportType, protocol, LoggerFactory); try @@ -679,7 +679,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests public async Task CanInvokeClientMethodFromServer(string protocolName, HttpTransportType transportType, string path) { var protocol = HubProtocols[protocolName]; - using (var server = await StartServer()) + await using (var server = await StartServer()) { const string originalMessage = "SignalR"; @@ -713,7 +713,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests public async Task InvokeNonExistantClientMethodFromServer(string protocolName, HttpTransportType transportType, string path) { var protocol = HubProtocols[protocolName]; - using (var server = await StartServer()) + await using (var server = await StartServer()) { var connection = CreateHubConnection(server.Url, path, transportType, protocol, LoggerFactory); var closeTcs = new TaskCompletionSource(); @@ -755,7 +755,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests public async Task CanStreamClientMethodFromServer(string protocolName, HttpTransportType transportType, string path) { var protocol = HubProtocols[protocolName]; - using (var server = await StartServer()) + await using (var server = await StartServer()) { var connection = CreateHubConnection(server.Url, path, transportType, protocol, LoggerFactory); try @@ -785,7 +785,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests public async Task CanStreamToAndFromClientInSameInvocation(string protocolName, HttpTransportType transportType, string path) { var protocol = HubProtocols[protocolName]; - using (var server = await StartServer()) + await using (var server = await StartServer()) { var connection = CreateHubConnection(server.Url, path, transportType, protocol, LoggerFactory); try @@ -822,7 +822,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests public async Task CanStreamToServerWithIAsyncEnumerable(string protocolName, HttpTransportType transportType, string path) { var protocol = HubProtocols[protocolName]; - using (var server = await StartServer()) + await using (var server = await StartServer()) { var connection = CreateHubConnection(server.Url, path, transportType, protocol, LoggerFactory); try @@ -869,7 +869,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests public async Task CanCancelIAsyncEnumerableClientToServerUpload(string protocolName, HttpTransportType transportType, string path) { var protocol = HubProtocols[protocolName]; - using (var server = await StartServer()) + await using (var server = await StartServer()) { var connection = CreateHubConnection(server.Url, path, transportType, protocol, LoggerFactory); try @@ -922,7 +922,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests public async Task StreamAsyncCanBeCanceledThroughGetAsyncEnumerator(string protocolName, HttpTransportType transportType, string path) { var protocol = HubProtocols[protocolName]; - using (var server = await StartServer()) + await using (var server = await StartServer()) { var connection = CreateHubConnection(server.Url, path, transportType, protocol, LoggerFactory); try @@ -963,7 +963,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests public async Task CanCloseStreamMethodEarly(string protocolName, HttpTransportType transportType, string path) { var protocol = HubProtocols[protocolName]; - using (var server = await StartServer()) + await using (var server = await StartServer()) { var connection = CreateHubConnection(server.Url, path, transportType, protocol, LoggerFactory); try @@ -1004,7 +1004,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests public async Task StreamDoesNotStartIfTokenAlreadyCanceled(string protocolName, HttpTransportType transportType, string path) { var protocol = HubProtocols[protocolName]; - using (var server = await StartServer()) + await using (var server = await StartServer()) { var connection = CreateHubConnection(server.Url, path, transportType, protocol, LoggerFactory); try @@ -1039,7 +1039,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests } var protocol = HubProtocols[protocolName]; - using (var server = await StartServer(ExpectedErrors)) + await using (var server = await StartServer(ExpectedErrors)) { var connection = CreateHubConnection(server.Url, path, transportType, protocol, LoggerFactory); try @@ -1067,7 +1067,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests public async Task ServerThrowsHubExceptionIfHubMethodCannotBeResolved(string hubProtocolName, HttpTransportType transportType, string hubPath) { var hubProtocol = HubProtocols[hubProtocolName]; - using (var server = await StartServer()) + await using (var server = await StartServer()) { var connection = CreateHubConnection(server.Url, hubPath, transportType, hubProtocol, LoggerFactory); try @@ -1094,7 +1094,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests public async Task ServerThrowsHubExceptionIfHubMethodCannotBeResolvedAndArgumentsPassedIn(string hubProtocolName, HttpTransportType transportType, string hubPath) { var hubProtocol = HubProtocols[hubProtocolName]; - using (var server = await StartServer()) + await using (var server = await StartServer()) { var connection = CreateHubConnection(server.Url, hubPath, transportType, hubProtocol, LoggerFactory); try @@ -1121,7 +1121,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests public async Task ServerThrowsHubExceptionOnHubMethodArgumentCountMismatch(string hubProtocolName) { var hubProtocol = HubProtocols[hubProtocolName]; - using (var server = await StartServer()) + await using (var server = await StartServer()) { var connection = CreateHubConnection(server.Url, "/default", HttpTransportType.LongPolling, hubProtocol, LoggerFactory); try @@ -1148,7 +1148,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests public async Task ServerThrowsHubExceptionOnHubMethodArgumentTypeMismatch(string hubProtocolName, HttpTransportType transportType, string hubPath) { var hubProtocol = HubProtocols[hubProtocolName]; - using (var server = await StartServer()) + await using (var server = await StartServer()) { var connection = CreateHubConnection(server.Url, hubPath, transportType, hubProtocol, LoggerFactory); try @@ -1175,7 +1175,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests public async Task ServerThrowsHubExceptionIfStreamingHubMethodCannotBeResolved(string hubProtocolName, HttpTransportType transportType, string hubPath) { var hubProtocol = HubProtocols[hubProtocolName]; - using (var server = await StartServer()) + await using (var server = await StartServer()) { var connection = CreateHubConnection(server.Url, hubPath, transportType, hubProtocol, LoggerFactory); try @@ -1203,7 +1203,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests public async Task ServerThrowsHubExceptionOnStreamingHubMethodArgumentCountMismatch(string hubProtocolName, HttpTransportType transportType, string hubPath) { var hubProtocol = HubProtocols[hubProtocolName]; - using (var server = await StartServer()) + await using (var server = await StartServer()) { var connection = CreateHubConnection(server.Url, hubPath, transportType, hubProtocol, LoggerFactory); try @@ -1231,7 +1231,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests public async Task ServerThrowsHubExceptionOnStreamingHubMethodArgumentTypeMismatch(string hubProtocolName, HttpTransportType transportType, string hubPath) { var hubProtocol = HubProtocols[hubProtocolName]; - using (var server = await StartServer()) + await using (var server = await StartServer()) { var connection = CreateHubConnection(server.Url, hubPath, transportType, hubProtocol, LoggerFactory); try @@ -1259,7 +1259,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests public async Task ServerThrowsHubExceptionIfNonStreamMethodInvokedWithStreamAsync(string hubProtocolName, HttpTransportType transportType, string hubPath) { var hubProtocol = HubProtocols[hubProtocolName]; - using (var server = await StartServer()) + await using (var server = await StartServer()) { var connection = CreateHubConnection(server.Url, hubPath, transportType, hubProtocol, LoggerFactory); try @@ -1286,7 +1286,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests public async Task ServerThrowsHubExceptionIfStreamMethodInvokedWithInvoke(string hubProtocolName, HttpTransportType transportType, string hubPath) { var hubProtocol = HubProtocols[hubProtocolName]; - using (var server = await StartServer()) + await using (var server = await StartServer()) { var connection = CreateHubConnection(server.Url, hubPath, transportType, hubProtocol, LoggerFactory); try @@ -1313,7 +1313,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests public async Task ServerThrowsHubExceptionIfBuildingAsyncEnumeratorIsNotPossible(string hubProtocolName, HttpTransportType transportType, string hubPath) { var hubProtocol = HubProtocols[hubProtocolName]; - using (var server = await StartServer()) + await using (var server = await StartServer()) { var connection = CreateHubConnection(server.Url, hubPath, transportType, hubProtocol, LoggerFactory); try @@ -1349,7 +1349,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests }; var protocol = HubProtocols[protocolName]; - using (var server = await StartServer(write => write.EventId.Name == "FailedWritingMessage")) + await using (var server = await StartServer(write => write.EventId.Name == "FailedWritingMessage")) { var connection = CreateHubConnection(server.Url, "/default", HttpTransportType.WebSockets, protocol, LoggerFactory); var closedTcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); @@ -1396,7 +1396,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests }; var protocol = HubProtocols[protocolName]; - using (var server = await StartServer(write => write.EventId.Name == "FailedWritingMessage")) + await using (var server = await StartServer(write => write.EventId.Name == "FailedWritingMessage")) { var connection = CreateHubConnection(server.Url, "/default", HttpTransportType.LongPolling, protocol, LoggerFactory); var closedTcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); @@ -1436,7 +1436,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests var hubProtocol = HubProtocols.First().Value; var transportType = TransportTypes().First().Cast().First(); - using (var server = await StartServer()) + await using (var server = await StartServer()) { var connection = CreateHubConnection(server.Url, hubPath, transportType, hubProtocol, LoggerFactory); await connection.StartAsync().OrTimeout(); @@ -1453,7 +1453,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests [MemberData(nameof(TransportTypes))] public async Task ClientCanUseJwtBearerTokenForAuthentication(HttpTransportType transportType) { - using (var server = await StartServer()) + await using (var server = await StartServer()) { async Task AccessTokenProvider() { @@ -1496,7 +1496,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests return writeContext.Exception is HttpRequestException; } - using (var server = await StartServer(ExpectedErrors)) + await using (var server = await StartServer(ExpectedErrors)) { var hubConnection = new HubConnectionBuilder() .WithLoggerFactory(LoggerFactory) @@ -1518,7 +1518,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests [MemberData(nameof(TransportTypes))] public async Task ClientCanUseJwtBearerTokenForAuthenticationWhenRedirected(HttpTransportType transportType) { - using (var server = await StartServer()) + await using (var server = await StartServer()) { var hubConnection = new HubConnectionBuilder() .WithLoggerFactory(LoggerFactory) @@ -1546,7 +1546,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests [MemberData(nameof(TransportTypes))] public async Task ClientCanSendHeaders(HttpTransportType transportType) { - using (var server = await StartServer()) + await using (var server = await StartServer()) { var hubConnection = new HubConnectionBuilder() .WithLoggerFactory(LoggerFactory) @@ -1577,7 +1577,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests [Fact] public async Task UserAgentIsSet() { - using (var server = await StartServer()) + await using (var server = await StartServer()) { var hubConnection = new HubConnectionBuilder() .WithLoggerFactory(LoggerFactory) @@ -1619,7 +1619,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests [Fact] public async Task UserAgentCanBeCleared() { - using (var server = await StartServer()) + await using (var server = await StartServer()) { var hubConnection = new HubConnectionBuilder() .WithLoggerFactory(LoggerFactory) @@ -1654,7 +1654,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests [Fact] public async Task UserAgentCanBeSet() { - using (var server = await StartServer()) + await using (var server = await StartServer()) { var hubConnection = new HubConnectionBuilder() .WithLoggerFactory(LoggerFactory) @@ -1690,7 +1690,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests [WebSocketsSupportedCondition] public async Task WebSocketOptionsAreApplied() { - using (var server = await StartServer()) + await using (var server = await StartServer()) { // System.Net has a HttpTransportType type which means we need to fully-qualify this rather than 'use' the namespace var cookieJar = new System.Net.CookieContainer(); @@ -1724,7 +1724,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests [Fact] public async Task CheckHttpConnectionFeatures() { - using (var server = await StartServer()) + await using (var server = await StartServer()) { var hubConnection = new HubConnectionBuilder() .WithLoggerFactory(LoggerFactory) @@ -1760,7 +1760,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests [Fact] public async Task UserIdProviderCanAccessHttpContext() { - using (var server = await StartServer()) + await using (var server = await StartServer()) { var hubConnection = new HubConnectionBuilder() .WithLoggerFactory(LoggerFactory) @@ -1791,7 +1791,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests [Fact] public async Task NegotiationSkipsServerSentEventsWhenUsingBinaryProtocol() { - using (var server = await StartServer()) + await using (var server = await StartServer()) { var hubConnectionBuilder = new HubConnectionBuilder() .WithLoggerFactory(LoggerFactory) @@ -1821,7 +1821,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests [Fact] public async Task StopCausesPollToReturnImmediately() { - using (var server = await StartServer()) + await using (var server = await StartServer()) { PollTrackingMessageHandler pollTracker = null; var hubConnection = new HubConnectionBuilder() @@ -1869,7 +1869,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests writeContext.EventId.Name == "ReconnectingWithError"; } - using (var server = await StartServer(ExpectedErrors)) + await using (var server = await StartServer(ExpectedErrors)) { var connection = CreateHubConnection( server.Url, @@ -1931,7 +1931,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests writeContext.EventId.Name == "ReconnectingWithError"; } - using (var server = await StartServer(ExpectedErrors)) + await using (var server = await StartServer(ExpectedErrors)) { var connection = new HubConnectionBuilder() .WithLoggerFactory(LoggerFactory) @@ -1991,7 +1991,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests writeContext.EventId.Name == "ReconnectingWithError"; } - using (var server = await StartServer(ExpectedErrors)) + await using (var server = await StartServer(ExpectedErrors)) { var connectionBuilder = new HubConnectionBuilder() .WithLoggerFactory(LoggerFactory) diff --git a/src/SignalR/clients/csharp/Client/test/FunctionalTests/HubProtocolVersionTests.cs b/src/SignalR/clients/csharp/Client/test/FunctionalTests/HubProtocolVersionTests.cs index a7240053b8..fbf5ea3fd6 100644 --- a/src/SignalR/clients/csharp/Client/test/FunctionalTests/HubProtocolVersionTests.cs +++ b/src/SignalR/clients/csharp/Client/test/FunctionalTests/HubProtocolVersionTests.cs @@ -35,7 +35,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests [MemberData(nameof(TransportTypes))] public async Task ClientUsingOldCallWithOriginalProtocol(HttpTransportType transportType) { - using (var server = await StartServer()) + await using (var server = await StartServer()) { var connectionBuilder = new HubConnectionBuilder() .WithLoggerFactory(LoggerFactory) @@ -67,7 +67,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests [MemberData(nameof(TransportTypes))] public async Task ClientUsingOldCallWithNewProtocol(HttpTransportType transportType) { - using (var server = await StartServer()) + await using (var server = await StartServer()) { var connectionBuilder = new HubConnectionBuilder() .WithLoggerFactory(LoggerFactory) @@ -100,7 +100,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests [MemberData(nameof(TransportTypes))] public async Task ClientUsingNewCallWithNewProtocol(HttpTransportType transportType) { - using (var server = await StartServer()) + await using (var server = await StartServer()) { var httpConnectionFactory = new HttpConnectionFactory( Options.Create(new HttpConnectionOptions @@ -166,7 +166,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests return writeContext.LoggerName == typeof(HubConnection).FullName; } - using (var server = await StartServer(ExpectedErrors)) + await using (var server = await StartServer(ExpectedErrors)) { var connectionBuilder = new HubConnectionBuilder() .WithLoggerFactory(LoggerFactory) diff --git a/src/SignalR/clients/csharp/Client/test/UnitTests/TimerAwaitableTests.cs b/src/SignalR/clients/csharp/Client/test/UnitTests/TimerAwaitableTests.cs index e0e7248df4..869626d7cd 100644 --- a/src/SignalR/clients/csharp/Client/test/UnitTests/TimerAwaitableTests.cs +++ b/src/SignalR/clients/csharp/Client/test/UnitTests/TimerAwaitableTests.cs @@ -13,7 +13,6 @@ namespace Microsoft.AspNetCore.SignalR.Client.Tests public class TimerAwaitableTests { [Fact] - [QuarantinedTest] public async Task FinalizerRunsIfTimerAwaitableReferencesObject() { var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); diff --git a/src/SignalR/clients/java/signalr/signalr.client.java.Tests.javaproj b/src/SignalR/clients/java/signalr/signalr.client.java.Tests.javaproj index 6a1851569e..84771b3fe4 100644 --- a/src/SignalR/clients/java/signalr/signalr.client.java.Tests.javaproj +++ b/src/SignalR/clients/java/signalr/signalr.client.java.Tests.javaproj @@ -78,7 +78,7 @@ - $(GradleOptions) -PpackageVersion="$(PackageVersion)" + $(GradleOptions) -PpackageVersion="$(PackageVersion)" chmod +x ./gradlew && ./gradlew $(GradleOptions) test call gradlew $(GradleOptions) test diff --git a/src/SignalR/clients/java/signalr/src/main/java/com/microsoft/signalr/Version.java b/src/SignalR/clients/java/signalr/src/main/java/com/microsoft/signalr/Version.java index 4c73a498f6..3877f515be 100644 --- a/src/SignalR/clients/java/signalr/src/main/java/com/microsoft/signalr/Version.java +++ b/src/SignalR/clients/java/signalr/src/main/java/com/microsoft/signalr/Version.java @@ -6,6 +6,6 @@ package com.microsoft.signalr; class Version { public static String getDetailedVersion() { - return "99.99.99-dev"; + return "5.0.0-dev"; } } diff --git a/src/SignalR/clients/ts/FunctionalTests/Program.cs b/src/SignalR/clients/ts/FunctionalTests/Program.cs index 2f67e3d5cd..bc1cc0a323 100644 --- a/src/SignalR/clients/ts/FunctionalTests/Program.cs +++ b/src/SignalR/clients/ts/FunctionalTests/Program.cs @@ -5,7 +5,9 @@ using System; using System.IO; using System.Runtime.InteropServices; using System.Security.Cryptography.X509Certificates; +using System.Threading.Tasks; using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Microsoft.Win32; @@ -13,7 +15,7 @@ namespace FunctionalTests { public class Program { - public static void Main(string[] args) + public static Task Main(string[] args) { string url = null; for (var i = 0; i < args.Length; i++) @@ -27,65 +29,69 @@ namespace FunctionalTests } } - var hostBuilder = new WebHostBuilder() - .ConfigureLogging(factory => + var hostBuilder = new HostBuilder() + .ConfigureWebHost(webHostBuilder => { - factory.AddConsole(options => + webHostBuilder + .ConfigureLogging(factory => { - options.IncludeScopes = true; - options.TimestampFormat = "[HH:mm:ss] "; - options.UseUtcTimestamp = true; - }); - factory.AddDebug(); - factory.SetMinimumLevel(LogLevel.Debug); - }) - .UseKestrel((builderContext, options) => - { - options.ConfigureHttpsDefaults(httpsOptions => - { - bool useRSA = false; - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + factory.AddConsole(options => { - // Detect Win10+ - var key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion"); - var major = key.GetValue("CurrentMajorVersionNumber") as int?; - var minor = key.GetValue("CurrentMinorVersionNumber") as int?; + options.IncludeScopes = true; + options.TimestampFormat = "[HH:mm:ss] "; + options.UseUtcTimestamp = true; + }); + factory.AddDebug(); + factory.SetMinimumLevel(LogLevel.Debug); + }) + .UseKestrel((builderContext, options) => + { + options.ConfigureHttpsDefaults(httpsOptions => + { + bool useRSA = false; + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + // Detect Win10+ + var key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion"); + var major = key.GetValue("CurrentMajorVersionNumber") as int?; + var minor = key.GetValue("CurrentMinorVersionNumber") as int?; - if (major.HasValue && minor.HasValue) + if (major.HasValue && minor.HasValue) + { + useRSA = true; + } + } + else { useRSA = true; } - } - else - { - useRSA = true; - } - if (useRSA) - { - // RSA cert, won't work on Windows 8.1 & Windows 2012 R2 using HTTP2, and ECC won't work in some Node environments - var certPath = Path.Combine(Directory.GetCurrentDirectory(), "testCert.pfx"); - httpsOptions.ServerCertificate = new X509Certificate2(certPath, "testPassword"); - } - else - { - // ECC cert, works on Windows 8.1 & Windows 2012 R2 using HTTP2 - var certPath = Path.Combine(Directory.GetCurrentDirectory(), "testCertECC.pfx"); - httpsOptions.ServerCertificate = new X509Certificate2(certPath, "testPassword"); - } - }); - }) - .UseContentRoot(Directory.GetCurrentDirectory()) - .UseIISIntegration() - .UseStartup(); + if (useRSA) + { + // RSA cert, won't work on Windows 8.1 & Windows 2012 R2 using HTTP2, and ECC won't work in some Node environments + var certPath = Path.Combine(Directory.GetCurrentDirectory(), "testCert.pfx"); + httpsOptions.ServerCertificate = new X509Certificate2(certPath, "testPassword"); + } + else + { + // ECC cert, works on Windows 8.1 & Windows 2012 R2 using HTTP2 + var certPath = Path.Combine(Directory.GetCurrentDirectory(), "testCertECC.pfx"); + httpsOptions.ServerCertificate = new X509Certificate2(certPath, "testPassword"); + } + }); + }) + .UseContentRoot(Directory.GetCurrentDirectory()) + .UseIISIntegration() + .UseStartup(); - if (!string.IsNullOrEmpty(url)) - { - Console.WriteLine($"Forcing URL to: {url}"); - hostBuilder.UseUrls(url); - } + if (!string.IsNullOrEmpty(url)) + { + Console.WriteLine($"Forcing URL to: {url}"); + webHostBuilder.UseUrls(url); + } + }); - hostBuilder.Build().Run(); + return hostBuilder.Build().RunAsync(); } } } diff --git a/src/SignalR/common/Http.Connections/test/MapConnectionHandlerTests.cs b/src/SignalR/common/Http.Connections/test/MapConnectionHandlerTests.cs index d603c0d083..7b734ac2fa 100644 --- a/src/SignalR/common/Http.Connections/test/MapConnectionHandlerTests.cs +++ b/src/SignalR/common/Http.Connections/test/MapConnectionHandlerTests.cs @@ -13,11 +13,13 @@ using Microsoft.AspNetCore.Connections; using Microsoft.AspNetCore.Cors; using Microsoft.AspNetCore.Cors.Infrastructure; using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Hosting.Server; using Microsoft.AspNetCore.Hosting.Server.Features; using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.SignalR.Tests; using Microsoft.AspNetCore.Testing; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Xunit; using Xunit.Abstractions; @@ -305,7 +307,7 @@ namespace Microsoft.AspNetCore.Http.Connections.Tests [WebSocketsSupportedCondition] public async Task MapConnectionHandlerWithWebSocketSubProtocolSetsProtocol() { - var host = BuildWebHost("/socket", + using var host = BuildWebHost("/socket", options => options.WebSockets.SubProtocolSelector = subprotocols => { Assert.Equal(new[] { "protocol1", "protocol2" }, subprotocols.ToArray()); @@ -314,7 +316,7 @@ namespace Microsoft.AspNetCore.Http.Connections.Tests await host.StartAsync(); - var feature = host.ServerFeatures.Get(); + var feature = host.Services.GetService().Features.Get(); var address = feature.Addresses.First().Replace("http", "ws") + "/socket"; var client = new ClientWebSocket(); @@ -377,44 +379,52 @@ namespace Microsoft.AspNetCore.Http.Connections.Tests } } - private IWebHost BuildWebHost(Action configure) + private IHost BuildWebHost(Action configure) { - return new WebHostBuilder() - .UseKestrel() - .ConfigureServices(services => + return new HostBuilder() + .ConfigureWebHost(webHostBuilder => { - services.AddConnections(); + webHostBuilder + .UseKestrel() + .ConfigureServices(services => + { + services.AddConnections(); + }) + .Configure(app => + { + app.UseRouting(); + app.UseEndpoints(endpoints => configure(endpoints)); + }) + .UseUrls("http://127.0.0.1:0"); }) - .Configure(app => - { - app.UseRouting(); - app.UseEndpoints(endpoints => configure(endpoints)); - }) - .UseUrls("http://127.0.0.1:0") .Build(); } - private IWebHost BuildWebHost(string path, Action configureOptions) where TConnectionHandler : ConnectionHandler + private IHost BuildWebHost(string path, Action configureOptions) where TConnectionHandler : ConnectionHandler { - return new WebHostBuilder() - .UseUrls("http://127.0.0.1:0") - .UseKestrel() - .ConfigureServices(services => + return new HostBuilder() + .ConfigureWebHost(webHostBuilder => { - services.AddConnections(); - }) - .Configure(app => - { - app.UseRouting(); - app.UseEndpoints(routes => + webHostBuilder + .UseUrls("http://127.0.0.1:0") + .UseKestrel() + .ConfigureServices(services => { - routes.MapConnectionHandler(path, configureOptions); + services.AddConnections(); + }) + .Configure(app => + { + app.UseRouting(); + app.UseEndpoints(routes => + { + routes.MapConnectionHandler(path, configureOptions); + }); + }) + .ConfigureLogging(factory => + { + factory.AddXunit(_output, LogLevel.Trace); }); }) - .ConfigureLogging(factory => - { - factory.AddXunit(_output, LogLevel.Trace); - }) .Build(); } } diff --git a/src/SignalR/common/testassets/Tests.Utils/InProcessTestServer.cs b/src/SignalR/common/testassets/Tests.Utils/InProcessTestServer.cs index 631220c7de..d50c425528 100644 --- a/src/SignalR/common/testassets/Tests.Utils/InProcessTestServer.cs +++ b/src/SignalR/common/testassets/Tests.Utils/InProcessTestServer.cs @@ -9,16 +9,16 @@ using System.Text; using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Hosting.Server; using Microsoft.AspNetCore.Hosting.Server.Features; using Microsoft.AspNetCore.Testing; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Logging.Testing; namespace Microsoft.AspNetCore.SignalR.Tests { - public abstract class InProcessTestServer : IDisposable + public abstract class InProcessTestServer : IAsyncDisposable { internal abstract event Action ServerLogged; @@ -26,7 +26,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests public abstract string Url { get; } - public abstract void Dispose(); + public abstract ValueTask DisposeAsync(); } public class InProcessTestServer : InProcessTestServer @@ -34,7 +34,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests { private readonly ILoggerFactory _loggerFactory; private readonly ILogger _logger; - private IWebHost _host; + private IHost _host; private IHostApplicationLifetime _lifetime; private readonly IDisposable _logToken; private readonly IDisposable _extraDisposable; @@ -91,15 +91,18 @@ namespace Microsoft.AspNetCore.SignalR.Tests // We're using 127.0.0.1 instead of localhost to ensure that we use IPV4 across different OSes var url = "http://127.0.0.1:0"; - _host = new WebHostBuilder() - .ConfigureLogging(builder => builder + _host = new HostBuilder() + .ConfigureWebHost(webHostBuilder => + { + webHostBuilder + .ConfigureLogging(builder => builder .SetMinimumLevel(LogLevel.Trace) .AddProvider(new ForwardingLoggerProvider(_loggerFactory))) - .UseStartup(typeof(TStartup)) - .UseKestrel() - .UseUrls(url) - .UseContentRoot(Directory.GetCurrentDirectory()) - .Build(); + .UseStartup(typeof(TStartup)) + .UseKestrel() + .UseUrls(url) + .UseContentRoot(Directory.GetCurrentDirectory()); + }).Build(); _logger.LogInformation("Starting test server..."); var cts = new CancellationTokenSource(TimeSpan.FromSeconds(30)); @@ -116,7 +119,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests _logger.LogInformation("Test Server started"); // Get the URL from the server - _url = _host.ServerFeatures.Get().Addresses.Single(); + _url = _host.Services.GetService().Features.Get().Addresses.Single(); _lifetime = _host.Services.GetRequiredService(); _lifetime.ApplicationStopped.Register(() => @@ -144,12 +147,19 @@ namespace Microsoft.AspNetCore.SignalR.Tests return builder.ToString(); } - public override void Dispose() + public override async ValueTask DisposeAsync() { - _extraDisposable?.Dispose(); - _logger.LogInformation("Shutting down test server"); - _host.Dispose(); - _loggerFactory.Dispose(); + try + { + _extraDisposable?.Dispose(); + _logger.LogInformation("Start shutting down test server"); + } + finally + { + await _host.StopAsync(); + _host.Dispose(); + _loggerFactory.Dispose(); + } } private class ForwardingLoggerProvider : ILoggerProvider diff --git a/src/SignalR/common/testassets/Tests.Utils/Microsoft.AspNetCore.SignalR.Tests.Utils.csproj b/src/SignalR/common/testassets/Tests.Utils/Microsoft.AspNetCore.SignalR.Tests.Utils.csproj index 86cb17cb5f..dc4198b924 100644 --- a/src/SignalR/common/testassets/Tests.Utils/Microsoft.AspNetCore.SignalR.Tests.Utils.csproj +++ b/src/SignalR/common/testassets/Tests.Utils/Microsoft.AspNetCore.SignalR.Tests.Utils.csproj @@ -1,4 +1,4 @@ - + $(DefaultNetCoreTargetFramework) diff --git a/src/SignalR/samples/JwtSample/JwtSample.csproj b/src/SignalR/samples/JwtSample/JwtSample.csproj index 552c9d63f2..b8ac2dc1a7 100644 --- a/src/SignalR/samples/JwtSample/JwtSample.csproj +++ b/src/SignalR/samples/JwtSample/JwtSample.csproj @@ -1,4 +1,4 @@ - + $(DefaultNetCoreTargetFramework) diff --git a/src/SignalR/samples/JwtSample/Program.cs b/src/SignalR/samples/JwtSample/Program.cs index a4bff29a37..06050394b7 100644 --- a/src/SignalR/samples/JwtSample/Program.cs +++ b/src/SignalR/samples/JwtSample/Program.cs @@ -1,29 +1,35 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.IO; +using System.Threading.Tasks; using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; namespace JwtSample { public class Program { - public static void Main(string[] args) + public static Task Main(string[] args) { - new WebHostBuilder() - .ConfigureLogging(factory => + return Host.CreateDefaultBuilder(args) + .ConfigureWebHost(webHostBuilder => { - factory.AddConsole(); - factory.AddFilter("Console", level => level >= LogLevel.Information); - factory.AddDebug(); + webHostBuilder + .ConfigureLogging(factory => + { + factory.AddConsole(); + factory.AddFilter("Console", level => level >= LogLevel.Information); + factory.AddDebug(); + }) + .UseKestrel() + .UseContentRoot(Directory.GetCurrentDirectory()) + .UseIISIntegration() + .UseStartup(); }) - .UseKestrel() - .UseContentRoot(Directory.GetCurrentDirectory()) - .UseIISIntegration() - .UseStartup() .Build() - .Run(); + .RunAsync(); } } } diff --git a/src/SignalR/samples/SignalRSamples/Program.cs b/src/SignalR/samples/SignalRSamples/Program.cs index 2f932a18a4..c56a2c5b59 100644 --- a/src/SignalR/samples/SignalRSamples/Program.cs +++ b/src/SignalR/samples/SignalRSamples/Program.cs @@ -3,9 +3,11 @@ using System.IO; using System.Net; +using System.Threading.Tasks; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.SignalR; using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using SignalRSamples.Hubs; @@ -13,36 +15,40 @@ namespace SignalRSamples { public class Program { - public static void Main(string[] args) + public static Task Main(string[] args) { var config = new ConfigurationBuilder() .AddCommandLine(args) .Build(); - var host = new WebHostBuilder() - .UseConfiguration(config) - .UseSetting(WebHostDefaults.PreventHostingStartupKey, "true") - .ConfigureLogging(factory => + var host = Host.CreateDefaultBuilder(args) + .ConfigureWebHost(webHostBuilder => { - factory.AddConsole(); - }) - .UseKestrel(options => - { - // Default port - options.ListenLocalhost(5000); - - // Hub bound to TCP end point - options.Listen(IPAddress.Any, 9001, builder => + webHostBuilder + .UseConfiguration(config) + .UseSetting(WebHostDefaults.PreventHostingStartupKey, "true") + .ConfigureLogging((c, factory) => { - builder.UseHub(); - }); - }) - .UseContentRoot(Directory.GetCurrentDirectory()) - .UseIISIntegration() - .UseStartup() - .Build(); + factory.AddConfiguration(c.Configuration.GetSection("Logging")); + factory.AddConsole(); + }) + .UseKestrel(options => + { + // Default port + options.ListenLocalhost(5000); - host.Run(); + // Hub bound to TCP end point + options.Listen(IPAddress.Any, 9001, builder => + { + builder.UseHub(); + }); + }) + .UseContentRoot(Directory.GetCurrentDirectory()) + .UseIISIntegration() + .UseStartup(); + }).Build(); + + return host.RunAsync(); } } } diff --git a/src/SignalR/samples/SocialWeather/Program.cs b/src/SignalR/samples/SocialWeather/Program.cs index 426f89226b..24169976a6 100644 --- a/src/SignalR/samples/SocialWeather/Program.cs +++ b/src/SignalR/samples/SocialWeather/Program.cs @@ -2,29 +2,35 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.IO; +using System.Threading.Tasks; using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; namespace SocialWeather { public class Program { - public static void Main(string[] args) + public static Task Main(string[] args) { - var host = new WebHostBuilder() - .UseSetting(WebHostDefaults.PreventHostingStartupKey, "true") - .ConfigureLogging(factory => + var host = Host.CreateDefaultBuilder(args) + .ConfigureWebHost(webHostBuilder => { - factory.AddConsole(); - factory.AddFilter("Console", level => level >= LogLevel.Information); + webHostBuilder + .UseSetting(WebHostDefaults.PreventHostingStartupKey, "true") + .ConfigureLogging(factory => + { + factory.AddConsole(); + factory.AddFilter("Console", level => level >= LogLevel.Information); + }) + .UseKestrel() + .UseContentRoot(Directory.GetCurrentDirectory()) + .UseIISIntegration() + .UseStartup(); }) - .UseKestrel() - .UseContentRoot(Directory.GetCurrentDirectory()) - .UseIISIntegration() - .UseStartup() .Build(); - host.Run(); + return host.RunAsync(); } } } diff --git a/src/SignalR/samples/SocialWeather/SocialWeather.csproj b/src/SignalR/samples/SocialWeather/SocialWeather.csproj index ea9308fee5..fe8e362e2c 100644 --- a/src/SignalR/samples/SocialWeather/SocialWeather.csproj +++ b/src/SignalR/samples/SocialWeather/SocialWeather.csproj @@ -1,4 +1,4 @@ - + $(DefaultNetCoreTargetFramework) diff --git a/src/SignalR/server/SignalR/test/EndToEndTests.cs b/src/SignalR/server/SignalR/test/EndToEndTests.cs index 7461b2e90e..caebf870c6 100644 --- a/src/SignalR/server/SignalR/test/EndToEndTests.cs +++ b/src/SignalR/server/SignalR/test/EndToEndTests.cs @@ -36,7 +36,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests [Fact] public async Task CanStartAndStopConnectionUsingDefaultTransport() { - using (var server = await StartServer()) + await using (var server = await StartServer()) { var url = server.Url + "/echo"; // The test should connect to the server using WebSockets transport on Windows 8 and newer. @@ -56,7 +56,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests writeContext.EventId.Name == "ErrorStartingTransport"; } - using (var server = await StartServer(expectedErrorsFilter: ExpectedErrors)) + await using (var server = await StartServer(expectedErrorsFilter: ExpectedErrors)) { var url = server.Url + "/echo"; // The test should connect to the server using WebSockets transport on Windows 8 and newer. @@ -74,7 +74,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests [LogLevel(LogLevel.Trace)] public async Task CanStartAndStopConnectionUsingGivenTransport(HttpTransportType transportType) { - using (var server = await StartServer()) + await using (var server = await StartServer()) { var url = server.Url + "/echo"; var connection = new HttpConnection(new HttpConnectionOptions { Url = new Uri(url), Transports = transportType, DefaultTransferFormat = TransferFormat.Text }, LoggerFactory); @@ -87,7 +87,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests [WebSocketsSupportedCondition] public async Task WebSocketsTest() { - using (var server = await StartServer()) + await using (var server = await StartServer()) { var logger = LoggerFactory.CreateLogger(); @@ -125,7 +125,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests [WebSocketsSupportedCondition] public async Task WebSocketsReceivesAndSendsPartialFramesTest() { - using (var server = await StartServer()) + await using (var server = await StartServer()) { var logger = LoggerFactory.CreateLogger(); @@ -164,7 +164,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests [WebSocketsSupportedCondition] public async Task HttpRequestsNotSentWhenWebSocketsTransportRequestedAndSkipNegotiationSet() { - using (var server = await StartServer()) + await using (var server = await StartServer()) { var logger = LoggerFactory.CreateLogger(); var url = server.Url + "/echo"; @@ -214,7 +214,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests [InlineData(HttpTransportType.ServerSentEvents)] public async Task HttpConnectionThrowsIfSkipNegotiationSetAndTransportIsNotWebSockets(HttpTransportType transportType) { - using (var server = await StartServer()) + await using (var server = await StartServer()) { var logger = LoggerFactory.CreateLogger(); var url = server.Url + "/echo"; @@ -257,7 +257,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests [LogLevel(LogLevel.Trace)] public async Task ConnectionCanSendAndReceiveMessages(HttpTransportType transportType, TransferFormat requestedTransferFormat) { - using (var server = await StartServer()) + await using (var server = await StartServer()) { var logger = LoggerFactory.CreateLogger(); @@ -315,7 +315,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests public async Task ConnectionCanSendAndReceiveDifferentMessageSizesWebSocketsTransport(int length) { var message = new string('A', length); - using (var server = await StartServer()) + await using (var server = await StartServer()) { var logger = LoggerFactory.CreateLogger(); @@ -379,7 +379,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests writeContext.EventId.Name == "ErrorWithNegotiation"; } - using (var server = await StartServer(ExpectedErrors)) + await using (var server = await StartServer(ExpectedErrors)) { var logger = LoggerFactory.CreateLogger(); @@ -403,7 +403,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests writeContext.EventId.Name == "ErrorStartingTransport"; } - using (var server = await StartServer(ExpectedErrors)) + await using (var server = await StartServer(ExpectedErrors)) { var logger = LoggerFactory.CreateLogger(); @@ -433,7 +433,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests writeContext.EventId.Name == "ErrorWithNegotiation"; } - using (var server = await StartServer(ExpectedErrors)) + await using (var server = await StartServer(ExpectedErrors)) { var logger = LoggerFactory.CreateLogger(); @@ -469,7 +469,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests writeContext.EventId.Name == "ErrorWithNegotiation"; } - using (var server = await StartServer(ExpectedErrors)) + await using (var server = await StartServer(ExpectedErrors)) { var logger = LoggerFactory.CreateLogger(); @@ -539,7 +539,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests private async Task ServerClosesConnectionWithErrorIfHubCannotBeCreated(HttpTransportType transportType) { - using (var server = await StartServer()) + await using (var server = await StartServer()) { var logger = LoggerFactory.CreateLogger(); @@ -604,7 +604,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests writeContext.EventId.Name == "ErrorWithNegotiation"; } - using (var server = await StartServer(ExpectedErrors)) + await using (var server = await StartServer(ExpectedErrors)) { var logger = LoggerFactory.CreateLogger(); @@ -643,7 +643,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests writeContext.EventId.Name == "ErrorWithNegotiation"; } - using (var server = await StartServer(ExpectedErrors)) + await using (var server = await StartServer(ExpectedErrors)) { var logger = LoggerFactory.CreateLogger(); diff --git a/src/SignalR/server/SignalR/test/MapSignalRTests.cs b/src/SignalR/server/SignalR/test/MapSignalRTests.cs index 8f1a79dc4a..695a5683c7 100644 --- a/src/SignalR/server/SignalR/test/MapSignalRTests.cs +++ b/src/SignalR/server/SignalR/test/MapSignalRTests.cs @@ -5,6 +5,7 @@ using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http.Connections; using Microsoft.AspNetCore.Routing; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; using Xunit; namespace Microsoft.AspNetCore.SignalR.Tests @@ -29,9 +30,11 @@ namespace Microsoft.AspNetCore.SignalR.Tests public void NotAddingSignalRServiceThrows() { var executedConfigure = false; - var builder = new WebHostBuilder(); + var builder = new HostBuilder(); - builder + builder.ConfigureWebHost(webHostBuilder => + { + webHostBuilder .UseKestrel() .ConfigureServices(services => { @@ -54,6 +57,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests "'IServiceCollection.AddSignalR' inside the call to 'ConfigureServices(...)' in the application startup code.", ex.Message); }) .UseUrls("http://127.0.0.1:0"); + }); using (var host = builder.Build()) { @@ -338,20 +342,24 @@ namespace Microsoft.AspNetCore.SignalR.Tests { } - private IWebHost BuildWebHost(Action configure) + private IHost BuildWebHost(Action configure) { - return new WebHostBuilder() - .UseKestrel() - .ConfigureServices(services => + return new HostBuilder() + .ConfigureWebHost(webHostBuilder => { - services.AddSignalR(); + webHostBuilder + .UseKestrel() + .ConfigureServices(services => + { + services.AddSignalR(); + }) + .Configure(app => + { + app.UseRouting(); + app.UseEndpoints(endpoints => configure(endpoints)); + }) + .UseUrls("http://127.0.0.1:0"); }) - .Configure(app => - { - app.UseRouting(); - app.UseEndpoints(endpoints => configure(endpoints)); - }) - .UseUrls("http://127.0.0.1:0") .Build(); } } diff --git a/src/SignalR/server/SignalR/test/WebSocketsTransportTests.cs b/src/SignalR/server/SignalR/test/WebSocketsTransportTests.cs index 2c059c3edc..6736265a72 100644 --- a/src/SignalR/server/SignalR/test/WebSocketsTransportTests.cs +++ b/src/SignalR/server/SignalR/test/WebSocketsTransportTests.cs @@ -53,7 +53,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests [WebSocketsSupportedCondition] public async Task WebSocketsTransportStopsSendAndReceiveLoopsWhenTransportIsStopped() { - using (var server = await StartServer()) + await using (var server = await StartServer()) { var webSocketsTransport = new WebSocketsTransport(httpConnectionOptions: null, loggerFactory: LoggerFactory, accessTokenProvider: null); await webSocketsTransport.StartAsync(new Uri(server.WebSocketsUrl + "/echo"), @@ -67,7 +67,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests [WebSocketsSupportedCondition] public async Task WebSocketsTransportSendsUserAgent() { - using (var server = await StartServer()) + await using (var server = await StartServer()) { var webSocketsTransport = new WebSocketsTransport(httpConnectionOptions: null, loggerFactory: LoggerFactory, accessTokenProvider: null); await webSocketsTransport.StartAsync(new Uri(server.WebSocketsUrl + "/httpheader"), @@ -98,7 +98,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests [WebSocketsSupportedCondition] public async Task WebSocketsTransportSendsXRequestedWithHeader() { - using (var server = await StartServer()) + await using (var server = await StartServer()) { var webSocketsTransport = new WebSocketsTransport(httpConnectionOptions: null, loggerFactory: LoggerFactory, accessTokenProvider: null); await webSocketsTransport.StartAsync(new Uri(server.WebSocketsUrl + "/httpheader"), @@ -121,7 +121,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests [WebSocketsSupportedCondition] public async Task WebSocketsTransportStopsWhenConnectionChannelClosed() { - using (var server = await StartServer()) + await using (var server = await StartServer()) { var webSocketsTransport = new WebSocketsTransport(httpConnectionOptions: null, loggerFactory: LoggerFactory, accessTokenProvider: null); await webSocketsTransport.StartAsync(new Uri(server.WebSocketsUrl + "/echo"), @@ -137,7 +137,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests [InlineData(TransferFormat.Binary)] public async Task WebSocketsTransportStopsWhenConnectionClosedByTheServer(TransferFormat transferFormat) { - using (var server = await StartServer()) + await using (var server = await StartServer()) { var webSocketsTransport = new WebSocketsTransport(httpConnectionOptions: null, loggerFactory: LoggerFactory, accessTokenProvider: null); await webSocketsTransport.StartAsync(new Uri(server.WebSocketsUrl + "/echoAndClose"), transferFormat); @@ -159,7 +159,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests [InlineData(TransferFormat.Binary)] public async Task WebSocketsTransportSetsTransferFormat(TransferFormat transferFormat) { - using (var server = await StartServer()) + await using (var server = await StartServer()) { var webSocketsTransport = new WebSocketsTransport(httpConnectionOptions: null, loggerFactory: LoggerFactory, accessTokenProvider: null); diff --git a/src/SignalR/server/StackExchangeRedis/test/RedisServerFixture.cs b/src/SignalR/server/StackExchangeRedis/test/RedisServerFixture.cs index ab063ee02a..50ecafbb9f 100644 --- a/src/SignalR/server/StackExchangeRedis/test/RedisServerFixture.cs +++ b/src/SignalR/server/StackExchangeRedis/test/RedisServerFixture.cs @@ -6,12 +6,11 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.SignalR.Tests; using Microsoft.AspNetCore.Testing; using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Logging.Testing; using Xunit; namespace Microsoft.AspNetCore.SignalR.StackExchangeRedis.Tests { - public class RedisServerFixture : IAsyncLifetime, IDisposable + public class RedisServerFixture : IAsyncLifetime where TStartup : class { public InProcessTestServer FirstServer { get; private set; } @@ -37,13 +36,24 @@ namespace Microsoft.AspNetCore.SignalR.StackExchangeRedis.Tests Docker.Default.Start(_logger); } - public Task DisposeAsync() + public async Task DisposeAsync() { - return Task.CompletedTask; + if (Docker.Default != null) + { + await FirstServer.DisposeAsync(); + await SecondServer.DisposeAsync(); + Docker.Default.Stop(_logger); + _logToken.Dispose(); + } } public async Task InitializeAsync() { + if (Docker.Default == null) + { + return; + } + FirstServer = await StartServer(); SecondServer = await StartServer(); } @@ -60,16 +70,5 @@ namespace Microsoft.AspNetCore.SignalR.StackExchangeRedis.Tests throw; } } - - public void Dispose() - { - if (Docker.Default != null) - { - FirstServer.Dispose(); - SecondServer.Dispose(); - Docker.Default.Stop(_logger); - _logToken.Dispose(); - } - } } } diff --git a/src/Tools/dotnet-watch/test/AppWithDepsTests.cs b/src/Tools/dotnet-watch/test/AppWithDepsTests.cs index 5954f540b5..c74e24a6c5 100644 --- a/src/Tools/dotnet-watch/test/AppWithDepsTests.cs +++ b/src/Tools/dotnet-watch/test/AppWithDepsTests.cs @@ -20,7 +20,6 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests } [Fact] - [QuarantinedTest] public async Task ChangeFileInDependency() { await _app.StartWatcherAsync(); diff --git a/src/Tools/dotnet-watch/test/DotNetWatcherTests.cs b/src/Tools/dotnet-watch/test/DotNetWatcherTests.cs index d07f4e25a4..f085a358ae 100644 --- a/src/Tools/dotnet-watch/test/DotNetWatcherTests.cs +++ b/src/Tools/dotnet-watch/test/DotNetWatcherTests.cs @@ -23,7 +23,6 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests } [Fact] - [QuarantinedTest] public async Task RunsWithDotnetWatchEnvVariable() { Assert.True(string.IsNullOrEmpty(Environment.GetEnvironmentVariable("DOTNET_WATCH")), "DOTNET_WATCH cannot be set already when this test is running"); @@ -36,7 +35,6 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests } [Fact] - [QuarantinedTest] public async Task RunsWithIterationEnvVariable() { await _app.StartWatcherAsync(); diff --git a/src/Tools/dotnet-watch/test/GlobbingAppTests.cs b/src/Tools/dotnet-watch/test/GlobbingAppTests.cs index 9383b2d728..8ec696e1fe 100644 --- a/src/Tools/dotnet-watch/test/GlobbingAppTests.cs +++ b/src/Tools/dotnet-watch/test/GlobbingAppTests.cs @@ -24,7 +24,6 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests [Theory] [InlineData(true)] [InlineData(false)] - [QuarantinedTest] public async Task ChangeCompiledFile(bool usePollingWatcher) { _app.UsePollingWatcher = usePollingWatcher; @@ -43,7 +42,6 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests } [Fact] - [QuarantinedTest] public async Task DeleteCompiledFile() { await _app.StartWatcherAsync(); @@ -60,7 +58,6 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests } [Fact] - [QuarantinedTest] public async Task DeleteSourceFolder() { await _app.StartWatcherAsync(); @@ -77,7 +74,6 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests } [Fact] - [QuarantinedTest] public async Task RenameCompiledFile() { await _app.StartWatcherAsync(); @@ -90,7 +86,6 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests } [Fact] - [QuarantinedTest] public async Task ChangeExcludedFile() { await _app.StartWatcherAsync(); diff --git a/src/Tools/dotnet-watch/test/MsBuildFileSetFactoryTest.cs b/src/Tools/dotnet-watch/test/MsBuildFileSetFactoryTest.cs index 4c5907dda6..d3aee43cac 100644 --- a/src/Tools/dotnet-watch/test/MsBuildFileSetFactoryTest.cs +++ b/src/Tools/dotnet-watch/test/MsBuildFileSetFactoryTest.cs @@ -77,7 +77,6 @@ namespace Microsoft.DotNet.Watcher.Tools.Tests } [Fact] - [QuarantinedTest] public async Task SingleTfm() { _tempDir diff --git a/src/Tools/dotnet-watch/test/NoDepsAppTests.cs b/src/Tools/dotnet-watch/test/NoDepsAppTests.cs index b7171d5ad2..6b943e262c 100644 --- a/src/Tools/dotnet-watch/test/NoDepsAppTests.cs +++ b/src/Tools/dotnet-watch/test/NoDepsAppTests.cs @@ -24,7 +24,6 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests } [Fact] - [QuarantinedTest] public async Task RestartProcessOnFileChange() { await _app.StartWatcherAsync(new[] { "--no-exit" }); @@ -43,7 +42,6 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests } [Fact] - [QuarantinedTest] public async Task RestartProcessThatTerminatesAfterFileChange() { await _app.StartWatcherAsync(); diff --git a/src/Tools/dotnet-watch/test/ProgramTests.cs b/src/Tools/dotnet-watch/test/ProgramTests.cs index 1b3f33c5b9..9aa2f540cc 100644 --- a/src/Tools/dotnet-watch/test/ProgramTests.cs +++ b/src/Tools/dotnet-watch/test/ProgramTests.cs @@ -24,7 +24,6 @@ namespace Microsoft.DotNet.Watcher.Tools.Tests } [Fact] - [QuarantinedTest] public async Task ConsoleCancelKey() { _tempDir