2
0
Эх сурвалжийг харах

Merge branch 'master' into merge/release/3.0-preview4-to-master

Doug Bunting 7 жил өмнө
parent
commit
6b3327ee35
57 өөрчлөгдсөн 3080 нэмэгдсэн , 1412 устгасан
  1. 15 15
      .github/CODEOWNERS
  2. 1 0
      build/sources.props
  3. 1 1
      build/tasks/RepoTasks.csproj
  4. 188 188
      eng/Version.Details.xml
  5. 94 94
      eng/Versions.props
  6. 1 1
      global.json
  7. 2 2
      korebuild-lock.txt
  8. 0 1
      src/Components/Blazor/Templates/src/content/BlazorHosted-CSharp/BlazorHosted-CSharp.Server/BlazorHosted-CSharp.Server.csproj
  9. 42 118
      src/Installers/Windows/AspNetCoreModule-Setup/ANCMIISExpressV2/ancm_iis_expressv2.wxs
  10. 134 0
      src/Installers/Windows/AspNetCoreModule-Setup/CustomAction/aspnetcoreCA.cpp
  11. 2 0
      src/Installers/Windows/AspNetCoreModule-Setup/CustomAction/aspnetcoreCA.def
  12. BIN
      src/Installers/Windows/UpgradeLog.htm
  13. 0 2
      src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/wwwroot/css/site.css
  14. 0 2
      src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/wwwroot/css/site.css
  15. 0 2
      src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-FSharp/wwwroot/css/site.css
  16. 2 0
      src/Servers/IIS/IIS/test/Common.FunctionalTests/LogFileTests.cs
  17. 2 0
      src/Servers/Kestrel/Core/ref/Microsoft.AspNetCore.Server.Kestrel.Core.netcoreapp3.0.cs
  18. 117 15
      src/Servers/Kestrel/Core/src/Internal/Http/Http1Connection.cs
  19. 3 0
      src/Servers/Kestrel/Core/src/Internal/Http/Http1ParsingHandler.cs
  20. 556 796
      src/Servers/Kestrel/Core/src/Internal/Http/HttpHeaders.Generated.cs
  21. 1 0
      src/Servers/Kestrel/Core/src/Internal/Http/HttpHeaders.cs
  22. 1 0
      src/Servers/Kestrel/Core/src/Internal/Http/HttpParser.cs
  23. 14 3
      src/Servers/Kestrel/Core/src/Internal/Http/HttpProtocol.cs
  24. 67 11
      src/Servers/Kestrel/Core/src/Internal/Http/HttpRequestHeaders.cs
  25. 1 0
      src/Servers/Kestrel/Core/src/Internal/Http/IHttpHeadersHandler.cs
  26. 3 0
      src/Servers/Kestrel/Core/src/Internal/Http2/Http2Connection.cs
  27. 261 0
      src/Servers/Kestrel/Core/src/Internal/Infrastructure/StringUtilities.cs
  28. 9 0
      src/Servers/Kestrel/Core/src/KestrelServerOptions.cs
  29. 88 9
      src/Servers/Kestrel/Core/test/AsciiDecoding.cs
  30. 2 0
      src/Servers/Kestrel/Core/test/HPackDecoderTests.cs
  31. 2 0
      src/Servers/Kestrel/Core/test/HttpParserTests.cs
  32. 342 1
      src/Servers/Kestrel/Core/test/HttpRequestHeadersTests.cs
  33. 1 0
      src/Servers/Kestrel/Core/test/Microsoft.AspNetCore.Server.Kestrel.Core.Tests.csproj
  34. 536 0
      src/Servers/Kestrel/Core/test/StartLineTests.cs
  35. 3 0
      src/Servers/Kestrel/perf/Kestrel.Performance/Http1ConnectionBenchmark.cs
  36. 7 0
      src/Servers/Kestrel/perf/Kestrel.Performance/HttpParserBenchmark.cs
  37. 1 0
      src/Servers/Kestrel/perf/Kestrel.Performance/Mocks/NullParser.cs
  38. 11 0
      src/Servers/Kestrel/perf/PlatformBenchmarks/BenchmarkApplication.HttpConnection.cs
  39. 431 129
      src/Servers/Kestrel/shared/KnownHeaders.cs
  40. 2 0
      src/Servers/Kestrel/test/BindTests/AddressRegistrationTests.cs
  41. 1 0
      src/Servers/Kestrel/test/FunctionalTests/RequestTests.cs
  42. 2 0
      src/Servers/Kestrel/test/InMemory.FunctionalTests/Http2/Http2TestBase.cs
  43. 1 1
      src/Servers/Kestrel/test/InMemory.FunctionalTests/Http2/Http2TimeoutTests.cs
  44. 1 1
      src/Servers/Kestrel/test/InMemory.FunctionalTests/HttpsConnectionAdapterTests.cs
  45. 2 0
      src/Servers/Kestrel/test/InMemory.FunctionalTests/LoggingConnectionAdapterTests.cs
  46. 4 2
      src/Servers/Kestrel/test/InMemory.FunctionalTests/RequestTests.cs
  47. 4 0
      src/Servers/Kestrel/tools/CodeGenerator/CodeGenerator.csproj
  48. 2 1
      src/Servers/Kestrel/xunit.runner.json
  49. 7 6
      src/Shared/E2ETesting/BrowserFixture.cs
  50. 5 7
      src/SignalR/clients/csharp/Client/test/FunctionalTests/HubConnectionTests.cs
  51. 5 0
      src/SignalR/clients/ts/FunctionalTests/TestHub.cs
  52. 76 0
      src/SignalR/clients/ts/FunctionalTests/ts/HubConnectionTests.ts
  53. 1 0
      src/SignalR/clients/ts/signalr/src/HttpConnection.ts
  54. 7 0
      src/SignalR/clients/ts/signalr/src/HubConnection.ts
  55. 17 2
      src/SignalR/perf/benchmarkapps/Crankier/Client.cs
  56. 1 1
      src/SignalR/perf/benchmarkapps/Crankier/Worker.cs
  57. 1 1
      version.props

+ 15 - 15
.github/CODEOWNERS

@@ -1,18 +1,18 @@
 # Users referenced in this file will automatically be requested as reviewers for PRs that modify the given paths.
 # See https://help.github.com/articles/about-code-owners/
 
-/.azure/ @dougbu
-/.config/ @dougbu
-/build/ @dougbu
-/eng/ @dougbu
-/src/Components/ @SteveSandersonMS
-/src/DefaultBuilder/ @tratcher @anurse
-/src/Hosting/ @tratcher @anurse
-/src/Http/ @tratcher @jkotalik @anurse
-/src/Middleware/ @tratcher @anurse
-/src/ProjectTemplates/ @ryanbrandenburg
-/src/Security/ @tratcher @anurse
-/src/Servers/ @tratcher @jkotalik @anurse
-/src/Middleware/Rewrite @jkotalik @anurse
-/src/Middleware/HttpsPolicy @jkotalik @anurse
-/src/SignalR/ @mikaelm12 @BrennanConroy @halter73 @anurse
+/.azure/                        @aspnet/build
+/.config/                       @aspnet/build
+/build/                         @aspnet/build
+/eng/                           @aspnet/build
+/src/Components/                @SteveSandersonMS
+/src/DefaultBuilder/            @tratcher @anurse
+/src/Hosting/                   @tratcher @anurse
+/src/Http/                      @tratcher @jkotalik @anurse
+/src/Middleware/                @tratcher @anurse
+/src/ProjectTemplates/          @ryanbrandenburg
+/src/Security/                  @tratcher @anurse
+/src/Servers/                   @tratcher @jkotalik @anurse
+/src/Middleware/Rewrite         @jkotalik @anurse
+/src/Middleware/HttpsPolicy     @jkotalik @anurse
+/src/SignalR/                   @mikaelm12 @BrennanConroy @halter73 @anurse

+ 1 - 0
build/sources.props

@@ -20,6 +20,7 @@
       https://dotnet.myget.org/F/aspnetcore-tools/api/v3/index.json;
       https://dotnet.myget.org/F/blazor-dev/api/v3/index.json;
       https://dotnet.myget.org/F/dotnet-core/api/v3/index.json;
+      https://dotnet.myget.org/F/nuget-build/api/v3/index.json;
       https://dotnet.myget.org/F/roslyn-tools/api/v3/index.json;
       https://dotnet.myget.org/F/roslyn/api/v3/index.json;
       https://vside.myget.org/F/devcore/api/v3/index.json;

+ 1 - 1
build/tasks/RepoTasks.csproj

@@ -12,7 +12,7 @@
 
   <ItemGroup>
     <PackageReference Remove="Internal.AspNetCore.Sdk" />
-    <PackageReference Include="NuGet.Build.Tasks" Version="4.9.3" />
+    <PackageReference Include="NuGet.Build.Tasks" Version="5.1.0-rtm.5921" />
     <PackageReference Include="Microsoft.Extensions.DependencyModel" Version="2.1.0" />
     <PackageReference Include="Yarn.MSBuild" Version="1.13.0" />
   </ItemGroup>

+ 188 - 188
eng/Version.Details.xml

@@ -9,384 +9,384 @@
 -->
 <Dependencies>
   <ProductDependencies>
-    <Dependency Name="Microsoft.AspNetCore.Razor.Language" Version="3.0.0-preview4.19209.3">
+    <Dependency Name="Microsoft.AspNetCore.Razor.Language" Version="3.0.0-preview5.19208.6">
       <Uri>https://github.com/aspnet/AspNetCore-Tooling</Uri>
-      <Sha>699014190668f9d631583a771ecfa1be39183624</Sha>
+      <Sha>beebdf43f54ec82e06a48b99812d9740cb9f38cf</Sha>
     </Dependency>
-    <Dependency Name="Microsoft.AspNetCore.Mvc.Razor.Extensions" Version="3.0.0-preview4.19209.3">
+    <Dependency Name="Microsoft.AspNetCore.Mvc.Razor.Extensions" Version="3.0.0-preview5.19208.6">
       <Uri>https://github.com/aspnet/AspNetCore-Tooling</Uri>
-      <Sha>699014190668f9d631583a771ecfa1be39183624</Sha>
+      <Sha>beebdf43f54ec82e06a48b99812d9740cb9f38cf</Sha>
     </Dependency>
-    <Dependency Name="Microsoft.CodeAnalysis.Razor" Version="3.0.0-preview4.19209.3">
+    <Dependency Name="Microsoft.CodeAnalysis.Razor" Version="3.0.0-preview5.19208.6">
       <Uri>https://github.com/aspnet/AspNetCore-Tooling</Uri>
-      <Sha>699014190668f9d631583a771ecfa1be39183624</Sha>
+      <Sha>beebdf43f54ec82e06a48b99812d9740cb9f38cf</Sha>
     </Dependency>
-    <Dependency Name="Microsoft.NET.Sdk.Razor" Version="3.0.0-preview4.19209.3">
+    <Dependency Name="Microsoft.NET.Sdk.Razor" Version="3.0.0-preview5.19208.6">
       <Uri>https://github.com/aspnet/AspNetCore-Tooling</Uri>
-      <Sha>699014190668f9d631583a771ecfa1be39183624</Sha>
+      <Sha>beebdf43f54ec82e06a48b99812d9740cb9f38cf</Sha>
     </Dependency>
-    <Dependency Name="dotnet-ef" Version="3.0.0-preview4.19209.6">
+    <Dependency Name="dotnet-ef" Version="3.0.0-preview5.19208.4">
       <Uri>https://github.com/aspnet/EntityFrameworkCore</Uri>
-      <Sha>c6daea74750e0d3b89f3aa8581ceef068f60373c</Sha>
+      <Sha>243ea5080c4d7eefc96797134c9e10b2fa75f835</Sha>
     </Dependency>
-    <Dependency Name="Microsoft.EntityFrameworkCore.InMemory" Version="3.0.0-preview4.19209.6">
+    <Dependency Name="Microsoft.EntityFrameworkCore.InMemory" Version="3.0.0-preview5.19208.4">
       <Uri>https://github.com/aspnet/EntityFrameworkCore</Uri>
-      <Sha>c6daea74750e0d3b89f3aa8581ceef068f60373c</Sha>
+      <Sha>243ea5080c4d7eefc96797134c9e10b2fa75f835</Sha>
     </Dependency>
-    <Dependency Name="Microsoft.EntityFrameworkCore.Relational" Version="3.0.0-preview4.19209.6">
+    <Dependency Name="Microsoft.EntityFrameworkCore.Relational" Version="3.0.0-preview5.19208.4">
       <Uri>https://github.com/aspnet/EntityFrameworkCore</Uri>
-      <Sha>c6daea74750e0d3b89f3aa8581ceef068f60373c</Sha>
+      <Sha>243ea5080c4d7eefc96797134c9e10b2fa75f835</Sha>
     </Dependency>
-    <Dependency Name="Microsoft.EntityFrameworkCore.Sqlite" Version="3.0.0-preview4.19209.6">
+    <Dependency Name="Microsoft.EntityFrameworkCore.Sqlite" Version="3.0.0-preview5.19208.4">
       <Uri>https://github.com/aspnet/EntityFrameworkCore</Uri>
-      <Sha>c6daea74750e0d3b89f3aa8581ceef068f60373c</Sha>
+      <Sha>243ea5080c4d7eefc96797134c9e10b2fa75f835</Sha>
     </Dependency>
-    <Dependency Name="Microsoft.EntityFrameworkCore.SqlServer" Version="3.0.0-preview4.19209.6">
+    <Dependency Name="Microsoft.EntityFrameworkCore.SqlServer" Version="3.0.0-preview5.19208.4">
       <Uri>https://github.com/aspnet/EntityFrameworkCore</Uri>
-      <Sha>c6daea74750e0d3b89f3aa8581ceef068f60373c</Sha>
+      <Sha>243ea5080c4d7eefc96797134c9e10b2fa75f835</Sha>
     </Dependency>
-    <Dependency Name="Microsoft.EntityFrameworkCore.Tools" Version="3.0.0-preview4.19209.6">
+    <Dependency Name="Microsoft.EntityFrameworkCore.Tools" Version="3.0.0-preview5.19208.4">
       <Uri>https://github.com/aspnet/EntityFrameworkCore</Uri>
-      <Sha>c6daea74750e0d3b89f3aa8581ceef068f60373c</Sha>
+      <Sha>243ea5080c4d7eefc96797134c9e10b2fa75f835</Sha>
     </Dependency>
-    <Dependency Name="Microsoft.EntityFrameworkCore" Version="3.0.0-preview4.19209.6">
+    <Dependency Name="Microsoft.EntityFrameworkCore" Version="3.0.0-preview5.19208.4">
       <Uri>https://github.com/aspnet/EntityFrameworkCore</Uri>
-      <Sha>c6daea74750e0d3b89f3aa8581ceef068f60373c</Sha>
+      <Sha>243ea5080c4d7eefc96797134c9e10b2fa75f835</Sha>
     </Dependency>
-    <Dependency Name="Microsoft.AspNetCore.Analyzer.Testing" Version="3.0.0-preview4.19209.10" CoherentParentDependency="Microsoft.EntityFrameworkCore">
+    <Dependency Name="Microsoft.AspNetCore.Analyzer.Testing" Version="3.0.0-preview4.19207.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
       <Uri>https://github.com/aspnet/Extensions</Uri>
-      <Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha>
+      <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
     </Dependency>
-    <Dependency Name="Microsoft.AspNetCore.BenchmarkRunner.Sources" Version="3.0.0-preview4.19209.10" CoherentParentDependency="Microsoft.EntityFrameworkCore">
+    <Dependency Name="Microsoft.AspNetCore.BenchmarkRunner.Sources" Version="3.0.0-preview4.19207.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
       <Uri>https://github.com/aspnet/Extensions</Uri>
-      <Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha>
+      <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
     </Dependency>
-    <Dependency Name="Microsoft.Extensions.ActivatorUtilities.Sources" Version="3.0.0-preview4.19209.10" CoherentParentDependency="Microsoft.EntityFrameworkCore">
+    <Dependency Name="Microsoft.Extensions.ActivatorUtilities.Sources" Version="3.0.0-preview4.19207.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
       <Uri>https://github.com/aspnet/Extensions</Uri>
-      <Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha>
+      <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
     </Dependency>
-    <Dependency Name="Microsoft.Extensions.Caching.Abstractions" Version="3.0.0-preview4.19209.10" CoherentParentDependency="Microsoft.EntityFrameworkCore">
+    <Dependency Name="Microsoft.Extensions.Caching.Abstractions" Version="3.0.0-preview4.19207.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
       <Uri>https://github.com/aspnet/Extensions</Uri>
-      <Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha>
+      <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
     </Dependency>
-    <Dependency Name="Microsoft.Extensions.Caching.Memory" Version="3.0.0-preview4.19209.10" CoherentParentDependency="Microsoft.EntityFrameworkCore">
+    <Dependency Name="Microsoft.Extensions.Caching.Memory" Version="3.0.0-preview4.19207.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
       <Uri>https://github.com/aspnet/Extensions</Uri>
-      <Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha>
+      <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
     </Dependency>
-    <Dependency Name="Microsoft.Extensions.Caching.SqlServer" Version="3.0.0-preview4.19209.10" CoherentParentDependency="Microsoft.EntityFrameworkCore">
+    <Dependency Name="Microsoft.Extensions.Caching.SqlServer" Version="3.0.0-preview4.19207.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
       <Uri>https://github.com/aspnet/Extensions</Uri>
-      <Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha>
+      <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
     </Dependency>
-    <Dependency Name="Microsoft.Extensions.Caching.StackExchangeRedis" Version="3.0.0-preview4.19209.10" CoherentParentDependency="Microsoft.EntityFrameworkCore">
+    <Dependency Name="Microsoft.Extensions.Caching.StackExchangeRedis" Version="3.0.0-preview4.19207.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
       <Uri>https://github.com/aspnet/Extensions</Uri>
-      <Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha>
+      <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
     </Dependency>
-    <Dependency Name="Microsoft.Extensions.CommandLineUtils.Sources" Version="3.0.0-preview4.19209.10" CoherentParentDependency="Microsoft.EntityFrameworkCore">
+    <Dependency Name="Microsoft.Extensions.CommandLineUtils.Sources" Version="3.0.0-preview4.19207.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
       <Uri>https://github.com/aspnet/Extensions</Uri>
-      <Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha>
+      <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
     </Dependency>
-    <Dependency Name="Microsoft.Extensions.Configuration.Abstractions" Version="3.0.0-preview4.19209.10" CoherentParentDependency="Microsoft.EntityFrameworkCore">
+    <Dependency Name="Microsoft.Extensions.Configuration.Abstractions" Version="3.0.0-preview4.19207.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
       <Uri>https://github.com/aspnet/Extensions</Uri>
-      <Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha>
+      <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
     </Dependency>
-    <Dependency Name="Microsoft.Extensions.Configuration.AzureKeyVault" Version="3.0.0-preview4.19209.10" CoherentParentDependency="Microsoft.EntityFrameworkCore">
+    <Dependency Name="Microsoft.Extensions.Configuration.AzureKeyVault" Version="3.0.0-preview4.19207.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
       <Uri>https://github.com/aspnet/Extensions</Uri>
-      <Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha>
+      <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
     </Dependency>
-    <Dependency Name="Microsoft.Extensions.Configuration.Binder" Version="3.0.0-preview4.19209.10" CoherentParentDependency="Microsoft.EntityFrameworkCore">
+    <Dependency Name="Microsoft.Extensions.Configuration.Binder" Version="3.0.0-preview4.19207.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
       <Uri>https://github.com/aspnet/Extensions</Uri>
-      <Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha>
+      <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
     </Dependency>
-    <Dependency Name="Microsoft.Extensions.Configuration.CommandLine" Version="3.0.0-preview4.19209.10" CoherentParentDependency="Microsoft.EntityFrameworkCore">
+    <Dependency Name="Microsoft.Extensions.Configuration.CommandLine" Version="3.0.0-preview4.19207.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
       <Uri>https://github.com/aspnet/Extensions</Uri>
-      <Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha>
+      <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
     </Dependency>
-    <Dependency Name="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="3.0.0-preview4.19209.10" CoherentParentDependency="Microsoft.EntityFrameworkCore">
+    <Dependency Name="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="3.0.0-preview4.19207.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
       <Uri>https://github.com/aspnet/Extensions</Uri>
-      <Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha>
+      <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
     </Dependency>
-    <Dependency Name="Microsoft.Extensions.Configuration.FileExtensions" Version="3.0.0-preview4.19209.10" CoherentParentDependency="Microsoft.EntityFrameworkCore">
+    <Dependency Name="Microsoft.Extensions.Configuration.FileExtensions" Version="3.0.0-preview4.19207.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
       <Uri>https://github.com/aspnet/Extensions</Uri>
-      <Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha>
+      <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
     </Dependency>
-    <Dependency Name="Microsoft.Extensions.Configuration.Ini" Version="3.0.0-preview4.19209.10" CoherentParentDependency="Microsoft.EntityFrameworkCore">
+    <Dependency Name="Microsoft.Extensions.Configuration.Ini" Version="3.0.0-preview4.19207.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
       <Uri>https://github.com/aspnet/Extensions</Uri>
-      <Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha>
+      <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
     </Dependency>
-    <Dependency Name="Microsoft.Extensions.Configuration.Json" Version="3.0.0-preview4.19209.10" CoherentParentDependency="Microsoft.EntityFrameworkCore">
+    <Dependency Name="Microsoft.Extensions.Configuration.Json" Version="3.0.0-preview4.19207.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
       <Uri>https://github.com/aspnet/Extensions</Uri>
-      <Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha>
+      <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
     </Dependency>
-    <Dependency Name="Microsoft.Extensions.Configuration.KeyPerFile" Version="3.0.0-preview4.19209.10" CoherentParentDependency="Microsoft.EntityFrameworkCore">
+    <Dependency Name="Microsoft.Extensions.Configuration.KeyPerFile" Version="3.0.0-preview4.19207.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
       <Uri>https://github.com/aspnet/Extensions</Uri>
-      <Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha>
+      <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
     </Dependency>
-    <Dependency Name="Microsoft.Extensions.Configuration.UserSecrets" Version="3.0.0-preview4.19209.10" CoherentParentDependency="Microsoft.EntityFrameworkCore">
+    <Dependency Name="Microsoft.Extensions.Configuration.UserSecrets" Version="3.0.0-preview4.19207.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
       <Uri>https://github.com/aspnet/Extensions</Uri>
-      <Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha>
+      <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
     </Dependency>
-    <Dependency Name="Microsoft.Extensions.Configuration.Xml" Version="3.0.0-preview4.19209.10" CoherentParentDependency="Microsoft.EntityFrameworkCore">
+    <Dependency Name="Microsoft.Extensions.Configuration.Xml" Version="3.0.0-preview4.19207.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
       <Uri>https://github.com/aspnet/Extensions</Uri>
-      <Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha>
+      <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
     </Dependency>
-    <Dependency Name="Microsoft.Extensions.Configuration" Version="3.0.0-preview4.19209.10" CoherentParentDependency="Microsoft.EntityFrameworkCore">
+    <Dependency Name="Microsoft.Extensions.Configuration" Version="3.0.0-preview4.19207.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
       <Uri>https://github.com/aspnet/Extensions</Uri>
-      <Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha>
+      <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
     </Dependency>
-    <Dependency Name="Microsoft.Extensions.DependencyInjection.Abstractions" Version="3.0.0-preview4.19209.10" CoherentParentDependency="Microsoft.EntityFrameworkCore">
+    <Dependency Name="Microsoft.Extensions.DependencyInjection.Abstractions" Version="3.0.0-preview4.19207.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
       <Uri>https://github.com/aspnet/Extensions</Uri>
-      <Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha>
+      <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
     </Dependency>
-    <Dependency Name="Microsoft.Extensions.DependencyInjection" Version="3.0.0-preview4.19209.10" CoherentParentDependency="Microsoft.EntityFrameworkCore">
+    <Dependency Name="Microsoft.Extensions.DependencyInjection" Version="3.0.0-preview4.19207.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
       <Uri>https://github.com/aspnet/Extensions</Uri>
-      <Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha>
+      <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
     </Dependency>
-    <Dependency Name="Microsoft.Extensions.DiagnosticAdapter" Version="3.0.0-preview4.19209.10" CoherentParentDependency="Microsoft.EntityFrameworkCore">
+    <Dependency Name="Microsoft.Extensions.DiagnosticAdapter" Version="3.0.0-preview4.19207.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
       <Uri>https://github.com/aspnet/Extensions</Uri>
-      <Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha>
+      <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
     </Dependency>
-    <Dependency Name="Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions" Version="3.0.0-preview4.19209.10" CoherentParentDependency="Microsoft.EntityFrameworkCore">
+    <Dependency Name="Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions" Version="3.0.0-preview4.19207.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
       <Uri>https://github.com/aspnet/Extensions</Uri>
-      <Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha>
+      <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
     </Dependency>
-    <Dependency Name="Microsoft.Extensions.Diagnostics.HealthChecks" Version="3.0.0-preview4.19209.10" CoherentParentDependency="Microsoft.EntityFrameworkCore">
+    <Dependency Name="Microsoft.Extensions.Diagnostics.HealthChecks" Version="3.0.0-preview4.19207.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
       <Uri>https://github.com/aspnet/Extensions</Uri>
-      <Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha>
+      <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
     </Dependency>
-    <Dependency Name="Microsoft.Extensions.FileProviders.Abstractions" Version="3.0.0-preview4.19209.10" CoherentParentDependency="Microsoft.EntityFrameworkCore">
+    <Dependency Name="Microsoft.Extensions.FileProviders.Abstractions" Version="3.0.0-preview4.19207.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
       <Uri>https://github.com/aspnet/Extensions</Uri>
-      <Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha>
+      <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
     </Dependency>
-    <Dependency Name="Microsoft.Extensions.FileProviders.Composite" Version="3.0.0-preview4.19209.10" CoherentParentDependency="Microsoft.EntityFrameworkCore">
+    <Dependency Name="Microsoft.Extensions.FileProviders.Composite" Version="3.0.0-preview4.19207.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
       <Uri>https://github.com/aspnet/Extensions</Uri>
-      <Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha>
+      <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
     </Dependency>
-    <Dependency Name="Microsoft.Extensions.FileProviders.Embedded" Version="3.0.0-preview4.19209.10" CoherentParentDependency="Microsoft.EntityFrameworkCore">
+    <Dependency Name="Microsoft.Extensions.FileProviders.Embedded" Version="3.0.0-preview4.19207.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
       <Uri>https://github.com/aspnet/Extensions</Uri>
-      <Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha>
+      <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
     </Dependency>
-    <Dependency Name="Microsoft.Extensions.FileProviders.Physical" Version="3.0.0-preview4.19209.10" CoherentParentDependency="Microsoft.EntityFrameworkCore">
+    <Dependency Name="Microsoft.Extensions.FileProviders.Physical" Version="3.0.0-preview4.19207.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
       <Uri>https://github.com/aspnet/Extensions</Uri>
-      <Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha>
+      <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
     </Dependency>
-    <Dependency Name="Microsoft.Extensions.FileSystemGlobbing" Version="3.0.0-preview4.19209.10" CoherentParentDependency="Microsoft.EntityFrameworkCore">
+    <Dependency Name="Microsoft.Extensions.FileSystemGlobbing" Version="3.0.0-preview4.19207.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
       <Uri>https://github.com/aspnet/Extensions</Uri>
-      <Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha>
+      <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
     </Dependency>
-    <Dependency Name="Microsoft.Extensions.HashCodeCombiner.Sources" Version="3.0.0-preview4.19209.10" CoherentParentDependency="Microsoft.EntityFrameworkCore">
+    <Dependency Name="Microsoft.Extensions.HashCodeCombiner.Sources" Version="3.0.0-preview4.19207.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
       <Uri>https://github.com/aspnet/Extensions</Uri>
-      <Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha>
+      <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
     </Dependency>
-    <Dependency Name="Microsoft.Extensions.Hosting.Abstractions" Version="3.0.0-preview4.19209.10" CoherentParentDependency="Microsoft.EntityFrameworkCore">
+    <Dependency Name="Microsoft.Extensions.Hosting.Abstractions" Version="3.0.0-preview4.19207.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
       <Uri>https://github.com/aspnet/Extensions</Uri>
-      <Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha>
+      <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
     </Dependency>
-    <Dependency Name="Microsoft.Extensions.Hosting" Version="3.0.0-preview4.19209.10" CoherentParentDependency="Microsoft.EntityFrameworkCore">
+    <Dependency Name="Microsoft.Extensions.Hosting" Version="3.0.0-preview4.19207.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
       <Uri>https://github.com/aspnet/Extensions</Uri>
-      <Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha>
+      <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
     </Dependency>
-    <Dependency Name="Microsoft.Extensions.HostFactoryResolver.Sources" Version="3.0.0-preview4.19209.10" CoherentParentDependency="Microsoft.EntityFrameworkCore">
+    <Dependency Name="Microsoft.Extensions.HostFactoryResolver.Sources" Version="3.0.0-preview4.19207.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
       <Uri>https://github.com/aspnet/Extensions</Uri>
-      <Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha>
+      <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
     </Dependency>
-    <Dependency Name="Microsoft.Extensions.Http" Version="3.0.0-preview4.19209.10" CoherentParentDependency="Microsoft.EntityFrameworkCore">
+    <Dependency Name="Microsoft.Extensions.Http" Version="3.0.0-preview4.19207.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
       <Uri>https://github.com/aspnet/Extensions</Uri>
