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

This commit is contained in:
Doug Bunting 2019-04-10 09:07:12 -07:00 committed by GitHub
commit 6b3327ee35
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
57 changed files with 3079 additions and 1399 deletions

30
.github/CODEOWNERS vendored
View File

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

View File

@ -20,6 +20,7 @@
https://dotnet.myget.org/F/aspnetcore-tools/api/v3/index.json; 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/blazor-dev/api/v3/index.json;
https://dotnet.myget.org/F/dotnet-core/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-tools/api/v3/index.json;
https://dotnet.myget.org/F/roslyn/api/v3/index.json; https://dotnet.myget.org/F/roslyn/api/v3/index.json;
https://vside.myget.org/F/devcore/api/v3/index.json; https://vside.myget.org/F/devcore/api/v3/index.json;

View File

@ -12,7 +12,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Remove="Internal.AspNetCore.Sdk" /> <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="Microsoft.Extensions.DependencyModel" Version="2.1.0" />
<PackageReference Include="Yarn.MSBuild" Version="1.13.0" /> <PackageReference Include="Yarn.MSBuild" Version="1.13.0" />
</ItemGroup> </ItemGroup>

View File

@ -9,384 +9,384 @@
--> -->
<Dependencies> <Dependencies>
<ProductDependencies> <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> <Uri>https://github.com/aspnet/AspNetCore-Tooling</Uri>
<Sha>699014190668f9d631583a771ecfa1be39183624</Sha> <Sha>beebdf43f54ec82e06a48b99812d9740cb9f38cf</Sha>
</Dependency> </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> <Uri>https://github.com/aspnet/AspNetCore-Tooling</Uri>
<Sha>699014190668f9d631583a771ecfa1be39183624</Sha> <Sha>beebdf43f54ec82e06a48b99812d9740cb9f38cf</Sha>
</Dependency> </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> <Uri>https://github.com/aspnet/AspNetCore-Tooling</Uri>
<Sha>699014190668f9d631583a771ecfa1be39183624</Sha> <Sha>beebdf43f54ec82e06a48b99812d9740cb9f38cf</Sha>
</Dependency> </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> <Uri>https://github.com/aspnet/AspNetCore-Tooling</Uri>
<Sha>699014190668f9d631583a771ecfa1be39183624</Sha> <Sha>beebdf43f54ec82e06a48b99812d9740cb9f38cf</Sha>
</Dependency> </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> <Uri>https://github.com/aspnet/EntityFrameworkCore</Uri>
<Sha>c6daea74750e0d3b89f3aa8581ceef068f60373c</Sha> <Sha>243ea5080c4d7eefc96797134c9e10b2fa75f835</Sha>
</Dependency> </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> <Uri>https://github.com/aspnet/EntityFrameworkCore</Uri>
<Sha>c6daea74750e0d3b89f3aa8581ceef068f60373c</Sha> <Sha>243ea5080c4d7eefc96797134c9e10b2fa75f835</Sha>
</Dependency> </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> <Uri>https://github.com/aspnet/EntityFrameworkCore</Uri>
<Sha>c6daea74750e0d3b89f3aa8581ceef068f60373c</Sha> <Sha>243ea5080c4d7eefc96797134c9e10b2fa75f835</Sha>
</Dependency> </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> <Uri>https://github.com/aspnet/EntityFrameworkCore</Uri>
<Sha>c6daea74750e0d3b89f3aa8581ceef068f60373c</Sha> <Sha>243ea5080c4d7eefc96797134c9e10b2fa75f835</Sha>
</Dependency> </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> <Uri>https://github.com/aspnet/EntityFrameworkCore</Uri>
<Sha>c6daea74750e0d3b89f3aa8581ceef068f60373c</Sha> <Sha>243ea5080c4d7eefc96797134c9e10b2fa75f835</Sha>
</Dependency> </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> <Uri>https://github.com/aspnet/EntityFrameworkCore</Uri>
<Sha>c6daea74750e0d3b89f3aa8581ceef068f60373c</Sha> <Sha>243ea5080c4d7eefc96797134c9e10b2fa75f835</Sha>
</Dependency> </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> <Uri>https://github.com/aspnet/EntityFrameworkCore</Uri>
<Sha>c6daea74750e0d3b89f3aa8581ceef068f60373c</Sha> <Sha>243ea5080c4d7eefc96797134c9e10b2fa75f835</Sha>
</Dependency> </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> <Uri>https://github.com/aspnet/Extensions</Uri>
<Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha> <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
</Dependency> </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> <Uri>https://github.com/aspnet/Extensions</Uri>
<Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha> <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
</Dependency> </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> <Uri>https://github.com/aspnet/Extensions</Uri>
<Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha> <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
</Dependency> </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> <Uri>https://github.com/aspnet/Extensions</Uri>
<Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha> <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
</Dependency> </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> <Uri>https://github.com/aspnet/Extensions</Uri>
<Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha> <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
</Dependency> </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> <Uri>https://github.com/aspnet/Extensions</Uri>
<Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha> <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
</Dependency> </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> <Uri>https://github.com/aspnet/Extensions</Uri>
<Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha> <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
</Dependency> </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> <Uri>https://github.com/aspnet/Extensions</Uri>
<Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha> <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
</Dependency> </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> <Uri>https://github.com/aspnet/Extensions</Uri>
<Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha> <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
</Dependency> </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> <Uri>https://github.com/aspnet/Extensions</Uri>
<Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha> <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
</Dependency> </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> <Uri>https://github.com/aspnet/Extensions</Uri>
<Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha> <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
</Dependency> </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> <Uri>https://github.com/aspnet/Extensions</Uri>
<Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha> <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
</Dependency> </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> <Uri>https://github.com/aspnet/Extensions</Uri>
<Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha> <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
</Dependency> </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> <Uri>https://github.com/aspnet/Extensions</Uri>
<Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha> <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
</Dependency> </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> <Uri>https://github.com/aspnet/Extensions</Uri>
<Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha> <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
</Dependency> </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> <Uri>https://github.com/aspnet/Extensions</Uri>
<Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha> <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
</Dependency> </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> <Uri>https://github.com/aspnet/Extensions</Uri>
<Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha> <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
</Dependency> </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> <Uri>https://github.com/aspnet/Extensions</Uri>
<Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha> <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
</Dependency> </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> <Uri>https://github.com/aspnet/Extensions</Uri>
<Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha> <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
</Dependency> </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> <Uri>https://github.com/aspnet/Extensions</Uri>
<Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha> <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
</Dependency> </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> <Uri>https://github.com/aspnet/Extensions</Uri>
<Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha> <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
</Dependency> </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> <Uri>https://github.com/aspnet/Extensions</Uri>
<Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha> <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
</Dependency> </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> <Uri>https://github.com/aspnet/Extensions</Uri>
<Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha> <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
</Dependency> </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> <Uri>https://github.com/aspnet/Extensions</Uri>
<Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha> <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
</Dependency> </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> <Uri>https://github.com/aspnet/Extensions</Uri>
<Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha> <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
</Dependency> </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> <Uri>https://github.com/aspnet/Extensions</Uri>
<Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha> <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
</Dependency> </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> <Uri>https://github.com/aspnet/Extensions</Uri>
<Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha> <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
</Dependency> </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> <Uri>https://github.com/aspnet/Extensions</Uri>
<Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha> <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
</Dependency> </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> <Uri>https://github.com/aspnet/Extensions</Uri>
<Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha> <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
</Dependency> </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> <Uri>https://github.com/aspnet/Extensions</Uri>
<Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha> <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
</Dependency> </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> <Uri>https://github.com/aspnet/Extensions</Uri>
<Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha> <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
</Dependency> </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> <Uri>https://github.com/aspnet/Extensions</Uri>
<Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha> <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
</Dependency> </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> <Uri>https://github.com/aspnet/Extensions</Uri>
<Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha> <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
</Dependency> </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> <Uri>https://github.com/aspnet/Extensions</Uri>
<Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha> <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
</Dependency> </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> <Uri>https://github.com/aspnet/Extensions</Uri>
<Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha> <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
</Dependency> </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> <Uri>https://github.com/aspnet/Extensions</Uri>
<Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha> <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
</Dependency> </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> <Uri>https://github.com/aspnet/Extensions</Uri>
<Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha> <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
</Dependency> </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> <Uri>https://github.com/aspnet/Extensions</Uri>
<Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha> <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
</Dependency> </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> <Uri>https://github.com/aspnet/Extensions</Uri>
<Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha> <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
</Dependency> </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> <Uri>https://github.com/aspnet/Extensions</Uri>
<Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha> <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
</Dependency> </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> <Uri>https://github.com/aspnet/Extensions</Uri>
<Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha> <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
</Dependency> </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> <Uri>https://github.com/aspnet/Extensions</Uri>
<Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha> <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
</Dependency> </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> <Uri>https://github.com/aspnet/Extensions</Uri>
<Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha> <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
</Dependency> </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> <Uri>https://github.com/aspnet/Extensions</Uri>
<Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha> <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
</Dependency> </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> <Uri>https://github.com/aspnet/Extensions</Uri>
<Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha> <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
</Dependency> </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> <Uri>https://github.com/aspnet/Extensions</Uri>
<Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha> <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
</Dependency> </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> <Uri>https://github.com/aspnet/Extensions</Uri>
<Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha> <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
</Dependency> </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> <Uri>https://github.com/aspnet/Extensions</Uri>
<Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha> <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
</Dependency> </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> <Uri>https://github.com/aspnet/Extensions</Uri>
<Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha> <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
</Dependency> </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> <Uri>https://github.com/aspnet/Extensions</Uri>
<Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha> <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
</Dependency> </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> <Uri>https://github.com/aspnet/Extensions</Uri>
<Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha> <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
</Dependency> </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> <Uri>https://github.com/aspnet/Extensions</Uri>
<Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha> <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
</Dependency> </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> <Uri>https://github.com/aspnet/Extensions</Uri>
<Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha> <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
</Dependency> </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> <Uri>https://github.com/aspnet/Extensions</Uri>
<Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha> <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
</Dependency> </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> <Uri>https://github.com/aspnet/Extensions</Uri>
<Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha> <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
</Dependency> </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> <Uri>https://github.com/aspnet/Extensions</Uri>
<Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha> <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
</Dependency> </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> <Uri>https://github.com/aspnet/Extensions</Uri>
<Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha> <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
</Dependency> </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> <Uri>https://github.com/aspnet/Extensions</Uri>
<Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha> <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
</Dependency> </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> <Uri>https://github.com/dotnet/corefx</Uri>
<Sha>e0a01a12c2676d69cefa61aa2526a414d7f2dabb</Sha> <Sha>81fe62442228cb26bd0d95ceec3e0a3b74bde0a2</Sha>
</Dependency> </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> <Uri>https://github.com/dotnet/corefx</Uri>
<Sha>e0a01a12c2676d69cefa61aa2526a414d7f2dabb</Sha> <Sha>81fe62442228cb26bd0d95ceec3e0a3b74bde0a2</Sha>
</Dependency> </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> <Uri>https://github.com/dotnet/corefx</Uri>
<Sha>e0a01a12c2676d69cefa61aa2526a414d7f2dabb</Sha> <Sha>81fe62442228cb26bd0d95ceec3e0a3b74bde0a2</Sha>
</Dependency> </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> <Uri>https://github.com/dotnet/corefx</Uri>
<Sha>e0a01a12c2676d69cefa61aa2526a414d7f2dabb</Sha> <Sha>81fe62442228cb26bd0d95ceec3e0a3b74bde0a2</Sha>
</Dependency> </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> <Uri>https://github.com/dotnet/corefx</Uri>
<Sha>e0a01a12c2676d69cefa61aa2526a414d7f2dabb</Sha> <Sha>81fe62442228cb26bd0d95ceec3e0a3b74bde0a2</Sha>
</Dependency> </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> <Uri>https://github.com/dotnet/corefx</Uri>
<Sha>e0a01a12c2676d69cefa61aa2526a414d7f2dabb</Sha> <Sha>81fe62442228cb26bd0d95ceec3e0a3b74bde0a2</Sha>
</Dependency> </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> <Uri>https://github.com/dotnet/corefx</Uri>
<Sha>e0a01a12c2676d69cefa61aa2526a414d7f2dabb</Sha> <Sha>81fe62442228cb26bd0d95ceec3e0a3b74bde0a2</Sha>
</Dependency> </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> <Uri>https://github.com/dotnet/corefx</Uri>
<Sha>e0a01a12c2676d69cefa61aa2526a414d7f2dabb</Sha> <Sha>81fe62442228cb26bd0d95ceec3e0a3b74bde0a2</Sha>
</Dependency> </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> <Uri>https://github.com/dotnet/corefx</Uri>
<Sha>e0a01a12c2676d69cefa61aa2526a414d7f2dabb</Sha> <Sha>81fe62442228cb26bd0d95ceec3e0a3b74bde0a2</Sha>
</Dependency> </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> <Uri>https://github.com/dotnet/corefx</Uri>
<Sha>e0a01a12c2676d69cefa61aa2526a414d7f2dabb</Sha> <Sha>81fe62442228cb26bd0d95ceec3e0a3b74bde0a2</Sha>
</Dependency> </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> <Uri>https://github.com/dotnet/corefx</Uri>
<Sha>e0a01a12c2676d69cefa61aa2526a414d7f2dabb</Sha> <Sha>81fe62442228cb26bd0d95ceec3e0a3b74bde0a2</Sha>
</Dependency> </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> <Uri>https://github.com/dotnet/corefx</Uri>
<Sha>e0a01a12c2676d69cefa61aa2526a414d7f2dabb</Sha> <Sha>81fe62442228cb26bd0d95ceec3e0a3b74bde0a2</Sha>
</Dependency> </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> <Uri>https://github.com/dotnet/corefx</Uri>
<Sha>e0a01a12c2676d69cefa61aa2526a414d7f2dabb</Sha> <Sha>81fe62442228cb26bd0d95ceec3e0a3b74bde0a2</Sha>
</Dependency> </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> <Uri>https://github.com/dotnet/corefx</Uri>
<Sha>e0a01a12c2676d69cefa61aa2526a414d7f2dabb</Sha> <Sha>81fe62442228cb26bd0d95ceec3e0a3b74bde0a2</Sha>
</Dependency> </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> <Uri>https://github.com/dotnet/corefx</Uri>
<Sha>e0a01a12c2676d69cefa61aa2526a414d7f2dabb</Sha> <Sha>81fe62442228cb26bd0d95ceec3e0a3b74bde0a2</Sha>
</Dependency> </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> <Uri>https://github.com/dotnet/corefx</Uri>
<Sha>e0a01a12c2676d69cefa61aa2526a414d7f2dabb</Sha> <Sha>81fe62442228cb26bd0d95ceec3e0a3b74bde0a2</Sha>
</Dependency> </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> <Uri>https://github.com/dotnet/corefx</Uri>
<Sha>e0a01a12c2676d69cefa61aa2526a414d7f2dabb</Sha> <Sha>81fe62442228cb26bd0d95ceec3e0a3b74bde0a2</Sha>
</Dependency> </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> <Uri>https://github.com/dotnet/corefx</Uri>
<Sha>e0a01a12c2676d69cefa61aa2526a414d7f2dabb</Sha> <Sha>81fe62442228cb26bd0d95ceec3e0a3b74bde0a2</Sha>
</Dependency> </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> <Uri>https://github.com/dotnet/corefx</Uri>
<Sha>e0a01a12c2676d69cefa61aa2526a414d7f2dabb</Sha> <Sha>81fe62442228cb26bd0d95ceec3e0a3b74bde0a2</Sha>
</Dependency> </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> <Uri>https://github.com/dotnet/core-setup</Uri>
<Sha>89ba5a781188bb95f7de3c2714fdddd19f341f32</Sha> <Sha>42a6743d709c3d74f1cb7a2af8740e3183a022f4</Sha>
</Dependency> </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> <Uri>https://github.com/dotnet/core-setup</Uri>
<Sha>89ba5a781188bb95f7de3c2714fdddd19f341f32</Sha> <Sha>42a6743d709c3d74f1cb7a2af8740e3183a022f4</Sha>
</Dependency> </Dependency>
</ProductDependencies> </ProductDependencies>
<ToolsetDependencies> <ToolsetDependencies>
<!-- Listed explicitly to workaround https://github.com/dotnet/cli/issues/10528 --> <!-- 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> <Uri>https://github.com/dotnet/corefx</Uri>
<Sha>e0a01a12c2676d69cefa61aa2526a414d7f2dabb</Sha> <Sha>81fe62442228cb26bd0d95ceec3e0a3b74bde0a2</Sha>
</Dependency> </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> <Uri>https://github.com/aspnet/Extensions</Uri>
<Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha> <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
</Dependency> </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> <Uri>https://github.com/dotnet/arcade</Uri>
<Sha>b1f9e12fe3ee71c48ea60b15968745850ac0a4a7</Sha> <Sha>9d7e665ecf2606094677524ecd5af0fc39c7bb49</Sha>
</Dependency> </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> <Uri>https://github.com/aspnet/Extensions</Uri>
<Sha>0af12a60cf8f1c245b78488e50968907d5b5e671</Sha> <Sha>8749bf15c942cb1e4c9c01f3e7a9b2af84293d4b</Sha>
</Dependency> </Dependency>
</ToolsetDependencies> </ToolsetDependencies>
</Dependencies> </Dependencies>