-      <Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha>
+      <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
     </Dependency>
-    <Dependency Name="Microsoft.Extensions.Localization.Abstractions" Version="3.0.0-preview4.19209.10" CoherentParentDependency="Microsoft.EntityFrameworkCore">
+    <Dependency Name="Microsoft.Extensions.Localization.Abstractions" Version="3.0.0-preview4.19207.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
       <Uri>https://github.com/aspnet/Extensions</Uri>
-      <Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha>
+      <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
     </Dependency>
-    <Dependency Name="Microsoft.Extensions.Localization" Version="3.0.0-preview4.19209.10" CoherentParentDependency="Microsoft.EntityFrameworkCore">
+    <Dependency Name="Microsoft.Extensions.Localization" Version="3.0.0-preview4.19207.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
       <Uri>https://github.com/aspnet/Extensions</Uri>
-      <Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha>
+      <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
     </Dependency>
-    <Dependency Name="Microsoft.Extensions.Logging.Abstractions" Version="3.0.0-preview4.19209.10" CoherentParentDependency="Microsoft.EntityFrameworkCore">
+    <Dependency Name="Microsoft.Extensions.Logging.Abstractions" Version="3.0.0-preview4.19207.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
       <Uri>https://github.com/aspnet/Extensions</Uri>
-      <Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha>
+      <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
     </Dependency>
-    <Dependency Name="Microsoft.Extensions.Logging.AzureAppServices" Version="3.0.0-preview4.19209.10" CoherentParentDependency="Microsoft.EntityFrameworkCore">
+    <Dependency Name="Microsoft.Extensions.Logging.AzureAppServices" Version="3.0.0-preview4.19207.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
       <Uri>https://github.com/aspnet/Extensions</Uri>
-      <Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha>
+      <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
     </Dependency>
-    <Dependency Name="Microsoft.Extensions.Logging.Configuration" Version="3.0.0-preview4.19209.10" CoherentParentDependency="Microsoft.EntityFrameworkCore">
+    <Dependency Name="Microsoft.Extensions.Logging.Configuration" Version="3.0.0-preview4.19207.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
       <Uri>https://github.com/aspnet/Extensions</Uri>
-      <Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha>
+      <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
     </Dependency>
-    <Dependency Name="Microsoft.Extensions.Logging.Console" Version="3.0.0-preview4.19209.10" CoherentParentDependency="Microsoft.EntityFrameworkCore">
+    <Dependency Name="Microsoft.Extensions.Logging.Console" Version="3.0.0-preview4.19207.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
       <Uri>https://github.com/aspnet/Extensions</Uri>
-      <Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha>
+      <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
     </Dependency>
-    <Dependency Name="Microsoft.Extensions.Logging.Debug" Version="3.0.0-preview4.19209.10" CoherentParentDependency="Microsoft.EntityFrameworkCore">
+    <Dependency Name="Microsoft.Extensions.Logging.Debug" Version="3.0.0-preview4.19207.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
       <Uri>https://github.com/aspnet/Extensions</Uri>
-      <Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha>
+      <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
     </Dependency>
-    <Dependency Name="Microsoft.Extensions.Logging.EventSource" Version="3.0.0-preview4.19209.10" CoherentParentDependency="Microsoft.EntityFrameworkCore">
+    <Dependency Name="Microsoft.Extensions.Logging.EventSource" Version="3.0.0-preview4.19207.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
       <Uri>https://github.com/aspnet/Extensions</Uri>
-      <Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha>
+      <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
     </Dependency>
-    <Dependency Name="Microsoft.Extensions.Logging.TraceSource" Version="3.0.0-preview4.19209.10" CoherentParentDependency="Microsoft.EntityFrameworkCore">
+    <Dependency Name="Microsoft.Extensions.Logging.TraceSource" Version="3.0.0-preview4.19207.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
       <Uri>https://github.com/aspnet/Extensions</Uri>
-      <Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha>
+      <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
     </Dependency>
-    <Dependency Name="Microsoft.Extensions.Logging.Testing" Version="3.0.0-preview4.19209.10" CoherentParentDependency="Microsoft.EntityFrameworkCore">
+    <Dependency Name="Microsoft.Extensions.Logging.Testing" Version="3.0.0-preview4.19207.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
       <Uri>https://github.com/aspnet/Extensions</Uri>
-      <Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha>
+      <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
     </Dependency>
-    <Dependency Name="Microsoft.Extensions.Logging" Version="3.0.0-preview4.19209.10" CoherentParentDependency="Microsoft.EntityFrameworkCore">
+    <Dependency Name="Microsoft.Extensions.Logging" Version="3.0.0-preview4.19207.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
       <Uri>https://github.com/aspnet/Extensions</Uri>
-      <Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha>
+      <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
     </Dependency>
-    <Dependency Name="Microsoft.Extensions.ObjectPool" Version="3.0.0-preview4.19209.10" CoherentParentDependency="Microsoft.EntityFrameworkCore">
+    <Dependency Name="Microsoft.Extensions.ObjectPool" Version="3.0.0-preview4.19207.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
       <Uri>https://github.com/aspnet/Extensions</Uri>
-      <Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha>
+      <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
     </Dependency>
-    <Dependency Name="Microsoft.Extensions.Options.ConfigurationExtensions" Version="3.0.0-preview4.19209.10" CoherentParentDependency="Microsoft.EntityFrameworkCore">
+    <Dependency Name="Microsoft.Extensions.Options.ConfigurationExtensions" Version="3.0.0-preview4.19207.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
       <Uri>https://github.com/aspnet/Extensions</Uri>
-      <Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha>
+      <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
     </Dependency>
-    <Dependency Name="Microsoft.Extensions.Options.DataAnnotations" Version="3.0.0-preview4.19209.10" CoherentParentDependency="Microsoft.EntityFrameworkCore">
+    <Dependency Name="Microsoft.Extensions.Options.DataAnnotations" Version="3.0.0-preview4.19207.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
       <Uri>https://github.com/aspnet/Extensions</Uri>
-      <Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha>
+      <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
     </Dependency>
-    <Dependency Name="Microsoft.Extensions.Options" Version="3.0.0-preview4.19209.10" CoherentParentDependency="Microsoft.EntityFrameworkCore">
+    <Dependency Name="Microsoft.Extensions.Options" Version="3.0.0-preview4.19207.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
       <Uri>https://github.com/aspnet/Extensions</Uri>
-      <Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha>
+      <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
     </Dependency>
-    <Dependency Name="Microsoft.Extensions.ParameterDefaultValue.Sources" Version="3.0.0-preview4.19209.10" CoherentParentDependency="Microsoft.EntityFrameworkCore">
+    <Dependency Name="Microsoft.Extensions.ParameterDefaultValue.Sources" Version="3.0.0-preview4.19207.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
       <Uri>https://github.com/aspnet/Extensions</Uri>
-      <Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha>
+      <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
     </Dependency>
-    <Dependency Name="Microsoft.Extensions.Primitives" Version="3.0.0-preview4.19209.10" CoherentParentDependency="Microsoft.EntityFrameworkCore">
+    <Dependency Name="Microsoft.Extensions.Primitives" Version="3.0.0-preview4.19207.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
       <Uri>https://github.com/aspnet/Extensions</Uri>
-      <Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha>
+      <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
     </Dependency>
-    <Dependency Name="Microsoft.Extensions.TypeNameHelper.Sources" Version="3.0.0-preview4.19209.10" CoherentParentDependency="Microsoft.EntityFrameworkCore">
+    <Dependency Name="Microsoft.Extensions.TypeNameHelper.Sources" Version="3.0.0-preview4.19207.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
       <Uri>https://github.com/aspnet/Extensions</Uri>
-      <Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha>
+      <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
     </Dependency>
-    <Dependency Name="Microsoft.Extensions.ValueStopwatch.Sources" Version="3.0.0-preview4.19209.10" CoherentParentDependency="Microsoft.EntityFrameworkCore">
+    <Dependency Name="Microsoft.Extensions.ValueStopwatch.Sources" Version="3.0.0-preview4.19207.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
       <Uri>https://github.com/aspnet/Extensions</Uri>
-      <Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha>
+      <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
     </Dependency>
-    <Dependency Name="Microsoft.Extensions.WebEncoders" Version="3.0.0-preview4.19209.10" CoherentParentDependency="Microsoft.EntityFrameworkCore">
+    <Dependency Name="Microsoft.Extensions.WebEncoders" Version="3.0.0-preview4.19207.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
       <Uri>https://github.com/aspnet/Extensions</Uri>
-      <Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha>
+      <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
     </Dependency>
-    <Dependency Name="Microsoft.Internal.Extensions.Refs" Version="3.0.0-preview4.19209.10" CoherentParentDependency="Microsoft.EntityFrameworkCore">
+    <Dependency Name="Microsoft.Internal.Extensions.Refs" Version="3.0.0-preview4.19207.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
       <Uri>https://github.com/aspnet/Extensions</Uri>
-      <Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha>
+      <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
     </Dependency>
-    <Dependency Name="Microsoft.JSInterop" Version="3.0.0-preview4.19209.10" CoherentParentDependency="Microsoft.EntityFrameworkCore">
+    <Dependency Name="Microsoft.JSInterop" Version="3.0.0-preview4.19207.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
       <Uri>https://github.com/aspnet/Extensions</Uri>
-      <Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha>
+      <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
     </Dependency>
-    <Dependency Name="Mono.WebAssembly.Interop" Version="3.0.0-preview4.19209.10" CoherentParentDependency="Microsoft.EntityFrameworkCore">
+    <Dependency Name="Mono.WebAssembly.Interop" Version="3.0.0-preview4.19207.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
       <Uri>https://github.com/aspnet/Extensions</Uri>
-      <Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha>
+      <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
     </Dependency>
-    <Dependency Name="Microsoft.Bcl.Json.Sources" Version="4.6.0-preview4.19208.6" CoherentParentDependency="Microsoft.NETCore.App">
+    <Dependency Name="Microsoft.Bcl.Json.Sources" Version="4.6.0-preview5.19206.5" CoherentParentDependency="Microsoft.NETCore.App">
       <Uri>https://github.com/dotnet/corefx</Uri>
-      <Sha>e0a01a12c2676d69cefa61aa2526a414d7f2dabb</Sha>
+      <Sha>81fe62442228cb26bd0d95ceec3e0a3b74bde0a2</Sha>
     </Dependency>
-    <Dependency Name="Microsoft.CSharp" Version="4.6.0-preview4.19208.6" CoherentParentDependency="Microsoft.NETCore.App">
+    <Dependency Name="Microsoft.CSharp" Version="4.6.0-preview5.19206.5" CoherentParentDependency="Microsoft.NETCore.App">
       <Uri>https://github.com/dotnet/corefx</Uri>
-      <Sha>e0a01a12c2676d69cefa61aa2526a414d7f2dabb</Sha>
+      <Sha>81fe62442228cb26bd0d95ceec3e0a3b74bde0a2</Sha>
     </Dependency>
-    <Dependency Name="Microsoft.Win32.Registry" Version="4.6.0-preview4.19208.6" CoherentParentDependency="Microsoft.NETCore.App">
+    <Dependency Name="Microsoft.Win32.Registry" Version="4.6.0-preview5.19206.5" CoherentParentDependency="Microsoft.NETCore.App">
       <Uri>https://github.com/dotnet/corefx</Uri>
-      <Sha>e0a01a12c2676d69cefa61aa2526a414d7f2dabb</Sha>
+      <Sha>81fe62442228cb26bd0d95ceec3e0a3b74bde0a2</Sha>
     </Dependency>
-    <Dependency Name="System.ComponentModel.Annotations" Version="4.6.0-preview4.19208.6" CoherentParentDependency="Microsoft.NETCore.App">
+    <Dependency Name="System.ComponentModel.Annotations" Version="4.6.0-preview5.19206.5" CoherentParentDependency="Microsoft.NETCore.App">
       <Uri>https://github.com/dotnet/corefx</Uri>
-      <Sha>e0a01a12c2676d69cefa61aa2526a414d7f2dabb</Sha>
+      <Sha>81fe62442228cb26bd0d95ceec3e0a3b74bde0a2</Sha>
     </Dependency>
-    <Dependency Name="System.Data.SqlClient" Version="4.7.0-preview4.19208.6" CoherentParentDependency="Microsoft.NETCore.App">
+    <Dependency Name="System.Data.SqlClient" Version="4.7.0-preview5.19206.5" CoherentParentDependency="Microsoft.NETCore.App">
       <Uri>https://github.com/dotnet/corefx</Uri>
-      <Sha>e0a01a12c2676d69cefa61aa2526a414d7f2dabb</Sha>
+      <Sha>81fe62442228cb26bd0d95ceec3e0a3b74bde0a2</Sha>
     </Dependency>
-    <Dependency Name="System.Diagnostics.EventLog" Version="4.6.0-preview4.19208.6" CoherentParentDependency="Microsoft.NETCore.App">
+    <Dependency Name="System.Diagnostics.EventLog" Version="4.6.0-preview5.19206.5" CoherentParentDependency="Microsoft.NETCore.App">
       <Uri>https://github.com/dotnet/corefx</Uri>
-      <Sha>e0a01a12c2676d69cefa61aa2526a414d7f2dabb</Sha>
+      <Sha>81fe62442228cb26bd0d95ceec3e0a3b74bde0a2</Sha>
     </Dependency>
-    <Dependency Name="System.IO.Pipelines" Version="4.6.0-preview4.19208.6" CoherentParentDependency="Microsoft.NETCore.App">
+    <Dependency Name="System.IO.Pipelines" Version="4.6.0-preview5.19206.5" CoherentParentDependency="Microsoft.NETCore.App">
       <Uri>https://github.com/dotnet/corefx</Uri>
-      <Sha>e0a01a12c2676d69cefa61aa2526a414d7f2dabb</Sha>
+      <Sha>81fe62442228cb26bd0d95ceec3e0a3b74bde0a2</Sha>
     </Dependency>
-    <Dependency Name="System.Net.Http.WinHttpHandler" Version="4.6.0-preview4.19208.6" CoherentParentDependency="Microsoft.NETCore.App">
+    <Dependency Name="System.Net.Http.WinHttpHandler" Version="4.6.0-preview5.19206.5" CoherentParentDependency="Microsoft.NETCore.App">
       <Uri>https://github.com/dotnet/corefx</Uri>
-      <Sha>e0a01a12c2676d69cefa61aa2526a414d7f2dabb</Sha>
+      <Sha>81fe62442228cb26bd0d95ceec3e0a3b74bde0a2</Sha>
     </Dependency>
-    <Dependency Name="System.Net.WebSockets.WebSocketProtocol" Version="4.6.0-preview4.19208.6" CoherentParentDependency="Microsoft.NETCore.App">
+    <Dependency Name="System.Net.WebSockets.WebSocketProtocol" Version="4.6.0-preview5.19206.5" CoherentParentDependency="Microsoft.NETCore.App">
       <Uri>https://github.com/dotnet/corefx</Uri>
-      <Sha>e0a01a12c2676d69cefa61aa2526a414d7f2dabb</Sha>
+      <Sha>81fe62442228cb26bd0d95ceec3e0a3b74bde0a2</Sha>
     </Dependency>
-    <Dependency Name="System.Reflection.Metadata" Version="1.7.0-preview4.19208.6" CoherentParentDependency="Microsoft.NETCore.App">
+    <Dependency Name="System.Reflection.Metadata" Version="1.7.0-preview5.19206.5" CoherentParentDependency="Microsoft.NETCore.App">
       <Uri>https://github.com/dotnet/corefx</Uri>
-      <Sha>e0a01a12c2676d69cefa61aa2526a414d7f2dabb</Sha>
+      <Sha>81fe62442228cb26bd0d95ceec3e0a3b74bde0a2</Sha>
     </Dependency>
-    <Dependency Name="System.Runtime.CompilerServices.Unsafe" Version="4.6.0-preview4.19208.6" CoherentParentDependency="Microsoft.NETCore.App">
+    <Dependency Name="System.Runtime.CompilerServices.Unsafe" Version="4.6.0-preview5.19206.5" CoherentParentDependency="Microsoft.NETCore.App">
       <Uri>https://github.com/dotnet/corefx</Uri>
-      <Sha>e0a01a12c2676d69cefa61aa2526a414d7f2dabb</Sha>
+      <Sha>81fe62442228cb26bd0d95ceec3e0a3b74bde0a2</Sha>
     </Dependency>
-    <Dependency Name="System.Security.Cryptography.Cng" Version="4.6.0-preview4.19208.6" CoherentParentDependency="Microsoft.NETCore.App">
+    <Dependency Name="System.Security.Cryptography.Cng" Version="4.6.0-preview5.19206.5" CoherentParentDependency="Microsoft.NETCore.App">
       <Uri>https://github.com/dotnet/corefx</Uri>
-      <Sha>e0a01a12c2676d69cefa61aa2526a414d7f2dabb</Sha>
+      <Sha>81fe62442228cb26bd0d95ceec3e0a3b74bde0a2</Sha>
     </Dependency>
-    <Dependency Name="System.Security.Cryptography.Pkcs" Version="4.6.0-preview4.19208.6" CoherentParentDependency="Microsoft.NETCore.App">
+    <Dependency Name="System.Security.Cryptography.Pkcs" Version="4.6.0-preview5.19206.5" CoherentParentDependency="Microsoft.NETCore.App">
       <Uri>https://github.com/dotnet/corefx</Uri>
-      <Sha>e0a01a12c2676d69cefa61aa2526a414d7f2dabb</Sha>
+      <Sha>81fe62442228cb26bd0d95ceec3e0a3b74bde0a2</Sha>
     </Dependency>
-    <Dependency Name="System.Security.Cryptography.Xml" Version="4.6.0-preview4.19208.6" CoherentParentDependency="Microsoft.NETCore.App">
+    <Dependency Name="System.Security.Cryptography.Xml" Version="4.6.0-preview5.19206.5" CoherentParentDependency="Microsoft.NETCore.App">
       <Uri>https://github.com/dotnet/corefx</Uri>
-      <Sha>e0a01a12c2676d69cefa61aa2526a414d7f2dabb</Sha>
+      <Sha>81fe62442228cb26bd0d95ceec3e0a3b74bde0a2</Sha>
     </Dependency>
-    <Dependency Name="System.Security.Permissions" Version="4.6.0-preview4.19208.6" CoherentParentDependency="Microsoft.NETCore.App">
+    <Dependency Name="System.Security.Permissions" Version="4.6.0-preview5.19206.5" CoherentParentDependency="Microsoft.NETCore.App">
       <Uri>https://github.com/dotnet/corefx</Uri>
-      <Sha>e0a01a12c2676d69cefa61aa2526a414d7f2dabb</Sha>
+      <Sha>81fe62442228cb26bd0d95ceec3e0a3b74bde0a2</Sha>
     </Dependency>
-    <Dependency Name="System.Security.Principal.Windows" Version="4.6.0-preview4.19208.6" CoherentParentDependency="Microsoft.NETCore.App">
+    <Dependency Name="System.Security.Principal.Windows" Version="4.6.0-preview5.19206.5" CoherentParentDependency="Microsoft.NETCore.App">
       <Uri>https://github.com/dotnet/corefx</Uri>
-      <Sha>e0a01a12c2676d69cefa61aa2526a414d7f2dabb</Sha>
+      <Sha>81fe62442228cb26bd0d95ceec3e0a3b74bde0a2</Sha>
     </Dependency>
-    <Dependency Name="System.ServiceProcess.ServiceController" Version="4.6.0-preview4.19208.6" CoherentParentDependency="Microsoft.NETCore.App">
+    <Dependency Name="System.ServiceProcess.ServiceController" Version="4.6.0-preview5.19206.5" CoherentParentDependency="Microsoft.NETCore.App">
       <Uri>https://github.com/dotnet/corefx</Uri>
-      <Sha>e0a01a12c2676d69cefa61aa2526a414d7f2dabb</Sha>
+      <Sha>81fe62442228cb26bd0d95ceec3e0a3b74bde0a2</Sha>
     </Dependency>
-    <Dependency Name="System.Text.Encodings.Web" Version="4.6.0-preview4.19208.6" CoherentParentDependency="Microsoft.NETCore.App">
+    <Dependency Name="System.Text.Encodings.Web" Version="4.6.0-preview5.19206.5" CoherentParentDependency="Microsoft.NETCore.App">
       <Uri>https://github.com/dotnet/corefx</Uri>
-      <Sha>e0a01a12c2676d69cefa61aa2526a414d7f2dabb</Sha>
+      <Sha>81fe62442228cb26bd0d95ceec3e0a3b74bde0a2</Sha>
     </Dependency>
-    <Dependency Name="System.Threading.Channels" Version="4.6.0-preview4.19208.6" CoherentParentDependency="Microsoft.NETCore.App">
+    <Dependency Name="System.Threading.Channels" Version="4.6.0-preview5.19206.5" CoherentParentDependency="Microsoft.NETCore.App">
       <Uri>https://github.com/dotnet/corefx</Uri>
-      <Sha>e0a01a12c2676d69cefa61aa2526a414d7f2dabb</Sha>
+      <Sha>81fe62442228cb26bd0d95ceec3e0a3b74bde0a2</Sha>
     </Dependency>
-    <Dependency Name="Microsoft.Extensions.DependencyModel" Version="3.0.0-preview4-27609-12" CoherentParentDependency="Microsoft.Extensions.Logging">
+    <Dependency Name="Microsoft.Extensions.DependencyModel" Version="3.0.0-preview5-27606-09" CoherentParentDependency="Microsoft.Extensions.Logging">
       <Uri>https://github.com/dotnet/core-setup</Uri>
-      <Sha>89ba5a781188bb95f7de3c2714fdddd19f341f32</Sha>
+      <Sha>42a6743d709c3d74f1cb7a2af8740e3183a022f4</Sha>
     </Dependency>
-    <Dependency Name="Microsoft.NETCore.App" Version="3.0.0-preview4-27609-12" CoherentParentDependency="Microsoft.Extensions.Logging">
+    <Dependency Name="Microsoft.NETCore.App" Version="3.0.0-preview5-27606-09" CoherentParentDependency="Microsoft.Extensions.Logging">
       <Uri>https://github.com/dotnet/core-setup</Uri>
-      <Sha>89ba5a781188bb95f7de3c2714fdddd19f341f32</Sha>
+      <Sha>42a6743d709c3d74f1cb7a2af8740e3183a022f4</Sha>
     </Dependency>
   </ProductDependencies>
   <ToolsetDependencies>
     <!-- Listed explicitly to workaround https://github.com/dotnet/cli/issues/10528 -->
-    <Dependency Name="Microsoft.NETCore.Platforms" Version="3.0.0-preview4.19208.6" CoherentParentDependency="Microsoft.NETCore.App">
+    <Dependency Name="Microsoft.NETCore.Platforms" Version="3.0.0-preview5.19206.5" CoherentParentDependency="Microsoft.NETCore.App">
       <Uri>https://github.com/dotnet/corefx</Uri>
-      <Sha>e0a01a12c2676d69cefa61aa2526a414d7f2dabb</Sha>
+      <Sha>81fe62442228cb26bd0d95ceec3e0a3b74bde0a2</Sha>
     </Dependency>
-    <Dependency Name="Internal.AspNetCore.Analyzers" Version="3.0.0-preview4.19209.10" CoherentParentDependency="Microsoft.EntityFrameworkCore">
+    <Dependency Name="Internal.AspNetCore.Analyzers" Version="3.0.0-preview4.19207.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
       <Uri>https://github.com/aspnet/Extensions</Uri>
-      <Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha>
+      <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
     </Dependency>
-    <Dependency Name="Microsoft.DotNet.GenAPI" Version="1.0.0-beta.19207.1">
+    <Dependency Name="Microsoft.DotNet.GenAPI" Version="1.0.0-beta.19209.1">
       <Uri>https://github.com/dotnet/arcade</Uri>
-      <Sha>b1f9e12fe3ee71c48ea60b15968745850ac0a4a7</Sha>
+      <Sha>9d7e665ecf2606094677524ecd5af0fc39c7bb49</Sha>
     </Dependency>
-    <Dependency Name="Microsoft.AspNetCore.Testing" Version="3.0.0-preview4.19209.10" CoherentParentDependency="Microsoft.EntityFrameworkCore">
+    <Dependency Name="Microsoft.AspNetCore.Testing" Version="3.0.0-preview4.19207.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
       <Uri>https://github.com/aspnet/Extensions</Uri>
-      <Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha>
+      <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
     </Dependency>
   </ToolsetDependencies>
 </Dependencies>

+ 94 - 94
eng/Versions.props

@@ -17,106 +17,106 @@
   -->
   <PropertyGroup Label="Automated">
     <!-- Packages from dotnet/arcade -->
-    <MicrosoftDotNetGenAPIPackageVersion>1.0.0-beta.19207.1</MicrosoftDotNetGenAPIPackageVersion>
+    <MicrosoftDotNetGenAPIPackageVersion>1.0.0-beta.19209.1</MicrosoftDotNetGenAPIPackageVersion>
     <!-- Packages from dotnet/core-setup -->
-    <MicrosoftExtensionsDependencyModelPackageVersion>3.0.0-preview4-27609-12</MicrosoftExtensionsDependencyModelPackageVersion>
-    <MicrosoftNETCoreAppPackageVersion>3.0.0-preview4-27609-12</MicrosoftNETCoreAppPackageVersion>
+    <MicrosoftExtensionsDependencyModelPackageVersion>3.0.0-preview5-27606-09</MicrosoftExtensionsDependencyModelPackageVersion>
+    <MicrosoftNETCoreAppPackageVersion>3.0.0-preview5-27606-09</MicrosoftNETCoreAppPackageVersion>
     <!-- Packages from dotnet/corefx -->
-    <MicrosoftBclJsonSourcesPackageVersion>4.6.0-preview4.19208.6</MicrosoftBclJsonSourcesPackageVersion>
-    <MicrosoftCSharpPackageVersion>4.6.0-preview4.19208.6</MicrosoftCSharpPackageVersion>
-    <MicrosoftWin32RegistryPackageVersion>4.6.0-preview4.19208.6</MicrosoftWin32RegistryPackageVersion>
-    <SystemComponentModelAnnotationsPackageVersion>4.6.0-preview4.19208.6</SystemComponentModelAnnotationsPackageVersion>
-    <SystemDataSqlClientPackageVersion>4.7.0-preview4.19208.6</SystemDataSqlClientPackageVersion>
-    <SystemDiagnosticsEventLogPackageVersion>4.6.0-preview4.19208.6</SystemDiagnosticsEventLogPackageVersion>
-    <SystemIOPipelinesPackageVersion>4.6.0-preview4.19208.6</SystemIOPipelinesPackageVersion>
-    <SystemNetHttpWinHttpHandlerPackageVersion>4.6.0-preview4.19208.6</SystemNetHttpWinHttpHandlerPackageVersion>
-    <SystemNetWebSocketsWebSocketProtocolPackageVersion>4.6.0-preview4.19208.6</SystemNetWebSocketsWebSocketProtocolPackageVersion>
-    <SystemReflectionMetadataPackageVersion>1.7.0-preview4.19208.6</SystemReflectionMetadataPackageVersion>
-    <SystemRuntimeCompilerServicesUnsafePackageVersion>4.6.0-preview4.19208.6</SystemRuntimeCompilerServicesUnsafePackageVersion>
-    <SystemSecurityCryptographyCngPackageVersion>4.6.0-preview4.19208.6</SystemSecurityCryptographyCngPackageVersion>
-    <SystemSecurityCryptographyPkcsPackageVersion>4.6.0-preview4.19208.6</SystemSecurityCryptographyPkcsPackageVersion>
-    <SystemSecurityCryptographyXmlPackageVersion>4.6.0-preview4.19208.6</SystemSecurityCryptographyXmlPackageVersion>
-    <SystemSecurityPermissionsPackageVersion>4.6.0-preview4.19208.6</SystemSecurityPermissionsPackageVersion>
-    <SystemSecurityPrincipalWindowsPackageVersion>4.6.0-preview4.19208.6</SystemSecurityPrincipalWindowsPackageVersion>
-    <SystemServiceProcessServiceControllerPackageVersion>4.6.0-preview4.19208.6</SystemServiceProcessServiceControllerPackageVersion>
-    <SystemTextEncodingsWebPackageVersion>4.6.0-preview4.19208.6</SystemTextEncodingsWebPackageVersion>
-    <SystemThreadingChannelsPackageVersion>4.6.0-preview4.19208.6</SystemThreadingChannelsPackageVersion>
+    <MicrosoftBclJsonSourcesPackageVersion>4.6.0-preview5.19206.5</MicrosoftBclJsonSourcesPackageVersion>
+    <MicrosoftCSharpPackageVersion>4.6.0-preview5.19206.5</MicrosoftCSharpPackageVersion>
+    <MicrosoftWin32RegistryPackageVersion>4.6.0-preview5.19206.5</MicrosoftWin32RegistryPackageVersion>
+    <SystemComponentModelAnnotationsPackageVersion>4.6.0-preview5.19206.5</SystemComponentModelAnnotationsPackageVersion>
+    <SystemDataSqlClientPackageVersion>4.7.0-preview5.19206.5</SystemDataSqlClientPackageVersion>
+    <SystemDiagnosticsEventLogPackageVersion>4.6.0-preview5.19206.5</SystemDiagnosticsEventLogPackageVersion>
+    <SystemIOPipelinesPackageVersion>4.6.0-preview5.19206.5</SystemIOPipelinesPackageVersion>
+    <SystemNetHttpWinHttpHandlerPackageVersion>4.6.0-preview5.19206.5</SystemNetHttpWinHttpHandlerPackageVersion>
+    <SystemNetWebSocketsWebSocketProtocolPackageVersion>4.6.0-preview5.19206.5</SystemNetWebSocketsWebSocketProtocolPackageVersion>
+    <SystemReflectionMetadataPackageVersion>1.7.0-preview5.19206.5</SystemReflectionMetadataPackageVersion>
+    <SystemRuntimeCompilerServicesUnsafePackageVersion>4.6.0-preview5.19206.5</SystemRuntimeCompilerServicesUnsafePackageVersion>
+    <SystemSecurityCryptographyCngPackageVersion>4.6.0-preview5.19206.5</SystemSecurityCryptographyCngPackageVersion>
+    <SystemSecurityCryptographyPkcsPackageVersion>4.6.0-preview5.19206.5</SystemSecurityCryptographyPkcsPackageVersion>
+    <SystemSecurityCryptographyXmlPackageVersion>4.6.0-preview5.19206.5</SystemSecurityCryptographyXmlPackageVersion>
+    <SystemSecurityPermissionsPackageVersion>4.6.0-preview5.19206.5</SystemSecurityPermissionsPackageVersion>
+    <SystemSecurityPrincipalWindowsPackageVersion>4.6.0-preview5.19206.5</SystemSecurityPrincipalWindowsPackageVersion>
+    <SystemServiceProcessServiceControllerPackageVersion>4.6.0-preview5.19206.5</SystemServiceProcessServiceControllerPackageVersion>
+    <SystemTextEncodingsWebPackageVersion>4.6.0-preview5.19206.5</SystemTextEncodingsWebPackageVersion>
+    <SystemThreadingChannelsPackageVersion>4.6.0-preview5.19206.5</SystemThreadingChannelsPackageVersion>
     <!-- Only listed explicitly to workaround https://github.com/dotnet/cli/issues/10528 -->
-    <MicrosoftNETCorePlatformsPackageVersion>3.0.0-preview4.19208.6</MicrosoftNETCorePlatformsPackageVersion>
+    <MicrosoftNETCorePlatformsPackageVersion>3.0.0-preview5.19206.5</MicrosoftNETCorePlatformsPackageVersion>
     <!-- Packages from aspnet/Extensions -->
-    <InternalAspNetCoreAnalyzersPackageVersion>3.0.0-preview4.19209.10</InternalAspNetCoreAnalyzersPackageVersion>
-    <MicrosoftAspNetCoreAnalyzerTestingPackageVersion>3.0.0-preview4.19209.10</MicrosoftAspNetCoreAnalyzerTestingPackageVersion>
-    <MicrosoftAspNetCoreBenchmarkRunnerSourcesPackageVersion>3.0.0-preview4.19209.10</MicrosoftAspNetCoreBenchmarkRunnerSourcesPackageVersion>
-    <MicrosoftAspNetCoreTestingPackageVersion>3.0.0-preview4.19209.10</MicrosoftAspNetCoreTestingPackageVersion>
-    <MicrosoftExtensionsActivatorUtilitiesSourcesPackageVersion>3.0.0-preview4.19209.10</MicrosoftExtensionsActivatorUtilitiesSourcesPackageVersion>
-    <MicrosoftExtensionsCachingAbstractionsPackageVersion>3.0.0-preview4.19209.10</MicrosoftExtensionsCachingAbstractionsPackageVersion>
-    <MicrosoftExtensionsCachingMemoryPackageVersion>3.0.0-preview4.19209.10</MicrosoftExtensionsCachingMemoryPackageVersion>
-    <MicrosoftExtensionsCachingSqlServerPackageVersion>3.0.0-preview4.19209.10</MicrosoftExtensionsCachingSqlServerPackageVersion>
-    <MicrosoftExtensionsCachingStackExchangeRedisPackageVersion>3.0.0-preview4.19209.10</MicrosoftExtensionsCachingStackExchangeRedisPackageVersion>
-    <MicrosoftExtensionsCommandLineUtilsSourcesPackageVersion>3.0.0-preview4.19209.10</MicrosoftExtensionsCommandLineUtilsSourcesPackageVersion>
-    <MicrosoftExtensionsConfigurationAbstractionsPackageVersion>3.0.0-preview4.19209.10</MicrosoftExtensionsConfigurationAbstractionsPackageVersion>
-    <MicrosoftExtensionsConfigurationAzureKeyVaultPackageVersion>3.0.0-preview4.19209.10</MicrosoftExtensionsConfigurationAzureKeyVaultPackageVersion>
-    <MicrosoftExtensionsConfigurationBinderPackageVersion>3.0.0-preview4.19209.10</MicrosoftExtensionsConfigurationBinderPackageVersion>
-    <MicrosoftExtensionsConfigurationCommandLinePackageVersion>3.0.0-preview4.19209.10</MicrosoftExtensionsConfigurationCommandLinePackageVersion>
-    <MicrosoftExtensionsConfigurationEnvironmentVariablesPackageVersion>3.0.0-preview4.19209.10</MicrosoftExtensionsConfigurationEnvironmentVariablesPackageVersion>
-    <MicrosoftExtensionsConfigurationFileExtensionsPackageVersion>3.0.0-preview4.19209.10</MicrosoftExtensionsConfigurationFileExtensionsPackageVersion>
-    <MicrosoftExtensionsConfigurationIniPackageVersion>3.0.0-preview4.19209.10</MicrosoftExtensionsConfigurationIniPackageVersion>
-    <MicrosoftExtensionsConfigurationJsonPackageVersion>3.0.0-preview4.19209.10</MicrosoftExtensionsConfigurationJsonPackageVersion>
-    <MicrosoftExtensionsConfigurationKeyPerFilePackageVersion>3.0.0-preview4.19209.10</MicrosoftExtensionsConfigurationKeyPerFilePackageVersion>
-    <MicrosoftExtensionsConfigurationPackageVersion>3.0.0-preview4.19209.10</MicrosoftExtensionsConfigurationPackageVersion>
-    <MicrosoftExtensionsConfigurationUserSecretsPackageVersion>3.0.0-preview4.19209.10</MicrosoftExtensionsConfigurationUserSecretsPackageVersion>
-    <MicrosoftExtensionsConfigurationXmlPackageVersion>3.0.0-preview4.19209.10</MicrosoftExtensionsConfigurationXmlPackageVersion>
-    <MicrosoftExtensionsDependencyInjectionAbstractionsPackageVersion>3.0.0-preview4.19209.10</MicrosoftExtensionsDependencyInjectionAbstractionsPackageVersion>
-    <MicrosoftExtensionsDependencyInjectionPackageVersion>3.0.0-preview4.19209.10</MicrosoftExtensionsDependencyInjectionPackageVersion>
-    <MicrosoftExtensionsDiagnosticAdapterPackageVersion>3.0.0-preview4.19209.10</MicrosoftExtensionsDiagnosticAdapterPackageVersion>
-    <MicrosoftExtensionsDiagnosticsHealthChecksAbstractionsPackageVersion>3.0.0-preview4.19209.10</MicrosoftExtensionsDiagnosticsHealthChecksAbstractionsPackageVersion>
-    <MicrosoftExtensionsDiagnosticsHealthChecksPackageVersion>3.0.0-preview4.19209.10</MicrosoftExtensionsDiagnosticsHealthChecksPackageVersion>
-    <MicrosoftExtensionsFileProvidersAbstractionsPackageVersion>3.0.0-preview4.19209.10</MicrosoftExtensionsFileProvidersAbstractionsPackageVersion>
-    <MicrosoftExtensionsFileProvidersCompositePackageVersion>3.0.0-preview4.19209.10</MicrosoftExtensionsFileProvidersCompositePackageVersion>
-    <MicrosoftExtensionsFileProvidersEmbeddedPackageVersion>3.0.0-preview4.19209.10</MicrosoftExtensionsFileProvidersEmbeddedPackageVersion>
-    <MicrosoftExtensionsFileProvidersPhysicalPackageVersion>3.0.0-preview4.19209.10</MicrosoftExtensionsFileProvidersPhysicalPackageVersion>
-    <MicrosoftExtensionsFileSystemGlobbingPackageVersion>3.0.0-preview4.19209.10</MicrosoftExtensionsFileSystemGlobbingPackageVersion>
-    <MicrosoftExtensionsHashCodeCombinerSourcesPackageVersion>3.0.0-preview4.19209.10</MicrosoftExtensionsHashCodeCombinerSourcesPackageVersion>
-    <MicrosoftExtensionsHostingAbstractionsPackageVersion>3.0.0-preview4.19209.10</MicrosoftExtensionsHostingAbstractionsPackageVersion>
-    <MicrosoftExtensionsHostingPackageVersion>3.0.0-preview4.19209.10</MicrosoftExtensionsHostingPackageVersion>
-    <MicrosoftExtensionsHostFactoryResolverSourcesPackageVersion>3.0.0-preview4.19209.10</MicrosoftExtensionsHostFactoryResolverSourcesPackageVersion>
-    <MicrosoftExtensionsHttpPackageVersion>3.0.0-preview4.19209.10</MicrosoftExtensionsHttpPackageVersion>
-    <MicrosoftExtensionsLocalizationAbstractionsPackageVersion>3.0.0-preview4.19209.10</MicrosoftExtensionsLocalizationAbstractionsPackageVersion>
-    <MicrosoftExtensionsLocalizationPackageVersion>3.0.0-preview4.19209.10</MicrosoftExtensionsLocalizationPackageVersion>
-    <MicrosoftExtensionsLoggingAbstractionsPackageVersion>3.0.0-preview4.19209.10</MicrosoftExtensionsLoggingAbstractionsPackageVersion>
-    <MicrosoftExtensionsLoggingAzureAppServicesPackageVersion>3.0.0-preview4.19209.10</MicrosoftExtensionsLoggingAzureAppServicesPackageVersion>
-    <MicrosoftExtensionsLoggingConfigurationPackageVersion>3.0.0-preview4.19209.10</MicrosoftExtensionsLoggingConfigurationPackageVersion>
-    <MicrosoftExtensionsLoggingConsolePackageVersion>3.0.0-preview4.19209.10</MicrosoftExtensionsLoggingConsolePackageVersion>
-    <MicrosoftExtensionsLoggingDebugPackageVersion>3.0.0-preview4.19209.10</MicrosoftExtensionsLoggingDebugPackageVersion>
-    <MicrosoftExtensionsLoggingEventSourcePackageVersion>3.0.0-preview4.19209.10</MicrosoftExtensionsLoggingEventSourcePackageVersion>
-    <MicrosoftExtensionsLoggingPackageVersion>3.0.0-preview4.19209.10</MicrosoftExtensionsLoggingPackageVersion>
-    <MicrosoftExtensionsLoggingTestingPackageVersion>3.0.0-preview4.19209.10</MicrosoftExtensionsLoggingTestingPackageVersion>
-    <MicrosoftExtensionsLoggingTraceSourcePackageVersion>3.0.0-preview4.19209.10</MicrosoftExtensionsLoggingTraceSourcePackageVersion>
-    <MicrosoftExtensionsObjectPoolPackageVersion>3.0.0-preview4.19209.10</MicrosoftExtensionsObjectPoolPackageVersion>
-    <MicrosoftExtensionsOptionsConfigurationExtensionsPackageVersion>3.0.0-preview4.19209.10</MicrosoftExtensionsOptionsConfigurationExtensionsPackageVersion>
-    <MicrosoftExtensionsOptionsDataAnnotationsPackageVersion>3.0.0-preview4.19209.10</MicrosoftExtensionsOptionsDataAnnotationsPackageVersion>
-    <MicrosoftExtensionsOptionsPackageVersion>3.0.0-preview4.19209.10</MicrosoftExtensionsOptionsPackageVersion>
-    <MicrosoftExtensionsParameterDefaultValueSourcesPackageVersion>3.0.0-preview4.19209.10</MicrosoftExtensionsParameterDefaultValueSourcesPackageVersion>
-    <MicrosoftExtensionsPrimitivesPackageVersion>3.0.0-preview4.19209.10</MicrosoftExtensionsPrimitivesPackageVersion>
-    <MicrosoftExtensionsTypeNameHelperSourcesPackageVersion>3.0.0-preview4.19209.10</MicrosoftExtensionsTypeNameHelperSourcesPackageVersion>
-    <MicrosoftExtensionsValueStopwatchSourcesPackageVersion>3.0.0-preview4.19209.10</MicrosoftExtensionsValueStopwatchSourcesPackageVersion>
-    <MicrosoftExtensionsWebEncodersPackageVersion>3.0.0-preview4.19209.10</MicrosoftExtensionsWebEncodersPackageVersion>
-    <MicrosoftInternalExtensionsRefsPackageVersion>3.0.0-preview4.19209.10</MicrosoftInternalExtensionsRefsPackageVersion>
-    <MicrosoftJSInteropPackageVersion>3.0.0-preview4.19209.10</MicrosoftJSInteropPackageVersion>
-    <MonoWebAssemblyInteropPackageVersion>3.0.0-preview4.19209.10</MonoWebAssemblyInteropPackageVersion>
+    <InternalAspNetCoreAnalyzersPackageVersion>3.0.0-preview4.19207.2</InternalAspNetCoreAnalyzersPackageVersion>
+    <MicrosoftAspNetCoreAnalyzerTestingPackageVersion>3.0.0-preview4.19207.2</MicrosoftAspNetCoreAnalyzerTestingPackageVersion>
+    <MicrosoftAspNetCoreBenchmarkRunnerSourcesPackageVersion>3.0.0-preview4.19207.2</MicrosoftAspNetCoreBenchmarkRunnerSourcesPackageVersion>
+    <MicrosoftAspNetCoreTestingPackageVersion>3.0.0-preview4.19207.2</MicrosoftAspNetCoreTestingPackageVersion>
+    <MicrosoftExtensionsActivatorUtilitiesSourcesPackageVersion>3.0.0-preview4.19207.2</MicrosoftExtensionsActivatorUtilitiesSourcesPackageVersion>
+    <MicrosoftExtensionsCachingAbstractionsPackageVersion>3.0.0-preview4.19207.2</MicrosoftExtensionsCachingAbstractionsPackageVersion>
+    <MicrosoftExtensionsCachingMemoryPackageVersion>3.0.0-preview4.19207.2</MicrosoftExtensionsCachingMemoryPackageVersion>
+    <MicrosoftExtensionsCachingSqlServerPackageVersion>3.0.0-preview4.19207.2</MicrosoftExtensionsCachingSqlServerPackageVersion>
+    <MicrosoftExtensionsCachingStackExchangeRedisPackageVersion>3.0.0-preview4.19207.2</MicrosoftExtensionsCachingStackExchangeRedisPackageVersion>
+    <MicrosoftExtensionsCommandLineUtilsSourcesPackageVersion>3.0.0-preview4.19207.2</MicrosoftExtensionsCommandLineUtilsSourcesPackageVersion>
+    <MicrosoftExtensionsConfigurationAbstractionsPackageVersion>3.0.0-preview4.19207.2</MicrosoftExtensionsConfigurationAbstractionsPackageVersion>
+    <MicrosoftExtensionsConfigurationAzureKeyVaultPackageVersion>3.0.0-preview4.19207.2</MicrosoftExtensionsConfigurationAzureKeyVaultPackageVersion>
+    <MicrosoftExtensionsConfigurationBinderPackageVersion>3.0.0-preview4.19207.2</MicrosoftExtensionsConfigurationBinderPackageVersion>
+    <MicrosoftExtensionsConfigurationCommandLinePackageVersion>3.0.0-preview4.19207.2</MicrosoftExtensionsConfigurationCommandLinePackageVersion>
+    <MicrosoftExtensionsConfigurationEnvironmentVariablesPackageVersion>3.0.0-preview4.19207.2</MicrosoftExtensionsConfigurationEnvironmentVariablesPackageVersion>
+    <MicrosoftExtensionsConfigurationFileExtensionsPackageVersion>3.0.0-preview4.19207.2</MicrosoftExtensionsConfigurationFileExtensionsPackageVersion>
+    <MicrosoftExtensionsConfigurationIniPackageVersion>3.0.0-preview4.19207.2</MicrosoftExtensionsConfigurationIniPackageVersion>
+    <MicrosoftExtensionsConfigurationJsonPackageVersion>3.0.0-preview4.19207.2</MicrosoftExtensionsConfigurationJsonPackageVersion>
+    <MicrosoftExtensionsConfigurationKeyPerFilePackageVersion>3.0.0-preview4.19207.2</MicrosoftExtensionsConfigurationKeyPerFilePackageVersion>
+    <MicrosoftExtensionsConfigurationPackageVersion>3.0.0-preview4.19207.2</MicrosoftExtensionsConfigurationPackageVersion>
+    <MicrosoftExtensionsConfigurationUserSecretsPackageVersion>3.0.0-preview4.19207.2</MicrosoftExtensionsConfigurationUserSecretsPackageVersion>
+    <MicrosoftExtensionsConfigurationXmlPackageVersion>3.0.0-preview4.19207.2</MicrosoftExtensionsConfigurationXmlPackageVersion>
+    <MicrosoftExtensionsDependencyInjectionAbstractionsPackageVersion>3.0.0-preview4.19207.2</MicrosoftExtensionsDependencyInjectionAbstractionsPackageVersion>
+    <MicrosoftExtensionsDependencyInjectionPackageVersion>3.0.0-preview4.19207.2</MicrosoftExtensionsDependencyInjectionPackageVersion>
+    <MicrosoftExtensionsDiagnosticAdapterPackageVersion>3.0.0-preview4.19207.2</MicrosoftExtensionsDiagnosticAdapterPackageVersion>
+    <MicrosoftExtensionsDiagnosticsHealthChecksAbstractionsPackageVersion>3.0.0-preview4.19207.2</MicrosoftExtensionsDiagnosticsHealthChecksAbstractionsPackageVersion>
+    <MicrosoftExtensionsDiagnosticsHealthChecksPackageVersion>3.0.0-preview4.19207.2</MicrosoftExtensionsDiagnosticsHealthChecksPackageVersion>
+    <MicrosoftExtensionsFileProvidersAbstractionsPackageVersion>3.0.0-preview4.19207.2</MicrosoftExtensionsFileProvidersAbstractionsPackageVersion>
+    <MicrosoftExtensionsFileProvidersCompositePackageVersion>3.0.0-preview4.19207.2</MicrosoftExtensionsFileProvidersCompositePackageVersion>
+    <MicrosoftExtensionsFileProvidersEmbeddedPackageVersion>3.0.0-preview4.19207.2</MicrosoftExtensionsFileProvidersEmbeddedPackageVersion>
+    <MicrosoftExtensionsFileProvidersPhysicalPackageVersion>3.0.0-preview4.19207.2</MicrosoftExtensionsFileProvidersPhysicalPackageVersion>
+    <MicrosoftExtensionsFileSystemGlobbingPackageVersion>3.0.0-preview4.19207.2</MicrosoftExtensionsFileSystemGlobbingPackageVersion>
+    <MicrosoftExtensionsHashCodeCombinerSourcesPackageVersion>3.0.0-preview4.19207.2</MicrosoftExtensionsHashCodeCombinerSourcesPackageVersion>
+    <MicrosoftExtensionsHostingAbstractionsPackageVersion>3.0.0-preview4.19207.2</MicrosoftExtensionsHostingAbstractionsPackageVersion>
+    <MicrosoftExtensionsHostingPackageVersion>3.0.0-preview4.19207.2</MicrosoftExtensionsHostingPackageVersion>
+    <MicrosoftExtensionsHostFactoryResolverSourcesPackageVersion>3.0.0-preview4.19207.2</MicrosoftExtensionsHostFactoryResolverSourcesPackageVersion>
+    <MicrosoftExtensionsHttpPackageVersion>3.0.0-preview4.19207.2</MicrosoftExtensionsHttpPackageVersion>
+    <MicrosoftExtensionsLocalizationAbstractionsPackageVersion>3.0.0-preview4.19207.2</MicrosoftExtensionsLocalizationAbstractionsPackageVersion>
+    <MicrosoftExtensionsLocalizationPackageVersion>3.0.0-preview4.19207.2</MicrosoftExtensionsLocalizationPackageVersion>
+    <MicrosoftExtensionsLoggingAbstractionsPackageVersion>3.0.0-preview4.19207.2</MicrosoftExtensionsLoggingAbstractionsPackageVersion>
+    <MicrosoftExtensionsLoggingAzureAppServicesPackageVersion>3.0.0-preview4.19207.2</MicrosoftExtensionsLoggingAzureAppServicesPackageVersion>
+    <MicrosoftExtensionsLoggingConfigurationPackageVersion>3.0.0-preview4.19207.2</MicrosoftExtensionsLoggingConfigurationPackageVersion>
+    <MicrosoftExtensionsLoggingConsolePackageVersion>3.0.0-preview4.19207.2</MicrosoftExtensionsLoggingConsolePackageVersion>
+    <MicrosoftExtensionsLoggingDebugPackageVersion>3.0.0-preview4.19207.2</MicrosoftExtensionsLoggingDebugPackageVersion>
+    <MicrosoftExtensionsLoggingEventSourcePackageVersion>3.0.0-preview4.19207.2</MicrosoftExtensionsLoggingEventSourcePackageVersion>
+    <MicrosoftExtensionsLoggingPackageVersion>3.0.0-preview4.19207.2</MicrosoftExtensionsLoggingPackageVersion>
+    <MicrosoftExtensionsLoggingTestingPackageVersion>3.0.0-preview4.19207.2</MicrosoftExtensionsLoggingTestingPackageVersion>
+    <MicrosoftExtensionsLoggingTraceSourcePackageVersion>3.0.0-preview4.19207.2</MicrosoftExtensionsLoggingTraceSourcePackageVersion>
+    <MicrosoftExtensionsObjectPoolPackageVersion>3.0.0-preview4.19207.2</MicrosoftExtensionsObjectPoolPackageVersion>
+    <MicrosoftExtensionsOptionsConfigurationExtensionsPackageVersion>3.0.0-preview4.19207.2</MicrosoftExtensionsOptionsConfigurationExtensionsPackageVersion>
+    <MicrosoftExtensionsOptionsDataAnnotationsPackageVersion>3.0.0-preview4.19207.2</MicrosoftExtensionsOptionsDataAnnotationsPackageVersion>
+    <MicrosoftExtensionsOptionsPackageVersion>3.0.0-preview4.19207.2</MicrosoftExtensionsOptionsPackageVersion>
+    <MicrosoftExtensionsParameterDefaultValueSourcesPackageVersion>3.0.0-preview4.19207.2</MicrosoftExtensionsParameterDefaultValueSourcesPackageVersion>
+    <MicrosoftExtensionsPrimitivesPackageVersion>3.0.0-preview4.19207.2</MicrosoftExtensionsPrimitivesPackageVersion>
+    <MicrosoftExtensionsTypeNameHelperSourcesPackageVersion>3.0.0-preview4.19207.2</MicrosoftExtensionsTypeNameHelperSourcesPackageVersion>
+    <MicrosoftExtensionsValueStopwatchSourcesPackageVersion>3.0.0-preview4.19207.2</MicrosoftExtensionsValueStopwatchSourcesPackageVersion>
+    <MicrosoftExtensionsWebEncodersPackageVersion>3.0.0-preview4.19207.2</MicrosoftExtensionsWebEncodersPackageVersion>
+    <MicrosoftInternalExtensionsRefsPackageVersion>3.0.0-preview4.19207.2</MicrosoftInternalExtensionsRefsPackageVersion>
+    <MicrosoftJSInteropPackageVersion>3.0.0-preview4.19207.2</MicrosoftJSInteropPackageVersion>
+    <MonoWebAssemblyInteropPackageVersion>3.0.0-preview4.19207.2</MonoWebAssemblyInteropPackageVersion>
     <!-- Packages from aspnet/EntityFrameworkCore -->
-    <dotnetefPackageVersion>3.0.0-preview4.19209.6</dotnetefPackageVersion>
-    <MicrosoftEntityFrameworkCoreInMemoryPackageVersion>3.0.0-preview4.19209.6</MicrosoftEntityFrameworkCoreInMemoryPackageVersion>
-    <MicrosoftEntityFrameworkCoreRelationalPackageVersion>3.0.0-preview4.19209.6</MicrosoftEntityFrameworkCoreRelationalPackageVersion>
-    <MicrosoftEntityFrameworkCoreSqlitePackageVersion>3.0.0-preview4.19209.6</MicrosoftEntityFrameworkCoreSqlitePackageVersion>
-    <MicrosoftEntityFrameworkCoreSqlServerPackageVersion>3.0.0-preview4.19209.6</MicrosoftEntityFrameworkCoreSqlServerPackageVersion>
-    <MicrosoftEntityFrameworkCoreToolsPackageVersion>3.0.0-preview4.19209.6</MicrosoftEntityFrameworkCoreToolsPackageVersion>
-    <MicrosoftEntityFrameworkCorePackageVersion>3.0.0-preview4.19209.6</MicrosoftEntityFrameworkCorePackageVersion>
+    <dotnetefPackageVersion>3.0.0-preview5.19208.4</dotnetefPackageVersion>
+    <MicrosoftEntityFrameworkCoreInMemoryPackageVersion>3.0.0-preview5.19208.4</MicrosoftEntityFrameworkCoreInMemoryPackageVersion>
+    <MicrosoftEntityFrameworkCoreRelationalPackageVersion>3.0.0-preview5.19208.4</MicrosoftEntityFrameworkCoreRelationalPackageVersion>
+    <MicrosoftEntityFrameworkCoreSqlitePackageVersion>3.0.0-preview5.19208.4</MicrosoftEntityFrameworkCoreSqlitePackageVersion>
+    <MicrosoftEntityFrameworkCoreSqlServerPackageVersion>3.0.0-preview5.19208.4</MicrosoftEntityFrameworkCoreSqlServerPackageVersion>
+    <MicrosoftEntityFrameworkCoreToolsPackageVersion>3.0.0-preview5.19208.4</MicrosoftEntityFrameworkCoreToolsPackageVersion>
+    <MicrosoftEntityFrameworkCorePackageVersion>3.0.0-preview5.19208.4</MicrosoftEntityFrameworkCorePackageVersion>
     <!-- Packages from aspnet/AspNetCore-Tooling -->
-    <MicrosoftAspNetCoreMvcRazorExtensionsPackageVersion>3.0.0-preview4.19209.3</MicrosoftAspNetCoreMvcRazorExtensionsPackageVersion>
-    <MicrosoftAspNetCoreRazorLanguagePackageVersion>3.0.0-preview4.19209.3</MicrosoftAspNetCoreRazorLanguagePackageVersion>
-    <MicrosoftCodeAnalysisRazorPackageVersion>3.0.0-preview4.19209.3</MicrosoftCodeAnalysisRazorPackageVersion>
-    <MicrosoftNETSdkRazorPackageVersion>3.0.0-preview4.19209.3</MicrosoftNETSdkRazorPackageVersion>
+    <MicrosoftAspNetCoreMvcRazorExtensionsPackageVersion>3.0.0-preview5.19208.6</MicrosoftAspNetCoreMvcRazorExtensionsPackageVersion>
+    <MicrosoftAspNetCoreRazorLanguagePackageVersion>3.0.0-preview5.19208.6</MicrosoftAspNetCoreRazorLanguagePackageVersion>
+    <MicrosoftCodeAnalysisRazorPackageVersion>3.0.0-preview5.19208.6</MicrosoftCodeAnalysisRazorPackageVersion>
+    <MicrosoftNETSdkRazorPackageVersion>3.0.0-preview5.19208.6</MicrosoftNETSdkRazorPackageVersion>
   </PropertyGroup>
   <!--
 

+ 1 - 1
global.json