View File

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

View File

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

View File

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

View File

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

View File

@ -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;"/> 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"/> <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" <CustomAction Id="CA_ADD_CONFIGSECTION_PROPERTY"
Property="CA_ADD_CONFIGSECTION" Property="CA_ADD_CONFIGSECTION"
Value="[IISEXPRESS_APPHOST_CONFIG];[IISEXPRESS_APPHOST_CONFIG_TMP]"/> Value="[IISEXPRESS_APPHOST_CONFIG]"/>
<CustomAction Id="CA_ADD_CONFIGSECTION" Script="jscript" Execute="deferred" Return="check" Impersonate="no"> <CustomAction BinaryKey="IISCustomActionDll" Id="CA_ADD_CONFIGSECTION" DllEntry="AddConfigSection" Execute="deferred" Return="check" Impersonate="no"/>
<![CDATA[
var caData = Session.Property("CustomActionData"); <CustomAction Id="CA_ADD_CONFIGSECTION_PROPERTY_TMP"
configfiles = caData.split(';'); Property="CA_ADD_CONFIGSECTION_TMP"
for (var i = 0; i < configfiles.length; i++) { Value="[IISEXPRESS_APPHOST_CONFIG_TMP]"/>
var configfile = configfiles[i]; <CustomAction BinaryKey="IISCustomActionDll" Id="CA_ADD_CONFIGSECTION_TMP" DllEntry="AddConfigSection" Execute="deferred" Return="check" Impersonate="no"/>
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 -->
<CustomAction Id="CA_REMOVE_CONFIGSECTION_PROPERTY" <CustomAction Id="CA_REMOVE_CONFIGSECTION_PROPERTY"
Property="CA_REMOVE_CONFIGSECTION" Property="CA_REMOVE_CONFIGSECTION"
Value="[IISEXPRESS_APPHOST_CONFIG];[IISEXPRESS_APPHOST_CONFIG_TMP]"/> Value="[IISEXPRESS_APPHOST_CONFIG]"/>
<CustomAction Id="CA_REMOVE_CONFIGSECTION" Script="jscript" Execute="deferred" Return="check" Impersonate="no"> <CustomAction Id="CA_REMOVE_CONFIGSECTION" BinaryKey="IISCustomActionDll" DllEntry="RemoveConfigSection" Execute="deferred" Return="check" Impersonate="no" />
<![CDATA[
var caData = Session.Property("CustomActionData"); <CustomAction Id="CA_REMOVE_CONFIGSECTION_PROPERTY_TMP"
configfiles = caData.split(';'); Property="CA_REMOVE_CONFIGSECTION_TMP"
for (var i = 0; i < configfiles.length; i++) { Value="[IISEXPRESS_APPHOST_CONFIG_TMP]"/>
var configfile = configfiles[i]; <CustomAction Id="CA_REMOVE_CONFIGSECTION_TMP" BinaryKey="IISCustomActionDll" DllEntry="RemoveConfigSection" Execute="deferred" Return="check" Impersonate="no" />
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>
<?if $(var.Platform) = "x64" ?> <?if $(var.Platform) = "x64" ?>
<CustomAction Id="CA_UNLOCK_HANDLER32_PROPERTY" <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;"/> 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"/> <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" <CustomAction Id="CA_ADD_CONFIGSECTION32_PROPERTY"
Property="CA_ADD_CONFIGSECTION32" Property="CA_ADD_CONFIGSECTION32"
Value="[IISEXPRESS_APPHOST_CONFIG32];[IISEXPRESS_APPHOST_CONFIG_TMP32]"/> Value="[IISEXPRESS_APPHOST_CONFIG32]"/>
<CustomAction Id="CA_ADD_CONFIGSECTION32" Script="jscript" Execute="deferred" Return="check" Impersonate="no"> <CustomAction BinaryKey="IISCustomActionDll" Id="CA_ADD_CONFIGSECTION32" DllEntry="AddConfigSection" Execute="deferred" Return="check" Impersonate="no"/>
<!-- Warning LGHT1076: ICE03: String overflow. Orca.exe inspection shows the custom action value is populated correctly -->
<![CDATA[ <CustomAction Id="CA_ADD_CONFIGSECTION32_PROPERTY_TMP"
var caData = Session.Property("CustomActionData"); Property="CA_ADD_CONFIGSECTION32_TMP"
configfiles = caData.split(';'); Value="[IISEXPRESS_APPHOST_CONFIG_TMP32]"/>
for (var i = 0; i < configfiles.length; i++) { <CustomAction BinaryKey="IISCustomActionDll" Id="CA_ADD_CONFIGSECTION32_TMP" DllEntry="AddConfigSection" Execute="deferred" Return="check" Impersonate="no"/>
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 -->
<CustomAction Id="CA_REMOVE_CONFIGSECTION32_PROPERTY" <CustomAction Id="CA_REMOVE_CONFIGSECTION32_PROPERTY"
Property="CA_REMOVE_CONFIGSECTION32" Property="CA_REMOVE_CONFIGSECTION32"
Value="[IISEXPRESS_APPHOST_CONFIG32];[IISEXPRESS_APPHOST_CONFIG_TMP32]"/> Value="[IISEXPRESS_APPHOST_CONFIG32]"/>
<CustomAction Id="CA_REMOVE_CONFIGSECTION32" Script="jscript" Execute="deferred" Return="check" Impersonate="no"> <CustomAction Id="CA_REMOVE_CONFIGSECTION32" BinaryKey="IISCustomActionDll" DllEntry="RemoveConfigSection" Execute="deferred" Return="check" Impersonate="no" />
<![CDATA[
var caData = Session.Property("CustomActionData"); <CustomAction Id="CA_REMOVE_CONFIGSECTION32_PROPERTY_TMP"
configfiles = caData.split(';'); Property="CA_REMOVE_CONFIGSECTION32_TMP"
for (var i = 0; i < configfiles.length; i++) { Value="[IISEXPRESS_APPHOST_CONFIG_TMP32]"/>
var configfile = configfiles[i]; <CustomAction Id="CA_REMOVE_CONFIGSECTION32_TMP" BinaryKey="IISCustomActionDll" DllEntry="RemoveConfigSection" Execute="deferred" Return="check" Impersonate="no" />
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>
<?endif?> <?endif?>
<InstallExecuteSequence> <InstallExecuteSequence>
@ -600,7 +516,9 @@
<Custom Action="CA_SET_MODULE" After="CA_SET_MODULE_PROPERTY"><![CDATA[(NOT REMOVE)]]></Custom> <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_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_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" 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_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> <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_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_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" 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_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" 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> <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_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_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_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_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_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> <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_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_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" 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_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_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> <Custom Action="CA_REMOVE_TRACE_PROVIDER_DEFINITION_TMP32_PROPERTY" Before="CA_REMOVE_TRACE_PROVIDER_DEFINITION_TMP32"><![CDATA[(REMOVE~="ALL" AND NOT UPGRADINGPRODUCTCODE)]]></Custom>

View File

@ -2,6 +2,8 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
#include <precomp.h> #include <precomp.h>
#include <MsiQuery.h>
#include <msxml6.h>
DECLARE_DEBUG_PRINT_OBJECT( "proxyCA.dll" ); DECLARE_DEBUG_PRINT_OBJECT( "proxyCA.dll" );
@ -40,6 +42,138 @@ struct COMPRESSION_MIME_TYPE
COMPRESSION_MIME_TYPE gMimeTypes[] = COMPRESSION_MIME_TYPE gMimeTypes[] =
{ { L"text/event-stream", FALSE} }; { { 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 UINT
WINAPI WINAPI
RegisterANCMCompressionCA( RegisterANCMCompressionCA(

View File

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

Binary file not shown.

View File

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

View File

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

View File

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

View File

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

View File

@ -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 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 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 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.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() { throw null; }
public Microsoft.AspNetCore.Server.Kestrel.KestrelConfigurationLoader Configure(Microsoft.Extensions.Configuration.IConfiguration config) { 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 public partial interface IHttpHeadersHandler
{ {
void OnHeader(System.Span<byte> name, System.Span<byte> value); 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 public partial interface IHttpParser<TRequestHandler> where TRequestHandler : Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.IHttpHeadersHandler, Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.IHttpRequestLineHandler
{ {

View File

@ -19,6 +19,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
private const byte ByteAsterisk = (byte)'*'; private const byte ByteAsterisk = (byte)'*';
private const byte ByteForwardSlash = (byte)'/'; private const byte ByteForwardSlash = (byte)'/';
private const string Asterisk = "*"; private const string Asterisk = "*";
private const string ForwardSlash = "/";
private readonly HttpConnectionContext _context; private readonly HttpConnectionContext _context;
private readonly IHttpParser<Http1ParsingHandler> _parser; private readonly IHttpParser<Http1ParsingHandler> _parser;
@ -268,16 +269,68 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
_requestTargetForm = HttpRequestTarget.OriginForm; _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 // 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; // 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" // then encoded/escaped to ASCII https://www.ietf.org/rfc/rfc3987.txt "Mapping of IRIs to URIs"
try try
{ {
var disableStringReuse = ServerOptions.DisableStringReuse;
// Read raw target before mutating memory. // Read raw target before mutating memory.
RawTarget = target.GetAsciiStringNonNullCharacters(); var previousValue = _parsedRawTarget;
QueryString = query.GetAsciiStringNonNullCharacters(); if (disableStringReuse ||
Path = PathNormalizer.DecodePath(path, pathEncoded, RawTarget, query.Length); 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) catch (InvalidOperationException)
{ {
@ -312,9 +365,27 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
// //
// Allowed characters in the 'host + port' section of authority. // Allowed characters in the 'host + port' section of authority.
// See https://tools.ietf.org/html/rfc3986#section-3.2 // 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; Path = string.Empty;
QueryString = 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) private void OnAsteriskFormTarget(HttpMethod method)
@ -331,6 +402,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
RawTarget = Asterisk; RawTarget = Asterisk;
Path = string.Empty; Path = string.Empty;
QueryString = 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) 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 // a server MUST accept the absolute-form in requests, even though
// HTTP/1.1 clients will only send them in requests to proxies. // HTTP/1.1 clients will only send them in requests to proxies.
RawTarget = target.GetAsciiStringNonNullCharacters(); var disableStringReuse = ServerOptions.DisableStringReuse;
var previousValue = _parsedRawTarget;
// Validation of absolute URIs is slow, but clients if (disableStringReuse ||
// should not be sending this form anyways, so perf optimization previousValue == null || previousValue.Length != target.Length ||
// not high priority !StringUtilities.BytesOrdinalEqualsStringAndAscii(previousValue, target))
if (!Uri.TryCreate(RawTarget, UriKind.Absolute, out var uri))
{ {
ThrowRequestTargetRejected(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();
_absoluteRequestTarget = uri; // Validation of absolute URIs is slow, but clients
Path = uri.LocalPath; // should not be sending this form anyways, so perf optimization
// don't use uri.Query because we need the unescaped version // not high priority
QueryString = query.GetAsciiStringNonNullCharacters();
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
{
// As RawTarget is the same we can reuse the previous values.
RawTarget = _parsedRawTarget;
Path = _parsedPath;
QueryString = _parsedQueryString;
}
} }
internal void EnsureHostHeaderExists() internal void EnsureHostHeaderExists()

View File

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

View File

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

View File

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

View File

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

View File

@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System; using System;
using System.Buffers.Text;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
@ -13,6 +14,50 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
{ {
internal sealed partial class HttpRequestHeaders : HttpHeaders 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) private static long ParseContentLength(string value)
{ {
if (!HeaderUtilities.TryParseNonNegativeInt64(value, out var parsed)) if (!HeaderUtilities.TryParseNonNegativeInt64(value, out var parsed))
@ -23,34 +68,45 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
return parsed; return parsed;
} }
[MethodImpl(MethodImplOptions.NoInlining)]
private void AppendContentLength(Span<byte> value)
{
if (_contentLength.HasValue)
{
BadHttpRequestException.Throw(RequestRejectionReason.MultipleContentLengths);
}
if (!Utf8Parser.TryParse(value, out long parsed, out var consumed) ||
parsed < 0 ||
consumed != value.Length)
{
BadHttpRequestException.Throw(RequestRejectionReason.InvalidContentLength, value.GetAsciiOrUTF8StringNonNullCharacters());
}
_contentLength = parsed;
}
[MethodImpl(MethodImplOptions.NoInlining)] [MethodImpl(MethodImplOptions.NoInlining)]
private void SetValueUnknown(string key, StringValues value) private void SetValueUnknown(string key, StringValues value)
{ {
Unknown[key] = value; Unknown[key] = value;
} }
public unsafe void Append(Span<byte> name, string value)
{
fixed (byte* namePtr = name)
{
Append(namePtr, name.Length, value);
}
}
[MethodImpl(MethodImplOptions.NoInlining)] [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) fixed (char* keyBuffer = key)
{ {
if (!StringUtilities.TryGetAsciiString(pKeyBytes, keyBuffer, keyLength)) if (!StringUtilities.TryGetAsciiString(pKeyBytes, keyBuffer, name.Length))
{ {
BadHttpRequestException.Throw(RequestRejectionReason.InvalidCharactersInHeaderName); BadHttpRequestException.Throw(RequestRejectionReason.InvalidCharactersInHeaderName);
} }
} }
Unknown.TryGetValue(key, out var existing); Unknown.TryGetValue(key, out var existing);
Unknown[key] = AppendValue(existing, value); Unknown[key] = AppendValue(existing, valueString);
} }
public Enumerator GetEnumerator() public Enumerator GetEnumerator()

View File

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

View File

@ -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) private void ValidateHeader(Span<byte> name, Span<byte> value)
{ {
// http://httpwg.org/specs/rfc7540.html#rfc.section.8.1.2.1 // http://httpwg.org/specs/rfc7540.html#rfc.section.8.1.2.1

View File

@ -2,13 +2,19 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System; using System;
using System.Buffers.Binary;
using System.Diagnostics;
using System.Numerics; using System.Numerics;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Intrinsics.X86;
using System.Text;
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure
{ {
internal class StringUtilities internal class StringUtilities
{ {
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
public static unsafe bool TryGetAsciiString(byte* input, char* output, int count) public static unsafe bool TryGetAsciiString(byte* input, char* output, int count)
{ {
// Calculate end position // Calculate end position
@ -109,6 +115,261 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure
return isValid; 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(); private static readonly char[] s_encode16Chars = "0123456789ABCDEF".ToCharArray();
/// <summary> /// <summary>

View File

@ -54,6 +54,15 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core
/// </remarks> /// </remarks>
public bool AllowSynchronousIO { get; set; } = false; 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> /// <summary>
/// Enables the Listen options callback to resolve and use services registered by the application during startup. /// Enables the Listen options callback to resolve and use services registered by the application during startup.
/// Typically initialized by UseKestrel()"/>. /// Typically initialized by UseKestrel()"/>.

View File

@ -24,16 +24,28 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
.Concat(byteRange) .Concat(byteRange)
.ToArray(); .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++)
for (var i = 1; i < byteArray.Length; i++)
{ {
var sb = (byte)s[i]; // Test all the lengths to hit all the different length paths e.g. Vector, long, short, char
var b = byteArray[i]; Test(span.Slice(i));
}
Assert.Equal(sb, b); static void Test(Span<byte> asciiBytes)
{
var s = asciiBytes.GetAsciiStringNonNullCharacters();
Assert.True(StringUtilities.BytesOrdinalEqualsStringAndAscii(s, asciiBytes));
Assert.Equal(s.Length, asciiBytes.Length);
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 byteRange = Enumerable.Range(0, 16384 + 64).Select(x => (byte)((x & 0x7f) | 0x01)).ToArray();
var expectedByteRange = byteRange.Concat(byteRange).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); 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 sb = (byte)((s[i] & 0x7f) | 0x01);
var b = expectedByteRange[i]; var b = expectedByteRange[i];
}
Assert.Equal(sb, b); 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();
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));
}
} }
} }
} }

View File

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

View File

@ -483,6 +483,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
Headers[name.GetAsciiStringNonNullCharacters()] = value.GetAsciiStringNonNullCharacters(); 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) 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(); Method = method != HttpMethod.Custom ? HttpUtilities.MethodToString(method) : customMethod.GetAsciiStringNonNullCharacters();

View File

@ -3,11 +3,13 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Text; using System.Text;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http; using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
using Microsoft.Extensions.Primitives; using Microsoft.Extensions.Primitives;
using Xunit; using Xunit;
using static CodeGenerator.KnownHeaders;
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests 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 encoding = Encoding.GetEncoding("iso-8859-1");
var exception = Assert.Throws<BadHttpRequestException>( 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); 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 }));
} }
} }

View File

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

View File

@ -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://root@contoso.com/path", "/path", "")]
[InlineData("http://root:password@contoso.com/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();
}
}
}

View File

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

View File

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

View File

@ -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>(_hostHeaderName), new Span<byte>(_hostHeaderValue));
handler.OnHeader(new Span<byte>(_acceptHeaderName), new Span<byte>(_acceptHeaderValue)); handler.OnHeader(new Span<byte>(_acceptHeaderName), new Span<byte>(_acceptHeaderValue));
handler.OnHeader(new Span<byte>(_connectionHeaderName), new Span<byte>(_connectionHeaderValue)); handler.OnHeader(new Span<byte>(_connectionHeaderName), new Span<byte>(_connectionHeaderValue));
handler.OnHeadersComplete();
consumedBytes = 0; consumedBytes = 0;
consumed = buffer.Start; consumed = buffer.Start;

View File

@ -125,6 +125,12 @@ namespace PlatformBenchmarks
{ {
} }
#if NETCOREAPP3_0
public void OnHeadersComplete()
{
}
#endif
public async ValueTask OnReadCompletedAsync() public async ValueTask OnReadCompletedAsync()
{ {
await Writer.FlushAsync(); 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) 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); => RequestHandler.OnStartLine(method, version, target, path, query, customMethod, pathEncoded);
#if NETCOREAPP3_0
public void OnHeadersComplete()
=> RequestHandler.OnHeadersComplete();
#endif
} }
} }

View File

@ -11,114 +11,11 @@ namespace CodeGenerator
{ {
public class KnownHeaders public class KnownHeaders
{ {
static string Each<T>(IEnumerable<T> values, Func<T, string> formatter) public readonly static KnownHeader[] RequestHeaders;
{ public readonly static KnownHeader[] ResponseHeaders;
return values.Any() ? values.Select(formatter).Aggregate((a, b) => a + b) : ""; public readonly static KnownHeader[] ResponseTrailers;
}
static string AppendSwitch(IEnumerable<IGrouping<int, KnownHeader>> values, string className) => static KnownHeaders()
$@"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 static string GeneratedFile()
{ {
var requestPrimaryHeaders = new[] var requestPrimaryHeaders = new[]
{ {
@ -173,7 +70,7 @@ namespace CodeGenerator
{ {
"Host" "Host"
}; };
var requestHeaders = commonHeaders.Concat(new[] RequestHeaders = commonHeaders.Concat(new[]
{ {
"Accept", "Accept",
"Accept-Charset", "Accept-Charset",
@ -196,6 +93,8 @@ namespace CodeGenerator
"TE", "TE",
"Translate", "Translate",
"User-Agent", "User-Agent",
"DNT",
"Upgrade-Insecure-Requests"
}) })
.Concat(corsRequestHeaders) .Concat(corsRequestHeaders)
.Select((header, index) => new KnownHeader .Select((header, index) => new KnownHeader
@ -213,8 +112,6 @@ namespace CodeGenerator
PrimaryHeader = requestPrimaryHeaders.Contains("Content-Length") PrimaryHeader = requestPrimaryHeaders.Contains("Content-Length")
}}) }})
.ToArray(); .ToArray();
Debug.Assert(requestHeaders.Length <= 64);
Debug.Assert(requestHeaders.Max(x => x.Index) <= 62);
var responseHeadersExistence = new[] var responseHeadersExistence = new[]
{ {
@ -240,7 +137,7 @@ namespace CodeGenerator
"Access-Control-Expose-Headers", "Access-Control-Expose-Headers",
"Access-Control-Max-Age", "Access-Control-Max-Age",
}; };
var responseHeaders = commonHeaders.Concat(new[] ResponseHeaders = commonHeaders.Concat(new[]
{ {
"Accept-Ranges", "Accept-Ranges",
"Age", "Age",
@ -271,7 +168,7 @@ namespace CodeGenerator
}}) }})
.ToArray(); .ToArray();
var responseTrailers = new[] ResponseTrailers = new[]
{ {
"ETag", "ETag",
} }
@ -284,11 +181,359 @@ namespace CodeGenerator
PrimaryHeader = responsePrimaryHeaders.Contains(header) PrimaryHeader = responsePrimaryHeaders.Contains(header)
}) })
.ToArray(); .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) // 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.Length <= 63);
Debug.Assert(responseHeaders.Count(x => x.Index == 63) == 1); Debug.Assert(responseHeaders.Count(x => x.Index == 63) == 1);
var responseTrailers = ResponseTrailers;
var loops = new[] var loops = new[]
{ {
new new
@ -331,8 +576,10 @@ using System.Collections.Generic;
using System.Buffers; using System.Buffers;
using System.IO.Pipelines; using System.IO.Pipelines;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Microsoft.Extensions.Primitives; using Microsoft.Extensions.Primitives;
using Microsoft.Net.Http.Headers; using Microsoft.Net.Http.Headers;
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure;
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http 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},")} {Each(loop.Bytes, b => $"{b},")}
}};" }};"
: "")} : "")}
private long _bits = 0;
private HeaderReferences _headers; private HeaderReferences _headers;
{Each(loop.Headers.Where(header => header.ExistenceCheck), header => $@" {Each(loop.Headers.Where(header => header.ExistenceCheck), header => $@"
public bool Has{header.Identifier} => {header.TestBit()};")} public bool Has{header.Identifier} => {header.TestBit()};")}
@ -510,8 +755,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
return MaybeUnknown?.Remove(key) ?? false; return MaybeUnknown?.Remove(key) ?? false;
}} }}
{(loop.ClassName != "HttpRequestHeaders" ?
protected override void ClearFast() $@" protected override void ClearFast()
{{ {{
MaybeUnknown?.Clear(); MaybeUnknown?.Clear();
_contentLength = null; _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) protected override bool CopyToFast(KeyValuePair<string, StringValues>[] array, int arrayIndex)
{{ {{
if (arrayIndex < 0) if (arrayIndex < 0)
@ -625,22 +886,63 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
}} }}
}} }}
}} while (tempBits != 0); }} while (tempBits != 0);
}}" : "")} }}" : "")}{(loop.ClassName == "HttpRequestHeaders" ? $@"
{(loop.ClassName == "HttpRequestHeaders" ? $@" [MethodImpl(MethodImplOptions.AggressiveOptimization)]
public unsafe void Append(byte* pKeyBytes, int keyLength, string value) public unsafe void Append(Span<byte> name, Span<byte> value)
{{ {{
var pUB = pKeyBytes; ref byte nameStart = ref MemoryMarshal.GetReference(name);
{AppendSwitch(loop.Headers.Where(h => h.PrimaryHeader).GroupBy(x => x.Name.Length), loop.ClassName)} 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) if (flag != 0)
{{ {{
var pUB = pKeyBytes; // Matched a known header
{AppendSwitch(loop.Headers.Where(h => !h.PrimaryHeader).GroupBy(x => x.Name.Length), loop.ClassName)} 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;
AppendUnknownHeaders(pKeyBytes, keyLength, value); // 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;
}}
}}
}}
// 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 private struct HeaderReferences

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -3,21 +3,20 @@
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Threading.Tasks; using System.Threading.Tasks;
using OpenQA.Selenium; using OpenQA.Selenium;
using OpenQA.Selenium.Chrome; using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.Remote; using OpenQA.Selenium.Remote;
using Xunit;
using Xunit.Abstractions; using Xunit.Abstractions;
namespace Microsoft.AspNetCore.E2ETesting 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 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) 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(); browser.Dispose();
} }
@ -71,6 +71,8 @@ namespace Microsoft.AspNetCore.E2ETesting
return _browsers.GetOrAdd(isolationContext, CreateBrowserAsync, output); return _browsers.GetOrAdd(isolationContext, CreateBrowserAsync, output);
} }
public Task InitializeAsync() => Task.CompletedTask;
private async Task<(IWebDriver browser, ILogs log)> CreateBrowserAsync(string context, ITestOutputHelper output) private async Task<(IWebDriver browser, ILogs log)> CreateBrowserAsync(string context, ITestOutputHelper output)
{ {
var opts = new ChromeOptions(); var opts = new ChromeOptions();
@ -115,7 +117,6 @@ namespace Microsoft.AspNetCore.E2ETesting
driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(1); driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(1);
var logs = new RemoteLogs(driver); var logs = new RemoteLogs(driver);
_browsersToDispose.Add(driver);
return (driver, logs); return (driver, logs);
} }
catch catch