@@ -1,6 +1,6 @@
 {
   "sdk": {
-    "version": "3.0.100-preview4-010309"
+    "version": "3.0.100-preview4-011136"
   },
   "msbuild-sdks": {
     "Yarn.MSBuild": "1.13.0"

+ 2 - 2
korebuild-lock.txt

@@ -1,2 +1,2 @@
-version:3.0.0-build-20190322.1
-commithash:c38761a564c72b5bc96356ec99c89de5f281a358
+version:3.0.0-build-20190408.1
+commithash:8b533cbfa5357e5785f4c4231231c1234cfc2c5f

+ 0 - 1
src/Components/Blazor/Templates/src/content/BlazorHosted-CSharp/BlazorHosted-CSharp.Server/BlazorHosted-CSharp.Server.csproj

@@ -11,7 +11,6 @@
 
   <ItemGroup>
     <PackageReference Include="Microsoft.AspNetCore.Blazor.Server" Version="$(TemplateBlazorPackageVersion)" />
-    <PackageReference Include="Microsoft.AspNetCore.Components.Server" Version="$(TemplateComponentsPackageVersion)" />
     <PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="$(TemplateComponentsPackageVersion)" />
   </ItemGroup>
 

+ 42 - 118
src/Installers/Windows/AspNetCoreModule-Setup/ANCMIISExpressV2/ancm_iis_expressv2.wxs

@@ -366,66 +366,25 @@
                           Value="&quot;[IISEXPRESS_INSTALL_PATH]appcmd.exe&quot; set config -section:system.webServer/httpCompression /+&quot;dynamicTypes.[\[]mimeType='text/event-stream',enabled='FALSE'[\]]&quot; /apphostconfig:&quot;[IISEXPRESS_APPHOST_CONFIG_TMP]&quot;"/>
         <CustomAction Id="CA_UPDATE_DYNAMIC_COMPRESSION_TMP" BinaryKey="WixCA" DllEntry="CAQuietExec" Execute="deferred" Return="ignore" Impersonate="no"/>
 
-        <!-- CA to add config section to applicationhost.config -->
         <CustomAction Id="CA_ADD_CONFIGSECTION_PROPERTY"
                           Property="CA_ADD_CONFIGSECTION"
-                          Value="[IISEXPRESS_APPHOST_CONFIG];[IISEXPRESS_APPHOST_CONFIG_TMP]"/>
-        <CustomAction Id="CA_ADD_CONFIGSECTION" Script="jscript" Execute="deferred" Return="check" Impersonate="no">
-            <![CDATA[
-                var caData = Session.Property("CustomActionData");
-                configfiles = caData.split(';');
-                for (var i = 0; i < configfiles.length; i++) {
-                    var configfile = configfiles[i];
-                    var xmlDoc = new ActiveXObject("Msxml2.DOMDocument");
-                    xmlDoc.async = false;
-                    xmlDoc.preserveWhiteSpace = true;
-                    xmlDoc.load(configfile );
-                    if (xmlDoc.parseError.errorCode == 0) {
-                        xmlDoc.setProperty("SelectionLanguage", "XPath");
-                        var websvrNode = xmlDoc.selectSingleNode("//configuration/configSections/sectionGroup[@name=\"system.webServer\"]");
-                        if (websvrNode != null) {
-                            var ancmNode = xmlDoc.selectSingleNode("//configuration/configSections/sectionGroup[@name=\"system.webServer\"]/section[@name=\"$(var.AspNetCoreSectionName)\"]");
-                            if (ancmNode == null) {
-                                ancmNode = xmlDoc.createElement("section");
-                                ancmNode.setAttribute("name", "$(var.AspNetCoreSectionName)");
-                                ancmNode.setAttribute("overrideModeDefault", "Allow");
-                                websvrNode.appendChild(ancmNode);
-                                xmlDoc.save(configfile );
-                            }
-                        }
-                    }
-                }
-            ]]>
-        </CustomAction>
-
-        <!-- CA to remove config section to applicationhost.config -->
+                          Value="[IISEXPRESS_APPHOST_CONFIG]"/>
+        <CustomAction BinaryKey="IISCustomActionDll" Id="CA_ADD_CONFIGSECTION" DllEntry="AddConfigSection" Execute="deferred" Return="check" Impersonate="no"/>
+
+        <CustomAction Id="CA_ADD_CONFIGSECTION_PROPERTY_TMP"
+                          Property="CA_ADD_CONFIGSECTION_TMP"
+                          Value="[IISEXPRESS_APPHOST_CONFIG_TMP]"/>
+        <CustomAction BinaryKey="IISCustomActionDll" Id="CA_ADD_CONFIGSECTION_TMP" DllEntry="AddConfigSection" Execute="deferred" Return="check" Impersonate="no"/>
+
         <CustomAction Id="CA_REMOVE_CONFIGSECTION_PROPERTY"
-                          Property="CA_REMOVE_CONFIGSECTION"
-                          Value="[IISEXPRESS_APPHOST_CONFIG];[IISEXPRESS_APPHOST_CONFIG_TMP]"/>
-        <CustomAction Id="CA_REMOVE_CONFIGSECTION" Script="jscript" Execute="deferred" Return="check" Impersonate="no">
-            <![CDATA[
-                var caData = Session.Property("CustomActionData");
-                configfiles = caData.split(';');
-                for (var i = 0; i < configfiles.length; i++) {
-                    var configfile = configfiles[i];
-                    var xmlDoc = new ActiveXObject("Msxml2.DOMDocument");
-                    xmlDoc.async = false;
-                    xmlDoc.preserveWhiteSpace = true;
-                    xmlDoc.load(configfile );
-                    if (xmlDoc.parseError.errorCode == 0) {
-                        xmlDoc.setProperty("SelectionLanguage", "XPath");
-                        var websvrNode = xmlDoc.selectSingleNode("//configuration/configSections/sectionGroup[@name=\"system.webServer\"]");
-                        if (websvrNode != null) {
-                            var ancmNode = xmlDoc.selectSingleNode("//configuration/configSections/sectionGroup[@name=\"system.webServer\"]/section[@name=\"$(var.AspNetCoreSectionName)\"]");
-                            if (ancmNode != null) {
-                                websvrNode.removeChild(ancmNode);
-                                xmlDoc.save(configfile );
-                            }
-                        }
-                    }
-                }
-            ]]>
-        </CustomAction>
+                            Property="CA_REMOVE_CONFIGSECTION"
+                            Value="[IISEXPRESS_APPHOST_CONFIG]"/>
+        <CustomAction Id="CA_REMOVE_CONFIGSECTION" BinaryKey="IISCustomActionDll" DllEntry="RemoveConfigSection" Execute="deferred" Return="check" Impersonate="no" />
+
+        <CustomAction Id="CA_REMOVE_CONFIGSECTION_PROPERTY_TMP"
+                Property="CA_REMOVE_CONFIGSECTION_TMP"
+                Value="[IISEXPRESS_APPHOST_CONFIG_TMP]"/>
+        <CustomAction Id="CA_REMOVE_CONFIGSECTION_TMP" BinaryKey="IISCustomActionDll" DllEntry="RemoveConfigSection" Execute="deferred" Return="check" Impersonate="no" />
 
         <?if $(var.Platform) = "x64" ?>
             <CustomAction Id="CA_UNLOCK_HANDLER32_PROPERTY"
@@ -520,68 +479,25 @@
                               Value="&quot;[IISEXPRESS_INSTALL_PATH32]appcmd.exe&quot; set config -section:system.webServer/httpCompression /+&quot;dynamicTypes.[\[]mimeType='text/event-stream',enabled='FALSE'[\]]&quot; /apphostconfig:&quot;[IISEXPRESS_APPHOST_CONFIG32]&quot;"/>
             <CustomAction Id="CA_UPDATE_DYNAMIC_COMPRESSION_TMP32" BinaryKey="WixCA" DllEntry="CAQuietExec" Execute="deferred" Return="ignore" Impersonate="no"/>
 
-
-      <!-- CA to add config section to applicationhost.config -->
             <CustomAction Id="CA_ADD_CONFIGSECTION32_PROPERTY"
-                              Property="CA_ADD_CONFIGSECTION32"
-                              Value="[IISEXPRESS_APPHOST_CONFIG32];[IISEXPRESS_APPHOST_CONFIG_TMP32]"/>
-            <CustomAction Id="CA_ADD_CONFIGSECTION32" Script="jscript" Execute="deferred" Return="check" Impersonate="no">
-                <!-- Warning LGHT1076: ICE03: String overflow. Orca.exe inspection shows the custom action value is populated correctly -->
-                <![CDATA[
-                    var caData = Session.Property("CustomActionData");
-                    configfiles = caData.split(';');
-                    for (var i = 0; i < configfiles.length; i++) {
-                        var configfile = configfiles[i];
-                        var xmlDoc = new ActiveXObject("Msxml2.DOMDocument");
-                        xmlDoc.async = false;
-                        xmlDoc.preserveWhiteSpace = true;
-                        xmlDoc.load(configfile);
-                        if (xmlDoc.parseError.errorCode == 0) {
-                            xmlDoc.setProperty("SelectionLanguage", "XPath");
-                            var websvrNode = xmlDoc.selectSingleNode("//configuration/configSections/sectionGroup[@name=\"system.webServer\"]");
-                            if (websvrNode != null) {
-                                var ancmNode = xmlDoc.selectSingleNode("//configuration/configSections/sectionGroup[@name=\"system.webServer\"]/section[@name=\"$(var.AspNetCoreSectionName)\"]");
-                                if (ancmNode == null) {
-                                    ancmNode = xmlDoc.createElement("section");
-                                    ancmNode.setAttribute("name", "$(var.AspNetCoreSectionName)");
-                                    ancmNode.setAttribute("overrideModeDefault", "Allow");
-                                    websvrNode.appendChild(ancmNode);
-                                    xmlDoc.save(configfile);
-                                }
-                            }
-                        }
-                    }
-                ]]>
-            </CustomAction>
-
-            <!-- CA to remove config section to applicationhost.config -->
+                            Property="CA_ADD_CONFIGSECTION32"
+                            Value="[IISEXPRESS_APPHOST_CONFIG32]"/>
+            <CustomAction BinaryKey="IISCustomActionDll" Id="CA_ADD_CONFIGSECTION32" DllEntry="AddConfigSection" Execute="deferred" Return="check" Impersonate="no"/>
+
+            <CustomAction Id="CA_ADD_CONFIGSECTION32_PROPERTY_TMP"
+                            Property="CA_ADD_CONFIGSECTION32_TMP"
+                            Value="[IISEXPRESS_APPHOST_CONFIG_TMP32]"/>
+            <CustomAction BinaryKey="IISCustomActionDll" Id="CA_ADD_CONFIGSECTION32_TMP" DllEntry="AddConfigSection" Execute="deferred" Return="check" Impersonate="no"/>
+
             <CustomAction Id="CA_REMOVE_CONFIGSECTION32_PROPERTY"
                               Property="CA_REMOVE_CONFIGSECTION32"
-                              Value="[IISEXPRESS_APPHOST_CONFIG32];[IISEXPRESS_APPHOST_CONFIG_TMP32]"/>
-            <CustomAction Id="CA_REMOVE_CONFIGSECTION32" Script="jscript" Execute="deferred" Return="check" Impersonate="no">
-                <![CDATA[
-                    var caData = Session.Property("CustomActionData");
-                    configfiles = caData.split(';');
-                    for (var i = 0; i < configfiles.length; i++) {
-                        var configfile = configfiles[i];
-                        var xmlDoc = new ActiveXObject("Msxml2.DOMDocument");
-                        xmlDoc.async = false;
-                        xmlDoc.preserveWhiteSpace = true;
-                        xmlDoc.load(configfile);
-                        if (xmlDoc.parseError.errorCode == 0) {
-                            xmlDoc.setProperty("SelectionLanguage", "XPath");
-                            var websvrNode = xmlDoc.selectSingleNode("//configuration/configSections/sectionGroup[@name=\"system.webServer\"]");
-                            if (websvrNode != null) {
-                                var ancmNode = xmlDoc.selectSingleNode("//configuration/configSections/sectionGroup[@name=\"system.webServer\"]/section[@name=\"$(var.AspNetCoreSectionName)\"]");
-                                if (ancmNode != null) {
-                                    websvrNode.removeChild(ancmNode);
-                                    xmlDoc.save(configfile);
-                                }
-                            }
-                        }
-                    }
-                ]]>
-           </CustomAction>
+                              Value="[IISEXPRESS_APPHOST_CONFIG32]"/>
+            <CustomAction Id="CA_REMOVE_CONFIGSECTION32" BinaryKey="IISCustomActionDll" DllEntry="RemoveConfigSection" Execute="deferred" Return="check" Impersonate="no" />
+
+            <CustomAction Id="CA_REMOVE_CONFIGSECTION32_PROPERTY_TMP"
+                    Property="CA_REMOVE_CONFIGSECTION32_TMP"
+                    Value="[IISEXPRESS_APPHOST_CONFIG_TMP32]"/>
+            <CustomAction Id="CA_REMOVE_CONFIGSECTION32_TMP" BinaryKey="IISCustomActionDll" DllEntry="RemoveConfigSection" Execute="deferred" Return="check" Impersonate="no" />
         <?endif?>
 
         <InstallExecuteSequence>
@@ -600,7 +516,9 @@
             <Custom Action="CA_SET_MODULE" After="CA_SET_MODULE_PROPERTY"><![CDATA[(NOT REMOVE)]]></Custom>
             <Custom Action="CA_ADD_CONFIGSECTION_PROPERTY" After="CA_SET_MODULE"><![CDATA[(NOT REMOVE)]]></Custom>
             <Custom Action="CA_ADD_CONFIGSECTION" After="CA_ADD_CONFIGSECTION_PROPERTY"><![CDATA[(NOT REMOVE)]]></Custom>
-            <Custom Action="CA_ADD_TRACE_PROVIDER_DEFINITION_PROPERTY" After="CA_ADD_CONFIGSECTION"><![CDATA[(NOT REMOVE)]]></Custom>
+            <Custom Action="CA_ADD_CONFIGSECTION_PROPERTY_TMP" After="CA_ADD_CONFIGSECTION"><![CDATA[(NOT REMOVE)]]></Custom>
+            <Custom Action="CA_ADD_CONFIGSECTION_TMP" After="CA_ADD_CONFIGSECTION_PROPERTY_TMP"><![CDATA[(NOT REMOVE)]]></Custom>
+            <Custom Action="CA_ADD_TRACE_PROVIDER_DEFINITION_PROPERTY" After="CA_ADD_CONFIGSECTION_TMP"><![CDATA[(NOT REMOVE)]]></Custom>
             <Custom Action="CA_ADD_TRACE_PROVIDER_DEFINITION" After="CA_ADD_TRACE_PROVIDER_DEFINITION_PROPERTY"><![CDATA[(NOT REMOVE)]]></Custom>
             <Custom Action="CA_ADD_TRACE_PROVIDER_DEFINITION_TMP_PROPERTY" After="CA_ADD_TRACE_PROVIDER_DEFINITION"><![CDATA[(NOT REMOVE)]]></Custom>
             <Custom Action="CA_ADD_TRACE_PROVIDER_DEFINITION_TMP" After="CA_ADD_TRACE_PROVIDER_DEFINITION_TMP_PROPERTY"><![CDATA[(NOT REMOVE)]]></Custom>
@@ -610,6 +528,8 @@
             <Custom Action="CA_REMOVE_MODULE" Before="RemoveFiles"><![CDATA[(REMOVE~="ALL" AND NOT UPGRADINGPRODUCTCODE)]]></Custom>
             <Custom Action="CA_REMOVE_CONFIGSECTION_PROPERTY" Before="CA_REMOVE_CONFIGSECTION"><![CDATA[(REMOVE~="ALL" AND NOT UPGRADINGPRODUCTCODE)]]></Custom>
             <Custom Action="CA_REMOVE_CONFIGSECTION" Before="RemoveFiles"><![CDATA[(REMOVE~="ALL" AND NOT UPGRADINGPRODUCTCODE)]]></Custom>
+            <Custom Action="CA_REMOVE_CONFIGSECTION_PROPERTY_TMP" Before="CA_REMOVE_CONFIGSECTION_TMP"><![CDATA[(REMOVE~="ALL" AND NOT UPGRADINGPRODUCTCODE)]]></Custom>
+            <Custom Action="CA_REMOVE_CONFIGSECTION_TMP" Before="RemoveFiles"><![CDATA[(REMOVE~="ALL" AND NOT UPGRADINGPRODUCTCODE)]]></Custom>
             <Custom Action="CA_REMOVE_TRACE_PROVIDER_DEFINITION_PROPERTY" Before="CA_REMOVE_TRACE_PROVIDER_DEFINITION"><![CDATA[(REMOVE~="ALL" AND NOT UPGRADINGPRODUCTCODE)]]></Custom>
             <Custom Action="CA_REMOVE_TRACE_PROVIDER_DEFINITION" Before="RemoveFiles"><![CDATA[(REMOVE~="ALL" AND NOT UPGRADINGPRODUCTCODE)]]></Custom>
             <Custom Action="CA_REMOVE_TRACE_PROVIDER_DEFINITION_TMP_PROPERTY" Before="CA_REMOVE_TRACE_PROVIDER_DEFINITION_TMP"><![CDATA[(REMOVE~="ALL" AND NOT UPGRADINGPRODUCTCODE)]]></Custom>
@@ -640,7 +560,9 @@
                 <Custom Action="CA_SET_MODULE32" After="CA_ADD_MODULE32_PROPERTY"><![CDATA[(NOT REMOVE AND IISEXPRESS_INSTALL_PATH32)]]></Custom>
                 <Custom Action="CA_ADD_CONFIGSECTION32_PROPERTY" After="CA_SET_MODULE32"><![CDATA[(NOT REMOVE)]]></Custom>
                 <Custom Action="CA_ADD_CONFIGSECTION32" After="CA_ADD_CONFIGSECTION32_PROPERTY"><![CDATA[(NOT REMOVE)]]></Custom>
-                <Custom Action="CA_ADD_TRACE_PROVIDER_DEFINITION32_PROPERTY" After="CA_ADD_CONFIGSECTION32"><![CDATA[(NOT REMOVE)]]></Custom>
+                <Custom Action="CA_ADD_CONFIGSECTION32_PROPERTY_TMP" After="CA_ADD_CONFIGSECTION32"><![CDATA[(NOT REMOVE)]]></Custom>
+                <Custom Action="CA_ADD_CONFIGSECTION32_TMP" After="CA_ADD_CONFIGSECTION32_PROPERTY_TMP"><![CDATA[(NOT REMOVE)]]></Custom>
+                <Custom Action="CA_ADD_TRACE_PROVIDER_DEFINITION32_PROPERTY" After="CA_ADD_CONFIGSECTION32_TMP"><![CDATA[(NOT REMOVE)]]></Custom>
                 <Custom Action="CA_ADD_TRACE_PROVIDER_DEFINITION32" After="CA_ADD_TRACE_PROVIDER_DEFINITION32_PROPERTY"><![CDATA[(NOT REMOVE)]]></Custom>
                 <Custom Action="CA_ADD_TRACE_PROVIDER_DEFINITION_TMP32_PROPERTY" After="CA_ADD_TRACE_PROVIDER_DEFINITION32"><![CDATA[(NOT REMOVE)]]></Custom>
                 <Custom Action="CA_ADD_TRACE_PROVIDER_DEFINITION_TMP32" After="CA_ADD_TRACE_PROVIDER_DEFINITION_TMP32_PROPERTY"><![CDATA[(NOT REMOVE)]]></Custom>
@@ -650,6 +572,8 @@
                 <Custom Action="CA_REMOVE_MODULE32" After="CA_REMOVE_MODULE32_PROPERTY"><![CDATA[(REMOVE~="ALL" AND IISEXPRESS_INSTALL_PATH32 AND NOT UPGRADINGPRODUCTCODE)]]></Custom>
                 <Custom Action="CA_REMOVE_CONFIGSECTION32_PROPERTY" Before="CA_REMOVE_CONFIGSECTION32"><![CDATA[(REMOVE~="ALL" AND NOT UPGRADINGPRODUCTCODE)]]></Custom>
                 <Custom Action="CA_REMOVE_CONFIGSECTION32" Before="RemoveFiles"><![CDATA[(REMOVE~="ALL" AND NOT UPGRADINGPRODUCTCODE)]]></Custom>
+                <Custom Action="CA_REMOVE_CONFIGSECTION32_PROPERTY_TMP" Before="CA_REMOVE_CONFIGSECTION32_TMP"><![CDATA[(REMOVE~="ALL" AND NOT UPGRADINGPRODUCTCODE)]]></Custom>
+                <Custom Action="CA_REMOVE_CONFIGSECTION32_TMP" Before="RemoveFiles"><![CDATA[(REMOVE~="ALL" AND NOT UPGRADINGPRODUCTCODE)]]></Custom>
                 <Custom Action="CA_REMOVE_TRACE_PROVIDER_DEFINITION32_PROPERTY" Before="CA_REMOVE_TRACE_PROVIDER_DEFINITION32"><![CDATA[(REMOVE~="ALL" AND NOT UPGRADINGPRODUCTCODE)]]></Custom>
                 <Custom Action="CA_REMOVE_TRACE_PROVIDER_DEFINITION32" Before="RemoveFiles"><![CDATA[(REMOVE~="ALL" AND NOT UPGRADINGPRODUCTCODE)]]></Custom>
                 <Custom Action="CA_REMOVE_TRACE_PROVIDER_DEFINITION_TMP32_PROPERTY" Before="CA_REMOVE_TRACE_PROVIDER_DEFINITION_TMP32"><![CDATA[(REMOVE~="ALL" AND NOT UPGRADINGPRODUCTCODE)]]></Custom>

+ 134 - 0
src/Installers/Windows/AspNetCoreModule-Setup/CustomAction/aspnetcoreCA.cpp

@@ -2,6 +2,8 @@
 // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
 
 #include <precomp.h>
+#include <MsiQuery.h>
+#include <msxml6.h>
 
 DECLARE_DEBUG_PRINT_OBJECT( "proxyCA.dll" );
 
@@ -40,6 +42,138 @@ struct COMPRESSION_MIME_TYPE
 COMPRESSION_MIME_TYPE gMimeTypes[] =
     { { L"text/event-stream", FALSE} };
 
+#define _HR_RET(hr)                                             __pragma(warning(push)) \
+    __pragma(warning(disable:26498)) /*disable constexpr warning */ \
+    const HRESULT __hrRet = hr; \
+    __pragma(warning(pop))
+
+#define _GOTO_FINISHED()                                        __pragma(warning(push)) \
+    __pragma(warning(disable:26438)) /*disable avoid goto warning*/ \
+    goto Finished \
+    __pragma(warning(pop))
+
+#define RETURN_IF_FAILED(hrr)                                 do { _HR_RET(hrr); if (FAILED(__hrRet)) { hr = __hrRet; IISLogWrite(SETUP_LOG_SEVERITY_INFORMATION, L"Exiting hr=0x%x", hr); return hr; }} while (0, 0)
+
+// Modifies the configSections to include the aspNetCore section
+UINT
+WINAPI
+AddConfigSection(
+	IN MSIHANDLE handle
+)
+{
+    HRESULT hr;
+    CComPtr<IXMLDOMDocument2> pXMLDoc;
+    VARIANT_BOOL variantResult;
+    IXMLDOMNode* webServerNode;
+    IXMLDOMNode* aspNetCoreNode;
+    IXMLDOMNode* tempNode;
+    IXMLDOMElement* element;
+    STRU customActionData;
+
+	CComBSTR selectLanguage = SysAllocString(L"SelectionLanguage");
+	CComBSTR xPath = SysAllocString(L"XPath");
+	CComBSTR webServerPath = SysAllocString(L"//configuration/configSections/sectionGroup[@name=\"system.webServer\"]");
+	CComBSTR aspNetCorePath = SysAllocString(L"//configuration/configSections/sectionGroup[@name=\"system.webServer\"]/section[@name=\"aspNetCore\"]");
+	CComBSTR section = SysAllocString(L"section");
+	CComBSTR name = SysAllocString(L"name");
+	CComBSTR aspNetCore = SysAllocString(L"aspNetCore");
+	CComBSTR overrideMode = SysAllocString(L"overrideModeDefault");
+	CComBSTR allow = SysAllocString(L"Allow");
+
+	RETURN_IF_FAILED(CoInitialize(NULL));
+
+	hr = MsiUtilGetProperty(handle, TEXT("CustomActionData"), &customActionData);
+
+	RETURN_IF_FAILED(hr = pXMLDoc.CoCreateInstance(__uuidof(DOMDocument60)));
+
+	RETURN_IF_FAILED(hr = pXMLDoc->put_async(false));
+
+	RETURN_IF_FAILED(hr = pXMLDoc->load(CComVariant(customActionData.QueryStr()), &variantResult));
+
+	if (variantResult == VARIANT_FALSE)
+	{
+		return ERROR_SUCCESS;
+	}
+
+	RETURN_IF_FAILED(hr = pXMLDoc->setProperty(selectLanguage, CComVariant(xPath)));
+
+	RETURN_IF_FAILED(hr = pXMLDoc->selectSingleNode(webServerPath, &webServerNode));
+
+	RETURN_IF_FAILED(hr = pXMLDoc->selectSingleNode(aspNetCorePath, &aspNetCoreNode));
+
+	if (aspNetCoreNode == NULL)
+	{
+		RETURN_IF_FAILED(hr = pXMLDoc->createElement(section, &element));
+		
+		RETURN_IF_FAILED(hr = element->setAttribute(name, CComVariant(aspNetCore)));
+
+		RETURN_IF_FAILED(hr = element->setAttribute(overrideMode, CComVariant(allow)));
+
+		RETURN_IF_FAILED(hr = webServerNode->appendChild(element, &tempNode));
+
+		RETURN_IF_FAILED(hr = pXMLDoc->save(CComVariant(customActionData.QueryStr())));
+	}
+
+	return ERROR_SUCCESS;
+}
+
+// Modifies the configSections to remove the aspNetCore section
+UINT
+WINAPI
+RemoveConfigSection(
+    IN MSIHANDLE handle
+)
+{
+    HRESULT hr;
+    CComPtr<IXMLDOMDocument2> pXMLDoc;
+    VARIANT_BOOL variantResult;
+    IXMLDOMNode* webServerNode;
+    IXMLDOMNode* aspNetCoreNode;
+    IXMLDOMNode* tempNode;
+    IXMLDOMElement* element;
+    STRU customActionData;
+
+    CComBSTR selectLanguage = SysAllocString(L"SelectionLanguage");
+    CComBSTR xPath = SysAllocString(L"XPath");
+    CComBSTR webServerPath = SysAllocString(L"//configuration/configSections/sectionGroup[@name=\"system.webServer\"]");
+    CComBSTR aspNetCorePath = SysAllocString(L"//configuration/configSections/sectionGroup[@name=\"system.webServer\"]/section[@name=\"aspNetCore\"]");
+    CComBSTR section = SysAllocString(L"section");
+    CComBSTR name = SysAllocString(L"name");
+    CComBSTR aspNetCore = SysAllocString(L"aspNetCore");
+    CComBSTR overrideMode = SysAllocString(L"overrideModeDefault");
+    CComBSTR allow = SysAllocString(L"Allow");
+
+    RETURN_IF_FAILED(CoInitialize(NULL));
+
+    hr = MsiUtilGetProperty(handle, TEXT("CustomActionData"), &customActionData);
+
+    RETURN_IF_FAILED(hr = pXMLDoc.CoCreateInstance(__uuidof(DOMDocument60)));
+
+    RETURN_IF_FAILED(hr = pXMLDoc->put_async(false));
+
+    RETURN_IF_FAILED(hr = pXMLDoc->load(CComVariant(customActionData.QueryStr()), &variantResult));
+
+    if (variantResult == VARIANT_FALSE)
+    {
+        return ERROR_SUCCESS;
+    }
+
+    RETURN_IF_FAILED(hr = pXMLDoc->setProperty(selectLanguage, CComVariant(xPath)));
+
+    RETURN_IF_FAILED(hr = pXMLDoc->selectSingleNode(webServerPath, &webServerNode));
+
+    RETURN_IF_FAILED(hr = pXMLDoc->selectSingleNode(aspNetCorePath, &aspNetCoreNode));
+
+    if (aspNetCoreNode != NULL)
+    {
+        RETURN_IF_FAILED(webServerNode->removeChild(aspNetCoreNode, &tempNode));
+
+        RETURN_IF_FAILED(hr = pXMLDoc->save(CComVariant(customActionData.QueryStr())));
+    }
+
+    return ERROR_SUCCESS;
+}
+
 UINT
 WINAPI
 RegisterANCMCompressionCA(

+ 2 - 0
src/Installers/Windows/AspNetCoreModule-Setup/CustomAction/aspnetcoreCA.def

@@ -18,6 +18,8 @@ EXPORTS
     ExecuteCleanUpWindowsHotfixCA
     ScheduleRebootIfRequiredCA
 
+    AddConfigSection
+    RemoveConfigSection
     RegisterANCMCompressionCA
 
     CheckForServicesRunningCA

BIN
src/Installers/Windows/UpgradeLog.htm


+ 0 - 2
src/ProjectTemplates/Web.ProjectTemplates/content/RazorPagesWeb-CSharp/wwwroot/css/site.css

@@ -50,7 +50,5 @@ body {
   bottom: 0;
   width: 100%;
   white-space: nowrap;
-  /* Set the fixed height of the footer here */
-  height: 60px;
   line-height: 60px; /* Vertically center the text there */
 }

+ 0 - 2
src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/wwwroot/css/site.css

@@ -50,7 +50,5 @@ body {
   bottom: 0;
   width: 100%;
   white-space: nowrap;
-  /* Set the fixed height of the footer here */
-  height: 60px;
   line-height: 60px; /* Vertically center the text there */
 }

+ 0 - 2
src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-FSharp/wwwroot/css/site.css

@@ -50,7 +50,5 @@ body {
   bottom: 0;
   width: 100%;
   white-space: nowrap;
-  /* Set the fixed height of the footer here */
-  height: 60px;
   line-height: 60px; /* Vertically center the text there */
 }

+ 2 - 0
src/Servers/IIS/IIS/test/Common.FunctionalTests/LogFileTests.cs

@@ -7,6 +7,7 @@ using System.Threading.Tasks;
 using Microsoft.AspNetCore.Server.IIS.FunctionalTests.Utilities;
 using Microsoft.AspNetCore.Server.IntegrationTesting;
 using Microsoft.AspNetCore.Server.IntegrationTesting.IIS;
+using Microsoft.AspNetCore.Testing;
 using Microsoft.AspNetCore.Testing.xunit;
 using Xunit;
 
@@ -170,6 +171,7 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
         }
 
         [ConditionalTheory]
+        [Flaky("https://github.com/aspnet/AspNetCore-Internal/issues/2200", FlakyOn.All)]
         [MemberData(nameof(TestVariants))]
         public async Task CheckUTF8File(TestVariant variant)
         {

+ 2 - 0
src/Servers/Kestrel/Core/ref/Microsoft.AspNetCore.Server.Kestrel.Core.netcoreapp3.0.cs

@@ -121,6 +121,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core
         public Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal.SchedulingMode ApplicationSchedulingMode { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
         public System.IServiceProvider ApplicationServices { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
         public Microsoft.AspNetCore.Server.Kestrel.KestrelConfigurationLoader ConfigurationLoader { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
+        public bool DisableStringReuse { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
         public Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServerLimits Limits { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } }
         public Microsoft.AspNetCore.Server.Kestrel.KestrelConfigurationLoader Configure() { throw null; }
         public Microsoft.AspNetCore.Server.Kestrel.KestrelConfigurationLoader Configure(Microsoft.Extensions.Configuration.IConfiguration config) { throw null; }
@@ -251,6 +252,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
     public partial interface IHttpHeadersHandler
     {
         void OnHeader(System.Span<byte> name, System.Span<byte> value);
+        void OnHeadersComplete();
     }
     public partial interface IHttpParser<TRequestHandler> where TRequestHandler : Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.IHttpHeadersHandler, Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.IHttpRequestLineHandler
     {

+ 117 - 15
src/Servers/Kestrel/Core/src/Internal/Http/Http1Connection.cs

@@ -19,6 +19,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
         private const byte ByteAsterisk = (byte)'*';
         private const byte ByteForwardSlash = (byte)'/';
         private const string Asterisk = "*";
+        private const string ForwardSlash = "/";
 
         private readonly HttpConnectionContext _context;
         private readonly IHttpParser<Http1ParsingHandler> _parser;
@@ -268,16 +269,68 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
 
             _requestTargetForm = HttpRequestTarget.OriginForm;
 
+            if (target.Length == 1)
+            {
+                // If target.Length == 1 it can only be a forward slash (e.g. home page)
+                // and we know RawTarget and Path are the same and QueryString is Empty
+                RawTarget = ForwardSlash;
+                Path = ForwardSlash;
+                QueryString = string.Empty;
+                // Clear parsedData as we won't check it if we come via this path again,
+                // an setting to null is fast as it doesn't need to use a GC write barrier.
+                _parsedRawTarget = _parsedPath = _parsedQueryString = null;
+                return;
+            }
+
             // URIs are always encoded/escaped to ASCII https://tools.ietf.org/html/rfc3986#page-11
             // Multibyte Internationalized Resource Identifiers (IRIs) are first converted to utf8;
             // then encoded/escaped to ASCII  https://www.ietf.org/rfc/rfc3987.txt "Mapping of IRIs to URIs"
 
             try
             {
+                var disableStringReuse = ServerOptions.DisableStringReuse;
                 // Read raw target before mutating memory.
-                RawTarget = target.GetAsciiStringNonNullCharacters();
-                QueryString = query.GetAsciiStringNonNullCharacters();
-                Path = PathNormalizer.DecodePath(path, pathEncoded, RawTarget, query.Length);
+                var previousValue = _parsedRawTarget;
+                if (disableStringReuse ||
+                    previousValue == null || previousValue.Length != target.Length ||
+                    !StringUtilities.BytesOrdinalEqualsStringAndAscii(previousValue, target))
+                {
+                    // The previous string does not match what the bytes would convert to,
+                    // so we will need to generate a new string.
+                    RawTarget = _parsedRawTarget = target.GetAsciiStringNonNullCharacters();
+
+                    previousValue = _parsedQueryString;
+                    if (disableStringReuse ||
+                        previousValue == null || previousValue.Length != query.Length ||
+                        !StringUtilities.BytesOrdinalEqualsStringAndAscii(previousValue, query))
+                    {
+                        // The previous string does not match what the bytes would convert to,
+                        // so we will need to generate a new string.
+                        QueryString = _parsedQueryString = query.GetAsciiStringNonNullCharacters();
+                    }
+                    else
+                    {
+                        // Same as previous
+                        QueryString = _parsedQueryString;
+                    }
+
+                    if (path.Length == 1)
+                    {
+                        // If path.Length == 1 it can only be a forward slash (e.g. home page)
+                        Path = _parsedPath = ForwardSlash;
+                    }
+                    else
+                    {
+                        Path = _parsedPath = PathNormalizer.DecodePath(path, pathEncoded, RawTarget, query.Length);
+                    }
+                }
+                else
+                {
+                    // As RawTarget is the same we can reuse the previous parsed values.
+                    RawTarget = _parsedRawTarget;
+                    Path = _parsedPath;
+                    QueryString = _parsedQueryString;
+                }
             }
             catch (InvalidOperationException)
             {
@@ -312,9 +365,27 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
             //
             // Allowed characters in the 'host + port' section of authority.
             // See https://tools.ietf.org/html/rfc3986#section-3.2
-            RawTarget = target.GetAsciiStringNonNullCharacters();
+
+            var previousValue = _parsedRawTarget;
+            if (ServerOptions.DisableStringReuse ||
+                previousValue == null || previousValue.Length != target.Length ||
+                !StringUtilities.BytesOrdinalEqualsStringAndAscii(previousValue, target))
+            {
+                // The previous string does not match what the bytes would convert to,
+                // so we will need to generate a new string.
+                RawTarget = _parsedRawTarget = target.GetAsciiStringNonNullCharacters();
+            }
+            else
+            {
+                // Reuse previous value
+                RawTarget = _parsedRawTarget;
+            }
+
             Path = string.Empty;
             QueryString = string.Empty;
+            // Clear parsedData for path and queryString as we won't check it if we come via this path again,
+            // an setting to null is fast as it doesn't need to use a GC write barrier.
+            _parsedPath = _parsedQueryString = null;
         }
 
         private void OnAsteriskFormTarget(HttpMethod method)
@@ -331,6 +402,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
             RawTarget = Asterisk;
             Path = string.Empty;
             QueryString = string.Empty;
+            // Clear parsedData as we won't check it if we come via this path again,
+            // an setting to null is fast as it doesn't need to use a GC write barrier.
+            _parsedRawTarget = _parsedPath = _parsedQueryString = null;
         }
 
         private void OnAbsoluteFormTarget(Span<byte> target, Span<byte> query)
@@ -346,21 +420,49 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
             //    a server MUST accept the absolute-form in requests, even though
             //    HTTP/1.1 clients will only send them in requests to proxies.
 
-            RawTarget = target.GetAsciiStringNonNullCharacters();
+            var disableStringReuse = ServerOptions.DisableStringReuse;
+            var previousValue = _parsedRawTarget;
+            if (disableStringReuse ||
+                previousValue == null || previousValue.Length != target.Length ||
+                !StringUtilities.BytesOrdinalEqualsStringAndAscii(previousValue, target))
+            {
+                // The previous string does not match what the bytes would convert to,
+                // so we will need to generate a new string.
+                RawTarget = _parsedRawTarget = target.GetAsciiStringNonNullCharacters();
 
-            // Validation of absolute URIs is slow, but clients
-            // should not be sending this form anyways, so perf optimization
-            // not high priority
+                // Validation of absolute URIs is slow, but clients
+                // should not be sending this form anyways, so perf optimization
+                // not high priority
 
-            if (!Uri.TryCreate(RawTarget, UriKind.Absolute, out var uri))
+                if (!Uri.TryCreate(RawTarget, UriKind.Absolute, out var uri))
+                {
+                    ThrowRequestTargetRejected(target);
+                }
+
+                _absoluteRequestTarget = uri;
+                Path = _parsedPath = uri.LocalPath;
+                // don't use uri.Query because we need the unescaped version
+                previousValue = _parsedQueryString;
+                if (disableStringReuse ||
+                    previousValue == null || previousValue.Length != query.Length ||
+                    !StringUtilities.BytesOrdinalEqualsStringAndAscii(previousValue, query))
+                {
+                    // The previous string does not match what the bytes would convert to,
+                    // so we will need to generate a new string.
+                    QueryString = _parsedQueryString = query.GetAsciiStringNonNullCharacters();
+                }
+                else
+                {
+                    QueryString = _parsedQueryString;
+                }
+            }
+            else
             {
-                ThrowRequestTargetRejected(target);
+                // As RawTarget is the same we can reuse the previous values.
+                RawTarget = _parsedRawTarget;
+                Path = _parsedPath;
+                QueryString = _parsedQueryString;
             }
-
-            _absoluteRequestTarget = uri;
-            Path = uri.LocalPath;
-            // don't use uri.Query because we need the unescaped version
-            QueryString = query.GetAsciiStringNonNullCharacters();
         }
 
         internal void EnsureHostHeaderExists()

+ 3 - 0
src/Servers/Kestrel/Core/src/Internal/Http/Http1ParsingHandler.cs

@@ -17,6 +17,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
         public void OnHeader(Span<byte> name, Span<byte> value)
             => Connection.OnHeader(name, value);
 
+        public void OnHeadersComplete()
+            => Connection.OnHeadersComplete();
+
         public void OnStartLine(HttpMethod method, HttpVersion version, Span<byte> target, Span<byte> path, Span<byte> query, Span<byte> customMethod, bool pathEncoded)
             => Connection.OnStartLine(method, version, target, path, query, customMethod, pathEncoded);
     }

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 556 - 796
src/Servers/Kestrel/Core/src/Internal/Http/HttpHeaders.Generated.cs


+ 1 - 0
src/Servers/Kestrel/Core/src/Internal/Http/HttpHeaders.cs

@@ -16,6 +16,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
 {
     internal abstract class HttpHeaders : IHeaderDictionary
     {
+        protected long _bits = 0;
         protected long? _contentLength;
         protected bool _isReadOnly;
         protected Dictionary<string, StringValues> MaybeUnknown;

+ 1 - 0
src/Servers/Kestrel/Core/src/Internal/Http/HttpParser.cs

@@ -241,6 +241,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
                                     }
 
                                     done = true;
+                                    handler.OnHeadersComplete();
                                     return true;
                                 }
 

+ 14 - 3
src/Servers/Kestrel/Core/src/Internal/Http/HttpProtocol.cs

@@ -74,6 +74,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
             _context = context;
 
             ServerOptions = ServiceContext.ServerOptions;
+            HttpRequestHeaders = new HttpRequestHeaders(reuseHeaderValues: !ServerOptions.DisableStringReuse);
             HttpResponseControl = this;
         }
 
@@ -124,8 +125,14 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
         public string Scheme { get; set; }
         public HttpMethod Method { get; set; }
         public string PathBase { get; set; }
+
+        protected string _parsedPath = null;
         public string Path { get; set; }
+
+        protected string _parsedQueryString = null;
         public string QueryString { get; set; }
+
+        protected string _parsedRawTarget = null;
         public string RawTarget { get; set; }
 
         public string HttpVersion
@@ -275,7 +282,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
 
         public bool HasFlushedHeaders => _requestProcessingStatus == RequestProcessingStatus.HeadersFlushed;
 
-        protected HttpRequestHeaders HttpRequestHeaders { get; } = new HttpRequestHeaders();
+        protected HttpRequestHeaders HttpRequestHeaders { get; }
 
         protected HttpResponseHeaders HttpResponseHeaders { get; } = new HttpResponseHeaders();
 
@@ -492,9 +499,13 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
             {
                 BadHttpRequestException.Throw(RequestRejectionReason.TooManyHeaders);
             }
-            var valueString = value.GetAsciiOrUTF8StringNonNullCharacters();
 
-            HttpRequestHeaders.Append(name, valueString);
+            HttpRequestHeaders.Append(name, value);
+        }
+
+        public void OnHeadersComplete()
+        {
+            HttpRequestHeaders.OnHeadersComplete();
         }
 
         public async Task ProcessRequestsAsync<TContext>(IHttpApplication<TContext> application)

+ 67 - 11
src/Servers/Kestrel/Core/src/Internal/Http/HttpRequestHeaders.cs

@@ -2,6 +2,7 @@
 // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
 
 using System;
+using System.Buffers.Text;
 using System.Collections;
 using System.Collections.Generic;
 using System.Runtime.CompilerServices;
@@ -13,6 +14,50 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
 {
     internal sealed partial class HttpRequestHeaders : HttpHeaders
     {
+        private readonly bool _reuseHeaderValues;
+        private long _previousBits = 0;
+
+        public HttpRequestHeaders(bool reuseHeaderValues = true)
+        {
+            _reuseHeaderValues = reuseHeaderValues;
+        }
+
+        public void OnHeadersComplete()
+        {
+            var bitsToClear = _previousBits & ~_bits;
+            _previousBits = 0;
+
+            if (bitsToClear != 0)
+            {
+                // Some previous headers were not reused or overwritten.
+
+                // While they cannot be accessed by the current request (as they were not supplied by it)
+                // there is no point in holding on to them, so clear them now,
+                // to allow them to get collected by the GC.
+                Clear(bitsToClear);
+            }
+        }
+
+        protected override void ClearFast()
+        {
+            if (!_reuseHeaderValues)
+            {
+                // If we aren't reusing headers clear them all
+                Clear(_bits);
+            }
+            else
+            {
+                // If we are reusing headers, store the currently set headers for comparison later
+                _previousBits = _bits;
+            }
+
+            // Mark no headers as currently in use
+            _bits = 0;
+            // Clear ContentLength and any unknown headers as we will never reuse them 
+            _contentLength = null;
+            MaybeUnknown?.Clear();
+        }
+
         private static long ParseContentLength(string value)
         {
             if (!HeaderUtilities.TryParseNonNegativeInt64(value, out var parsed))
@@ -24,33 +69,44 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
         }
 
         [MethodImpl(MethodImplOptions.NoInlining)]
-        private void SetValueUnknown(string key, StringValues value)
+        private void AppendContentLength(Span<byte> value)
         {
-            Unknown[key] = value;
-        }
+            if (_contentLength.HasValue)
+            {
+                BadHttpRequestException.Throw(RequestRejectionReason.MultipleContentLengths);
+            }
 
-        public unsafe void Append(Span<byte> name, string value)
-        {
-            fixed (byte* namePtr = name)
+            if (!Utf8Parser.TryParse(value, out long parsed, out var consumed) ||
+                parsed < 0 ||
+                consumed != value.Length)
             {
-                Append(namePtr, name.Length, value);
+                BadHttpRequestException.Throw(RequestRejectionReason.InvalidContentLength, value.GetAsciiOrUTF8StringNonNullCharacters());
             }
+
+            _contentLength = parsed;
+        }
+
+        [MethodImpl(MethodImplOptions.NoInlining)]
+        private void SetValueUnknown(string key, StringValues value)
+        {
+            Unknown[key] = value;
         }
 
         [MethodImpl(MethodImplOptions.NoInlining)]
-        private unsafe void AppendUnknownHeaders(byte* pKeyBytes, int keyLength, string value)
+        private unsafe void AppendUnknownHeaders(Span<byte> name, string valueString)
         {
-            string key = new string('\0', keyLength);
+            string key = new string('\0', name.Length);
+            fixed (byte* pKeyBytes = name)
             fixed (char* keyBuffer = key)
             {
-                if (!StringUtilities.TryGetAsciiString(pKeyBytes, keyBuffer, keyLength))
+                if (!StringUtilities.TryGetAsciiString(pKeyBytes, keyBuffer, name.Length))
                 {
                     BadHttpRequestException.Throw(RequestRejectionReason.InvalidCharactersInHeaderName);
                 }
             }
 
             Unknown.TryGetValue(key, out var existing);
-            Unknown[key] = AppendValue(existing, value);
+            Unknown[key] = AppendValue(existing, valueString);
         }
 
         public Enumerator GetEnumerator()

+ 1 - 0
src/Servers/Kestrel/Core/src/Internal/Http/IHttpHeadersHandler.cs

@@ -8,5 +8,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
     public interface IHttpHeadersHandler
     {
         void OnHeader(Span<byte> name, Span<byte> value);
+        void OnHeadersComplete();
     }
 }

+ 3 - 0
src/Servers/Kestrel/Core/src/Internal/Http2/Http2Connection.cs

@@ -1092,6 +1092,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
             }
         }
 
+        public void OnHeadersComplete()
+            => _currentHeadersStream.OnHeadersComplete();
+
         private void ValidateHeader(Span<byte> name, Span<byte> value)
         {
             // http://httpwg.org/specs/rfc7540.html#rfc.section.8.1.2.1

+ 261 - 0
src/Servers/Kestrel/Core/src/Internal/Infrastructure/StringUtilities.cs

@@ -2,13 +2,19 @@
 // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
 
 using System;
+using System.Buffers.Binary;
+using System.Diagnostics;
 using System.Numerics;
 using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics.X86;
+using System.Text;
 
 namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure
 {
     internal class StringUtilities
     {
+        [MethodImpl(MethodImplOptions.AggressiveOptimization)]
         public static unsafe bool TryGetAsciiString(byte* input, char* output, int count)
         {
             // Calculate end position
@@ -109,6 +115,261 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure
             return isValid;
         }
 
+        [MethodImpl(MethodImplOptions.AggressiveOptimization)]
+        public unsafe static bool BytesOrdinalEqualsStringAndAscii(string previousValue, Span<byte> newValue)
+        {
+            // previousValue is a previously materialized string which *must* have already passed validation.
+            Debug.Assert(IsValidHeaderString(previousValue));
+
+            // Ascii bytes => Utf-16 chars will be the same length.
+            // The caller should have already compared lengths before calling this method.
+            // However; let's double check, and early exit if they are not the same length.
+            if (previousValue.Length != newValue.Length)
+            {
+                // Lengths don't match, so there cannot be an exact ascii conversion between the two.
+                goto NotEqual;
+            }
+
+            // Use IntPtr values rather than int, to avoid unnecessary 32 -> 64 movs on 64-bit.
+            // Unfortunately this means we also need to cast to byte* for comparisons as IntPtr doesn't
+            // support operator comparisons (e.g. <=, >, etc).
+            //
+            // Note: Pointer comparison is unsigned, so we use the compare pattern (offset + length <= count)
+            // rather than (offset <= count - length) which we'd do with signed comparison to avoid overflow.
+            // This isn't problematic as we know the maximum length is max string length (from test above)
+            // which is a signed value so half the size of the unsigned pointer value so we can safely add
+            // a Vector<byte>.Count to it without overflowing.
+            var count = (IntPtr)newValue.Length;
+            var offset = (IntPtr)0;
+
+            // Get references to the first byte in the span, and the first char in the string.
+            ref var bytes = ref MemoryMarshal.GetReference(newValue);
+            ref var str = ref MemoryMarshal.GetReference(previousValue.AsSpan());
+
+            do
+            {
+                // If Vector not-accelerated or remaining less than vector size
+                if (!Vector.IsHardwareAccelerated || (byte*)(offset + Vector<byte>.Count) > (byte*)count)
+                {
+                    if (IntPtr.Size == 8) // Use Intrinsic switch for branch elimination
+                    {
+                        // 64-bit: Loop longs by default
+                        while ((byte*)(offset + sizeof(long)) <= (byte*)count)
+                        {
+                            if (!WidenFourAsciiBytesToUtf16AndCompareToChars(
+                                    ref Unsafe.Add(ref str, offset),
+                                    Unsafe.ReadUnaligned<uint>(ref Unsafe.Add(ref bytes, offset))) ||
+                                !WidenFourAsciiBytesToUtf16AndCompareToChars(
+                                    ref Unsafe.Add(ref str, offset + 4),
+                                    Unsafe.ReadUnaligned<uint>(ref Unsafe.Add(ref bytes, offset + 4))))
+                            {
+                                goto NotEqual;
+                            }
+
+                            offset += sizeof(long);
+                        }
+                        if ((byte*)(offset + sizeof(int)) <= (byte*)count)
+                        {
+                            if (!WidenFourAsciiBytesToUtf16AndCompareToChars(
+                                ref Unsafe.Add(ref str, offset),
+                                Unsafe.ReadUnaligned<uint>(ref Unsafe.Add(ref bytes, offset))))
+                            {
+                                goto NotEqual;
+                            }
+
+                            offset += sizeof(int);
+                        }
+                    }
+                    else
+                    {
+                        // 32-bit: Loop ints by default
+                        while ((byte*)(offset + sizeof(int)) <= (byte*)count)
+                        {
+                            if (!WidenFourAsciiBytesToUtf16AndCompareToChars(
+                                ref Unsafe.Add(ref str, offset),
+                                Unsafe.ReadUnaligned<uint>(ref Unsafe.Add(ref bytes, offset))))
+                            {
+                                goto NotEqual;
+                            }
+
+                            offset += sizeof(int);
+                        }
+                    }
+                    if ((byte*)(offset + sizeof(short)) <= (byte*)count)
+                    {
+                        if (!WidenTwoAsciiBytesToUtf16AndCompareToChars(
+                            ref Unsafe.Add(ref str, offset),
+                            Unsafe.ReadUnaligned<ushort>(ref Unsafe.Add(ref bytes, offset))))
+                        {
+                            goto NotEqual;
+                        }
+
+                        offset += sizeof(short);
+                    }
+                    if ((byte*)offset < (byte*)count)
+                    {
+                        var ch = (char)Unsafe.Add(ref bytes, offset);
+                        if (((ch & 0x80) != 0) || Unsafe.Add(ref str, offset) != ch)
+                        {
+                            goto NotEqual;
+                        }
+                    }
+
+                    // End of input reached, there are no inequalities via widening; so the input bytes are both ascii
+                    // and a match to the string if it was converted via Encoding.ASCII.GetString(...)
+                    return true;
+                }
+
+                // Create a comparision vector for all bits being equal
+                var AllTrue = new Vector<short>(-1);
+                // do/while as entry condition already checked, remaining length must be Vector<byte>.Count or larger.
+                do
+                {
+                    // Read a Vector length from the input as bytes
+                    var vector = Unsafe.ReadUnaligned<Vector<sbyte>>(ref Unsafe.Add(ref bytes, offset));
+                    if (!CheckBytesInAsciiRange(vector))
+                    {
+                        goto NotEqual;
+                    }
+                    // Widen the bytes directly to chars (ushort) as if they were ascii.
+                    // As widening doubles the size we get two vectors back.
+                    Vector.Widen(vector, out var vector0, out var vector1);
+                    // Read two char vectors from the string to perform the match.
+                    var compare0 = Unsafe.ReadUnaligned<Vector<short>>(ref Unsafe.As<char, byte>(ref Unsafe.Add(ref str, offset)));
+                    var compare1 = Unsafe.ReadUnaligned<Vector<short>>(ref Unsafe.As<char, byte>(ref Unsafe.Add(ref str, offset + Vector<ushort>.Count)));
+
+                    // If the string is not ascii, then the widened bytes cannot match
+                    // as each widened byte element as chars will be in the range 0-255
+                    // so cannot match any higher unicode values.
+
+                    // Compare to our all bits true comparision vector
+                    if (!AllTrue.Equals(
+                        // BitwiseAnd the two equals together
+                        Vector.BitwiseAnd(
+                            // Check equality for the two widened vectors
+                            Vector.Equals(compare0, vector0),
+                            Vector.Equals(compare1, vector1))))
+                    {
+                        goto NotEqual;
+                    }
+
+                    offset += Vector<byte>.Count;
+                } while ((byte*)(offset + Vector<byte>.Count) <= (byte*)count);
+
+                // Vector path done, loop back to do non-Vector
+                // If is a exact multiple of vector size, bail now
+            } while ((byte*)offset < (byte*)count);
+
+            // If we get here (input is exactly a multiple of Vector length) then there are no inequalities via widening;
+            // so the input bytes are both ascii and a match to the string if it was converted via Encoding.ASCII.GetString(...)
+            return true;
+        NotEqual:
+            return false;
+        }
+
+        /// <summary>
+        /// Given a DWORD which represents a buffer of 4 bytes, widens the buffer into 4 WORDs and
+        /// compares them to the WORD buffer with machine endianness.
+        /// </summary>
+        [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
+        private static bool WidenFourAsciiBytesToUtf16AndCompareToChars(ref char charStart, uint value)
+        {
+            if (!AllBytesInUInt32AreAscii(value))
+            {
+                return false;
+            }
+
+            if (Bmi2.X64.IsSupported)
+            {
+                // BMI2 will work regardless of the processor's endianness.
+                return Unsafe.ReadUnaligned<ulong>(ref Unsafe.As<char, byte>(ref charStart)) ==
+                    Bmi2.X64.ParallelBitDeposit(value, 0x00FF00FF_00FF00FFul);
+            }
+            else
+            {
+                if (BitConverter.IsLittleEndian)
+                {
+                    return charStart == (char)(byte)value &&
+                        Unsafe.Add(ref charStart, 1) == (char)(byte)(value >> 8) &&
+                        Unsafe.Add(ref charStart, 2) == (char)(byte)(value >> 16) &&
+                        Unsafe.Add(ref charStart, 3) == (char)(value >> 24);
+                }
+                else
+                {
+                    return Unsafe.Add(ref charStart, 3) == (char)(byte)value &&
+                        Unsafe.Add(ref charStart, 2) == (char)(byte)(value >> 8) &&
+                        Unsafe.Add(ref charStart, 1) == (char)(byte)(value >> 16) &&
+                        charStart == (char)(value >> 24);
+                }
+            }
+        }
+
+        /// <summary>
+        /// Given a WORD which represents a buffer of 2 bytes, widens the buffer into 2 WORDs and
+        /// compares them to the WORD buffer with machine endianness.
+        /// </summary>
+        [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
+        private static bool WidenTwoAsciiBytesToUtf16AndCompareToChars(ref char charStart, ushort value)
+        {
+            if (!AllBytesInUInt16AreAscii(value))
+            {
+                return false;
+            }
+
+            if (Bmi2.IsSupported)
+            {
+                // BMI2 will work regardless of the processor's endianness.
+                return Unsafe.ReadUnaligned<uint>(ref Unsafe.As<char, byte>(ref charStart)) ==
+                    Bmi2.ParallelBitDeposit(value, 0x00FF00FFu);
+            }
+            else
+            {
+                if (BitConverter.IsLittleEndian)
+                {
+                    return charStart == (char)(byte)value &&
+                        Unsafe.Add(ref charStart, 1) == (char)(byte)(value >> 8);
+                }
+                else
+                {
+                    return Unsafe.Add(ref charStart, 1) == (char)(byte)value &&
+                        charStart == (char)(byte)(value >> 8);
+                }
+            }
+        }
+
+        /// <summary>
+        /// Returns <see langword="true"/> iff all bytes in <paramref name="value"/> are ASCII.
+        /// </summary>
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        private static bool AllBytesInUInt32AreAscii(uint value)
+        {
+            return ((value & 0x80808080u) == 0);
+        }
+
+        /// <summary>
+        /// Returns <see langword="true"/> iff all bytes in <paramref name="value"/> are ASCII.
+        /// </summary>
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        private static bool AllBytesInUInt16AreAscii(ushort value)
+        {
+            return ((value & 0x8080u) == 0);
+        }
+
+        private unsafe static bool IsValidHeaderString(string value)
+        {
+            // Method for Debug.Assert to ensure BytesOrdinalEqualsStringAndAscii
+            // is not called with an unvalidated string comparitor.
+            try
+            {
+                if (value is null) return false;
+                new UTF8Encoding(encoderShouldEmitUTF8Identifier: false, throwOnInvalidBytes: true).GetByteCount(value);
+                return !value.Contains('\0');
+            }
+            catch (DecoderFallbackException) {
+                return false;
+            }
+        }
+
         private static readonly char[] s_encode16Chars = "0123456789ABCDEF".ToCharArray();
 
         /// <summary>

+ 9 - 0
src/Servers/Kestrel/Core/src/KestrelServerOptions.cs

@@ -54,6 +54,15 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core
         /// </remarks>
         public bool AllowSynchronousIO { get; set; } = false;
 
+        /// <summary>
+        /// Gets or sets a value that controls whether the string values materialized
+        /// will be reused across requests; if they match, or if the strings will always be reallocated.
+        /// </summary>
+        /// <remarks>
+        /// Defaults to false.
+        /// </remarks>
+        public bool DisableStringReuse { get; set; } = false;
+
         /// <summary>
         /// Enables the Listen options callback to resolve and use services registered by the application during startup.
         /// Typically initialized by UseKestrel()"/>.

+ 88 - 9
src/Servers/Kestrel/Core/test/AsciiDecoding.cs

@@ -24,16 +24,28 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
                 .Concat(byteRange)
                 .ToArray();
 
-            var s = new Span<byte>(byteArray).GetAsciiStringNonNullCharacters();
+            var span = new Span<byte>(byteArray);
 
-            Assert.Equal(s.Length, byteArray.Length);
+            for (var i = 0; i <= byteArray.Length; i++)
+            {
+                // Test all the lengths to hit all the different length paths e.g. Vector, long, short, char
+                Test(span.Slice(i));
+            }
 
-            for (var i = 1; i < byteArray.Length; i++)
+            static void Test(Span<byte> asciiBytes)
             {
-                var sb = (byte)s[i];
-                var b = byteArray[i];
+                var s = asciiBytes.GetAsciiStringNonNullCharacters();
+
+                Assert.True(StringUtilities.BytesOrdinalEqualsStringAndAscii(s, asciiBytes));
+                Assert.Equal(s.Length, asciiBytes.Length);
 
-                Assert.Equal(sb, b);
+                for (var i = 0; i < asciiBytes.Length; i++)
+                {
+                    var sb = (byte)s[i];
+                    var b = asciiBytes[i];
+
+                    Assert.Equal(sb, b);
+                }
             }
         }
 
@@ -59,8 +71,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
         {
             var byteRange = Enumerable.Range(0, 16384 + 64).Select(x => (byte)((x & 0x7f) | 0x01)).ToArray();
             var expectedByteRange = byteRange.Concat(byteRange).ToArray();
-            
-            var s = new Span<byte>(expectedByteRange).GetAsciiStringNonNullCharacters();
+
+            var span = new Span<byte>(expectedByteRange);
+            var s = span.GetAsciiStringNonNullCharacters();
 
             Assert.Equal(expectedByteRange.Length, s.Length);
 
@@ -68,8 +81,74 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
             {
                 var sb = (byte)((s[i] & 0x7f) | 0x01);
                 var b = expectedByteRange[i];
+            }
+
+            Assert.True(StringUtilities.BytesOrdinalEqualsStringAndAscii(s, span));
+        }
+
+        [Fact]
+        private void DifferentLengthsAreNotEqual()
+        {
+            var byteRange = Enumerable.Range(0, 4096).Select(x => (byte)((x & 0x7f) | 0x01)).ToArray();
+            var expectedByteRange = byteRange.Concat(byteRange).ToArray();
+
+            for (var i = 1; i < byteRange.Length; i++)
+            {
+                var span = new Span<byte>(expectedByteRange);
+                var s = span.GetAsciiStringNonNullCharacters();
+
+                Assert.True(StringUtilities.BytesOrdinalEqualsStringAndAscii(s, span));
+
+                // One off end
+                Assert.False(StringUtilities.BytesOrdinalEqualsStringAndAscii(s, span.Slice(0, span.Length - 1)));
+                Assert.False(StringUtilities.BytesOrdinalEqualsStringAndAscii(s.Substring(0, s.Length - 1), span));
+
+                // One off start
+                Assert.False(StringUtilities.BytesOrdinalEqualsStringAndAscii(s, span.Slice(1, span.Length - 1)));
+                Assert.False(StringUtilities.BytesOrdinalEqualsStringAndAscii(s.Substring(1, s.Length - 1), span));
+            }
+        }
+
+        [Fact]
+        private void AsciiBytesEqualAsciiStrings()
+        {
+            var byteRange = Enumerable.Range(1, 127).Select(x => (byte)x);
+
+            var byteArray = byteRange
+                .Concat(byteRange)
+                .Concat(byteRange)
+                .Concat(byteRange)
+                .Concat(byteRange)
+                .Concat(byteRange)
+                .ToArray();
 
-                Assert.Equal(sb, b);
+            var span = new Span<byte>(byteArray);
+
+            for (var i = 0; i <= byteArray.Length; i++)
+            {
+                // Test all the lengths to hit all the different length paths e.g. Vector, long, short, char
+                Test(span.Slice(i));
+            }
+
+            static void Test(Span<byte> asciiBytes)
+            {
+                var s = asciiBytes.GetAsciiStringNonNullCharacters();
+
+                // Should start as equal
+                Assert.True(StringUtilities.BytesOrdinalEqualsStringAndAscii(s, asciiBytes));
+
+                for (var i = 0; i < asciiBytes.Length; i++)
+                {
+                    var b = asciiBytes[i];
+
+                    // Change one byte, ensure is not equal
+                    asciiBytes[i] = (byte)(b + 1);
+                    Assert.False(StringUtilities.BytesOrdinalEqualsStringAndAscii(s, asciiBytes));
+
+                    // Change byte back for next iteration, ensure is equal again
+                    asciiBytes[i] = b;
+                    Assert.True(StringUtilities.BytesOrdinalEqualsStringAndAscii(s, asciiBytes));
+                }
             }
         }
     }

+ 2 - 0
src/Servers/Kestrel/Core/test/HPackDecoderTests.cs

@@ -103,6 +103,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
             _decodedHeaders[name.GetAsciiStringNonNullCharacters()] = value.GetAsciiStringNonNullCharacters();
         }
 
+        void IHttpHeadersHandler.OnHeadersComplete() { }
+
         [Fact]
         public void DecodesIndexedHeaderField_StaticTable()
         {

+ 2 - 0
src/Servers/Kestrel/Core/test/HttpParserTests.cs

@@ -483,6 +483,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
                 Headers[name.GetAsciiStringNonNullCharacters()] = value.GetAsciiStringNonNullCharacters();
             }
 
+            void IHttpHeadersHandler.OnHeadersComplete() { }
+
             public void OnStartLine(HttpMethod method, HttpVersion version, Span<byte> target, Span<byte> path, Span<byte> query, Span<byte> customMethod, bool pathEncoded)
             {
                 Method = method != HttpMethod.Custom ? HttpUtilities.MethodToString(method) : customMethod.GetAsciiStringNonNullCharacters();

+ 342 - 1
src/Servers/Kestrel/Core/test/HttpRequestHeadersTests.cs

@@ -3,11 +3,13 @@
 
 using System;
 using System.Collections.Generic;
+using System.Linq;
 using System.Text;
 using Microsoft.AspNetCore.Http;
 using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
 using Microsoft.Extensions.Primitives;
 using Xunit;
+using static CodeGenerator.KnownHeaders;
 
 namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
 {
@@ -307,8 +309,347 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
 
             var encoding = Encoding.GetEncoding("iso-8859-1");
             var exception = Assert.Throws<BadHttpRequestException>(
-                () => headers.Append(encoding.GetBytes(key), "value"));
+                () => headers.Append(encoding.GetBytes(key), Encoding.ASCII.GetBytes("value")));
             Assert.Equal(StatusCodes.Status400BadRequest, exception.StatusCode);
         }
+
+        [Theory]
+        [MemberData(nameof(KnownRequestHeaders))]
+        public void ValueReuseOnlyWhenAllowed(bool reuseValue, KnownHeader header)
+        {
+            const string HeaderValue = "Hello";
+            var headers = new HttpRequestHeaders(reuseHeaderValues: reuseValue);
+
+            for (var i = 0; i < 6; i++)
+            {
+                var prevName = ChangeNameCase(header.Name, variant: i);
+                var nextName = ChangeNameCase(header.Name, variant: i + 1);
+
+                var values = GetHeaderValues(headers, prevName, nextName, HeaderValue, HeaderValue);
+
+                Assert.Equal(HeaderValue, values.PrevHeaderValue);
+                Assert.NotSame(HeaderValue, values.PrevHeaderValue);
+
+                Assert.Equal(HeaderValue, values.NextHeaderValue);
+                Assert.NotSame(HeaderValue, values.NextHeaderValue);
+
+                Assert.Equal(values.PrevHeaderValue, values.NextHeaderValue);
+                if (reuseValue)
+                {
+                    // When materalized string is reused previous and new should be the same object
+                    Assert.Same(values.PrevHeaderValue, values.NextHeaderValue);
+                }
+                else
+                {
+                    // When materalized string is not reused previous and new should be the different objects
+                    Assert.NotSame(values.PrevHeaderValue, values.NextHeaderValue);
+            }
+            }
+        }
+
+        [Theory]
+        [MemberData(nameof(KnownRequestHeaders))]
+        public void ValueReuseChangedValuesOverwrite(bool reuseValue, KnownHeader header)
+        {
+            const string HeaderValue1 = "Hello1";
+            const string HeaderValue2 = "Hello2";
+            var headers = new HttpRequestHeaders(reuseHeaderValues: reuseValue);
+
+            for (var i = 0; i < 6; i++)
+            {
+                var prevName = ChangeNameCase(header.Name, variant: i);
+                var nextName = ChangeNameCase(header.Name, variant: i + 1);
+
+                var values = GetHeaderValues(headers, prevName, nextName, HeaderValue1, HeaderValue2);
+
+                Assert.Equal(HeaderValue1, values.PrevHeaderValue);
+                Assert.NotSame(HeaderValue1, values.PrevHeaderValue);
+
+                Assert.Equal(HeaderValue2, values.NextHeaderValue);
+                Assert.NotSame(HeaderValue2, values.NextHeaderValue);
+
+                Assert.NotEqual(values.PrevHeaderValue, values.NextHeaderValue);
+            }
+        }
+
+        [Theory]
+        [MemberData(nameof(KnownRequestHeaders))]
+        public void ValueReuseMissingValuesClear(bool reuseValue, KnownHeader header)
+        {
+            const string HeaderValue1 = "Hello1";
+            var headers = new HttpRequestHeaders(reuseHeaderValues: reuseValue);
+
+            for (var i = 0; i < 6; i++)
+            {
+                var prevName = ChangeNameCase(header.Name, variant: i);
+                var nextName = ChangeNameCase(header.Name, variant: i + 1);
+
+                var values = GetHeaderValues(headers, prevName, nextName, HeaderValue1, nextValue: null);
+
+                Assert.Equal(HeaderValue1, values.PrevHeaderValue);
+                Assert.NotSame(HeaderValue1, values.PrevHeaderValue);
+
+                Assert.Equal(string.Empty, values.NextHeaderValue);
+
+                Assert.NotEqual(values.PrevHeaderValue, values.NextHeaderValue);
+            }
+        }
+
+        [Theory]
+        [MemberData(nameof(KnownRequestHeaders))]
+        public void ValueReuseNeverWhenNotAscii(bool reuseValue, KnownHeader header)
+        {
+            const string HeaderValue = "Hello \u03a0";
+
+            var headers = new HttpRequestHeaders(reuseHeaderValues: reuseValue);
+
+            for (var i = 0; i < 6; i++)
+            {
+                var prevName = ChangeNameCase(header.Name, variant: i);
+                var nextName = ChangeNameCase(header.Name, variant: i + 1);
+
+                var values = GetHeaderValues(headers, prevName, nextName, HeaderValue, HeaderValue);
+
+                Assert.Equal(HeaderValue, values.PrevHeaderValue);
+                Assert.NotSame(HeaderValue, values.PrevHeaderValue);
+
+                Assert.Equal(HeaderValue, values.NextHeaderValue);
+                Assert.NotSame(HeaderValue, values.NextHeaderValue);
+
+                Assert.Equal(values.PrevHeaderValue, values.NextHeaderValue);
+
+                Assert.NotSame(values.PrevHeaderValue, values.NextHeaderValue);
+            }
+        }
+
+        [Theory]
+        [MemberData(nameof(KnownRequestHeaders))]
+        public void ValueReuseLatin1NotConfusedForUtf16AndStillRejected(bool reuseValue, KnownHeader header)
+        {
+            var headers = new HttpRequestHeaders(reuseHeaderValues: reuseValue);
+
+            var headerValue = new char[127]; // 64 + 32 + 16 + 8 + 4 + 2 + 1
+            for (var i = 0; i < headerValue.Length; i++)
+            {
+                headerValue[i] = 'a';
+            }
+
+            for (var i = 0; i < headerValue.Length; i++)
+            {
+                // Set non-ascii Latin char that is valid Utf16 when widened; but not a valid utf8 -> utf16 conversion.
+                headerValue[i] = '\u00a3';
+
+                for (var mode = 0; mode <= 1; mode++)
+                {
+                    string headerValueUtf16Latin1CrossOver;
+                    if (mode == 0)
+                    {
+                        // Full length
+                        headerValueUtf16Latin1CrossOver = new string(headerValue);
+                    }
+                    else
+                    {
+                        // Truncated length (to ensure different paths from changing lengths in matching)
+                        headerValueUtf16Latin1CrossOver = new string(headerValue.AsSpan().Slice(0, i + 1));
+                    }
+
+                    headers.Reset();
+
+                    var headerName = Encoding.ASCII.GetBytes(header.Name).AsSpan();
+                    var prevSpan = Encoding.UTF8.GetBytes(headerValueUtf16Latin1CrossOver).AsSpan();
+
+                    headers.Append(headerName, prevSpan);
+                    headers.OnHeadersComplete();
+                    var prevHeaderValue = ((IHeaderDictionary)headers)[header.Name].ToString();
+
+                    Assert.Equal(headerValueUtf16Latin1CrossOver, prevHeaderValue);
+                    Assert.NotSame(headerValueUtf16Latin1CrossOver, prevHeaderValue);
+
+                    headers.Reset();
+
+                    Assert.Throws<InvalidOperationException>(() =>
+                    {
+                        var headerName = Encoding.ASCII.GetBytes(header.Name).AsSpan();
+                        var nextSpan = Encoding.GetEncoding("iso-8859-1").GetBytes(headerValueUtf16Latin1CrossOver).AsSpan();
+
+                        Assert.False(nextSpan.SequenceEqual(Encoding.ASCII.GetBytes(headerValueUtf16Latin1CrossOver)));
+
+                        headers.Append(headerName, nextSpan);
+                    });
+                }
+
+                // Reset back to Ascii
+                headerValue[i] = 'a';
+            }
+        }
+
+        [Fact]
+        public void ValueReuseNeverWhenUnknownHeader()
+        {
+            const string HeaderName = "An-Unknown-Header";
+            const string HeaderValue = "Hello";
+
+            var headers = new HttpRequestHeaders(reuseHeaderValues: true);
+
+            for (var i = 0; i < 6; i++)
+            {
+                var prevName = ChangeNameCase(HeaderName, variant: i);
+                var nextName = ChangeNameCase(HeaderName, variant: i + 1);
+
+                var values = GetHeaderValues(headers, prevName, nextName, HeaderValue, HeaderValue);
+
+                Assert.Equal(HeaderValue, values.PrevHeaderValue);
+                Assert.NotSame(HeaderValue, values.PrevHeaderValue);
+
+                Assert.Equal(HeaderValue, values.NextHeaderValue);
+                Assert.NotSame(HeaderValue, values.NextHeaderValue);
+
+                Assert.Equal(values.PrevHeaderValue, values.NextHeaderValue);
+
+                Assert.NotSame(values.PrevHeaderValue, values.NextHeaderValue);
+            }
+        }
+
+        [Theory]
+        [MemberData(nameof(KnownRequestHeaders))]
+        public void ValueReuseEmptyAfterReset(bool reuseValue, KnownHeader header)
+        {
+            const string HeaderValue = "Hello";
+
+            var headers = new HttpRequestHeaders(reuseHeaderValues: reuseValue);
+            var headerName = Encoding.ASCII.GetBytes(header.Name).AsSpan();
+            var prevSpan = Encoding.UTF8.GetBytes(HeaderValue).AsSpan();
+
+            headers.Append(headerName, prevSpan);
+            headers.OnHeadersComplete();
+            var prevHeaderValue = ((IHeaderDictionary)headers)[header.Name].ToString();
+
+            Assert.NotNull(prevHeaderValue);
+            Assert.NotEqual(string.Empty, prevHeaderValue);
+            Assert.Equal(HeaderValue, prevHeaderValue);
+            Assert.NotSame(HeaderValue, prevHeaderValue);
+            Assert.Single(headers);
+            var count = headers.Count;
+            Assert.Equal(1, count);
+
+            headers.Reset();
+
+            // Empty after reset
+            var nextHeaderValue = ((IHeaderDictionary)headers)[header.Name].ToString();
+
+            Assert.NotNull(nextHeaderValue);
+            Assert.Equal(string.Empty, nextHeaderValue);
+            Assert.NotEqual(HeaderValue, nextHeaderValue);
+            Assert.Empty(headers);
+            count = headers.Count;
+            Assert.Equal(0, count);
+
+            headers.OnHeadersComplete();
+
+            // Still empty after complete
+            nextHeaderValue = ((IHeaderDictionary)headers)[header.Name].ToString();
+
+            Assert.NotNull(nextHeaderValue);
+            Assert.Equal(string.Empty, nextHeaderValue);
+            Assert.NotEqual(HeaderValue, nextHeaderValue);
+            Assert.Empty(headers);
+            count = headers.Count;
+            Assert.Equal(0, count);
+        }
+
+        [Theory]
+        [MemberData(nameof(KnownRequestHeaders))]
+        public void MultiValueReuseEmptyAfterReset(bool reuseValue, KnownHeader header)
+        {
+            const string HeaderValue1 = "Hello1";
+            const string HeaderValue2 = "Hello2";
+
+            var headers = new HttpRequestHeaders(reuseHeaderValues: reuseValue);
+            var headerName = Encoding.ASCII.GetBytes(header.Name).AsSpan();
+            var prevSpan1 = Encoding.UTF8.GetBytes(HeaderValue1).AsSpan();
+            var prevSpan2 = Encoding.UTF8.GetBytes(HeaderValue2).AsSpan();
+
+            headers.Append(headerName, prevSpan1);
+            headers.Append(headerName, prevSpan2);
+            headers.OnHeadersComplete();
+            var prevHeaderValue = ((IHeaderDictionary)headers)[header.Name];
+
+            Assert.Equal(2, prevHeaderValue.Count);
+
+            Assert.NotEqual(string.Empty, prevHeaderValue.ToString());
+            Assert.Single(headers);
+            var count = headers.Count;
+            Assert.Equal(1, count);
+
+            headers.Reset();
+
+            // Empty after reset
+            var nextHeaderValue = ((IHeaderDictionary)headers)[header.Name].ToString();
+
+            Assert.NotNull(nextHeaderValue);
+            Assert.Equal(string.Empty, nextHeaderValue);
+            Assert.Empty(headers);
+            count = headers.Count;
+            Assert.Equal(0, count);
+
+            headers.OnHeadersComplete();
+
+            // Still empty after complete
+            nextHeaderValue = ((IHeaderDictionary)headers)[header.Name].ToString();
+
+            Assert.NotNull(nextHeaderValue);
+            Assert.Equal(string.Empty, nextHeaderValue);
+            Assert.Empty(headers);
+            count = headers.Count;
+            Assert.Equal(0, count);
+        }
+
+        private static (string PrevHeaderValue, string NextHeaderValue) GetHeaderValues(HttpRequestHeaders headers, string prevName, string nextName, string prevValue, string nextValue)
+        {
+            headers.Reset();
+            var headerName = Encoding.ASCII.GetBytes(prevName).AsSpan();
+            var prevSpan = Encoding.UTF8.GetBytes(prevValue).AsSpan();
+
+            headers.Append(headerName, prevSpan);
+            headers.OnHeadersComplete();
+            var prevHeaderValue = ((IHeaderDictionary)headers)[prevName].ToString();
+
+            headers.Reset();
+
+            if (nextValue != null)
+            {
+                headerName = Encoding.ASCII.GetBytes(prevName).AsSpan();
+                var nextSpan = Encoding.UTF8.GetBytes(nextValue).AsSpan();
+                headers.Append(headerName, nextSpan);
+            }
+
+            headers.OnHeadersComplete();
+
+            var newHeaderValue = ((IHeaderDictionary)headers)[nextName].ToString();
+
+            return (prevHeaderValue, newHeaderValue);
+        }
+
+        private static string ChangeNameCase(string name, int variant)
+        {
+            switch ((variant / 2) % 3)
+            {
+                case 0:
+                    return name;
+                case 1:
+                    return name.ToLowerInvariant();
+                case 2:
+                    return name.ToUpperInvariant();
+            }
+
+            // Never reached
+            Assert.False(true);
+            return name;
+        }
+
+        // Content-Length is numeric not a string, so we exclude it from the string reuse tests
+        public static IEnumerable<object[]> KnownRequestHeaders =>
+            RequestHeaders.Where(h => h.Name != "Content-Length").Select(h => new object[] { true, h }).Concat(
+            RequestHeaders.Where(h => h.Name != "Content-Length").Select(h => new object[] { false, h }));
     }
 }

+ 1 - 0
src/Servers/Kestrel/Core/test/Microsoft.AspNetCore.Server.Kestrel.Core.Tests.csproj

@@ -10,6 +10,7 @@
     <Compile Include="$(SharedSourceRoot)NullScope.cs" />
     <Compile Include="$(SharedSourceRoot)Buffers.Testing\*.cs" />
     <Compile Include="$(KestrelSharedSourceRoot)test\*.cs" LinkBase="shared" />
+    <Compile Include="$(KestrelSharedSourceRoot)KnownHeaders.cs" LinkBase="shared" />
     <Content Include="$(KestrelSharedSourceRoot)test\TestCertificates\*.pfx" LinkBase="shared\TestCertificates" CopyToOutputDirectory="PreserveNewest" />
   </ItemGroup>
 

+ 536 - 0
src/Servers/Kestrel/Core/test/StartLineTests.cs

@@ -0,0 +1,536 @@
+// 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.Buffers;
+using System.IO.Pipelines;
+using System.Text;
+using Microsoft.AspNetCore.Http.Features;
+using Microsoft.AspNetCore.Server.Kestrel.Core;
+using Microsoft.AspNetCore.Server.Kestrel.Core.Internal;
+using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
+using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure;
+using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal;
+using Moq;
+using Xunit;
+
+namespace Microsoft.AspNetCore.Server.Kestrel.InMemory.FunctionalTests
+{
+    public class StartLineTests : IDisposable
+    {
+        private readonly static IKestrelTrace _trace = Mock.Of<IKestrelTrace>();
+
+        private IDuplexPipe Transport { get; }
+        private MemoryPool<byte> MemoryPool { get; }
+        private Http1Connection Http1Connection { get; }
+        private Http1ParsingHandler ParsingHandler {get;}
+        private IHttpParser<Http1ParsingHandler> Parser { get; }
+
+        [Fact]
+        public void InOriginForm()
+        {
+            var rawTarget = "/path%20with%20spaces?q=123&w=xyzw1";
+            var path = "/path with spaces";
+            var query = "?q=123&w=xyzw1";
+            Http1Connection.Reset();
+            // RawTarget, Path, QueryString are null after reset
+            Assert.Null(Http1Connection.RawTarget);
+            Assert.Null(Http1Connection.Path);
+            Assert.Null(Http1Connection.QueryString);
+
+            var ros = new ReadOnlySequence<byte>(Encoding.ASCII.GetBytes($"POST {rawTarget} HTTP/1.1\r\n"));
+            Assert.True(Parser.ParseRequestLine(ParsingHandler, ros, out _, out _));
+
+            // Equal the inputs.
+            Assert.Equal(rawTarget, Http1Connection.RawTarget);
+            Assert.Equal(path, Http1Connection.Path);
+            Assert.Equal(query, Http1Connection.QueryString);
+
+            // But not the same as the inputs.
+            Assert.NotSame(rawTarget, Http1Connection.RawTarget);
+            Assert.NotSame(path, Http1Connection.Path);
+            Assert.NotSame(query, Http1Connection.QueryString);
+        }
+
+        [Fact]
+        public void InAuthorityForm()
+        {
+            var rawTarget = "example.com:1234";
+            var path = string.Empty;
+            var query = string.Empty;
+            Http1Connection.Reset();
+            // RawTarget, Path, QueryString are null after reset
+            Assert.Null(Http1Connection.RawTarget);
+            Assert.Null(Http1Connection.Path);
+            Assert.Null(Http1Connection.QueryString);
+
+            var ros = new ReadOnlySequence<byte>(Encoding.ASCII.GetBytes($"CONNECT {rawTarget} HTTP/1.1\r\n"));
+            Assert.True(Parser.ParseRequestLine(ParsingHandler, ros, out _, out _));
+
+            // Equal the inputs.
+            Assert.Equal(rawTarget, Http1Connection.RawTarget);
+            Assert.Equal(path, Http1Connection.Path);
+            Assert.Equal(query, Http1Connection.QueryString);
+
+            // But not the same as the inputs.
+            Assert.NotSame(rawTarget, Http1Connection.RawTarget);
+            // Empty strings, so interned and the same.
+            Assert.Same(path, Http1Connection.Path);
+            Assert.Same(query, Http1Connection.QueryString);
+        }
+
+        [Fact]
+        public void InAbsoluteForm()
+        {
+            var rawTarget = "http://localhost/path1?q=123&w=xyzw";
+            var path = "/path1";
+            var query = "?q=123&w=xyzw";
+            Http1Connection.Reset();
+            // RawTarget, Path, QueryString are null after reset
+            Assert.Null(Http1Connection.RawTarget);
+            Assert.Null(Http1Connection.Path);
+            Assert.Null(Http1Connection.QueryString);
+
+            var ros = new ReadOnlySequence<byte>(Encoding.ASCII.GetBytes($"CONNECT {rawTarget} HTTP/1.1\r\n"));
+            Assert.True(Parser.ParseRequestLine(ParsingHandler, ros, out _, out _));
+
+            // Equal the inputs.
+            Assert.Equal(rawTarget, Http1Connection.RawTarget);
+            Assert.Equal(path, Http1Connection.Path);
+            Assert.Equal(query, Http1Connection.QueryString);
+
+            // But not the same as the inputs.
+            Assert.NotSame(rawTarget, Http1Connection.RawTarget);
+            Assert.NotSame(path, Http1Connection.Path);
+            Assert.NotSame(query, Http1Connection.QueryString);
+        }
+
+        [Fact]
+        public void InAsteriskForm()
+        {
+            var rawTarget = "*";
+            var path = string.Empty;
+            var query = string.Empty;
+            Http1Connection.Reset();
+            // RawTarget, Path, QueryString are null after reset
+            Assert.Null(Http1Connection.RawTarget);
+            Assert.Null(Http1Connection.Path);
+            Assert.Null(Http1Connection.QueryString);
+
+            var ros = new ReadOnlySequence<byte>(Encoding.ASCII.GetBytes($"OPTIONS {rawTarget} HTTP/1.1\r\n"));
+            Assert.True(Parser.ParseRequestLine(ParsingHandler, ros, out _, out _));
+
+            // Equal the inputs.
+            Assert.Equal(rawTarget, Http1Connection.RawTarget);
+            Assert.Equal(path, Http1Connection.Path);
+            Assert.Equal(query, Http1Connection.QueryString);
+
+            // Asterisk is interned string, so the same.
+            Assert.Same(rawTarget, Http1Connection.RawTarget);
+            // Empty strings, so interned and the same.
+            Assert.Same(path, Http1Connection.Path);
+            Assert.Same(query, Http1Connection.QueryString);
+        }
+
+        [Fact]
+        public void DifferentFormsWorkTogether()
+        {
+            // InOriginForm
+            var rawTarget = "/a%20path%20with%20spaces?q=123&w=xyzw12";
+            var path = "/a path with spaces";
+            var query = "?q=123&w=xyzw12";
+            Http1Connection.Reset();
+            var ros = new ReadOnlySequence<byte>(Encoding.ASCII.GetBytes($"POST {rawTarget} HTTP/1.1\r\n"));
+            Assert.True(Parser.ParseRequestLine(ParsingHandler, ros, out _, out _));
+
+            // Equal the inputs.
+            Assert.Equal(rawTarget, Http1Connection.RawTarget);
+            Assert.Equal(path, Http1Connection.Path);
+            Assert.Equal(query, Http1Connection.QueryString);
+
+            // But not the same as the inputs.
+            Assert.NotSame(rawTarget, Http1Connection.RawTarget);
+            Assert.NotSame(path, Http1Connection.Path);
+            Assert.NotSame(query, Http1Connection.QueryString);
+
+            InAuthorityForm();
+
+            InOriginForm();
+            InAbsoluteForm();
+
+            InOriginForm();
+            InAsteriskForm();
+
+            InAuthorityForm();
+            InAsteriskForm();
+
+            InAbsoluteForm();
+            InAuthorityForm();
+
+            InAbsoluteForm();
+            InAsteriskForm();
+
+            InAbsoluteForm();
+            InAuthorityForm();
+        }
+
+        [Theory]
+        [InlineData("/abs/path", "/abs/path", "")]
+        [InlineData("/", "/", "")]
+        [InlineData("/path", "/path", "")]
+        [InlineData("/?q=123&w=xyz", "/", "?q=123&w=xyz")]
+        [InlineData("/path?q=123&w=xyz", "/path", "?q=123&w=xyz")]
+        [InlineData("/path%20with%20space?q=abc%20123", "/path with space", "?q=abc%20123")]
+        public void OriginForms(string rawTarget, string path, string query)
+        {
+            Http1Connection.Reset();
+            var ros = new ReadOnlySequence<byte>(Encoding.ASCII.GetBytes($"GET {rawTarget} HTTP/1.1\r\n"));
+            Assert.True(Parser.ParseRequestLine(ParsingHandler, ros, out _, out _));
+
+            var prevRequestUrl = Http1Connection.RawTarget;
+            var prevPath = Http1Connection.Path;
+            var prevQuery = Http1Connection.QueryString;
+
+            // Identical requests keep same materialized string values
+            for (var i = 0; i < 5; i++)
+            {
+                Http1Connection.Reset();
+                // RawTarget, Path, QueryString are null after reset
+                Assert.Null(Http1Connection.RawTarget);
+                Assert.Null(Http1Connection.Path);
+                Assert.Null(Http1Connection.QueryString);
+
+                // Parser decodes % encoding in place, so we need to recreate the ROS
+                ros = new ReadOnlySequence<byte>(Encoding.ASCII.GetBytes($"GET {rawTarget} HTTP/1.1\r\n"));
+                Assert.True(Parser.ParseRequestLine(ParsingHandler, ros, out _, out _));
+
+                // Equal the inputs.
+                Assert.Equal(rawTarget, Http1Connection.RawTarget);
+                Assert.Equal(path, Http1Connection.Path);
+                Assert.Equal(query, Http1Connection.QueryString);
+
+                // But not the same as the inputs.
+
+                Assert.NotSame(rawTarget, Http1Connection.RawTarget);
+                Assert.NotSame(path, Http1Connection.Path);
+                // string.Empty is used for empty strings, so should be the same.
+                Assert.True(query.Length == 0 || !ReferenceEquals(query, Http1Connection.QueryString));
+
+                // However, materalized strings are reused if generated for previous requests.
+
+                Assert.Same(prevRequestUrl, Http1Connection.RawTarget);
+                Assert.Same(prevPath, Http1Connection.Path);
+                Assert.Same(prevQuery, Http1Connection.QueryString);
+
+                prevRequestUrl = Http1Connection.RawTarget;
+                prevPath = Http1Connection.Path;
+                prevQuery = Http1Connection.QueryString;
+            }
+
+            // Different OriginForm request changes values
+
+            rawTarget = "/path1?q=123&w=xyzw";
+            path = "/path1";
+            query = "?q=123&w=xyzw";
+
+            Http1Connection.Reset();
+            ros = new ReadOnlySequence<byte>(Encoding.ASCII.GetBytes($"GET {rawTarget} HTTP/1.1\r\n"));
+            Parser.ParseRequestLine(ParsingHandler, ros, out _, out _);
+
+            // Equal the inputs.
+            Assert.Equal(rawTarget, Http1Connection.RawTarget);
+            Assert.Equal(path, Http1Connection.Path);
+            Assert.Equal(query, Http1Connection.QueryString);
+
+            // But not the same as the inputs.
+            Assert.NotSame(rawTarget, Http1Connection.RawTarget);
+            Assert.NotSame(path, Http1Connection.Path);
+            Assert.NotSame(query, Http1Connection.QueryString);
+
+            // Not equal previous request.
+            Assert.NotEqual(prevRequestUrl, Http1Connection.RawTarget);
+            Assert.NotEqual(prevPath, Http1Connection.Path);
+            Assert.NotEqual(prevQuery, Http1Connection.QueryString);
+
+            DifferentFormsWorkTogether();
+        }
+
+        [Theory]
+        [InlineData("http://localhost/abs/path", "/abs/path", "")]
+        [InlineData("https://localhost/abs/path", "/abs/path", "")] // handles mismatch scheme
+        [InlineData("https://localhost:22/abs/path", "/abs/path", "")] // handles mismatched ports
+        [InlineData("https://differenthost/abs/path", "/abs/path", "")] // handles mismatched hostname
+        [InlineData("http://localhost/", "/", "")]
+        [InlineData("http://[email protected]/path", "/path", "")]
+        [InlineData("http://root:[email protected]/path", "/path", "")]
+        [InlineData("https://localhost/", "/", "")]
+        [InlineData("http://localhost", "/", "")]
+        [InlineData("http://127.0.0.1/", "/", "")]
+        [InlineData("http://[::1]/", "/", "")]
+        [InlineData("http://[::1]:8080/", "/", "")]
+        [InlineData("http://localhost?q=123&w=xyz", "/", "?q=123&w=xyz")]
+        [InlineData("http://localhost/?q=123&w=xyz", "/", "?q=123&w=xyz")]
+        [InlineData("http://localhost/path?q=123&w=xyz", "/path", "?q=123&w=xyz")]
+        [InlineData("http://localhost/path%20with%20space?q=abc%20123", "/path with space", "?q=abc%20123")]
+        public void AbsoluteForms(string rawTarget, string path, string query)
+        {
+            Http1Connection.Reset();
+            var ros = new ReadOnlySequence<byte>(Encoding.ASCII.GetBytes($"GET {rawTarget} HTTP/1.1\r\n"));
+            Assert.True(Parser.ParseRequestLine(ParsingHandler, ros, out _, out _));
+
+            var prevRequestUrl = Http1Connection.RawTarget;
+            var prevPath = Http1Connection.Path;
+            var prevQuery = Http1Connection.QueryString;
+
+            // Identical requests keep same materialized string values
+            for (var i = 0; i < 5; i++)
+            {
+                Http1Connection.Reset();
+                // RawTarget, Path, QueryString are null after reset
+                Assert.Null(Http1Connection.RawTarget);
+                Assert.Null(Http1Connection.Path);
+                Assert.Null(Http1Connection.QueryString);
+
+                ros = new ReadOnlySequence<byte>(Encoding.ASCII.GetBytes($"GET {rawTarget} HTTP/1.1\r\n"));
+                Assert.True(Parser.ParseRequestLine(ParsingHandler, ros, out _, out _));
+
+                // Equal the inputs.
+                Assert.Equal(rawTarget, Http1Connection.RawTarget);
+                Assert.Equal(path, Http1Connection.Path);
+                Assert.Equal(query, Http1Connection.QueryString);
+
+                // But not the same as the inputs.
+
+                Assert.NotSame(rawTarget, Http1Connection.RawTarget);
+                Assert.NotSame(path, Http1Connection.Path);
+                // string.Empty is used for empty strings, so should be the same.
+                Assert.True(query.Length == 0 || !ReferenceEquals(query, Http1Connection.QueryString));
+
+                // However, materalized strings are reused if generated for previous requests.
+
+                Assert.Same(prevRequestUrl, Http1Connection.RawTarget);
+                Assert.Same(prevPath, Http1Connection.Path);
+                Assert.Same(prevQuery, Http1Connection.QueryString);
+
+                prevRequestUrl = Http1Connection.RawTarget;
+                prevPath = Http1Connection.Path;
+                prevQuery = Http1Connection.QueryString;
+            }
+
+            // Different Absolute Form request changes values
+
+            rawTarget = "http://localhost/path1?q=123&w=xyzw";
+            path = "/path1";
+            query = "?q=123&w=xyzw";
+
+            Http1Connection.Reset();
+            ros = new ReadOnlySequence<byte>(Encoding.ASCII.GetBytes($"GET {rawTarget} HTTP/1.1\r\n"));
+            Parser.ParseRequestLine(ParsingHandler, ros, out _, out _);
+
+            // Equal the inputs.
+            Assert.Equal(rawTarget, Http1Connection.RawTarget);
+            Assert.Equal(path, Http1Connection.Path);
+            Assert.Equal(query, Http1Connection.QueryString);
+
+            // But not the same as the inputs.
+            Assert.NotSame(rawTarget, Http1Connection.RawTarget);
+            Assert.NotSame(path, Http1Connection.Path);
+            Assert.NotSame(query, Http1Connection.QueryString);
+
+            // Not equal previous request.
+            Assert.NotEqual(prevRequestUrl, Http1Connection.RawTarget);
+            Assert.NotEqual(prevPath, Http1Connection.Path);
+            Assert.NotEqual(prevQuery, Http1Connection.QueryString);
+
+            DifferentFormsWorkTogether();
+        }
+
+        [Fact]
+        public void AsteriskForms()
+        {
+            var rawTarget = "*";
+            var path = string.Empty;
+            var query = string.Empty;
+
+            Http1Connection.Reset();
+            var ros = new ReadOnlySequence<byte>(Encoding.ASCII.GetBytes($"OPTIONS {rawTarget} HTTP/1.1\r\n"));
+            Assert.True(Parser.ParseRequestLine(ParsingHandler, ros, out _, out _));
+
+            var prevRequestUrl = Http1Connection.RawTarget;
+            var prevPath = Http1Connection.Path;
+            var prevQuery = Http1Connection.QueryString;
+
+            // Identical requests keep same materialized string values
+            for (var i = 0; i < 5; i++)
+            {
+                Http1Connection.Reset();
+                // RawTarget, Path, QueryString are null after reset
+                Assert.Null(Http1Connection.RawTarget);
+                Assert.Null(Http1Connection.Path);
+                Assert.Null(Http1Connection.QueryString);
+
+                ros = new ReadOnlySequence<byte>(Encoding.ASCII.GetBytes($"OPTIONS {rawTarget} HTTP/1.1\r\n"));
+                Assert.True(Parser.ParseRequestLine(ParsingHandler, ros, out _, out _));
+
+                // Equal the inputs.
+                Assert.Equal(rawTarget, Http1Connection.RawTarget);
+                Assert.Equal(path, Http1Connection.Path);
+                Assert.Equal(query, Http1Connection.QueryString);
+
+                // Also same as the inputs (interned strings).
+
+                Assert.Same(rawTarget, Http1Connection.RawTarget);
+                Assert.Same(path, Http1Connection.Path);
+                Assert.Same(query, Http1Connection.QueryString);
+
+                // Materalized strings are reused if generated for previous requests.
+
+                Assert.Same(prevRequestUrl, Http1Connection.RawTarget);
+                Assert.Same(prevPath, Http1Connection.Path);
+                Assert.Same(prevQuery, Http1Connection.QueryString);
+
+                prevRequestUrl = Http1Connection.RawTarget;
+                prevPath = Http1Connection.Path;
+                prevQuery = Http1Connection.QueryString;
+            }
+
+            // Different request changes values (can't be Astrisk Form as all the same)
+            rawTarget = "http://localhost/path1?q=123&w=xyzw";
+            path = "/path1";
+            query = "?q=123&w=xyzw";
+
+            Http1Connection.Reset();
+            ros = new ReadOnlySequence<byte>(Encoding.ASCII.GetBytes($"GET {rawTarget} HTTP/1.1\r\n"));
+            Parser.ParseRequestLine(ParsingHandler, ros, out _, out _);
+
+            // Equal the inputs.
+            Assert.Equal(rawTarget, Http1Connection.RawTarget);
+            Assert.Equal(path, Http1Connection.Path);
+            Assert.Equal(query, Http1Connection.QueryString);
+
+            // But not the same as the inputs.
+            Assert.NotSame(rawTarget, Http1Connection.RawTarget);
+            Assert.NotSame(path, Http1Connection.Path);
+            Assert.NotSame(query, Http1Connection.QueryString);
+
+            // Not equal previous request.
+            Assert.NotEqual(prevRequestUrl, Http1Connection.RawTarget);
+            Assert.NotEqual(prevPath, Http1Connection.Path);
+            Assert.NotEqual(prevQuery, Http1Connection.QueryString);
+
+            DifferentFormsWorkTogether();
+        }
+
+        [Theory]
+        [InlineData("localhost", "", "")]
+        [InlineData("localhost:22", "", "")] // handles mismatched ports
+        [InlineData("differenthost", "", "")] // handles mismatched hostname
+        [InlineData("127.0.0.1", "", "")]
+        [InlineData("[::1]", "", "")]
+        [InlineData("[::1]:8080", "", "")]
+        public void AuthorityForms(string rawTarget, string path, string query)
+        {
+            Http1Connection.Reset();
+            var ros = new ReadOnlySequence<byte>(Encoding.ASCII.GetBytes($"CONNECT {rawTarget} HTTP/1.1\r\n"));
+            Assert.True(Parser.ParseRequestLine(ParsingHandler, ros, out _, out _));
+
+            var prevRequestUrl = Http1Connection.RawTarget;
+            var prevPath = Http1Connection.Path;
+            var prevQuery = Http1Connection.QueryString;
+
+            // Identical requests keep same materialized string values
+            for (var i = 0; i < 5; i++)
+            {
+                Http1Connection.Reset();
+                // RawTarget, Path, QueryString are null after reset
+                Assert.Null(Http1Connection.RawTarget);
+                Assert.Null(Http1Connection.Path);
+                Assert.Null(Http1Connection.QueryString);
+
+                ros = new ReadOnlySequence<byte>(Encoding.ASCII.GetBytes($"CONNECT {rawTarget} HTTP/1.1\r\n"));
+                Assert.True(Parser.ParseRequestLine(ParsingHandler, ros, out _, out _));
+
+                // Equal the inputs.
+                Assert.Equal(rawTarget, Http1Connection.RawTarget);
+                Assert.Equal(path, Http1Connection.Path);
+                Assert.Equal(query, Http1Connection.QueryString);
+
+                // RawTarget not the same as the input.
+                Assert.NotSame(rawTarget, Http1Connection.RawTarget);
+                // Others same as the inputs, empty strings.
+                Assert.Same(path, Http1Connection.Path);
+                Assert.Same(query, Http1Connection.QueryString);
+
+                // However, materalized strings are reused if generated for previous requests.
+
+                Assert.Same(prevRequestUrl, Http1Connection.RawTarget);
+                Assert.Same(prevPath, Http1Connection.Path);
+                Assert.Same(prevQuery, Http1Connection.QueryString);
+
+                prevRequestUrl = Http1Connection.RawTarget;
+                prevPath = Http1Connection.Path;
+                prevQuery = Http1Connection.QueryString;
+            }
+
+            // Different Authority Form request changes values
+            rawTarget = "example.org:2345";
+            path = "";
+            query = "";
+
+            Http1Connection.Reset();
+            ros = new ReadOnlySequence<byte>(Encoding.ASCII.GetBytes($"CONNECT {rawTarget} HTTP/1.1\r\n"));
+            Parser.ParseRequestLine(ParsingHandler, ros, out _, out _);
+
+            // Equal the inputs.
+            Assert.Equal(rawTarget, Http1Connection.RawTarget);
+            Assert.Equal(path, Http1Connection.Path);
+            Assert.Equal(query, Http1Connection.QueryString);
+
+            // But not the same as the inputs.
+            Assert.NotSame(rawTarget, Http1Connection.RawTarget);
+            // Empty interned strings
+            Assert.Same(path, Http1Connection.Path);
+            Assert.Same(query, Http1Connection.QueryString);
+
+            // Not equal previous request.
+            Assert.NotEqual(prevRequestUrl, Http1Connection.RawTarget);
+
+            DifferentFormsWorkTogether();
+        }
+
+        public StartLineTests()
+        {
+            MemoryPool = KestrelMemoryPool.Create();
+            var options = new PipeOptions(MemoryPool, readerScheduler: PipeScheduler.Inline, writerScheduler: PipeScheduler.Inline, useSynchronizationContext: false);
+            var pair = DuplexPipe.CreateConnectionPair(options, options);
+            Transport = pair.Transport;
+
+            var serviceContext = new ServiceContext
+            {
+                ServerOptions = new KestrelServerOptions(),
+                Log = _trace,
+                HttpParser = new HttpParser<Http1ParsingHandler>()
+            };
+
+            Http1Connection = new Http1Connection(context: new HttpConnectionContext
+            {
+                ServiceContext = serviceContext,
+                ConnectionFeatures = new FeatureCollection(),
+                MemoryPool = MemoryPool,
+                Transport = Transport,
+                TimeoutControl = new TimeoutControl(timeoutHandler: null)
+            });
+
+            Parser = new HttpParser<Http1ParsingHandler>(showErrorDetails: true);
+            ParsingHandler = new Http1ParsingHandler(Http1Connection);
+        }
+
+        public void Dispose()
+        {
+            Transport.Input.Complete();
+            Transport.Output.Complete();
+
+            MemoryPool.Dispose();
+        }
+    }
+}

+ 3 - 0
src/Servers/Kestrel/perf/Kestrel.Performance/Http1ConnectionBenchmark.cs

@@ -107,6 +107,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
             public void OnHeader(Span<byte> name, Span<byte> value)
                 => RequestHandler.Connection.OnHeader(name, value);
 
+            public void OnHeadersComplete()
+                => RequestHandler.Connection.OnHeadersComplete();
+
             public void OnStartLine(HttpMethod method, HttpVersion version, Span<byte> target, Span<byte> path, Span<byte> query, Span<byte> customMethod, bool pathEncoded)
                 => RequestHandler.Connection.OnStartLine(method, version, target, path, query, customMethod, pathEncoded);
         }

+ 7 - 0
src/Servers/Kestrel/perf/Kestrel.Performance/HttpParserBenchmark.cs

@@ -72,6 +72,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
         {
         }
 
+        public void OnHeadersComplete()
+        {
+        }
+
         private struct Adapter : IHttpRequestLineHandler, IHttpHeadersHandler
         {
             public HttpParserBenchmark RequestHandler;
@@ -84,6 +88,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
             public void OnHeader(Span<byte> name, Span<byte> value)
                 => RequestHandler.OnHeader(name, value);
 
+            public void OnHeadersComplete()
+                => RequestHandler.OnHeadersComplete();
+
             public void OnStartLine(HttpMethod method, HttpVersion version, Span<byte> target, Span<byte> path, Span<byte> query, Span<byte> customMethod, bool pathEncoded)
                 => RequestHandler.OnStartLine(method, version, target, path, query, customMethod, pathEncoded);
         }

+ 1 - 0
src/Servers/Kestrel/perf/Kestrel.Performance/Mocks/NullParser.cs

@@ -26,6 +26,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
             handler.OnHeader(new Span<byte>(_hostHeaderName), new Span<byte>(_hostHeaderValue));
             handler.OnHeader(new Span<byte>(_acceptHeaderName), new Span<byte>(_acceptHeaderValue));
             handler.OnHeader(new Span<byte>(_connectionHeaderName), new Span<byte>(_connectionHeaderValue));