View File

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

View File

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

View File

@ -782,6 +782,9 @@ describe("hubConnection", () => {
expect(newConnectionId).not.toBe(initialConnectionId); expect(newConnectionId).not.toBe(initialConnectionId);
const serverConnectionId = await hubConnection.invoke<string>("GetCallerConnectionId");
expect(newConnectionId).toBe(serverConnectionId);
const postReconnectRedirects = await hubConnection.invoke<number>("GetNumRedirects"); const postReconnectRedirects = await hubConnection.invoke<number>("GetNumRedirects");
expect(postReconnectRedirects).toBeGreaterThan(preReconnectRedirects); 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") { if (typeof EventSource !== "undefined") {
it("allows Server-Sent Events when negotiating for JSON protocol", async (done) => { it("allows Server-Sent Events when negotiating for JSON protocol", async (done) => {
const hubConnection = getConnectionBuilder(undefined, TESTHUB_NOWEBSOCKETS_ENDPOINT_URL) const hubConnection = getConnectionBuilder(undefined, TESTHUB_NOWEBSOCKETS_ENDPOINT_URL)

View File

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

View File

@ -120,6 +120,13 @@ export class HubConnection {
return this.connectionState; 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. /** Starts the connection.
* *
* @returns {Promise<void>} A Promise that resolves when the connection has been successfully established, or rejects with an error. * @returns {Promise<void>} A Promise that resolves when the connection has been successfully established, or rejects with an error.

View File

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

View File

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

View File

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