+            handler.OnHeadersComplete();
 
             consumedBytes = 0;
             consumed = buffer.Start;

+ 11 - 0
src/Servers/Kestrel/perf/PlatformBenchmarks/BenchmarkApplication.HttpConnection.cs

@@ -125,6 +125,12 @@ namespace PlatformBenchmarks
         {
         }
 
+#if NETCOREAPP3_0
+        public void OnHeadersComplete()
+        {
+        }
+#endif
+
         public async ValueTask OnReadCompletedAsync()
         {
             await Writer.FlushAsync();
@@ -175,6 +181,11 @@ namespace PlatformBenchmarks
 
             public void OnStartLine(HttpMethod method, HttpVersion version, Span<byte> target, Span<byte> path, Span<byte> query, Span<byte> customMethod, bool pathEncoded)
                 => RequestHandler.OnStartLine(method, version, target, path, query, customMethod, pathEncoded);
+
+#if NETCOREAPP3_0
+            public void OnHeadersComplete()
+                => RequestHandler.OnHeadersComplete();
+#endif
         }
     }
 

+ 431 - 129
src/Servers/Kestrel/tools/CodeGenerator/KnownHeaders.cs → src/Servers/Kestrel/shared/KnownHeaders.cs

@@ -11,114 +11,11 @@ namespace CodeGenerator
 {
     public class KnownHeaders
     {
-        static string Each<T>(IEnumerable<T> values, Func<T, string> formatter)
-        {
-            return values.Any() ? values.Select(formatter).Aggregate((a, b) => a + b) : "";
-        }
-
-        static string AppendSwitch(IEnumerable<IGrouping<int, KnownHeader>> values, string className) =>
-             $@"var pUL = (ulong*)pUB;
-                var pUI = (uint*)pUB;
-                var pUS = (ushort*)pUB;
-                var stringValue = new StringValues(value);
-                switch (keyLength)
-                {{{Each(values, byLength => $@"
-                    case {byLength.Key}:
-                        {{{Each(byLength, header => $@"
-                            if ({header.EqualIgnoreCaseBytes()})
-                            {{{(header.Identifier == "ContentLength" ? $@"
-                                if (_contentLength.HasValue)
-                                {{
-                                    BadHttpRequestException.Throw(RequestRejectionReason.MultipleContentLengths);
-                                }}
-                                else
-                                {{
-                                    _contentLength = ParseContentLength(value);
-                                }}
-                                return;" : $@"
-                                if ({header.TestBit()})
-                                {{
-                                    _headers._{header.Identifier} = AppendValue(_headers._{header.Identifier}, value);
-                                }}
-                                else
-                                {{
-                                    {header.SetBit()};
-                                    _headers._{header.Identifier} = stringValue;{(header.EnhancedSetter == false ? "" : $@"
-                                    _headers._raw{header.Identifier} = null;")}
-                                }}
-                                return;")}
-                            }}
-                        ")}}}
-                        break;
-                ")}}}";
-
-        class KnownHeader
-        {
-            public string Name { get; set; }
-            public int Index { get; set; }
-            public string Identifier => Name.Replace("-", "");
-
-            public byte[] Bytes => Encoding.ASCII.GetBytes($"\r\n{Name}: ");
-            public int BytesOffset { get; set; }
-            public int BytesCount { get; set; }
-            public bool ExistenceCheck { get; set; }
-            public bool FastCount { get; set; }
-            public bool EnhancedSetter { get; set; }
-            public bool PrimaryHeader { get; set; }
-            public string TestBit() => $"(_bits & {"0x" + (1L << Index).ToString("x")}L) != 0";
-            public string TestTempBit() => $"(tempBits & {"0x" + (1L << Index).ToString("x")}L) != 0";
-            public string TestNotTempBit() => $"(tempBits & ~{"0x" + (1L << Index).ToString("x")}L) == 0";
-            public string TestNotBit() => $"(_bits & {"0x" + (1L << Index).ToString("x")}L) == 0";
-            public string SetBit() => $"_bits |= {"0x" + (1L << Index).ToString("x")}L";
-            public string ClearBit() => $"_bits &= ~{"0x" + (1L << Index).ToString("x")}L";
-
-            public string EqualIgnoreCaseBytes()
-            {
-                var result = "";
-                var delim = "";
-                var index = 0;
-                while (index != Name.Length)
-                {
-                    if (Name.Length - index >= 8)
-                    {
-                        result += delim + Term(Name, index, 8, "pUL", "uL");
-                        index += 8;
-                    }
-                    else if (Name.Length - index >= 4)
-                    {
-                        result += delim + Term(Name, index, 4, "pUI", "u");
-                        index += 4;
-                    }
-                    else if (Name.Length - index >= 2)
-                    {
-                        result += delim + Term(Name, index, 2, "pUS", "u");
-                        index += 2;
-                    }
-                    else
-                    {
-                        result += delim + Term(Name, index, 1, "pUB", "u");
-                        index += 1;
-                    }
-                    delim = " && ";
-                }
-                return $"({result})";
-            }
-            protected string Term(string name, int offset, int count, string array, string suffix)
-            {
-                ulong mask = 0;
-                ulong comp = 0;
-                for (var scan = 0; scan < count; scan++)
-                {
-                    var ch = (byte)name[offset + count - scan - 1];
-                    var isAlpha = (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z');
-                    comp = (comp << 8) + (ch & (isAlpha ? 0xdfu : 0xffu));
-                    mask = (mask << 8) + (isAlpha ? 0xdfu : 0xffu);
-                }
-                return $"(({array}[{offset / count}] & {mask}{suffix}) == {comp}{suffix})";
-            }
-        }
+        public readonly static KnownHeader[] RequestHeaders;
+        public readonly static KnownHeader[] ResponseHeaders;
+        public readonly static KnownHeader[] ResponseTrailers;
 
-        public static string GeneratedFile()
+        static KnownHeaders()
         {
             var requestPrimaryHeaders = new[]
             {
@@ -173,7 +70,7 @@ namespace CodeGenerator
             {
                 "Host"
             };
-            var requestHeaders = commonHeaders.Concat(new[]
+            RequestHeaders = commonHeaders.Concat(new[]
             {
                 "Accept",
                 "Accept-Charset",
@@ -196,6 +93,8 @@ namespace CodeGenerator
                 "TE",
                 "Translate",
                 "User-Agent",
+                "DNT",
+                "Upgrade-Insecure-Requests"
             })
             .Concat(corsRequestHeaders)
             .Select((header, index) => new KnownHeader
@@ -213,8 +112,6 @@ namespace CodeGenerator
                 PrimaryHeader = requestPrimaryHeaders.Contains("Content-Length")
             }})
             .ToArray();
-            Debug.Assert(requestHeaders.Length <= 64);
-            Debug.Assert(requestHeaders.Max(x => x.Index) <= 62);
 
             var responseHeadersExistence = new[]
             {
@@ -240,7 +137,7 @@ namespace CodeGenerator
                 "Access-Control-Expose-Headers",
                 "Access-Control-Max-Age",
             };
-            var responseHeaders = commonHeaders.Concat(new[]
+            ResponseHeaders = commonHeaders.Concat(new[]
             {
                 "Accept-Ranges",
                 "Age",
@@ -271,7 +168,7 @@ namespace CodeGenerator
             }})
             .ToArray();
 
-            var responseTrailers = new[]
+            ResponseTrailers = new[]
             {
                 "ETag",
             }
@@ -284,11 +181,359 @@ namespace CodeGenerator
                 PrimaryHeader = responsePrimaryHeaders.Contains(header)
             })
             .ToArray();
+        }
+
+        static string Each<T>(IEnumerable<T> values, Func<T, string> formatter)
+        {
+            return values.Any() ? values.Select(formatter).Aggregate((a, b) => a + b) : "";
+        }
+
+        static string Each<T>(IEnumerable<T> values, Func<T, int, string> formatter)
+        {
+            return values.Any() ? values.Select(formatter).Aggregate((a, b) => a + b) : "";
+        }
+
+        static string AppendSwitch(IEnumerable<IGrouping<int, KnownHeader>> values) =>
+             $@"switch (name.Length)
+            {{{Each(values, byLength => $@"
+                case {byLength.Key}:{AppendSwitchSection(byLength.Key, byLength.OrderBy(h => (h.PrimaryHeader ? "_" : "") + h.Name))}
+                    break;")}
+            }}";
+
+        static string AppendSwitchSection(int length, IOrderedEnumerable<KnownHeader> values)
+        {
+            var useVarForFirstTerm = values.Count() > 1 && values.Select(h => h.FirstNameIgnoreCaseSegment()).Distinct().Count() == 1;
+            var firstTermVarExpression = values.Select(h => h.FirstNameIgnoreCaseSegment()).FirstOrDefault();
+            var firstTermVar = $"firstTerm{length}";
+
+            var start = "";
+            if (useVarForFirstTerm)
+            {
+                start = $@"
+                    var {firstTermVar} = {firstTermVarExpression};";
+            }
+            else
+            {
+                firstTermVar = "";
+            }
+
+            var groups = values.GroupBy(header => header.EqualIgnoreCaseBytesFirstTerm());
+            return start + $@"{Each(groups,  (byFirstTerm, i) => $@"{(byFirstTerm.Count() == 1 ? $@"{Each(byFirstTerm, header => $@"
+                    {(i > 0 ? "else " : "")}if ({header.EqualIgnoreCaseBytes(firstTermVar)})
+                    {{{(header.Identifier == "ContentLength" ? $@"
+                        AppendContentLength(value);
+                        return;" : $@"
+                        flag = {header.FlagBit()};
+                        values = ref _headers._{header.Identifier};")}
+                    }}")}" : $@"
+                    if ({byFirstTerm.Key.Replace(firstTermVarExpression, firstTermVar)})
+                    {{{Each(byFirstTerm, (header, i) => $@"
+                        {(i > 0 ? "else " : "")}if ({header.EqualIgnoreCaseBytesSecondTermOnwards()})
+                        {{{(header.Identifier == "ContentLength" ? $@"
+                            AppendContentLength(value);
+                            return;" : $@"
+                            flag = {header.FlagBit()};
+                            values = ref _headers._{header.Identifier};")}
+                        }}")}
+                    }}")}")}";
+        }
+
+        public class KnownHeader
+        {
+            public string Name { get; set; }
+            public int Index { get; set; }
+            public string Identifier => Name.Replace("-", "");
+
+            public byte[] Bytes => Encoding.ASCII.GetBytes($"\r\n{Name}: ");
+            public int BytesOffset { get; set; }
+            public int BytesCount { get; set; }
+            public bool ExistenceCheck { get; set; }
+            public bool FastCount { get; set; }
+            public bool EnhancedSetter { get; set; }
+            public bool PrimaryHeader { get; set; }
+            public string FlagBit() => $"{"0x" + (1L << Index).ToString("x")}L";
+            public string TestBit() => $"(_bits & {"0x" + (1L << Index).ToString("x")}L) != 0";
+            public string TestTempBit() => $"(tempBits & {"0x" + (1L << Index).ToString("x")}L) != 0";
+            public string TestNotTempBit() => $"(tempBits & ~{"0x" + (1L << Index).ToString("x")}L) == 0";
+            public string TestNotBit() => $"(_bits & {"0x" + (1L << Index).ToString("x")}L) == 0";
+            public string SetBit() => $"_bits |= {"0x" + (1L << Index).ToString("x")}L";
+            public string ClearBit() => $"_bits &= ~{"0x" + (1L << Index).ToString("x")}L";
+
+            private void GetMaskAndComp(string name, int offset, int count, out ulong mask, out ulong comp)
+            {
+                mask = 0;
+                comp = 0;
+                for (var scan = 0; scan < count; scan++)
+                {
+                    var ch = (byte)name[offset + count - scan - 1];
+                    var isAlpha = (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z');
+                    comp = (comp << 8) + (ch & (isAlpha ? 0xdfu : 0xffu));
+                    mask = (mask << 8) + (isAlpha ? 0xdfu : 0xffu);
+                }
+            }
+
+            private string NameTerm(string name, int offset, int count, string type, string suffix)
+            {
+                GetMaskAndComp(name, offset, count, out var mask, out var comp);
+
+                if (offset == 0)
+                {
+                    if (type == "byte")
+                    {
+                        return $"(nameStart & 0x{mask:x}{suffix})";
+                    }
+                    else
+                    {
+                        return $"(Unsafe.ReadUnaligned<{type}>(ref nameStart) & 0x{mask:x}{suffix})";
+                    }
+                }
+                else
+                {
+                    if (type == "byte")
+                    {
+                        return $"(Unsafe.AddByteOffset(ref nameStart, (IntPtr){offset / count}) & 0x{mask:x}{suffix})";
+                    }
+                    else if ((offset / count) == 1)
+                    {
+                        return $"(Unsafe.ReadUnaligned<{type}>(ref Unsafe.AddByteOffset(ref nameStart, (IntPtr)sizeof({type}))) & 0x{mask:x}{suffix})";
+                    }
+                    else
+                    {
+                        return $"(Unsafe.ReadUnaligned<{type}>(ref Unsafe.AddByteOffset(ref nameStart, (IntPtr)({offset / count} * sizeof({type})))) & 0x{mask:x}{suffix})";
+                    }
+                }
+
+            }
+
+            private string EqualityTerm(string name, int offset, int count, string type, string suffix)
+            {
+                GetMaskAndComp(name, offset, count, out var mask, out var comp);
+
+                return $"0x{comp:x}{suffix}";
+            }
+
+            private string Term(string name, int offset, int count, string type, string suffix)
+            {
+                GetMaskAndComp(name, offset, count, out var mask, out var comp);
+
+                return $"({NameTerm(name, offset, count, type, suffix)} == {EqualityTerm(name, offset, count, type, suffix)})";
+            }
+
+            public string FirstNameIgnoreCaseSegment()
+            {
+                var result = "";
+                if (Name.Length >= 8)
+                {
+                    result = NameTerm(Name, 0, 8, "ulong", "uL");
+                }
+                else if (Name.Length >= 4)
+                {
+                    result = NameTerm(Name, 0, 4, "uint", "u");
+                }
+                else if (Name.Length >= 2)
+                {
+                    result = NameTerm(Name, 0, 2, "ushort", "u");
+                }
+                else
+                {
+                    result = NameTerm(Name, 0, 1, "byte", "u");
+                }
+
+                return result;
+            }
+
+            public string EqualIgnoreCaseBytes(string firstTermVar = "")
+            {
+                if (!string.IsNullOrEmpty(firstTermVar))
+                {
+                    return EqualIgnoreCaseBytesWithVar(firstTermVar);
+                }
+
+                var result = "";
+                var delim = "";
+                var index = 0;
+                while (index != Name.Length)
+                {
+                    if (Name.Length - index >= 8)
+                    {
+                        result += delim + Term(Name, index, 8, "ulong", "uL");
+                        index += 8;
+                    }
+                    else if (Name.Length - index >= 4)
+                    {
+                        result += delim + Term(Name, index, 4, "uint", "u");
+                        index += 4;
+                    }
+                    else if (Name.Length - index >= 2)
+                    {
+                        result += delim + Term(Name, index, 2, "ushort", "u");
+                        index += 2;
+                    }
+                    else
+                    {
+                        result += delim + Term(Name, index, 1, "byte", "u");
+                        index += 1;
+                    }
+                    delim = " && ";
+                }
+                return result;
+
+                string EqualIgnoreCaseBytesWithVar(string firstTermVar)
+                {
+                    var result = "";
+                    var delim = " && ";
+                    var index = 0;
+                    var isFirst = true;
+                    while (index != Name.Length)
+                    {
+                        if (Name.Length - index >= 8)
+                        {
+                            if (isFirst)
+                            {
+                                result = $"({firstTermVar} == {EqualityTerm(Name, index, 8, "ulong", "uL")})";
+                            }
+                            else
+                            {
+                                result += delim + Term(Name, index, 8, "ulong", "uL");
+                            }
+
+                            index += 8;
+                        }
+                        else if (Name.Length - index >= 4)
+                        {
+                            if (isFirst)
+                            {
+                                result = $"({firstTermVar} == {EqualityTerm(Name, index, 4, "uint", "u")})";
+                            }
+                            else
+                            {
+                                result += delim + Term(Name, index, 4, "uint", "u");
+                            }
+                            index += 4;
+                        }
+                        else if (Name.Length - index >= 2)
+                        {
+                            if (isFirst)
+                            {
+                                result = $"({firstTermVar} == {EqualityTerm(Name, index, 2, "ushort", "u")})";
+                            }
+                            else
+                            {
+                                result += delim + Term(Name, index, 2, "ushort", "u");
+                            }
+                            index += 2;
+                        }
+                        else
+                        {
+                            if (isFirst)
+                            {
+                                result = $"({firstTermVar} == {EqualityTerm(Name, index, 1, "byte", "u")})";
+                            }
+                            else
+                            {
+                                result += delim + Term(Name, index, 1, "byte", "u");
+                            }
+                            index += 1;
+                        }
+
+                        isFirst = false;
+                    }
+                    return result;
+                }
+            }
+
+            public string EqualIgnoreCaseBytesFirstTerm()
+            {
+                var result = "";
+                if (Name.Length >= 8)
+                {
+                    result = Term(Name, 0, 8, "ulong", "uL");
+                }
+                else if (Name.Length >= 4)
+                {
+                    result = Term(Name, 0, 4, "uint", "u");
+                }
+                else if (Name.Length >= 2)
+                {
+                    result = Term(Name, 0, 2, "ushort", "u");
+                }
+                else
+                {
+                    result = Term(Name, 0, 1, "byte", "u");
+                }
+
+                return result;
+            }
+
+            public string EqualIgnoreCaseBytesSecondTermOnwards()
+            {
+                var result = "";
+                var delim = "";
+                var index = 0;
+                var isFirst = true;
+                while (index != Name.Length)
+                {
+                    if (Name.Length - index >= 8)
+                    {
+                        if (!isFirst)
+                        {
+                            result += delim + Term(Name, index, 8, "ulong", "uL");
+                        }
+
+                        index += 8;
+                    }
+                    else if (Name.Length - index >= 4)
+                    {
+                        if (!isFirst)
+                        {
+                            result += delim + Term(Name, index, 4, "uint", "u");
+                        }
+                        index += 4;
+                    }
+                    else if (Name.Length - index >= 2)
+                    {
+                        if (!isFirst)
+                        {
+                            result += delim + Term(Name, index, 2, "ushort", "u");
+                        }
+                        index += 2;
+                    }
+                    else
+                    {
+                        if (!isFirst)
+                        {
+                            result += delim + Term(Name, index, 1, "byte", "u");
+                        }
+                        index += 1;
+                    }
+
+                    if (isFirst)
+                    {
+                        isFirst = false;
+                    }
+                    else
+                    {
+                        delim = " && ";
+                    }
+                }
+                return result;
+            }
+        }
+
+        public static string GeneratedFile()
+        {
+
+            var requestHeaders = RequestHeaders;
+            Debug.Assert(requestHeaders.Length <= 64);
+            Debug.Assert(requestHeaders.Max(x => x.Index) <= 62);
 
             // 63 for responseHeaders as it steals one bit for Content-Length in CopyTo(ref MemoryPoolIterator output)
+            var responseHeaders = ResponseHeaders;
             Debug.Assert(responseHeaders.Length <= 63);
             Debug.Assert(responseHeaders.Count(x => x.Index == 63) == 1);
 
+            var responseTrailers = ResponseTrailers;
+
             var loops = new[]
             {
                 new
@@ -331,8 +576,10 @@ using System.Collections.Generic;
 using System.Buffers;
 using System.IO.Pipelines;
 using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
 using Microsoft.Extensions.Primitives;
 using Microsoft.Net.Http.Headers;
+using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure;
 
 namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
 {{
@@ -345,8 +592,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
             {Each(loop.Bytes, b => $"{b},")}
         }};"
         : "")}
-
-        private long _bits = 0;
         private HeaderReferences _headers;
 {Each(loop.Headers.Where(header => header.ExistenceCheck), header => $@"
         public bool Has{header.Identifier} => {header.TestBit()};")}
@@ -510,8 +755,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
 
             return MaybeUnknown?.Remove(key) ?? false;
         }}
-
-        protected override void ClearFast()
+{(loop.ClassName != "HttpRequestHeaders" ?
+ $@"        protected override void ClearFast()
         {{
             MaybeUnknown?.Clear();
             _contentLength = null;
@@ -534,7 +779,23 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
             }}
             ")}
         }}
-
+" :
+$@"        private void Clear(long bitsToClear)
+        {{
+            var tempBits = bitsToClear;
+            {Each(loop.Headers.Where(header => header.Identifier != "ContentLength").OrderBy(h => !h.PrimaryHeader), header => $@"
+            if ({header.TestTempBit()})
+            {{
+                _headers._{header.Identifier} = default(StringValues);
+                if({header.TestNotTempBit()})
+                {{
+                    return;
+                }}
+                tempBits &= ~{"0x" + (1L << header.Index).ToString("x")}L;
+            }}
+            ")}
+        }}
+")}
         protected override bool CopyToFast(KeyValuePair<string, StringValues>[] array, int arrayIndex)
         {{
             if (arrayIndex < 0)
@@ -625,22 +886,63 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
                     }}
                 }}
             }} while (tempBits != 0);
-        }}" : "")}
-        {(loop.ClassName == "HttpRequestHeaders" ? $@"
-        public unsafe void Append(byte* pKeyBytes, int keyLength, string value)
+        }}" : "")}{(loop.ClassName == "HttpRequestHeaders" ? $@"
+        [MethodImpl(MethodImplOptions.AggressiveOptimization)]
+        public unsafe void Append(Span<byte> name, Span<byte> value)
         {{
-            var pUB = pKeyBytes;
-            {AppendSwitch(loop.Headers.Where(h => h.PrimaryHeader).GroupBy(x => x.Name.Length), loop.ClassName)}
+            ref byte nameStart = ref MemoryMarshal.GetReference(name);
+            ref StringValues values = ref Unsafe.AsRef<StringValues>(null);
+            var flag = 0L;
 
-            AppendNonPrimaryHeaders(pKeyBytes, keyLength, value);
-        }}
+            // Does the name matched any ""known"" headers
+            {AppendSwitch(loop.Headers.GroupBy(x => x.Name.Length).OrderBy(x => x.Key))}
 
-        private unsafe void AppendNonPrimaryHeaders(byte* pKeyBytes, int keyLength, string value)
-        {{
-                var pUB = pKeyBytes;
-                {AppendSwitch(loop.Headers.Where(h => !h.PrimaryHeader).GroupBy(x => x.Name.Length), loop.ClassName)}
+            if (flag != 0)
+            {{
+                // Matched a known header
+                if ((_previousBits & flag) != 0)
+                {{
+                    // Had a previous string for this header, mark it as used so we don't clear it OnHeadersComplete or consider it if we get a second header
+                    _previousBits ^= flag;
+
+                    // We will only reuse this header if there was only one previous header
+                    if (values.Count == 1)
+                    {{
+                        var previousValue = values.ToString();
+                        // Check lengths are the same, then if the bytes were converted to an ascii string if they would be the same.
+                        // We do not consider Utf8 headers for reuse.
+                        if (previousValue.Length == value.Length &&
+                            StringUtilities.BytesOrdinalEqualsStringAndAscii(previousValue, value))
+                        {{
+                            // The previous string matches what the bytes would convert to, so we will just use that one.
+                            _bits |= flag;
+                            return;
+                        }}
+                    }}
+                }}
 
-                AppendUnknownHeaders(pKeyBytes, keyLength, value);
+                // We didn't have a previous matching header value, or have already added a header, so get the string for this value.
+                var valueStr = value.GetAsciiOrUTF8StringNonNullCharacters();
+                if ((_bits & flag) == 0)
+                {{
+                    // We didn't already have a header set, so add a new one.
+                    _bits |= flag;
+                    values = new StringValues(valueStr);
+                }}
+                else
+                {{
+                    // We already had a header set, so concatenate the new one.
+                    values = AppendValue(values, valueStr);
+                }}
+            }}
+            else
+            {{
+                // The header was not one of the ""known"" headers.
+                // Convert value to string first, because passing two spans causes 8 bytes stack zeroing in 
+                // this method with rep stosd, which is slower than necessary.
+                var valueStr = value.GetAsciiOrUTF8StringNonNullCharacters();
+                AppendUnknownHeaders(name, valueStr);
+            }}
         }}" : "")}
 
         private struct HeaderReferences

+ 2 - 0
src/Servers/Kestrel/test/BindTests/AddressRegistrationTests.cs

@@ -154,6 +154,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
         }
 
         [ConditionalTheory]
+        [Flaky("https://github.com/aspnet/AspNetCore-Internal/issues/2179", FlakyOn.Helix.All)]
         [MemberData(nameof(AddressRegistrationDataIPv6ScopeId))]
         [IPv6SupportedCondition]
         [IPv6ScopeIdPresentCondition]
@@ -589,6 +590,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
         }
 
         [Fact]
+        [Flaky("https://github.com/aspnet/AspNetCore-Internal/issues/2178", FlakyOn.All)]
         public async Task DoesNotOverrideDirectConfigurationWithIServerAddressesFeature_IfPreferHostingUrlsFalse()
         {
             var useUrlsAddress = $"http://127.0.0.1:0";

+ 1 - 0
src/Servers/Kestrel/test/FunctionalTests/RequestTests.cs

@@ -542,6 +542,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
         }
 
         [Theory]
+        [Flaky("https://github.com/aspnet/AspNetCore-Internal/issues/2181", FlakyOn.Helix.All)]
         [MemberData(nameof(ConnectionAdapterData))]
         public async Task ConnectionClosedTokenFiresOnServerFIN(ListenOptions listenOptions)
         {

+ 2 - 0
src/Servers/Kestrel/test/InMemory.FunctionalTests/Http2/Http2TestBase.cs

@@ -406,6 +406,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
             _decodedHeaders[name.GetAsciiStringNonNullCharacters()] = value.GetAsciiOrUTF8StringNonNullCharacters();
         }
 
+        void IHttpHeadersHandler.OnHeadersComplete() { }
+
         protected void CreateConnection()
         {
             var limits = _serviceContext.ServerOptions.Limits;

+ 1 - 1
src/Servers/Kestrel/test/InMemory.FunctionalTests/Http2/Http2TimeoutTests.cs

@@ -492,7 +492,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
             _mockConnectionContext.VerifyNoOtherCalls();
         }
 
-        [Fact]
+        [Fact(Skip = "https://github.com/aspnet/AspNetCore-Internal/issues/2197")]
         public async Task DATA_Sent_TooSlowlyDueToOutputFlowControlOnMultipleStreams_AbortsConnectionAfterAdditiveRateTimeout()
         {
             var mockSystemClock = _serviceContext.MockSystemClock;

+ 1 - 1
src/Servers/Kestrel/test/InMemory.FunctionalTests/HttpsConnectionAdapterTests.cs

@@ -484,7 +484,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.InMemory.FunctionalTests
             }
         }
 
-        [Theory]
+        [ConditionalTheory]
         [SkipOnHelix]
         [InlineData(ClientCertificateMode.AllowCertificate)]
         [InlineData(ClientCertificateMode.RequireCertificate)]

+ 2 - 0
src/Servers/Kestrel/test/InMemory.FunctionalTests/LoggingConnectionAdapterTests.cs

@@ -6,6 +6,7 @@ using Microsoft.AspNetCore.Hosting;
 using Microsoft.AspNetCore.Http;
 using Microsoft.AspNetCore.Server.Kestrel.InMemory.FunctionalTests.TestTransport;
 using Microsoft.AspNetCore.Testing;
+using Microsoft.AspNetCore.Testing.xunit;
 using Microsoft.Extensions.Logging.Testing;
 using Xunit;
 
@@ -14,6 +15,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.InMemory.FunctionalTests
     public class LoggingConnectionAdapterTests : LoggedTest
     {
         [Fact]
+        [Flaky("https://github.com/aspnet/AspNetCore-Internal/issues/1753", FlakyOn.Helix.All)]
         public async Task LoggingConnectionAdapterCanBeAddedBeforeAndAfterHttpsAdapter()
         {
             await using (var server = new TestServer(context =>

+ 4 - 2
src/Servers/Kestrel/test/InMemory.FunctionalTests/RequestTests.cs

@@ -17,6 +17,7 @@ using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
 using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure;
 using Microsoft.AspNetCore.Server.Kestrel.InMemory.FunctionalTests.TestTransport;
 using Microsoft.AspNetCore.Testing;
+using Microsoft.AspNetCore.Testing.xunit;
 using Microsoft.Extensions.Logging.Testing;
 using Xunit;
 
@@ -781,6 +782,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.InMemory.FunctionalTests
         }
 
         [Fact]
+        [Flaky("https://github.com/aspnet/AspNetCore-Internal/issues/2176", FlakyOn.All)]
         public async Task ContentLengthReadAsyncSingleBytesAtATime()
         {
             var testContext = new TestServiceContext(LoggerFactory);
@@ -811,10 +813,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel.InMemory.FunctionalTests
                         "Content-Length: 5",
                         "",
                         "fun");
-                    await tcs.Task;
+                    await tcs.Task.DefaultTimeout();
                     await connection.Send(
                         "n");
-                    await tcs2.Task;
+                    await tcs2.Task.DefaultTimeout();
                     await connection.Send(
                         "y");
                     await connection.ReceiveEnd(

+ 4 - 0
src/Servers/Kestrel/tools/CodeGenerator/CodeGenerator.csproj

@@ -7,6 +7,10 @@
     <IsTestAssetProject>true</IsTestAssetProject>
   </PropertyGroup>
 
+  <ItemGroup>
+    <Compile Include="$(KestrelSharedSourceRoot)KnownHeaders.cs" />
+  </ItemGroup>
+    
   <ItemGroup>
     <Reference Include="Microsoft.AspNetCore.Hosting" />
     <Reference Include="Microsoft.AspNetCore.Http.Features" />

+ 2 - 1
src/Servers/Kestrel/xunit.runner.json

@@ -3,5 +3,6 @@
   "appDomain": "denied",
   "methodDisplay": "method",
   "longRunningTestSeconds": 60,
-  "maxParallelThreads": -1
+  "maxParallelThreads": -1,
+  "diagnosticMessages": true
 }

+ 7 - 6
src/Shared/E2ETesting/BrowserFixture.cs

@@ -3,21 +3,20 @@
 
 using System;
 using System.Collections.Concurrent;
-using System.Collections.Generic;
 using System.Linq;
 using System.Reflection;
 using System.Threading.Tasks;
 using OpenQA.Selenium;
 using OpenQA.Selenium.Chrome;
 using OpenQA.Selenium.Remote;
+using Xunit;
 using Xunit.Abstractions;
 
 namespace Microsoft.AspNetCore.E2ETesting
 {
-    public class BrowserFixture : IDisposable
+    public class BrowserFixture : IAsyncLifetime
     {
         private ConcurrentDictionary<string, Task<(IWebDriver browser, ILogs log)>> _browsers = new ConcurrentDictionary<string, Task<(IWebDriver, ILogs)>>();
-        private List<IWebDriver> _browsersToDispose = new List<IWebDriver>();
 
         public BrowserFixture(IMessageSink diagnosticsMessageSink)
         {
@@ -52,9 +51,10 @@ namespace Microsoft.AspNetCore.E2ETesting
             }
         }
 
-        public void Dispose()
+        public async Task DisposeAsync()
         {
-            foreach (var browser in _browsersToDispose)
+            var browsers = await Task.WhenAll(_browsers.Values);
+            foreach (var (browser, log) in browsers)
             {
                 browser.Dispose();
             }
@@ -71,6 +71,8 @@ namespace Microsoft.AspNetCore.E2ETesting
             return _browsers.GetOrAdd(isolationContext, CreateBrowserAsync, output);
         }
 
+        public Task InitializeAsync() => Task.CompletedTask;
+
         private async Task<(IWebDriver browser, ILogs log)> CreateBrowserAsync(string context, ITestOutputHelper output)
         {
             var opts = new ChromeOptions();
@@ -115,7 +117,6 @@ namespace Microsoft.AspNetCore.E2ETesting
                     driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(1);
                     var logs = new RemoteLogs(driver);
 
-                    _browsersToDispose.Add(driver);
                     return (driver, logs);
                 }
                 catch

+ 5 - 7
src/SignalR/clients/csharp/Client/test/FunctionalTests/HubConnectionTests.cs

@@ -449,7 +449,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests
 
                     var cts = new CancellationTokenSource();
 
-                    var stream = connection.StreamAsync<int>("Stream", 5, cts.Token);
+                    var stream = connection.StreamAsync<int>("Stream", 1000, cts.Token);
                     var results = new List<int>();
 
                     var enumerator = stream.GetAsyncEnumerator();
@@ -462,8 +462,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests
                         }
                     });
 
-                    Assert.Single(results);
-                    Assert.Equal(0, results[0]);
+                    Assert.True(results.Count > 0 && results.Count < 1000);
                 }
                 catch (Exception ex)
                 {
@@ -665,7 +664,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests
         [Theory]
         [MemberData(nameof(HubProtocolsAndTransportsAndHubPaths))]
         [LogLevel(LogLevel.Trace)]
-        public async Task StreamAsyncCanBeCanceledThroughGetEnumerator(string protocolName, HttpTransportType transportType, string path)
+        public async Task StreamAsyncCanBeCanceledThroughGetAsyncEnumerator(string protocolName, HttpTransportType transportType, string path)
         {
             var protocol = HubProtocols[protocolName];
             using (StartServer<Startup>(out var server))
@@ -674,7 +673,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests
                 try
                 {
                     await connection.StartAsync().OrTimeout();
-                    var stream = connection.StreamAsync<int>("Stream", 5 );
+                    var stream = connection.StreamAsync<int>("Stream", 1000 );
                     var results = new List<int>();
 
                     var cts = new CancellationTokenSource();
@@ -689,8 +688,7 @@ namespace Microsoft.AspNetCore.SignalR.Client.FunctionalTests
                         }
                     });
 
-                    Assert.Single(results);
-                    Assert.Equal(0, results[0]);
+                    Assert.True(results.Count > 0 && results.Count < 1000);
                 }
                 catch (Exception ex)
                 {

+ 5 - 0
src/SignalR/clients/ts/FunctionalTests/TestHub.cs

@@ -34,6 +34,11 @@ namespace FunctionalTests
             return message;
         }
 
+        public string GetCallerConnectionId()
+        {
+            return Context.ConnectionId;
+        }
+
         public int GetNumRedirects()
         {
             return int.Parse(Context.GetHttpContext().Request.Query["numRedirects"]);

+ 76 - 0
src/SignalR/clients/ts/FunctionalTests/ts/HubConnectionTests.ts

@@ -782,6 +782,9 @@ describe("hubConnection", () => {
 
             expect(newConnectionId).not.toBe(initialConnectionId);
 
+            const serverConnectionId = await hubConnection.invoke<string>("GetCallerConnectionId");
+            expect(newConnectionId).toBe(serverConnectionId);
+
             const postReconnectRedirects = await hubConnection.invoke<number>("GetNumRedirects");
 
             expect(postReconnectRedirects).toBeGreaterThan(preReconnectRedirects);
@@ -838,6 +841,79 @@ describe("hubConnection", () => {
         }
     });
 
+    it("connection id matches server side connection id", async (done) => {
+        try {
+            const reconnectingPromise = new PromiseSource();
+            const reconnectedPromise = new PromiseSource<string | undefined>();
+            const hubConnection = getConnectionBuilder(undefined, TESTHUB_REDIRECT_ENDPOINT_URL)
+                .withAutomaticReconnect()
+                .build();
+
+            hubConnection.onreconnecting(() => {
+                reconnectingPromise.resolve();
+            });
+
+            hubConnection.onreconnected((connectionId?) => {
+                reconnectedPromise.resolve(connectionId);
+            });
+
+            expect(hubConnection.connectionId).toBeNull();
+
+            await hubConnection.start();
+
+            expect(hubConnection.connectionId).not.toBeNull();
+            let serverConnectionId = await hubConnection.invoke<string>("GetCallerConnectionId");
+            expect(hubConnection.connectionId).toBe(serverConnectionId);
+
+            const initialConnectionId = hubConnection.connectionId!;
+
+            // Induce reconnect
+            (hubConnection as any).serverTimeout();
+
+            await reconnectingPromise;
+            const newConnectionId = await reconnectedPromise;
+
+            expect(newConnectionId).not.toBe(initialConnectionId);
+
+            serverConnectionId = await hubConnection.invoke<string>("GetCallerConnectionId");
+            expect(newConnectionId).toBe(serverConnectionId);
+
+            await hubConnection.stop();
+            expect(hubConnection.connectionId).toBeNull();
+
+            done();
+        } catch (err) {
+            fail(err);
+            done();
+        }
+    });
+
+    it("connection id is alwys null is negotiation is skipped", async (done) => {
+        try {
+            const hubConnection = getConnectionBuilder(
+                    HttpTransportType.WebSockets,
+                    undefined,
+                    { skipNegotiation: true },
+                )
+                .build();
+
+            expect(hubConnection.connectionId).toBeNull();
+
+            await hubConnection.start();
+
+            expect(hubConnection.connectionId).toBeNull();
+
+            await hubConnection.stop();
+
+            expect(hubConnection.connectionId).toBeNull();
+
+            done();
+        } catch (err) {
+            fail(err);
+            done();
+        }
+    });
+
     if (typeof EventSource !== "undefined") {
         it("allows Server-Sent Events when negotiating for JSON protocol", async (done) => {
             const hubConnection = getConnectionBuilder(undefined, TESTHUB_NOWEBSOCKETS_ENDPOINT_URL)

+ 1 - 0
src/SignalR/clients/ts/signalr/src/HttpConnection.ts

@@ -450,6 +450,7 @@ export class HttpConnection implements IConnection {
             this.logger.log(LogLevel.Information, "Connection disconnected.");
         }
 
+        this.connectionId = undefined;
         this.connectionState = ConnectionState.Disconnected;
 
         if (this.onclose && this.connectionStarted) {

+ 7 - 0
src/SignalR/clients/ts/signalr/src/HubConnection.ts

@@ -120,6 +120,13 @@ export class HubConnection {
         return this.connectionState;
     }
 
+    /** Represents the connection id of the {@link HubConnection} on the server. The connection id will be null when the connection is either
+     *  in the disconnected state or if the negotiation step was skipped.
+     */
+    get connectionId(): string | null {
+        return this.connection ? (this.connection.connectionId || null) : null;
+    }
+
     /** Starts the connection.
      *
      * @returns {Promise<void>} A Promise that resolves when the connection has been successfully established, or rejects with an error.

+ 17 - 2
src/SignalR/perf/benchmarkapps/Crankier/Client.cs

@@ -12,12 +12,27 @@ namespace Microsoft.AspNetCore.SignalR.Crankier
 {
     public class Client
     {
+        private readonly int _processId;
+        private readonly IAgent _agent;
         private HubConnection _connection;
         private CancellationTokenSource _sendCts;
         private bool _sendInProgress;
         private volatile ConnectionState _connectionState = ConnectionState.Connecting;
 
         public ConnectionState State => _connectionState;
+        public Client(int processId, IAgent agent)
+        {
+            _processId = processId;
+            _agent = agent;
+        }
+
+        private void LogFault(string description, Exception exception)
+        {
+            var message = $"{description}: {exception.GetType()}: {exception.Message}";
+            Trace.WriteLine(message);
+            _agent.LogAsync(_processId, message);
+        }
+
         public async Task CreateAndStartConnectionAsync(string url, HttpTransportType transportType)
         {
             _connection = new HubConnectionBuilder()
@@ -33,7 +48,7 @@ namespace Microsoft.AspNetCore.SignalR.Crankier
                 }
                 else
                 {
-                    Trace.WriteLine($"Connection terminated with error: {ex.GetType()}: {ex.Message}");
+                    LogFault("Connection terminated with error", ex);
                     _connectionState = ConnectionState.Faulted;
                 }
 
@@ -57,7 +72,7 @@ namespace Microsoft.AspNetCore.SignalR.Crankier
                 }
                 catch (Exception ex)
                 {
-                    Trace.WriteLine($"Connection.Start Failed: {ex.GetType()}: {ex.Message}");
+                    LogFault("Connection.Start Failed", ex);
 
                     if (connectCount == 3)
                     {

+ 1 - 1
src/SignalR/perf/benchmarkapps/Crankier/Worker.cs

@@ -62,7 +62,7 @@ namespace Microsoft.AspNetCore.SignalR.Crankier
             _targetConnectionCount += numberOfConnections;
             for (var count = 0; count < numberOfConnections; count++)
             {
-                var client = new Client();
+                var client = new Client(_processId, _agent);
                 _clients.Add(client);
 
                 await client.CreateAndStartConnectionAsync(targetAddress, transportType);

+ 1 - 1
version.props

@@ -3,7 +3,7 @@
     <AspNetCoreMajorVersion>3</AspNetCoreMajorVersion>
     <AspNetCoreMinorVersion>0</AspNetCoreMinorVersion>
     <AspNetCorePatchVersion>0</AspNetCorePatchVersion>
-    <PreReleasePreviewNumber>4</PreReleasePreviewNumber>
+    <PreReleasePreviewNumber>5</PreReleasePreviewNumber>
     <PreReleaseLabel>preview$(PreReleasePreviewNumber)</PreReleaseLabel>
     <PreReleaseBrandingLabel>Preview $(PreReleasePreviewNumber)</PreReleaseBrandingLabel>
     <ExperimentalVersionPrefix>0.3.$(AspNetCorePatchVersion)</ExperimentalVersionPrefix>

Энэ ялгаанд хэт олон файл өөрчлөгдсөн тул зарим файлыг харуулаагүй болно