Merge branch 'release/3.0' => 'master' (#12805)
This commit is contained in:
commit
3148acfb10
|
|
@ -69,6 +69,11 @@ parameters:
|
|||
installJdk: true
|
||||
timeoutInMinutes: 180
|
||||
|
||||
# We need longer than the default amount of 5 minutes to upload our logs/artifacts. (We currently take around 5 mins in the best case).
|
||||
# This makes sure we have time to upload everything in the case of a build timeout - really important for investigating a build
|
||||
# timeout due to test hangs.
|
||||
cancelTimeoutInMinutes: 15
|
||||
|
||||
jobs:
|
||||
- job: ${{ coalesce(parameters.jobName, parameters.agentOs) }}
|
||||
displayName: ${{ coalesce(parameters.jobDisplayName, parameters.agentOs) }}
|
||||
|
|
|
|||
|
|
@ -101,7 +101,6 @@
|
|||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Razor" ProjectPath="$(RepoRoot)src\Razor\Razor\src\Microsoft.AspNetCore.Razor.csproj" RefProjectPath="$(RepoRoot)src\Razor\Razor\ref\Microsoft.AspNetCore.Razor.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Mvc.Abstractions" ProjectPath="$(RepoRoot)src\Mvc\Mvc.Abstractions\src\Microsoft.AspNetCore.Mvc.Abstractions.csproj" RefProjectPath="$(RepoRoot)src\Mvc\Mvc.Abstractions\ref\Microsoft.AspNetCore.Mvc.Abstractions.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Mvc.ApiExplorer" ProjectPath="$(RepoRoot)src\Mvc\Mvc.ApiExplorer\src\Microsoft.AspNetCore.Mvc.ApiExplorer.csproj" RefProjectPath="$(RepoRoot)src\Mvc\Mvc.ApiExplorer\ref\Microsoft.AspNetCore.Mvc.ApiExplorer.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Mvc.Components.Prerendering" ProjectPath="$(RepoRoot)src\Mvc\Mvc.Components.Prerendering\src\Microsoft.AspNetCore.Mvc.Components.Prerendering.csproj" RefProjectPath="$(RepoRoot)src\Mvc\Mvc.Components.Prerendering\ref\Microsoft.AspNetCore.Mvc.Components.Prerendering.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Mvc.Core" ProjectPath="$(RepoRoot)src\Mvc\Mvc.Core\src\Microsoft.AspNetCore.Mvc.Core.csproj" RefProjectPath="$(RepoRoot)src\Mvc\Mvc.Core\ref\Microsoft.AspNetCore.Mvc.Core.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Mvc.Cors" ProjectPath="$(RepoRoot)src\Mvc\Mvc.Cors\src\Microsoft.AspNetCore.Mvc.Cors.csproj" RefProjectPath="$(RepoRoot)src\Mvc\Mvc.Cors\ref\Microsoft.AspNetCore.Mvc.Cors.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Mvc.DataAnnotations" ProjectPath="$(RepoRoot)src\Mvc\Mvc.DataAnnotations\src\Microsoft.AspNetCore.Mvc.DataAnnotations.csproj" RefProjectPath="$(RepoRoot)src\Mvc\Mvc.DataAnnotations\ref\Microsoft.AspNetCore.Mvc.DataAnnotations.csproj" />
|
||||
|
|
|
|||
|
|
@ -73,7 +73,6 @@
|
|||
<AspNetCoreAppReference Include="Microsoft.AspNetCore.Razor" />
|
||||
<AspNetCoreAppReference Include="Microsoft.AspNetCore.Mvc.Abstractions" />
|
||||
<AspNetCoreAppReference Include="Microsoft.AspNetCore.Mvc.ApiExplorer" />
|
||||
<AspNetCoreAppReference Include="Microsoft.AspNetCore.Mvc.Components.Prerendering" />
|
||||
<AspNetCoreAppReference Include="Microsoft.AspNetCore.Mvc.Core" />
|
||||
<AspNetCoreAppReference Include="Microsoft.AspNetCore.Mvc.Cors" />
|
||||
<AspNetCoreAppReference Include="Microsoft.AspNetCore.Mvc.DataAnnotations" />
|
||||
|
|
|
|||
|
|
@ -9,412 +9,412 @@
|
|||
-->
|
||||
<Dependencies>
|
||||
<ProductDependencies>
|
||||
<Dependency Name="Microsoft.AspNetCore.Blazor.Mono" Version="0.10.0-preview8.19372.1">
|
||||
<Dependency Name="Microsoft.AspNetCore.Blazor.Mono" Version="3.0.0-preview9.19379.2">
|
||||
<Uri>https://github.com/aspnet/Blazor</Uri>
|
||||
<Sha>5228d074e954ca0d8e1adb398d6e0e0043f5168e</Sha>
|
||||
<Sha>cd9254a05cfa52defeacd31697d25b2a4ed17510</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.AspNetCore.Razor.Language" Version="3.0.0-preview8.19374.2">
|
||||
<Dependency Name="Microsoft.AspNetCore.Razor.Language" Version="3.0.0-preview9.19402.1">
|
||||
<Uri>https://github.com/aspnet/AspNetCore-Tooling</Uri>
|
||||
<Sha>cddc572f0bff131346550fb507e5bb970a143be9</Sha>
|
||||
<Sha>f039aa935462163dead64ca2d6f9c6d27f4e290b</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.AspNetCore.Mvc.Razor.Extensions" Version="3.0.0-preview8.19374.2">
|
||||
<Dependency Name="Microsoft.AspNetCore.Mvc.Razor.Extensions" Version="3.0.0-preview9.19402.1">
|
||||
<Uri>https://github.com/aspnet/AspNetCore-Tooling</Uri>
|
||||
<Sha>cddc572f0bff131346550fb507e5bb970a143be9</Sha>
|
||||
<Sha>f039aa935462163dead64ca2d6f9c6d27f4e290b</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.CodeAnalysis.Razor" Version="3.0.0-preview8.19374.2">
|
||||
<Dependency Name="Microsoft.CodeAnalysis.Razor" Version="3.0.0-preview9.19402.1">
|
||||
<Uri>https://github.com/aspnet/AspNetCore-Tooling</Uri>
|
||||
<Sha>cddc572f0bff131346550fb507e5bb970a143be9</Sha>
|
||||
<Sha>f039aa935462163dead64ca2d6f9c6d27f4e290b</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.NET.Sdk.Razor" Version="3.0.0-preview8.19374.2">
|
||||
<Dependency Name="Microsoft.NET.Sdk.Razor" Version="3.0.0-preview9.19402.1">
|
||||
<Uri>https://github.com/aspnet/AspNetCore-Tooling</Uri>
|
||||
<Sha>cddc572f0bff131346550fb507e5bb970a143be9</Sha>
|
||||
<Sha>f039aa935462163dead64ca2d6f9c6d27f4e290b</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="dotnet-ef" Version="3.0.0-preview8.19375.5">
|
||||
<Dependency Name="dotnet-ef" Version="3.0.0-preview9.19402.9">
|
||||
<Uri>https://github.com/aspnet/EntityFrameworkCore</Uri>
|
||||
<Sha>c39853fea2f835b6f06cf7fb23fa45f1115c5a12</Sha>
|
||||
<Sha>49f9f7632c742108e5652f182922cc35c19c9162</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.EntityFrameworkCore.InMemory" Version="3.0.0-preview8.19375.5">
|
||||
<Dependency Name="Microsoft.EntityFrameworkCore.InMemory" Version="3.0.0-preview9.19402.9">
|
||||
<Uri>https://github.com/aspnet/EntityFrameworkCore</Uri>
|
||||
<Sha>c39853fea2f835b6f06cf7fb23fa45f1115c5a12</Sha>
|
||||
<Sha>49f9f7632c742108e5652f182922cc35c19c9162</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.EntityFrameworkCore.Relational" Version="3.0.0-preview8.19375.5">
|
||||
<Dependency Name="Microsoft.EntityFrameworkCore.Relational" Version="3.0.0-preview9.19402.9">
|
||||
<Uri>https://github.com/aspnet/EntityFrameworkCore</Uri>
|
||||
<Sha>c39853fea2f835b6f06cf7fb23fa45f1115c5a12</Sha>
|
||||
<Sha>49f9f7632c742108e5652f182922cc35c19c9162</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.EntityFrameworkCore.Sqlite" Version="3.0.0-preview8.19375.5">
|
||||
<Dependency Name="Microsoft.EntityFrameworkCore.Sqlite" Version="3.0.0-preview9.19402.9">
|
||||
<Uri>https://github.com/aspnet/EntityFrameworkCore</Uri>
|
||||
<Sha>c39853fea2f835b6f06cf7fb23fa45f1115c5a12</Sha>
|
||||
<Sha>49f9f7632c742108e5652f182922cc35c19c9162</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.EntityFrameworkCore.SqlServer" Version="3.0.0-preview8.19375.5">
|
||||
<Dependency Name="Microsoft.EntityFrameworkCore.SqlServer" Version="3.0.0-preview9.19402.9">
|
||||
<Uri>https://github.com/aspnet/EntityFrameworkCore</Uri>
|
||||
<Sha>c39853fea2f835b6f06cf7fb23fa45f1115c5a12</Sha>
|
||||
<Sha>49f9f7632c742108e5652f182922cc35c19c9162</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.EntityFrameworkCore.Tools" Version="3.0.0-preview8.19375.5">
|
||||
<Dependency Name="Microsoft.EntityFrameworkCore.Tools" Version="3.0.0-preview9.19402.9">
|
||||
<Uri>https://github.com/aspnet/EntityFrameworkCore</Uri>
|
||||
<Sha>c39853fea2f835b6f06cf7fb23fa45f1115c5a12</Sha>
|
||||
<Sha>49f9f7632c742108e5652f182922cc35c19c9162</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.EntityFrameworkCore" Version="3.0.0-preview8.19375.5">
|
||||
<Dependency Name="Microsoft.EntityFrameworkCore" Version="3.0.0-preview9.19402.9">
|
||||
<Uri>https://github.com/aspnet/EntityFrameworkCore</Uri>
|
||||
<Sha>c39853fea2f835b6f06cf7fb23fa45f1115c5a12</Sha>
|
||||
<Sha>49f9f7632c742108e5652f182922cc35c19c9162</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.AspNetCore.Analyzer.Testing" Version="3.0.0-preview8.19374.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.AspNetCore.Analyzer.Testing" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>45647cef001961bd82c8ac4c112d24d4254e44cf</Sha>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.AspNetCore.BenchmarkRunner.Sources" Version="3.0.0-preview8.19374.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.AspNetCore.BenchmarkRunner.Sources" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>45647cef001961bd82c8ac4c112d24d4254e44cf</Sha>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.ActivatorUtilities.Sources" Version="3.0.0-preview8.19374.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.ActivatorUtilities.Sources" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>45647cef001961bd82c8ac4c112d24d4254e44cf</Sha>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Caching.Abstractions" Version="3.0.0-preview8.19374.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.Caching.Abstractions" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>45647cef001961bd82c8ac4c112d24d4254e44cf</Sha>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Caching.Memory" Version="3.0.0-preview8.19374.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.Caching.Memory" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>45647cef001961bd82c8ac4c112d24d4254e44cf</Sha>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Caching.SqlServer" Version="3.0.0-preview8.19374.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.Caching.SqlServer" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>45647cef001961bd82c8ac4c112d24d4254e44cf</Sha>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Caching.StackExchangeRedis" Version="3.0.0-preview8.19374.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.Caching.StackExchangeRedis" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>45647cef001961bd82c8ac4c112d24d4254e44cf</Sha>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.CommandLineUtils.Sources" Version="3.0.0-preview8.19374.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.CommandLineUtils.Sources" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>45647cef001961bd82c8ac4c112d24d4254e44cf</Sha>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Configuration.Abstractions" Version="3.0.0-preview8.19374.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.Configuration.Abstractions" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>45647cef001961bd82c8ac4c112d24d4254e44cf</Sha>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Configuration.AzureKeyVault" Version="3.0.0-preview8.19374.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.Configuration.AzureKeyVault" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>45647cef001961bd82c8ac4c112d24d4254e44cf</Sha>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Configuration.Binder" Version="3.0.0-preview8.19374.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.Configuration.Binder" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>45647cef001961bd82c8ac4c112d24d4254e44cf</Sha>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Configuration.CommandLine" Version="3.0.0-preview8.19374.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.Configuration.CommandLine" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>45647cef001961bd82c8ac4c112d24d4254e44cf</Sha>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="3.0.0-preview8.19374.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>45647cef001961bd82c8ac4c112d24d4254e44cf</Sha>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Configuration.FileExtensions" Version="3.0.0-preview8.19374.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.Configuration.FileExtensions" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>45647cef001961bd82c8ac4c112d24d4254e44cf</Sha>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Configuration.Ini" Version="3.0.0-preview8.19374.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.Configuration.Ini" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>45647cef001961bd82c8ac4c112d24d4254e44cf</Sha>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Configuration.Json" Version="3.0.0-preview8.19374.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.Configuration.Json" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>45647cef001961bd82c8ac4c112d24d4254e44cf</Sha>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Configuration.KeyPerFile" Version="3.0.0-preview8.19374.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.Configuration.KeyPerFile" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>45647cef001961bd82c8ac4c112d24d4254e44cf</Sha>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Configuration.UserSecrets" Version="3.0.0-preview8.19374.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.Configuration.UserSecrets" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>45647cef001961bd82c8ac4c112d24d4254e44cf</Sha>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Configuration.Xml" Version="3.0.0-preview8.19374.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.Configuration.Xml" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>45647cef001961bd82c8ac4c112d24d4254e44cf</Sha>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Configuration" Version="3.0.0-preview8.19374.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.Configuration" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>45647cef001961bd82c8ac4c112d24d4254e44cf</Sha>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.DependencyInjection.Abstractions" Version="3.0.0-preview8.19374.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.DependencyInjection.Abstractions" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>45647cef001961bd82c8ac4c112d24d4254e44cf</Sha>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.DependencyInjection" Version="3.0.0-preview8.19374.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.DependencyInjection" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>45647cef001961bd82c8ac4c112d24d4254e44cf</Sha>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.DiagnosticAdapter" Version="3.0.0-preview8.19374.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.DiagnosticAdapter" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>45647cef001961bd82c8ac4c112d24d4254e44cf</Sha>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions" Version="3.0.0-preview8.19374.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>45647cef001961bd82c8ac4c112d24d4254e44cf</Sha>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Diagnostics.HealthChecks" Version="3.0.0-preview8.19374.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.Diagnostics.HealthChecks" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>45647cef001961bd82c8ac4c112d24d4254e44cf</Sha>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.FileProviders.Abstractions" Version="3.0.0-preview8.19374.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.FileProviders.Abstractions" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>45647cef001961bd82c8ac4c112d24d4254e44cf</Sha>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.FileProviders.Composite" Version="3.0.0-preview8.19374.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.FileProviders.Composite" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>45647cef001961bd82c8ac4c112d24d4254e44cf</Sha>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.FileProviders.Embedded" Version="3.0.0-preview8.19374.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.FileProviders.Embedded" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>45647cef001961bd82c8ac4c112d24d4254e44cf</Sha>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.FileProviders.Physical" Version="3.0.0-preview8.19374.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.FileProviders.Physical" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>45647cef001961bd82c8ac4c112d24d4254e44cf</Sha>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.FileSystemGlobbing" Version="3.0.0-preview8.19374.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.FileSystemGlobbing" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>45647cef001961bd82c8ac4c112d24d4254e44cf</Sha>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.HashCodeCombiner.Sources" Version="3.0.0-preview8.19374.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.HashCodeCombiner.Sources" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>45647cef001961bd82c8ac4c112d24d4254e44cf</Sha>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Hosting.Abstractions" Version="3.0.0-preview8.19374.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.Hosting.Abstractions" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>45647cef001961bd82c8ac4c112d24d4254e44cf</Sha>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Hosting" Version="3.0.0-preview8.19374.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.Hosting" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>45647cef001961bd82c8ac4c112d24d4254e44cf</Sha>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.HostFactoryResolver.Sources" Version="3.0.0-preview8.19374.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.HostFactoryResolver.Sources" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>45647cef001961bd82c8ac4c112d24d4254e44cf</Sha>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Http" Version="3.0.0-preview8.19374.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.Http" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>45647cef001961bd82c8ac4c112d24d4254e44cf</Sha>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Localization.Abstractions" Version="3.0.0-preview8.19374.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.Localization.Abstractions" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>45647cef001961bd82c8ac4c112d24d4254e44cf</Sha>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Localization" Version="3.0.0-preview8.19374.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.Localization" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>45647cef001961bd82c8ac4c112d24d4254e44cf</Sha>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Logging.Abstractions" Version="3.0.0-preview8.19374.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.Logging.Abstractions" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>45647cef001961bd82c8ac4c112d24d4254e44cf</Sha>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Logging.AzureAppServices" Version="3.0.0-preview8.19374.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.Logging.AzureAppServices" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>45647cef001961bd82c8ac4c112d24d4254e44cf</Sha>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Logging.Configuration" Version="3.0.0-preview8.19374.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.Logging.Configuration" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>45647cef001961bd82c8ac4c112d24d4254e44cf</Sha>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Logging.Console" Version="3.0.0-preview8.19374.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.Logging.Console" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>45647cef001961bd82c8ac4c112d24d4254e44cf</Sha>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Logging.Debug" Version="3.0.0-preview8.19374.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.Logging.Debug" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>45647cef001961bd82c8ac4c112d24d4254e44cf</Sha>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Logging.EventSource" Version="3.0.0-preview8.19374.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.Logging.EventSource" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>45647cef001961bd82c8ac4c112d24d4254e44cf</Sha>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Logging.EventLog" Version="3.0.0-preview8.19374.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.Logging.EventLog" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>45647cef001961bd82c8ac4c112d24d4254e44cf</Sha>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Logging.TraceSource" Version="3.0.0-preview8.19374.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.Logging.TraceSource" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>45647cef001961bd82c8ac4c112d24d4254e44cf</Sha>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Logging.Testing" Version="3.0.0-preview8.19374.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.Logging.Testing" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>45647cef001961bd82c8ac4c112d24d4254e44cf</Sha>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Logging" Version="3.0.0-preview8.19374.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.Logging" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>45647cef001961bd82c8ac4c112d24d4254e44cf</Sha>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.ObjectPool" Version="3.0.0-preview8.19374.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.ObjectPool" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>45647cef001961bd82c8ac4c112d24d4254e44cf</Sha>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Options.ConfigurationExtensions" Version="3.0.0-preview8.19374.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.Options.ConfigurationExtensions" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>45647cef001961bd82c8ac4c112d24d4254e44cf</Sha>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Options.DataAnnotations" Version="3.0.0-preview8.19374.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.Options.DataAnnotations" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>45647cef001961bd82c8ac4c112d24d4254e44cf</Sha>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Options" Version="3.0.0-preview8.19374.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.Options" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>45647cef001961bd82c8ac4c112d24d4254e44cf</Sha>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.ParameterDefaultValue.Sources" Version="3.0.0-preview8.19374.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.ParameterDefaultValue.Sources" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>45647cef001961bd82c8ac4c112d24d4254e44cf</Sha>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Primitives" Version="3.0.0-preview8.19374.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.Primitives" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>45647cef001961bd82c8ac4c112d24d4254e44cf</Sha>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.TypeNameHelper.Sources" Version="3.0.0-preview8.19374.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.TypeNameHelper.Sources" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>45647cef001961bd82c8ac4c112d24d4254e44cf</Sha>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.ValueStopwatch.Sources" Version="3.0.0-preview8.19374.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.ValueStopwatch.Sources" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>45647cef001961bd82c8ac4c112d24d4254e44cf</Sha>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.WebEncoders" Version="3.0.0-preview8.19374.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.WebEncoders" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>45647cef001961bd82c8ac4c112d24d4254e44cf</Sha>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Internal.Extensions.Refs" Version="3.0.0-preview8.19374.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Internal.Extensions.Refs" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>45647cef001961bd82c8ac4c112d24d4254e44cf</Sha>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.JSInterop" Version="3.0.0-preview8.19374.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.JSInterop" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>45647cef001961bd82c8ac4c112d24d4254e44cf</Sha>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Mono.WebAssembly.Interop" Version="3.0.0-preview8.19374.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Mono.WebAssembly.Interop" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>45647cef001961bd82c8ac4c112d24d4254e44cf</Sha>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Bcl.AsyncInterfaces" Version="1.0.0-preview8.19372.8" CoherentParentDependency="Microsoft.NETCore.App.Runtime.win-x64">
|
||||
<Dependency Name="Microsoft.Bcl.AsyncInterfaces" Version="1.0.0-preview8.19378.8" CoherentParentDependency="Microsoft.NETCore.App.Runtime.win-x64">
|
||||
<Uri>https://github.com/dotnet/corefx</Uri>
|
||||
<Sha>d594cb2dbc5027d7e996491b0722c5be5204460f</Sha>
|
||||
<Sha>80f411d58df8338ccd9430900b541a037a9cb383</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.CSharp" Version="4.6.0-preview8.19372.8" CoherentParentDependency="Microsoft.NETCore.App.Runtime.win-x64">
|
||||
<Dependency Name="Microsoft.CSharp" Version="4.6.0-preview8.19378.8" CoherentParentDependency="Microsoft.NETCore.App.Runtime.win-x64">
|
||||
<Uri>https://github.com/dotnet/corefx</Uri>
|
||||
<Sha>d594cb2dbc5027d7e996491b0722c5be5204460f</Sha>
|
||||
<Sha>80f411d58df8338ccd9430900b541a037a9cb383</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Win32.Registry" Version="4.6.0-preview8.19372.8" CoherentParentDependency="Microsoft.NETCore.App.Runtime.win-x64">
|
||||
<Dependency Name="Microsoft.Win32.Registry" Version="4.6.0-preview8.19378.8" CoherentParentDependency="Microsoft.NETCore.App.Runtime.win-x64">
|
||||
<Uri>https://github.com/dotnet/corefx</Uri>
|
||||
<Sha>d594cb2dbc5027d7e996491b0722c5be5204460f</Sha>
|
||||
<Sha>80f411d58df8338ccd9430900b541a037a9cb383</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Win32.SystemEvents" Version="4.6.0-preview8.19372.8" CoherentParentDependency="Microsoft.NETCore.App.Runtime.win-x64">
|
||||
<Dependency Name="Microsoft.Win32.SystemEvents" Version="4.6.0-preview8.19378.8" CoherentParentDependency="Microsoft.NETCore.App.Runtime.win-x64">
|
||||
<Uri>https://github.com/dotnet/corefx</Uri>
|
||||
<Sha>d594cb2dbc5027d7e996491b0722c5be5204460f</Sha>
|
||||
<Sha>80f411d58df8338ccd9430900b541a037a9cb383</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="System.ComponentModel.Annotations" Version="4.6.0-preview8.19372.8" CoherentParentDependency="Microsoft.NETCore.App.Runtime.win-x64">
|
||||
<Dependency Name="System.ComponentModel.Annotations" Version="4.6.0-preview8.19378.8" CoherentParentDependency="Microsoft.NETCore.App.Runtime.win-x64">
|
||||
<Uri>https://github.com/dotnet/corefx</Uri>
|
||||
<Sha>d594cb2dbc5027d7e996491b0722c5be5204460f</Sha>
|
||||
<Sha>80f411d58df8338ccd9430900b541a037a9cb383</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="System.Data.SqlClient" Version="4.7.0-preview6.19264.9" CoherentParentDependency="Microsoft.NETCore.App.Runtime.win-x64" Pinned="true">
|
||||
<Uri>https://github.com/dotnet/corefx</Uri>
|
||||
<Sha>a28176b5ec68b6da1472934fe9493790d1665cae</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="System.Diagnostics.EventLog" Version="4.6.0-preview8.19372.8" CoherentParentDependency="Microsoft.NETCore.App.Runtime.win-x64">
|
||||
<Dependency Name="System.Diagnostics.EventLog" Version="4.6.0-preview8.19378.8" CoherentParentDependency="Microsoft.NETCore.App.Runtime.win-x64">
|
||||
<Uri>https://github.com/dotnet/corefx</Uri>
|
||||
<Sha>d594cb2dbc5027d7e996491b0722c5be5204460f</Sha>
|
||||
<Sha>80f411d58df8338ccd9430900b541a037a9cb383</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="System.Drawing.Common" Version="4.6.0-preview8.19372.8" CoherentParentDependency="Microsoft.NETCore.App.Runtime.win-x64">
|
||||
<Dependency Name="System.Drawing.Common" Version="4.6.0-preview8.19378.8" CoherentParentDependency="Microsoft.NETCore.App.Runtime.win-x64">
|
||||
<Uri>https://github.com/dotnet/corefx</Uri>
|
||||
<Sha>d594cb2dbc5027d7e996491b0722c5be5204460f</Sha>
|
||||
<Sha>80f411d58df8338ccd9430900b541a037a9cb383</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="System.IO.Pipelines" Version="4.6.0-preview8.19372.8" CoherentParentDependency="Microsoft.NETCore.App.Runtime.win-x64">
|
||||
<Dependency Name="System.IO.Pipelines" Version="4.6.0-preview8.19378.8" CoherentParentDependency="Microsoft.NETCore.App.Runtime.win-x64">
|
||||
<Uri>https://github.com/dotnet/corefx</Uri>
|
||||
<Sha>d594cb2dbc5027d7e996491b0722c5be5204460f</Sha>
|
||||
<Sha>80f411d58df8338ccd9430900b541a037a9cb383</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="System.Net.Http.WinHttpHandler" Version="4.6.0-preview8.19372.8" CoherentParentDependency="Microsoft.NETCore.App.Runtime.win-x64">
|
||||
<Dependency Name="System.Net.Http.WinHttpHandler" Version="4.6.0-preview8.19378.8" CoherentParentDependency="Microsoft.NETCore.App.Runtime.win-x64">
|
||||
<Uri>https://github.com/dotnet/corefx</Uri>
|
||||
<Sha>d594cb2dbc5027d7e996491b0722c5be5204460f</Sha>
|
||||
<Sha>80f411d58df8338ccd9430900b541a037a9cb383</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="System.Net.WebSockets.WebSocketProtocol" Version="4.6.0-preview8.19372.8" CoherentParentDependency="Microsoft.NETCore.App.Runtime.win-x64">
|
||||
<Dependency Name="System.Net.WebSockets.WebSocketProtocol" Version="4.6.0-preview8.19378.8" CoherentParentDependency="Microsoft.NETCore.App.Runtime.win-x64">
|
||||
<Uri>https://github.com/dotnet/corefx</Uri>
|
||||
<Sha>d594cb2dbc5027d7e996491b0722c5be5204460f</Sha>
|
||||
<Sha>80f411d58df8338ccd9430900b541a037a9cb383</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="System.Reflection.Metadata" Version="1.7.0-preview8.19372.8" CoherentParentDependency="Microsoft.NETCore.App.Runtime.win-x64">
|
||||
<Dependency Name="System.Reflection.Metadata" Version="1.7.0-preview8.19378.8" CoherentParentDependency="Microsoft.NETCore.App.Runtime.win-x64">
|
||||
<Uri>https://github.com/dotnet/corefx</Uri>
|
||||
<Sha>d594cb2dbc5027d7e996491b0722c5be5204460f</Sha>
|
||||
<Sha>80f411d58df8338ccd9430900b541a037a9cb383</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="System.Runtime.CompilerServices.Unsafe" Version="4.6.0-preview8.19372.8" CoherentParentDependency="Microsoft.NETCore.App.Runtime.win-x64">
|
||||
<Dependency Name="System.Runtime.CompilerServices.Unsafe" Version="4.6.0-preview8.19378.8" CoherentParentDependency="Microsoft.NETCore.App.Runtime.win-x64">
|
||||
<Uri>https://github.com/dotnet/corefx</Uri>
|
||||
<Sha>d594cb2dbc5027d7e996491b0722c5be5204460f</Sha>
|
||||
<Sha>80f411d58df8338ccd9430900b541a037a9cb383</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="System.Security.Cryptography.Cng" Version="4.6.0-preview8.19372.8" CoherentParentDependency="Microsoft.NETCore.App.Runtime.win-x64">
|
||||
<Dependency Name="System.Security.Cryptography.Cng" Version="4.6.0-preview8.19378.8" CoherentParentDependency="Microsoft.NETCore.App.Runtime.win-x64">
|
||||
<Uri>https://github.com/dotnet/corefx</Uri>
|
||||
<Sha>d594cb2dbc5027d7e996491b0722c5be5204460f</Sha>
|
||||
<Sha>80f411d58df8338ccd9430900b541a037a9cb383</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="System.Security.Cryptography.Pkcs" Version="4.6.0-preview8.19372.8" CoherentParentDependency="Microsoft.NETCore.App.Runtime.win-x64">
|
||||
<Dependency Name="System.Security.Cryptography.Pkcs" Version="4.6.0-preview8.19378.8" CoherentParentDependency="Microsoft.NETCore.App.Runtime.win-x64">
|
||||
<Uri>https://github.com/dotnet/corefx</Uri>
|
||||
<Sha>d594cb2dbc5027d7e996491b0722c5be5204460f</Sha>
|
||||
<Sha>80f411d58df8338ccd9430900b541a037a9cb383</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="System.Security.Cryptography.Xml" Version="4.6.0-preview8.19372.8" CoherentParentDependency="Microsoft.NETCore.App.Runtime.win-x64">
|
||||
<Dependency Name="System.Security.Cryptography.Xml" Version="4.6.0-preview8.19378.8" CoherentParentDependency="Microsoft.NETCore.App.Runtime.win-x64">
|
||||
<Uri>https://github.com/dotnet/corefx</Uri>
|
||||
<Sha>d594cb2dbc5027d7e996491b0722c5be5204460f</Sha>
|
||||
<Sha>80f411d58df8338ccd9430900b541a037a9cb383</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="System.Security.Permissions" Version="4.6.0-preview8.19372.8" CoherentParentDependency="Microsoft.NETCore.App.Runtime.win-x64">
|
||||
<Dependency Name="System.Security.Permissions" Version="4.6.0-preview8.19378.8" CoherentParentDependency="Microsoft.NETCore.App.Runtime.win-x64">
|
||||
<Uri>https://github.com/dotnet/corefx</Uri>
|
||||
<Sha>d594cb2dbc5027d7e996491b0722c5be5204460f</Sha>
|
||||
<Sha>80f411d58df8338ccd9430900b541a037a9cb383</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="System.Security.Principal.Windows" Version="4.6.0-preview8.19372.8" CoherentParentDependency="Microsoft.NETCore.App.Runtime.win-x64">
|
||||
<Dependency Name="System.Security.Principal.Windows" Version="4.6.0-preview8.19378.8" CoherentParentDependency="Microsoft.NETCore.App.Runtime.win-x64">
|
||||
<Uri>https://github.com/dotnet/corefx</Uri>
|
||||
<Sha>d594cb2dbc5027d7e996491b0722c5be5204460f</Sha>
|
||||
<Sha>80f411d58df8338ccd9430900b541a037a9cb383</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="System.ServiceProcess.ServiceController" Version="4.6.0-preview8.19372.8" CoherentParentDependency="Microsoft.NETCore.App.Runtime.win-x64">
|
||||
<Dependency Name="System.ServiceProcess.ServiceController" Version="4.6.0-preview8.19378.8" CoherentParentDependency="Microsoft.NETCore.App.Runtime.win-x64">
|
||||
<Uri>https://github.com/dotnet/corefx</Uri>
|
||||
<Sha>d594cb2dbc5027d7e996491b0722c5be5204460f</Sha>
|
||||
<Sha>80f411d58df8338ccd9430900b541a037a9cb383</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="System.Text.Encodings.Web" Version="4.6.0-preview8.19372.8" CoherentParentDependency="Microsoft.NETCore.App.Runtime.win-x64">
|
||||
<Dependency Name="System.Text.Encodings.Web" Version="4.6.0-preview8.19378.8" CoherentParentDependency="Microsoft.NETCore.App.Runtime.win-x64">
|
||||
<Uri>https://github.com/dotnet/corefx</Uri>
|
||||
<Sha>d594cb2dbc5027d7e996491b0722c5be5204460f</Sha>
|
||||
<Sha>80f411d58df8338ccd9430900b541a037a9cb383</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="System.Text.Json" Version="4.6.0-preview8.19372.8" CoherentParentDependency="Microsoft.NETCore.App.Runtime.win-x64">
|
||||
<Dependency Name="System.Text.Json" Version="4.6.0-preview8.19378.8" CoherentParentDependency="Microsoft.NETCore.App.Runtime.win-x64">
|
||||
<Uri>https://github.com/dotnet/corefx</Uri>
|
||||
<Sha>d594cb2dbc5027d7e996491b0722c5be5204460f</Sha>
|
||||
<Sha>80f411d58df8338ccd9430900b541a037a9cb383</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="System.Threading.Channels" Version="4.6.0-preview8.19372.8" CoherentParentDependency="Microsoft.NETCore.App.Runtime.win-x64">
|
||||
<Dependency Name="System.Threading.Channels" Version="4.6.0-preview8.19378.8" CoherentParentDependency="Microsoft.NETCore.App.Runtime.win-x64">
|
||||
<Uri>https://github.com/dotnet/corefx</Uri>
|
||||
<Sha>d594cb2dbc5027d7e996491b0722c5be5204460f</Sha>
|
||||
<Sha>80f411d58df8338ccd9430900b541a037a9cb383</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="System.Windows.Extensions" Version="4.6.0-preview8.19372.8" CoherentParentDependency="Microsoft.NETCore.App.Runtime.win-x64">
|
||||
<Dependency Name="System.Windows.Extensions" Version="4.6.0-preview8.19378.8" CoherentParentDependency="Microsoft.NETCore.App.Runtime.win-x64">
|
||||
<Uri>https://github.com/dotnet/corefx</Uri>
|
||||
<Sha>d594cb2dbc5027d7e996491b0722c5be5204460f</Sha>
|
||||
<Sha>80f411d58df8338ccd9430900b541a037a9cb383</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.DependencyModel" Version="3.0.0-preview8-28373-17" CoherentParentDependency="Microsoft.Extensions.Logging">
|
||||
<Dependency Name="Microsoft.Extensions.DependencyModel" Version="3.0.0-preview8-28379-05" CoherentParentDependency="Microsoft.Extensions.Logging">
|
||||
<Uri>https://github.com/dotnet/core-setup</Uri>
|
||||
<Sha>5d8d5e866113c9f144136a04222f191456dfff1d</Sha>
|
||||
<Sha>d15a0adeb874801e7bfaa4fbbb306a2efa268497</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.NETCore.App.Ref" Version="3.0.0-preview8-28373-17" CoherentParentDependency="Microsoft.Extensions.Logging">
|
||||
<Dependency Name="Microsoft.NETCore.App.Ref" Version="3.0.0-preview8-28379-05" CoherentParentDependency="Microsoft.Extensions.Logging">
|
||||
<Uri>https://github.com/dotnet/core-setup</Uri>
|
||||
<Sha>5d8d5e866113c9f144136a04222f191456dfff1d</Sha>
|
||||
<Sha>d15a0adeb874801e7bfaa4fbbb306a2efa268497</Sha>
|
||||
</Dependency>
|
||||
<!--
|
||||
Win-x64 is used here because we have picked an arbitrary runtime identifier to flow the version of the latest NETCore.App runtime.
|
||||
All Runtime.$rid packages should have the same version.
|
||||
-->
|
||||
<Dependency Name="Microsoft.NETCore.App.Runtime.win-x64" Version="3.0.0-preview8-28373-17" CoherentParentDependency="Microsoft.Extensions.Logging">
|
||||
<Dependency Name="Microsoft.NETCore.App.Runtime.win-x64" Version="3.0.0-preview8-28379-05" CoherentParentDependency="Microsoft.Extensions.Logging">
|
||||
<Uri>https://github.com/dotnet/core-setup</Uri>
|
||||
<Sha>5d8d5e866113c9f144136a04222f191456dfff1d</Sha>
|
||||
<Sha>d15a0adeb874801e7bfaa4fbbb306a2efa268497</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="NETStandard.Library.Ref" Version="2.1.0-preview8-28373-17" CoherentParentDependency="Microsoft.Extensions.Logging">
|
||||
<Dependency Name="NETStandard.Library.Ref" Version="2.1.0-preview8-28379-05" CoherentParentDependency="Microsoft.Extensions.Logging">
|
||||
<Uri>https://github.com/dotnet/core-setup</Uri>
|
||||
<Sha>5d8d5e866113c9f144136a04222f191456dfff1d</Sha>
|
||||
<Sha>d15a0adeb874801e7bfaa4fbbb306a2efa268497</Sha>
|
||||
</Dependency>
|
||||
</ProductDependencies>
|
||||
<ToolsetDependencies>
|
||||
<!-- Listed explicitly to workaround https://github.com/dotnet/cli/issues/10528 -->
|
||||
<Dependency Name="Microsoft.NETCore.Platforms" Version="3.0.0-preview8.19372.8" CoherentParentDependency="Microsoft.NETCore.App.Runtime.win-x64">
|
||||
<Dependency Name="Microsoft.NETCore.Platforms" Version="3.0.0-preview8.19378.8" CoherentParentDependency="Microsoft.NETCore.App.Runtime.win-x64">
|
||||
<Uri>https://github.com/dotnet/corefx</Uri>
|
||||
<Sha>d594cb2dbc5027d7e996491b0722c5be5204460f</Sha>
|
||||
<Sha>80f411d58df8338ccd9430900b541a037a9cb383</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Internal.AspNetCore.Analyzers" Version="3.0.0-preview8.19374.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Internal.AspNetCore.Analyzers" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>45647cef001961bd82c8ac4c112d24d4254e44cf</Sha>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.DotNet.GenAPI" Version="1.0.0-beta.19369.2">
|
||||
<Uri>https://github.com/dotnet/arcade</Uri>
|
||||
|
|
@ -428,13 +428,13 @@
|
|||
<Uri>https://github.com/dotnet/arcade</Uri>
|
||||
<Sha>a190d4865fe3c86a168ec49c4fc61c90c96ae051</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.AspNetCore.Testing" Version="3.0.0-preview8.19374.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.AspNetCore.Testing" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>45647cef001961bd82c8ac4c112d24d4254e44cf</Sha>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Net.Compilers.Toolset" Version="3.3.0-beta2-19374-02" CoherentParentDependency="Microsoft.Extensions.Logging">
|
||||
<Dependency Name="Microsoft.Net.Compilers.Toolset" Version="3.3.0-beta3-19401-01" CoherentParentDependency="Microsoft.Extensions.Logging">
|
||||
<Uri>https://github.com/dotnet/roslyn</Uri>
|
||||
<Sha>e4e7c09bc4d22648b1a6193b3bf645b0aa8a23ea</Sha>
|
||||
<Sha>e9b4c66fb2f26bca02d4a718c48c1c39e9963c9f</Sha>
|
||||
</Dependency>
|
||||
</ToolsetDependencies>
|
||||
</Dependencies>
|
||||
|
|
|
|||
|
|
@ -57,115 +57,115 @@
|
|||
<!-- Packages from dotnet/arcade -->
|
||||
<MicrosoftDotNetGenAPIPackageVersion>1.0.0-beta.19369.2</MicrosoftDotNetGenAPIPackageVersion>
|
||||
<!-- Packages from dotnet/roslyn -->
|
||||
<MicrosoftNetCompilersToolsetPackageVersion>3.3.0-beta2-19374-02</MicrosoftNetCompilersToolsetPackageVersion>
|
||||
<MicrosoftNetCompilersToolsetPackageVersion>3.3.0-beta3-19401-01</MicrosoftNetCompilersToolsetPackageVersion>
|
||||
<!-- Packages from dotnet/core-setup -->
|
||||
<MicrosoftExtensionsDependencyModelPackageVersion>3.0.0-preview8-28373-17</MicrosoftExtensionsDependencyModelPackageVersion>
|
||||
<MicrosoftNETCoreAppRefPackageVersion>3.0.0-preview8-28373-17</MicrosoftNETCoreAppRefPackageVersion>
|
||||
<MicrosoftNETCoreAppRuntimewinx64PackageVersion>3.0.0-preview8-28373-17</MicrosoftNETCoreAppRuntimewinx64PackageVersion>
|
||||
<NETStandardLibraryRefPackageVersion>2.1.0-preview8-28373-17</NETStandardLibraryRefPackageVersion>
|
||||
<MicrosoftExtensionsDependencyModelPackageVersion>3.0.0-preview8-28379-05</MicrosoftExtensionsDependencyModelPackageVersion>
|
||||
<MicrosoftNETCoreAppRefPackageVersion>3.0.0-preview8-28379-05</MicrosoftNETCoreAppRefPackageVersion>
|
||||
<MicrosoftNETCoreAppRuntimewinx64PackageVersion>3.0.0-preview8-28379-05</MicrosoftNETCoreAppRuntimewinx64PackageVersion>
|
||||
<NETStandardLibraryRefPackageVersion>2.1.0-preview8-28379-05</NETStandardLibraryRefPackageVersion>
|
||||
<!-- Packages from dotnet/corefx -->
|
||||
<MicrosoftBclAsyncInterfacesPackageVersion>1.0.0-preview8.19372.8</MicrosoftBclAsyncInterfacesPackageVersion>
|
||||
<MicrosoftCSharpPackageVersion>4.6.0-preview8.19372.8</MicrosoftCSharpPackageVersion>
|
||||
<MicrosoftWin32RegistryPackageVersion>4.6.0-preview8.19372.8</MicrosoftWin32RegistryPackageVersion>
|
||||
<MicrosoftWin32SystemEventsPackageVersion>4.6.0-preview8.19372.8</MicrosoftWin32SystemEventsPackageVersion>
|
||||
<SystemComponentModelAnnotationsPackageVersion>4.6.0-preview8.19372.8</SystemComponentModelAnnotationsPackageVersion>
|
||||
<MicrosoftBclAsyncInterfacesPackageVersion>1.0.0-preview8.19378.8</MicrosoftBclAsyncInterfacesPackageVersion>
|
||||
<MicrosoftCSharpPackageVersion>4.6.0-preview8.19378.8</MicrosoftCSharpPackageVersion>
|
||||
<MicrosoftWin32RegistryPackageVersion>4.6.0-preview8.19378.8</MicrosoftWin32RegistryPackageVersion>
|
||||
<MicrosoftWin32SystemEventsPackageVersion>4.6.0-preview8.19378.8</MicrosoftWin32SystemEventsPackageVersion>
|
||||
<SystemComponentModelAnnotationsPackageVersion>4.6.0-preview8.19378.8</SystemComponentModelAnnotationsPackageVersion>
|
||||
<SystemDataSqlClientPackageVersion>4.7.0-preview6.19264.9</SystemDataSqlClientPackageVersion>
|
||||
<SystemDiagnosticsEventLogPackageVersion>4.6.0-preview8.19372.8</SystemDiagnosticsEventLogPackageVersion>
|
||||
<SystemDrawingCommonPackageVersion>4.6.0-preview8.19372.8</SystemDrawingCommonPackageVersion>
|
||||
<SystemIOPipelinesPackageVersion>4.6.0-preview8.19372.8</SystemIOPipelinesPackageVersion>
|
||||
<SystemNetHttpWinHttpHandlerPackageVersion>4.6.0-preview8.19372.8</SystemNetHttpWinHttpHandlerPackageVersion>
|
||||
<SystemNetWebSocketsWebSocketProtocolPackageVersion>4.6.0-preview8.19372.8</SystemNetWebSocketsWebSocketProtocolPackageVersion>
|
||||
<SystemReflectionMetadataPackageVersion>1.7.0-preview8.19372.8</SystemReflectionMetadataPackageVersion>
|
||||
<SystemRuntimeCompilerServicesUnsafePackageVersion>4.6.0-preview8.19372.8</SystemRuntimeCompilerServicesUnsafePackageVersion>
|
||||
<SystemSecurityCryptographyCngPackageVersion>4.6.0-preview8.19372.8</SystemSecurityCryptographyCngPackageVersion>
|
||||
<SystemSecurityCryptographyPkcsPackageVersion>4.6.0-preview8.19372.8</SystemSecurityCryptographyPkcsPackageVersion>
|
||||
<SystemSecurityCryptographyXmlPackageVersion>4.6.0-preview8.19372.8</SystemSecurityCryptographyXmlPackageVersion>
|
||||
<SystemSecurityPermissionsPackageVersion>4.6.0-preview8.19372.8</SystemSecurityPermissionsPackageVersion>
|
||||
<SystemSecurityPrincipalWindowsPackageVersion>4.6.0-preview8.19372.8</SystemSecurityPrincipalWindowsPackageVersion>
|
||||
<SystemServiceProcessServiceControllerPackageVersion>4.6.0-preview8.19372.8</SystemServiceProcessServiceControllerPackageVersion>
|
||||
<SystemTextEncodingsWebPackageVersion>4.6.0-preview8.19372.8</SystemTextEncodingsWebPackageVersion>
|
||||
<SystemTextJsonPackageVersion>4.6.0-preview8.19372.8</SystemTextJsonPackageVersion>
|
||||
<SystemThreadingChannelsPackageVersion>4.6.0-preview8.19372.8</SystemThreadingChannelsPackageVersion>
|
||||
<SystemWindowsExtensionsPackageVersion>4.6.0-preview8.19372.8</SystemWindowsExtensionsPackageVersion>
|
||||
<SystemDiagnosticsEventLogPackageVersion>4.6.0-preview8.19378.8</SystemDiagnosticsEventLogPackageVersion>
|
||||
<SystemDrawingCommonPackageVersion>4.6.0-preview8.19378.8</SystemDrawingCommonPackageVersion>
|
||||
<SystemIOPipelinesPackageVersion>4.6.0-preview8.19378.8</SystemIOPipelinesPackageVersion>
|
||||
<SystemNetHttpWinHttpHandlerPackageVersion>4.6.0-preview8.19378.8</SystemNetHttpWinHttpHandlerPackageVersion>
|
||||
<SystemNetWebSocketsWebSocketProtocolPackageVersion>4.6.0-preview8.19378.8</SystemNetWebSocketsWebSocketProtocolPackageVersion>
|
||||
<SystemReflectionMetadataPackageVersion>1.7.0-preview8.19378.8</SystemReflectionMetadataPackageVersion>
|
||||
<SystemRuntimeCompilerServicesUnsafePackageVersion>4.6.0-preview8.19378.8</SystemRuntimeCompilerServicesUnsafePackageVersion>
|
||||
<SystemSecurityCryptographyCngPackageVersion>4.6.0-preview8.19378.8</SystemSecurityCryptographyCngPackageVersion>
|
||||
<SystemSecurityCryptographyPkcsPackageVersion>4.6.0-preview8.19378.8</SystemSecurityCryptographyPkcsPackageVersion>
|
||||
<SystemSecurityCryptographyXmlPackageVersion>4.6.0-preview8.19378.8</SystemSecurityCryptographyXmlPackageVersion>
|
||||
<SystemSecurityPermissionsPackageVersion>4.6.0-preview8.19378.8</SystemSecurityPermissionsPackageVersion>
|
||||
<SystemSecurityPrincipalWindowsPackageVersion>4.6.0-preview8.19378.8</SystemSecurityPrincipalWindowsPackageVersion>
|
||||
<SystemServiceProcessServiceControllerPackageVersion>4.6.0-preview8.19378.8</SystemServiceProcessServiceControllerPackageVersion>
|
||||
<SystemTextEncodingsWebPackageVersion>4.6.0-preview8.19378.8</SystemTextEncodingsWebPackageVersion>
|
||||
<SystemTextJsonPackageVersion>4.6.0-preview8.19378.8</SystemTextJsonPackageVersion>
|
||||
<SystemThreadingChannelsPackageVersion>4.6.0-preview8.19378.8</SystemThreadingChannelsPackageVersion>
|
||||
<SystemWindowsExtensionsPackageVersion>4.6.0-preview8.19378.8</SystemWindowsExtensionsPackageVersion>
|
||||
<!-- Only listed explicitly to workaround https://github.com/dotnet/cli/issues/10528 -->
|
||||
<MicrosoftNETCorePlatformsPackageVersion>3.0.0-preview8.19372.8</MicrosoftNETCorePlatformsPackageVersion>
|
||||
<MicrosoftNETCorePlatformsPackageVersion>3.0.0-preview8.19378.8</MicrosoftNETCorePlatformsPackageVersion>
|
||||
<!-- Packages from aspnet/Blazor -->
|
||||
<MicrosoftAspNetCoreBlazorMonoPackageVersion>0.10.0-preview8.19372.1</MicrosoftAspNetCoreBlazorMonoPackageVersion>
|
||||
<MicrosoftAspNetCoreBlazorMonoPackageVersion>3.0.0-preview9.19379.2</MicrosoftAspNetCoreBlazorMonoPackageVersion>
|
||||
<!-- Packages from aspnet/Extensions -->
|
||||
<InternalAspNetCoreAnalyzersPackageVersion>3.0.0-preview8.19374.2</InternalAspNetCoreAnalyzersPackageVersion>
|
||||
<MicrosoftAspNetCoreAnalyzerTestingPackageVersion>3.0.0-preview8.19374.2</MicrosoftAspNetCoreAnalyzerTestingPackageVersion>
|
||||
<MicrosoftAspNetCoreBenchmarkRunnerSourcesPackageVersion>3.0.0-preview8.19374.2</MicrosoftAspNetCoreBenchmarkRunnerSourcesPackageVersion>
|
||||
<MicrosoftAspNetCoreTestingPackageVersion>3.0.0-preview8.19374.2</MicrosoftAspNetCoreTestingPackageVersion>
|
||||
<MicrosoftExtensionsActivatorUtilitiesSourcesPackageVersion>3.0.0-preview8.19374.2</MicrosoftExtensionsActivatorUtilitiesSourcesPackageVersion>
|
||||
<MicrosoftExtensionsCachingAbstractionsPackageVersion>3.0.0-preview8.19374.2</MicrosoftExtensionsCachingAbstractionsPackageVersion>
|
||||
<MicrosoftExtensionsCachingMemoryPackageVersion>3.0.0-preview8.19374.2</MicrosoftExtensionsCachingMemoryPackageVersion>
|
||||
<MicrosoftExtensionsCachingSqlServerPackageVersion>3.0.0-preview8.19374.2</MicrosoftExtensionsCachingSqlServerPackageVersion>
|
||||
<MicrosoftExtensionsCachingStackExchangeRedisPackageVersion>3.0.0-preview8.19374.2</MicrosoftExtensionsCachingStackExchangeRedisPackageVersion>
|
||||
<MicrosoftExtensionsCommandLineUtilsSourcesPackageVersion>3.0.0-preview8.19374.2</MicrosoftExtensionsCommandLineUtilsSourcesPackageVersion>
|
||||
<MicrosoftExtensionsConfigurationAbstractionsPackageVersion>3.0.0-preview8.19374.2</MicrosoftExtensionsConfigurationAbstractionsPackageVersion>
|
||||
<MicrosoftExtensionsConfigurationAzureKeyVaultPackageVersion>3.0.0-preview8.19374.2</MicrosoftExtensionsConfigurationAzureKeyVaultPackageVersion>
|
||||
<MicrosoftExtensionsConfigurationBinderPackageVersion>3.0.0-preview8.19374.2</MicrosoftExtensionsConfigurationBinderPackageVersion>
|
||||
<MicrosoftExtensionsConfigurationCommandLinePackageVersion>3.0.0-preview8.19374.2</MicrosoftExtensionsConfigurationCommandLinePackageVersion>
|
||||
<MicrosoftExtensionsConfigurationEnvironmentVariablesPackageVersion>3.0.0-preview8.19374.2</MicrosoftExtensionsConfigurationEnvironmentVariablesPackageVersion>
|
||||
<MicrosoftExtensionsConfigurationFileExtensionsPackageVersion>3.0.0-preview8.19374.2</MicrosoftExtensionsConfigurationFileExtensionsPackageVersion>
|
||||
<MicrosoftExtensionsConfigurationIniPackageVersion>3.0.0-preview8.19374.2</MicrosoftExtensionsConfigurationIniPackageVersion>
|
||||
<MicrosoftExtensionsConfigurationJsonPackageVersion>3.0.0-preview8.19374.2</MicrosoftExtensionsConfigurationJsonPackageVersion>
|
||||
<MicrosoftExtensionsConfigurationKeyPerFilePackageVersion>3.0.0-preview8.19374.2</MicrosoftExtensionsConfigurationKeyPerFilePackageVersion>
|
||||
<MicrosoftExtensionsConfigurationPackageVersion>3.0.0-preview8.19374.2</MicrosoftExtensionsConfigurationPackageVersion>
|
||||
<MicrosoftExtensionsConfigurationUserSecretsPackageVersion>3.0.0-preview8.19374.2</MicrosoftExtensionsConfigurationUserSecretsPackageVersion>
|
||||
<MicrosoftExtensionsConfigurationXmlPackageVersion>3.0.0-preview8.19374.2</MicrosoftExtensionsConfigurationXmlPackageVersion>
|
||||
<MicrosoftExtensionsDependencyInjectionAbstractionsPackageVersion>3.0.0-preview8.19374.2</MicrosoftExtensionsDependencyInjectionAbstractionsPackageVersion>
|
||||
<MicrosoftExtensionsDependencyInjectionPackageVersion>3.0.0-preview8.19374.2</MicrosoftExtensionsDependencyInjectionPackageVersion>
|
||||
<MicrosoftExtensionsDiagnosticAdapterPackageVersion>3.0.0-preview8.19374.2</MicrosoftExtensionsDiagnosticAdapterPackageVersion>
|
||||
<MicrosoftExtensionsDiagnosticsHealthChecksAbstractionsPackageVersion>3.0.0-preview8.19374.2</MicrosoftExtensionsDiagnosticsHealthChecksAbstractionsPackageVersion>
|
||||
<MicrosoftExtensionsDiagnosticsHealthChecksPackageVersion>3.0.0-preview8.19374.2</MicrosoftExtensionsDiagnosticsHealthChecksPackageVersion>
|
||||
<MicrosoftExtensionsFileProvidersAbstractionsPackageVersion>3.0.0-preview8.19374.2</MicrosoftExtensionsFileProvidersAbstractionsPackageVersion>
|
||||
<MicrosoftExtensionsFileProvidersCompositePackageVersion>3.0.0-preview8.19374.2</MicrosoftExtensionsFileProvidersCompositePackageVersion>
|
||||
<MicrosoftExtensionsFileProvidersEmbeddedPackageVersion>3.0.0-preview8.19374.2</MicrosoftExtensionsFileProvidersEmbeddedPackageVersion>
|
||||
<MicrosoftExtensionsFileProvidersPhysicalPackageVersion>3.0.0-preview8.19374.2</MicrosoftExtensionsFileProvidersPhysicalPackageVersion>
|
||||
<MicrosoftExtensionsFileSystemGlobbingPackageVersion>3.0.0-preview8.19374.2</MicrosoftExtensionsFileSystemGlobbingPackageVersion>
|
||||
<MicrosoftExtensionsHashCodeCombinerSourcesPackageVersion>3.0.0-preview8.19374.2</MicrosoftExtensionsHashCodeCombinerSourcesPackageVersion>
|
||||
<MicrosoftExtensionsHostingAbstractionsPackageVersion>3.0.0-preview8.19374.2</MicrosoftExtensionsHostingAbstractionsPackageVersion>
|
||||
<MicrosoftExtensionsHostingPackageVersion>3.0.0-preview8.19374.2</MicrosoftExtensionsHostingPackageVersion>
|
||||
<MicrosoftExtensionsHostFactoryResolverSourcesPackageVersion>3.0.0-preview8.19374.2</MicrosoftExtensionsHostFactoryResolverSourcesPackageVersion>
|
||||
<MicrosoftExtensionsHttpPackageVersion>3.0.0-preview8.19374.2</MicrosoftExtensionsHttpPackageVersion>
|
||||
<MicrosoftExtensionsLocalizationAbstractionsPackageVersion>3.0.0-preview8.19374.2</MicrosoftExtensionsLocalizationAbstractionsPackageVersion>
|
||||
<MicrosoftExtensionsLocalizationPackageVersion>3.0.0-preview8.19374.2</MicrosoftExtensionsLocalizationPackageVersion>
|
||||
<MicrosoftExtensionsLoggingAbstractionsPackageVersion>3.0.0-preview8.19374.2</MicrosoftExtensionsLoggingAbstractionsPackageVersion>
|
||||
<MicrosoftExtensionsLoggingAzureAppServicesPackageVersion>3.0.0-preview8.19374.2</MicrosoftExtensionsLoggingAzureAppServicesPackageVersion>
|
||||
<MicrosoftExtensionsLoggingConfigurationPackageVersion>3.0.0-preview8.19374.2</MicrosoftExtensionsLoggingConfigurationPackageVersion>
|
||||
<MicrosoftExtensionsLoggingConsolePackageVersion>3.0.0-preview8.19374.2</MicrosoftExtensionsLoggingConsolePackageVersion>
|
||||
<MicrosoftExtensionsLoggingDebugPackageVersion>3.0.0-preview8.19374.2</MicrosoftExtensionsLoggingDebugPackageVersion>
|
||||
<MicrosoftExtensionsLoggingEventSourcePackageVersion>3.0.0-preview8.19374.2</MicrosoftExtensionsLoggingEventSourcePackageVersion>
|
||||
<MicrosoftExtensionsLoggingEventLogPackageVersion>3.0.0-preview8.19374.2</MicrosoftExtensionsLoggingEventLogPackageVersion>
|
||||
<MicrosoftExtensionsLoggingPackageVersion>3.0.0-preview8.19374.2</MicrosoftExtensionsLoggingPackageVersion>
|
||||
<MicrosoftExtensionsLoggingTestingPackageVersion>3.0.0-preview8.19374.2</MicrosoftExtensionsLoggingTestingPackageVersion>
|
||||
<MicrosoftExtensionsLoggingTraceSourcePackageVersion>3.0.0-preview8.19374.2</MicrosoftExtensionsLoggingTraceSourcePackageVersion>
|
||||
<MicrosoftExtensionsObjectPoolPackageVersion>3.0.0-preview8.19374.2</MicrosoftExtensionsObjectPoolPackageVersion>
|
||||
<MicrosoftExtensionsOptionsConfigurationExtensionsPackageVersion>3.0.0-preview8.19374.2</MicrosoftExtensionsOptionsConfigurationExtensionsPackageVersion>
|
||||
<MicrosoftExtensionsOptionsDataAnnotationsPackageVersion>3.0.0-preview8.19374.2</MicrosoftExtensionsOptionsDataAnnotationsPackageVersion>
|
||||
<MicrosoftExtensionsOptionsPackageVersion>3.0.0-preview8.19374.2</MicrosoftExtensionsOptionsPackageVersion>
|
||||
<MicrosoftExtensionsParameterDefaultValueSourcesPackageVersion>3.0.0-preview8.19374.2</MicrosoftExtensionsParameterDefaultValueSourcesPackageVersion>
|
||||
<MicrosoftExtensionsPrimitivesPackageVersion>3.0.0-preview8.19374.2</MicrosoftExtensionsPrimitivesPackageVersion>
|
||||
<MicrosoftExtensionsTypeNameHelperSourcesPackageVersion>3.0.0-preview8.19374.2</MicrosoftExtensionsTypeNameHelperSourcesPackageVersion>
|
||||
<MicrosoftExtensionsValueStopwatchSourcesPackageVersion>3.0.0-preview8.19374.2</MicrosoftExtensionsValueStopwatchSourcesPackageVersion>
|
||||
<MicrosoftExtensionsWebEncodersPackageVersion>3.0.0-preview8.19374.2</MicrosoftExtensionsWebEncodersPackageVersion>
|
||||
<MicrosoftInternalExtensionsRefsPackageVersion>3.0.0-preview8.19374.2</MicrosoftInternalExtensionsRefsPackageVersion>
|
||||
<MicrosoftJSInteropPackageVersion>3.0.0-preview8.19374.2</MicrosoftJSInteropPackageVersion>
|
||||
<MonoWebAssemblyInteropPackageVersion>3.0.0-preview8.19374.2</MonoWebAssemblyInteropPackageVersion>
|
||||
<InternalAspNetCoreAnalyzersPackageVersion>3.0.0-preview9.19401.2</InternalAspNetCoreAnalyzersPackageVersion>
|
||||
<MicrosoftAspNetCoreAnalyzerTestingPackageVersion>3.0.0-preview9.19401.2</MicrosoftAspNetCoreAnalyzerTestingPackageVersion>
|
||||
<MicrosoftAspNetCoreBenchmarkRunnerSourcesPackageVersion>3.0.0-preview9.19401.2</MicrosoftAspNetCoreBenchmarkRunnerSourcesPackageVersion>
|
||||
<MicrosoftAspNetCoreTestingPackageVersion>3.0.0-preview9.19401.2</MicrosoftAspNetCoreTestingPackageVersion>
|
||||
<MicrosoftExtensionsActivatorUtilitiesSourcesPackageVersion>3.0.0-preview9.19401.2</MicrosoftExtensionsActivatorUtilitiesSourcesPackageVersion>
|
||||
<MicrosoftExtensionsCachingAbstractionsPackageVersion>3.0.0-preview9.19401.2</MicrosoftExtensionsCachingAbstractionsPackageVersion>
|
||||
<MicrosoftExtensionsCachingMemoryPackageVersion>3.0.0-preview9.19401.2</MicrosoftExtensionsCachingMemoryPackageVersion>
|
||||
<MicrosoftExtensionsCachingSqlServerPackageVersion>3.0.0-preview9.19401.2</MicrosoftExtensionsCachingSqlServerPackageVersion>
|
||||
<MicrosoftExtensionsCachingStackExchangeRedisPackageVersion>3.0.0-preview9.19401.2</MicrosoftExtensionsCachingStackExchangeRedisPackageVersion>
|
||||
<MicrosoftExtensionsCommandLineUtilsSourcesPackageVersion>3.0.0-preview9.19401.2</MicrosoftExtensionsCommandLineUtilsSourcesPackageVersion>
|
||||
<MicrosoftExtensionsConfigurationAbstractionsPackageVersion>3.0.0-preview9.19401.2</MicrosoftExtensionsConfigurationAbstractionsPackageVersion>
|
||||
<MicrosoftExtensionsConfigurationAzureKeyVaultPackageVersion>3.0.0-preview9.19401.2</MicrosoftExtensionsConfigurationAzureKeyVaultPackageVersion>
|
||||
<MicrosoftExtensionsConfigurationBinderPackageVersion>3.0.0-preview9.19401.2</MicrosoftExtensionsConfigurationBinderPackageVersion>
|
||||
<MicrosoftExtensionsConfigurationCommandLinePackageVersion>3.0.0-preview9.19401.2</MicrosoftExtensionsConfigurationCommandLinePackageVersion>
|
||||
<MicrosoftExtensionsConfigurationEnvironmentVariablesPackageVersion>3.0.0-preview9.19401.2</MicrosoftExtensionsConfigurationEnvironmentVariablesPackageVersion>
|
||||
<MicrosoftExtensionsConfigurationFileExtensionsPackageVersion>3.0.0-preview9.19401.2</MicrosoftExtensionsConfigurationFileExtensionsPackageVersion>
|
||||
<MicrosoftExtensionsConfigurationIniPackageVersion>3.0.0-preview9.19401.2</MicrosoftExtensionsConfigurationIniPackageVersion>
|
||||
<MicrosoftExtensionsConfigurationJsonPackageVersion>3.0.0-preview9.19401.2</MicrosoftExtensionsConfigurationJsonPackageVersion>
|
||||
<MicrosoftExtensionsConfigurationKeyPerFilePackageVersion>3.0.0-preview9.19401.2</MicrosoftExtensionsConfigurationKeyPerFilePackageVersion>
|
||||
<MicrosoftExtensionsConfigurationPackageVersion>3.0.0-preview9.19401.2</MicrosoftExtensionsConfigurationPackageVersion>
|
||||
<MicrosoftExtensionsConfigurationUserSecretsPackageVersion>3.0.0-preview9.19401.2</MicrosoftExtensionsConfigurationUserSecretsPackageVersion>
|
||||
<MicrosoftExtensionsConfigurationXmlPackageVersion>3.0.0-preview9.19401.2</MicrosoftExtensionsConfigurationXmlPackageVersion>
|
||||
<MicrosoftExtensionsDependencyInjectionAbstractionsPackageVersion>3.0.0-preview9.19401.2</MicrosoftExtensionsDependencyInjectionAbstractionsPackageVersion>
|
||||
<MicrosoftExtensionsDependencyInjectionPackageVersion>3.0.0-preview9.19401.2</MicrosoftExtensionsDependencyInjectionPackageVersion>
|
||||
<MicrosoftExtensionsDiagnosticAdapterPackageVersion>3.0.0-preview9.19401.2</MicrosoftExtensionsDiagnosticAdapterPackageVersion>
|
||||
<MicrosoftExtensionsDiagnosticsHealthChecksAbstractionsPackageVersion>3.0.0-preview9.19401.2</MicrosoftExtensionsDiagnosticsHealthChecksAbstractionsPackageVersion>
|
||||
<MicrosoftExtensionsDiagnosticsHealthChecksPackageVersion>3.0.0-preview9.19401.2</MicrosoftExtensionsDiagnosticsHealthChecksPackageVersion>
|
||||
<MicrosoftExtensionsFileProvidersAbstractionsPackageVersion>3.0.0-preview9.19401.2</MicrosoftExtensionsFileProvidersAbstractionsPackageVersion>
|
||||
<MicrosoftExtensionsFileProvidersCompositePackageVersion>3.0.0-preview9.19401.2</MicrosoftExtensionsFileProvidersCompositePackageVersion>
|
||||
<MicrosoftExtensionsFileProvidersEmbeddedPackageVersion>3.0.0-preview9.19401.2</MicrosoftExtensionsFileProvidersEmbeddedPackageVersion>
|
||||
<MicrosoftExtensionsFileProvidersPhysicalPackageVersion>3.0.0-preview9.19401.2</MicrosoftExtensionsFileProvidersPhysicalPackageVersion>
|
||||
<MicrosoftExtensionsFileSystemGlobbingPackageVersion>3.0.0-preview9.19401.2</MicrosoftExtensionsFileSystemGlobbingPackageVersion>
|
||||
<MicrosoftExtensionsHashCodeCombinerSourcesPackageVersion>3.0.0-preview9.19401.2</MicrosoftExtensionsHashCodeCombinerSourcesPackageVersion>
|
||||
<MicrosoftExtensionsHostingAbstractionsPackageVersion>3.0.0-preview9.19401.2</MicrosoftExtensionsHostingAbstractionsPackageVersion>
|
||||
<MicrosoftExtensionsHostingPackageVersion>3.0.0-preview9.19401.2</MicrosoftExtensionsHostingPackageVersion>
|
||||
<MicrosoftExtensionsHostFactoryResolverSourcesPackageVersion>3.0.0-preview9.19401.2</MicrosoftExtensionsHostFactoryResolverSourcesPackageVersion>
|
||||
<MicrosoftExtensionsHttpPackageVersion>3.0.0-preview9.19401.2</MicrosoftExtensionsHttpPackageVersion>
|
||||
<MicrosoftExtensionsLocalizationAbstractionsPackageVersion>3.0.0-preview9.19401.2</MicrosoftExtensionsLocalizationAbstractionsPackageVersion>
|
||||
<MicrosoftExtensionsLocalizationPackageVersion>3.0.0-preview9.19401.2</MicrosoftExtensionsLocalizationPackageVersion>
|
||||
<MicrosoftExtensionsLoggingAbstractionsPackageVersion>3.0.0-preview9.19401.2</MicrosoftExtensionsLoggingAbstractionsPackageVersion>
|
||||
<MicrosoftExtensionsLoggingAzureAppServicesPackageVersion>3.0.0-preview9.19401.2</MicrosoftExtensionsLoggingAzureAppServicesPackageVersion>
|
||||
<MicrosoftExtensionsLoggingConfigurationPackageVersion>3.0.0-preview9.19401.2</MicrosoftExtensionsLoggingConfigurationPackageVersion>
|
||||
<MicrosoftExtensionsLoggingConsolePackageVersion>3.0.0-preview9.19401.2</MicrosoftExtensionsLoggingConsolePackageVersion>
|
||||
<MicrosoftExtensionsLoggingDebugPackageVersion>3.0.0-preview9.19401.2</MicrosoftExtensionsLoggingDebugPackageVersion>
|
||||
<MicrosoftExtensionsLoggingEventSourcePackageVersion>3.0.0-preview9.19401.2</MicrosoftExtensionsLoggingEventSourcePackageVersion>
|
||||
<MicrosoftExtensionsLoggingEventLogPackageVersion>3.0.0-preview9.19401.2</MicrosoftExtensionsLoggingEventLogPackageVersion>
|
||||
<MicrosoftExtensionsLoggingPackageVersion>3.0.0-preview9.19401.2</MicrosoftExtensionsLoggingPackageVersion>
|
||||
<MicrosoftExtensionsLoggingTestingPackageVersion>3.0.0-preview9.19401.2</MicrosoftExtensionsLoggingTestingPackageVersion>
|
||||
<MicrosoftExtensionsLoggingTraceSourcePackageVersion>3.0.0-preview9.19401.2</MicrosoftExtensionsLoggingTraceSourcePackageVersion>
|
||||
<MicrosoftExtensionsObjectPoolPackageVersion>3.0.0-preview9.19401.2</MicrosoftExtensionsObjectPoolPackageVersion>
|
||||
<MicrosoftExtensionsOptionsConfigurationExtensionsPackageVersion>3.0.0-preview9.19401.2</MicrosoftExtensionsOptionsConfigurationExtensionsPackageVersion>
|
||||
<MicrosoftExtensionsOptionsDataAnnotationsPackageVersion>3.0.0-preview9.19401.2</MicrosoftExtensionsOptionsDataAnnotationsPackageVersion>
|
||||
<MicrosoftExtensionsOptionsPackageVersion>3.0.0-preview9.19401.2</MicrosoftExtensionsOptionsPackageVersion>
|
||||
<MicrosoftExtensionsParameterDefaultValueSourcesPackageVersion>3.0.0-preview9.19401.2</MicrosoftExtensionsParameterDefaultValueSourcesPackageVersion>
|
||||
<MicrosoftExtensionsPrimitivesPackageVersion>3.0.0-preview9.19401.2</MicrosoftExtensionsPrimitivesPackageVersion>
|
||||
<MicrosoftExtensionsTypeNameHelperSourcesPackageVersion>3.0.0-preview9.19401.2</MicrosoftExtensionsTypeNameHelperSourcesPackageVersion>
|
||||
<MicrosoftExtensionsValueStopwatchSourcesPackageVersion>3.0.0-preview9.19401.2</MicrosoftExtensionsValueStopwatchSourcesPackageVersion>
|
||||
<MicrosoftExtensionsWebEncodersPackageVersion>3.0.0-preview9.19401.2</MicrosoftExtensionsWebEncodersPackageVersion>
|
||||
<MicrosoftInternalExtensionsRefsPackageVersion>3.0.0-preview9.19401.2</MicrosoftInternalExtensionsRefsPackageVersion>
|
||||
<MicrosoftJSInteropPackageVersion>3.0.0-preview9.19401.2</MicrosoftJSInteropPackageVersion>
|
||||
<MonoWebAssemblyInteropPackageVersion>3.0.0-preview9.19401.2</MonoWebAssemblyInteropPackageVersion>
|
||||
<!-- Packages from aspnet/EntityFrameworkCore -->
|
||||
<dotnetefPackageVersion>3.0.0-preview8.19375.5</dotnetefPackageVersion>
|
||||
<MicrosoftEntityFrameworkCoreInMemoryPackageVersion>3.0.0-preview8.19375.5</MicrosoftEntityFrameworkCoreInMemoryPackageVersion>
|
||||
<MicrosoftEntityFrameworkCoreRelationalPackageVersion>3.0.0-preview8.19375.5</MicrosoftEntityFrameworkCoreRelationalPackageVersion>
|
||||
<MicrosoftEntityFrameworkCoreSqlitePackageVersion>3.0.0-preview8.19375.5</MicrosoftEntityFrameworkCoreSqlitePackageVersion>
|
||||
<MicrosoftEntityFrameworkCoreSqlServerPackageVersion>3.0.0-preview8.19375.5</MicrosoftEntityFrameworkCoreSqlServerPackageVersion>
|
||||
<MicrosoftEntityFrameworkCoreToolsPackageVersion>3.0.0-preview8.19375.5</MicrosoftEntityFrameworkCoreToolsPackageVersion>
|
||||
<MicrosoftEntityFrameworkCorePackageVersion>3.0.0-preview8.19375.5</MicrosoftEntityFrameworkCorePackageVersion>
|
||||
<dotnetefPackageVersion>3.0.0-preview9.19402.9</dotnetefPackageVersion>
|
||||
<MicrosoftEntityFrameworkCoreInMemoryPackageVersion>3.0.0-preview9.19402.9</MicrosoftEntityFrameworkCoreInMemoryPackageVersion>
|
||||
<MicrosoftEntityFrameworkCoreRelationalPackageVersion>3.0.0-preview9.19402.9</MicrosoftEntityFrameworkCoreRelationalPackageVersion>
|
||||
<MicrosoftEntityFrameworkCoreSqlitePackageVersion>3.0.0-preview9.19402.9</MicrosoftEntityFrameworkCoreSqlitePackageVersion>
|
||||
<MicrosoftEntityFrameworkCoreSqlServerPackageVersion>3.0.0-preview9.19402.9</MicrosoftEntityFrameworkCoreSqlServerPackageVersion>
|
||||
<MicrosoftEntityFrameworkCoreToolsPackageVersion>3.0.0-preview9.19402.9</MicrosoftEntityFrameworkCoreToolsPackageVersion>
|
||||
<MicrosoftEntityFrameworkCorePackageVersion>3.0.0-preview9.19402.9</MicrosoftEntityFrameworkCorePackageVersion>
|
||||
<!-- Packages from aspnet/AspNetCore-Tooling -->
|
||||
<MicrosoftAspNetCoreMvcRazorExtensionsPackageVersion>3.0.0-preview8.19374.2</MicrosoftAspNetCoreMvcRazorExtensionsPackageVersion>
|
||||
<MicrosoftAspNetCoreRazorLanguagePackageVersion>3.0.0-preview8.19374.2</MicrosoftAspNetCoreRazorLanguagePackageVersion>
|
||||
<MicrosoftCodeAnalysisRazorPackageVersion>3.0.0-preview8.19374.2</MicrosoftCodeAnalysisRazorPackageVersion>
|
||||
<MicrosoftNETSdkRazorPackageVersion>3.0.0-preview8.19374.2</MicrosoftNETSdkRazorPackageVersion>
|
||||
<MicrosoftAspNetCoreMvcRazorExtensionsPackageVersion>3.0.0-preview9.19402.1</MicrosoftAspNetCoreMvcRazorExtensionsPackageVersion>
|
||||
<MicrosoftAspNetCoreRazorLanguagePackageVersion>3.0.0-preview9.19402.1</MicrosoftAspNetCoreRazorLanguagePackageVersion>
|
||||
<MicrosoftCodeAnalysisRazorPackageVersion>3.0.0-preview9.19402.1</MicrosoftCodeAnalysisRazorPackageVersion>
|
||||
<MicrosoftNETSdkRazorPackageVersion>3.0.0-preview9.19402.1</MicrosoftNETSdkRazorPackageVersion>
|
||||
</PropertyGroup>
|
||||
<!--
|
||||
|
||||
|
|
|
|||
|
|
@ -43,4 +43,9 @@
|
|||
This one sets UseSharedCompilation to false by default. -->
|
||||
<UseSharedCompilation>true</UseSharedCompilation>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<!-- Ignore warning about calling the Pack target on Web SDK projects. Our build scripts call /t:pack on everything in this repo. -->
|
||||
<WarnOnPackingNonPackableProject>false</WarnOnPackingNonPackableProject>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -15,11 +15,6 @@
|
|||
<BundledNETCorePlatformsPackageVersion>$(MicrosoftNETCorePlatformsPackageVersion)</BundledNETCorePlatformsPackageVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- Workaround https://github.com/dotnet/sdk/issues/2976 -->
|
||||
<ItemGroup>
|
||||
<PackageReference Update="Microsoft.NETCore.Platforms" PrivateAssets="All" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Workaround https://github.com/aspnet/AspNetCore/issues/7503. This chains GenerateSourceLinkFile before razor component targets run. -->
|
||||
<!-- Workaround https://github.com/dotnet/source-build/issues/1112. Source link is currently disabled in source build so do not apply this worksaround. -->
|
||||
<Target Condition="'$(DotNetBuildFromSource)' != 'true'"
|
||||
|
|
@ -30,12 +25,6 @@
|
|||
<!-- Workaround https://github.com/dotnet/source-build/issues/1112. Source link is currently disabled in source build so define this dummy target which is required for pack. -->
|
||||
<Import Condition="'$(DotNetBuildFromSource)' == 'true'" Project="WorkaroundsImported.targets" />
|
||||
|
||||
<!-- Workaround https://github.com/aspnet/websdk/pull/646. If merged, once we update to a websdk with this fix, we can move the setting below to Directory.Build.props. -->
|
||||
<PropertyGroup>
|
||||
<!-- Ignore warning about calling the Pack target on Web SDK projects. Our build scripts call /t:pack on everything in this repo. -->
|
||||
<WarnOnPackingNonPackableProject>false</WarnOnPackingNonPackableProject>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- Workaround for https://github.com/dotnet/arcade/issues/204 -->
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Internal.AspNetCore.BuildTasks" PrivateAssets="All" Version="$(InternalAspNetCoreBuildTasksPackageVersion)" IsImplicitlyDefined="true" />
|
||||
|
|
@ -47,18 +36,10 @@
|
|||
</RestoreSources>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- Workaround until we can build our repo with a 3.0 Preview 7 SDK which has https://github.com/dotnet/core-sdk/pull/2401. -->
|
||||
<ItemGroup Condition="'$(PreReleasePreviewNumber)' == '7' ">
|
||||
<KnownFrameworkReference Update="Microsoft.NETCore.App">
|
||||
<!--
|
||||
Temporary until we can update to build with the Preview7 SDK .
|
||||
Using PreReleasePreviewNumber to time-bomb this so we can remove this before RTM.
|
||||
|
||||
This workaround was also applied to src\ProjectTemplates\test\Infrastructure\TemplateTests.props.in.
|
||||
-->
|
||||
<RuntimePackNamePatterns>Microsoft.NETCore.App.Runtime.**RID**</RuntimePackNamePatterns>
|
||||
<AppHostPackNamePattern />
|
||||
<AppHostRuntimeIdentifiers />
|
||||
<!-- Workaround for netstandard2.1 projects until we can get a preview 8 SDK containing https://github.com/dotnet/sdk/pull/3463 fix. -->
|
||||
<ItemGroup>
|
||||
<KnownFrameworkReference Update="NETStandard.Library">
|
||||
<RuntimeFrameworkName>NETStandard.Library</RuntimeFrameworkName>
|
||||
</KnownFrameworkReference>
|
||||
</ItemGroup>
|
||||
|
||||
|
|
|
|||
|
|
@ -13,8 +13,12 @@ namespace Microsoft.AspNetCore.Analyzers.TestFiles.CompilationFeatureDetectorTes
|
|||
|
||||
app.UseEndpoints(endpoints =>
|
||||
{
|
||||
endpoints.MapBlazorHub();
|
||||
endpoints.MapBlazorHub<App>("app");
|
||||
});
|
||||
}
|
||||
|
||||
public class App : Microsoft.AspNetCore.Components.ComponentBase
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ namespace Microsoft.AspNetCore.Components.Analyzers
|
|||
new LocalizableResourceString(nameof(Resources.ComponentParameterSettersShouldBePublic_Title), Resources.ResourceManager, typeof(Resources)),
|
||||
new LocalizableResourceString(nameof(Resources.ComponentParameterSettersShouldBePublic_Format), Resources.ResourceManager, typeof(Resources)),
|
||||
"Encapsulation",
|
||||
DiagnosticSeverity.Warning,
|
||||
DiagnosticSeverity.Error,
|
||||
isEnabledByDefault: true,
|
||||
description: new LocalizableResourceString(nameof(Resources.ComponentParameterSettersShouldBePublic_Description), Resources.ResourceManager, typeof(Resources)));
|
||||
|
||||
|
|
@ -43,7 +43,7 @@ namespace Microsoft.AspNetCore.Components.Analyzers
|
|||
new LocalizableResourceString(nameof(Resources.ComponentParameterShouldBePublic_Title), Resources.ResourceManager, typeof(Resources)),
|
||||
new LocalizableResourceString(nameof(Resources.ComponentParameterShouldBePublic_Format), Resources.ResourceManager, typeof(Resources)),
|
||||
"Encapsulation",
|
||||
DiagnosticSeverity.Warning,
|
||||
DiagnosticSeverity.Error,
|
||||
isEnabledByDefault: true,
|
||||
description: new LocalizableResourceString(nameof(Resources.ComponentParametersShouldBePublic_Description), Resources.ResourceManager, typeof(Resources)));
|
||||
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ namespace Microsoft.AspNetCore.Components.Analyzers
|
|||
{
|
||||
Id = DiagnosticDescriptors.ComponentParameterSettersShouldBePublic.Id,
|
||||
Message = "Component parameter 'ConsoleApplication1.TypeName.MyProperty1' should have a public setter.",
|
||||
Severity = DiagnosticSeverity.Warning,
|
||||
Severity = DiagnosticSeverity.Error,
|
||||
Locations = new[]
|
||||
{
|
||||
new DiagnosticResultLocation("Test0.cs", 7, 39)
|
||||
|
|
@ -88,7 +88,7 @@ namespace Microsoft.AspNetCore.Components.Analyzers
|
|||
{
|
||||
Id = DiagnosticDescriptors.ComponentParameterSettersShouldBePublic.Id,
|
||||
Message = "Component parameter 'ConsoleApplication1.TypeName.MyProperty2' should have a public setter.",
|
||||
Severity = DiagnosticSeverity.Warning,
|
||||
Severity = DiagnosticSeverity.Error,
|
||||
Locations = new[]
|
||||
{
|
||||
new DiagnosticResultLocation("Test0.cs", 8, 39)
|
||||
|
|
@ -98,7 +98,7 @@ namespace Microsoft.AspNetCore.Components.Analyzers
|
|||
{
|
||||
Id = DiagnosticDescriptors.ComponentParameterSettersShouldBePublic.Id,
|
||||
Message = "Component parameter 'ConsoleApplication1.TypeName.MyProperty3' should have a public setter.",
|
||||
Severity = DiagnosticSeverity.Warning,
|
||||
Severity = DiagnosticSeverity.Error,
|
||||
Locations = new[]
|
||||
{
|
||||
new DiagnosticResultLocation("Test0.cs", 9, 39)
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ namespace Microsoft.AspNetCore.Components.Analyzers.Test
|
|||
{
|
||||
Id = DiagnosticDescriptors.ComponentParametersShouldBePublic.Id,
|
||||
Message = "Component parameter 'ConsoleApplication1.TypeName.BadProperty1' should be public.",
|
||||
Severity = DiagnosticSeverity.Warning,
|
||||
Severity = DiagnosticSeverity.Error,
|
||||
Locations = new[]
|
||||
{
|
||||
new DiagnosticResultLocation("Test0.cs", 8, 40)
|
||||
|
|
@ -85,7 +85,7 @@ namespace Microsoft.AspNetCore.Components.Analyzers.Test
|
|||
{
|
||||
Id = DiagnosticDescriptors.ComponentParameterSettersShouldBePublic.Id,
|
||||
Message = "Component parameter 'ConsoleApplication1.TypeName.MyProperty1' should have a public setter.",
|
||||
Severity = DiagnosticSeverity.Warning,
|
||||
Severity = DiagnosticSeverity.Error,
|
||||
Locations = new[]
|
||||
{
|
||||
new DiagnosticResultLocation("Test0.cs", 8, 39)
|
||||
|
|
@ -95,7 +95,7 @@ namespace Microsoft.AspNetCore.Components.Analyzers.Test
|
|||
{
|
||||
Id = DiagnosticDescriptors.ComponentParameterSettersShouldBePublic.Id,
|
||||
Message = "Component parameter 'ConsoleApplication1.TypeName.MyProperty2' should have a public setter.",
|
||||
Severity = DiagnosticSeverity.Warning,
|
||||
Severity = DiagnosticSeverity.Error,
|
||||
Locations = new[]
|
||||
{
|
||||
new DiagnosticResultLocation("Test0.cs", 9, 39)
|
||||
|
|
@ -105,7 +105,7 @@ namespace Microsoft.AspNetCore.Components.Analyzers.Test
|
|||
{
|
||||
Id = DiagnosticDescriptors.ComponentParameterSettersShouldBePublic.Id,
|
||||
Message = "Component parameter 'ConsoleApplication1.TypeName.MyProperty3' should have a public setter.",
|
||||
Severity = DiagnosticSeverity.Warning,
|
||||
Severity = DiagnosticSeverity.Error,
|
||||
Locations = new[]
|
||||
{
|
||||
new DiagnosticResultLocation("Test0.cs", 10, 39)
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ namespace Microsoft.AspNetCore.Components.Analyzers
|
|||
{
|
||||
Id = DiagnosticDescriptors.ComponentParametersShouldBePublic.Id,
|
||||
Message = "Component parameter 'ConsoleApplication1.TypeName.MyProperty1' should be public.",
|
||||
Severity = DiagnosticSeverity.Warning,
|
||||
Severity = DiagnosticSeverity.Error,
|
||||
Locations = new[]
|
||||
{
|
||||
new DiagnosticResultLocation("Test0.cs", 7, 32)
|
||||
|
|
@ -73,7 +73,7 @@ namespace Microsoft.AspNetCore.Components.Analyzers
|
|||
{
|
||||
Id = DiagnosticDescriptors.ComponentParametersShouldBePublic.Id,
|
||||
Message = "Component parameter 'ConsoleApplication1.TypeName.MyProperty2' should be public.",
|
||||
Severity = DiagnosticSeverity.Warning,
|
||||
Severity = DiagnosticSeverity.Error,
|
||||
Locations = new[]
|
||||
{
|
||||
new DiagnosticResultLocation("Test0.cs", 8, 40)
|
||||
|
|
@ -83,7 +83,7 @@ namespace Microsoft.AspNetCore.Components.Analyzers
|
|||
{
|
||||
Id = DiagnosticDescriptors.ComponentParametersShouldBePublic.Id,
|
||||
Message = "Component parameter 'ConsoleApplication1.TypeName.MyProperty3' should be public.",
|
||||
Severity = DiagnosticSeverity.Warning,
|
||||
Severity = DiagnosticSeverity.Error,
|
||||
Locations = new[]
|
||||
{
|
||||
new DiagnosticResultLocation("Test0.cs", 9, 42)
|
||||
|
|
@ -93,7 +93,7 @@ namespace Microsoft.AspNetCore.Components.Analyzers
|
|||
{
|
||||
Id = DiagnosticDescriptors.ComponentParametersShouldBePublic.Id,
|
||||
Message = "Component parameter 'ConsoleApplication1.TypeName.MyProperty4' should be public.",
|
||||
Severity = DiagnosticSeverity.Warning,
|
||||
Severity = DiagnosticSeverity.Error,
|
||||
Locations = new[]
|
||||
{
|
||||
new DiagnosticResultLocation("Test0.cs", 10, 41)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,15 @@
|
|||
// 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.
|
||||
|
||||
namespace Microsoft.AspNetCore.Blazor
|
||||
{
|
||||
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
|
||||
public static partial class JSInteropMethods
|
||||
{
|
||||
[Microsoft.JSInterop.JSInvokableAttribute("NotifyLocationChanged")]
|
||||
public static void NotifyLocationChanged(string uri, bool isInterceptedLink) { }
|
||||
}
|
||||
}
|
||||
namespace Microsoft.AspNetCore.Blazor.Hosting
|
||||
{
|
||||
public static partial class BlazorWebAssemblyHost
|
||||
|
|
@ -68,18 +77,6 @@ namespace Microsoft.AspNetCore.Blazor.Rendering
|
|||
protected override System.Threading.Tasks.Task UpdateDisplayAsync(in Microsoft.AspNetCore.Components.Rendering.RenderBatch batch) { throw null; }
|
||||
}
|
||||
}
|
||||
namespace Microsoft.AspNetCore.Blazor.Services
|
||||
{
|
||||
public partial class WebAssemblyUriHelper : Microsoft.AspNetCore.Components.UriHelperBase
|
||||
{
|
||||
internal WebAssemblyUriHelper() { }
|
||||
public static readonly Microsoft.AspNetCore.Blazor.Services.WebAssemblyUriHelper Instance;
|
||||
protected override void EnsureInitialized() { }
|
||||
protected override void NavigateToCore(string uri, bool forceLoad) { }
|
||||
[Microsoft.JSInterop.JSInvokableAttribute("NotifyLocationChanged")]
|
||||
public static void NotifyLocationChanged(string newAbsoluteUri, bool isInterceptedLink) { }
|
||||
}
|
||||
}
|
||||
namespace Microsoft.AspNetCore.Components.Builder
|
||||
{
|
||||
public static partial class ComponentsApplicationBuilderExtensions
|
||||
|
|
|
|||
|
|
@ -92,16 +92,16 @@ namespace Microsoft.AspNetCore.Blazor.Hosting
|
|||
services.AddSingleton<IWebAssemblyHost, WebAssemblyHost>();
|
||||
services.AddSingleton<IJSRuntime>(WebAssemblyJSRuntime.Instance);
|
||||
services.AddSingleton<IComponentContext, WebAssemblyComponentContext>();
|
||||
services.AddSingleton<IUriHelper>(WebAssemblyUriHelper.Instance);
|
||||
services.AddSingleton<NavigationManager>(WebAssemblyNavigationManager.Instance);
|
||||
services.AddSingleton<INavigationInterception>(WebAssemblyNavigationInterception.Instance);
|
||||
services.AddSingleton<ILoggerFactory, WebAssemblyLoggerFactory>();
|
||||
services.AddSingleton<HttpClient>(s =>
|
||||
{
|
||||
// Creating the URI helper needs to wait until the JS Runtime is initialized, so defer it.
|
||||
var uriHelper = s.GetRequiredService<IUriHelper>();
|
||||
var navigationManager = s.GetRequiredService<NavigationManager>();
|
||||
return new HttpClient
|
||||
{
|
||||
BaseAddress = new Uri(WebAssemblyUriHelper.Instance.GetBaseUri())
|
||||
BaseAddress = new Uri(navigationManager.BaseUri)
|
||||
};
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,26 @@
|
|||
// 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.ComponentModel;
|
||||
using Microsoft.AspNetCore.Blazor.Services;
|
||||
using Microsoft.JSInterop;
|
||||
|
||||
namespace Microsoft.AspNetCore.Blazor
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains methods called by interop. Intended for framework use only, not supported for use in application
|
||||
/// code.
|
||||
/// </summary>
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public static class JSInteropMethods
|
||||
{
|
||||
/// <summary>
|
||||
/// For framework use only.
|
||||
/// </summary>
|
||||
[JSInvokable(nameof(NotifyLocationChanged))]
|
||||
public static void NotifyLocationChanged(string uri, bool isInterceptedLink)
|
||||
{
|
||||
WebAssemblyNavigationManager.Instance.SetLocation(uri, isInterceptedLink);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Components.Routing;
|
||||
using Interop = Microsoft.AspNetCore.Components.Web.BrowserUriHelperInterop;
|
||||
using Interop = Microsoft.AspNetCore.Components.Web.BrowserNavigationManagerInterop;
|
||||
|
||||
namespace Microsoft.AspNetCore.Blazor.Services
|
||||
{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,53 @@
|
|||
// 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 Microsoft.AspNetCore.Components;
|
||||
using Interop = Microsoft.AspNetCore.Components.Web.BrowserNavigationManagerInterop;
|
||||
|
||||
namespace Microsoft.AspNetCore.Blazor.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Default client-side implementation of <see cref="NavigationManager"/>.
|
||||
/// </summary>
|
||||
internal class WebAssemblyNavigationManager : NavigationManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the instance of <see cref="WebAssemblyNavigationManager"/>.
|
||||
/// </summary>
|
||||
public static readonly WebAssemblyNavigationManager Instance = new WebAssemblyNavigationManager();
|
||||
|
||||
// For simplicity we force public consumption of the BrowserNavigationManager through
|
||||
// a singleton. Only a single instance can be updated by the browser through
|
||||
// interop. We can construct instances for testing.
|
||||
internal WebAssemblyNavigationManager()
|
||||
{
|
||||
}
|
||||
|
||||
protected override void EnsureInitialized()
|
||||
{
|
||||
// As described in the comment block above, BrowserNavigationManager is only for
|
||||
// client-side (Mono) use, so it's OK to rely on synchronicity here.
|
||||
var baseUri = WebAssemblyJSRuntime.Instance.Invoke<string>(Interop.GetBaseUri);
|
||||
var uri = WebAssemblyJSRuntime.Instance.Invoke<string>(Interop.GetLocationHref);
|
||||
Initialize(baseUri, uri);
|
||||
}
|
||||
|
||||
public void SetLocation(string uri, bool isInterceptedLink)
|
||||
{
|
||||
Uri = uri;
|
||||
NotifyLocationChanged(isInterceptedLink);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void NavigateToCore(string uri, bool forceLoad)
|
||||
{
|
||||
if (uri == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(uri));
|
||||
}
|
||||
|
||||
WebAssemblyJSRuntime.Instance.Invoke<object>(Interop.NavigateTo, uri, forceLoad);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,85 +0,0 @@
|
|||
// 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 Microsoft.AspNetCore.Components;
|
||||
using Microsoft.JSInterop;
|
||||
using Interop = Microsoft.AspNetCore.Components.Web.BrowserUriHelperInterop;
|
||||
|
||||
namespace Microsoft.AspNetCore.Blazor.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Default client-side implementation of <see cref="IUriHelper"/>.
|
||||
/// </summary>
|
||||
public class WebAssemblyUriHelper : UriHelperBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the instance of <see cref="WebAssemblyUriHelper"/>.
|
||||
/// </summary>
|
||||
public static readonly WebAssemblyUriHelper Instance = new WebAssemblyUriHelper();
|
||||
|
||||
// For simplicity we force public consumption of the BrowserUriHelper through
|
||||
// a singleton. Only a single instance can be updated by the browser through
|
||||
// interop. We can construct instances for testing.
|
||||
internal WebAssemblyUriHelper()
|
||||
{
|
||||
}
|
||||
|
||||
protected override void EnsureInitialized()
|
||||
{
|
||||
WebAssemblyJSRuntime.Instance.Invoke<object>(
|
||||
Interop.ListenForNavigationEvents,
|
||||
typeof(WebAssemblyUriHelper).Assembly.GetName().Name,
|
||||
nameof(NotifyLocationChanged));
|
||||
|
||||
// As described in the comment block above, BrowserUriHelper is only for
|
||||
// client-side (Mono) use, so it's OK to rely on synchronicity here.
|
||||
var baseUri = WebAssemblyJSRuntime.Instance.Invoke<string>(Interop.GetBaseUri);
|
||||
var uri = WebAssemblyJSRuntime.Instance.Invoke<string>(Interop.GetLocationHref);
|
||||
InitializeState(uri, baseUri);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void NavigateToCore(string uri, bool forceLoad)
|
||||
{
|
||||
if (uri == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(uri));
|
||||
}
|
||||
|
||||
WebAssemblyJSRuntime.Instance.Invoke<object>(Interop.NavigateTo, uri, forceLoad);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// For framework use only.
|
||||
/// </summary>
|
||||
[JSInvokable(nameof(NotifyLocationChanged))]
|
||||
public static void NotifyLocationChanged(string newAbsoluteUri, bool isInterceptedLink)
|
||||
{
|
||||
Instance.SetAbsoluteUri(newAbsoluteUri);
|
||||
Instance.TriggerOnLocationChanged(isInterceptedLink);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Given the document's document.baseURI value, returns the URI
|
||||
/// that can be prepended to relative URI paths to produce an absolute URI.
|
||||
/// This is computed by removing anything after the final slash.
|
||||
/// Internal for tests.
|
||||
/// </summary>
|
||||
/// <param name="absoluteBaseUri">The page's document.baseURI value.</param>
|
||||
/// <returns>The URI prefix</returns>
|
||||
internal static string ToBaseUri(string absoluteBaseUri)
|
||||
{
|
||||
if (absoluteBaseUri != null)
|
||||
{
|
||||
var lastSlashIndex = absoluteBaseUri.LastIndexOf('/');
|
||||
if (lastSlashIndex >= 0)
|
||||
{
|
||||
return absoluteBaseUri.Substring(0, lastSlashIndex + 1);
|
||||
}
|
||||
}
|
||||
|
||||
return "/";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,57 +0,0 @@
|
|||
// 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 Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Blazor.Services.Test
|
||||
{
|
||||
public class WebAssemblyUriHelperTest
|
||||
{
|
||||
private WebAssemblyUriHelper _uriHelper = new WebAssemblyUriHelper();
|
||||
|
||||
[Theory]
|
||||
[InlineData("scheme://host/", "scheme://host/")]
|
||||
[InlineData("scheme://host:123/", "scheme://host:123/")]
|
||||
[InlineData("scheme://host/path", "scheme://host/")]
|
||||
[InlineData("scheme://host/path/", "scheme://host/path/")]
|
||||
[InlineData("scheme://host/path/page?query=string&another=here", "scheme://host/path/")]
|
||||
public void ComputesCorrectBaseUri(string baseUri, string expectedResult)
|
||||
{
|
||||
var actualResult = WebAssemblyUriHelper.ToBaseUri(baseUri);
|
||||
Assert.Equal(expectedResult, actualResult);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("scheme://host/", "scheme://host", "")]
|
||||
[InlineData("scheme://host/", "scheme://host/", "")]
|
||||
[InlineData("scheme://host/", "scheme://host/path", "path")]
|
||||
[InlineData("scheme://host/path/", "scheme://host/path/", "")]
|
||||
[InlineData("scheme://host/path/", "scheme://host/path/more", "more")]
|
||||
[InlineData("scheme://host/path/", "scheme://host/path", "")]
|
||||
[InlineData("scheme://host/path/", "scheme://host/path#hash", "#hash")]
|
||||
[InlineData("scheme://host/path/", "scheme://host/path/#hash", "#hash")]
|
||||
[InlineData("scheme://host/path/", "scheme://host/path/more#hash", "more#hash")]
|
||||
public void ComputesCorrectValidBaseRelativePaths(string baseUri, string absoluteUri, string expectedResult)
|
||||
{
|
||||
var actualResult = _uriHelper.ToBaseRelativePath(baseUri, absoluteUri);
|
||||
Assert.Equal(expectedResult, actualResult);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("scheme://host/", "otherscheme://host/")]
|
||||
[InlineData("scheme://host/", "scheme://otherhost/")]
|
||||
[InlineData("scheme://host/path/", "scheme://host/")]
|
||||
public void ThrowsForInvalidBaseRelativePaths(string baseUri, string absoluteUri)
|
||||
{
|
||||
var ex = Assert.Throws<ArgumentException>(() =>
|
||||
{
|
||||
_uriHelper.ToBaseRelativePath(baseUri, absoluteUri);
|
||||
});
|
||||
|
||||
Assert.Equal(
|
||||
$"The URI '{absoluteUri}' is not contained by the base URI '{baseUri}'.",
|
||||
ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -208,8 +208,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
|
|||
..\..\.editorconfig = ..\..\.editorconfig
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Mvc.Components.Prerendering", "..\Mvc\Mvc.Components.Prerendering\src\Microsoft.AspNetCore.Mvc.Components.Prerendering.csproj", "{3A4132B6-60DA-43A0-8E7B-4BF346F3247C}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.SignalR.Protocols.Json", "..\SignalR\common\Protocols.Json\src\Microsoft.AspNetCore.SignalR.Protocols.Json.csproj", "{ED210157-461B-45BB-9D86-B81A62792C30}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.SignalR.Client", "..\SignalR\clients\csharp\Client\src\Microsoft.AspNetCore.SignalR.Client.csproj", "{DA137BD4-F7F1-4D53-855F-5EC40CEA36B0}"
|
||||
|
|
@ -1330,18 +1328,6 @@ Global
|
|||
{9088E4E4-B855-457F-AE9E-D86709A5E1F4}.Release|x64.Build.0 = Debug|Any CPU
|
||||
{9088E4E4-B855-457F-AE9E-D86709A5E1F4}.Release|x86.ActiveCfg = Debug|Any CPU
|
||||
{9088E4E4-B855-457F-AE9E-D86709A5E1F4}.Release|x86.Build.0 = Debug|Any CPU
|
||||
{3A4132B6-60DA-43A0-8E7B-4BF346F3247C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{3A4132B6-60DA-43A0-8E7B-4BF346F3247C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{3A4132B6-60DA-43A0-8E7B-4BF346F3247C}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{3A4132B6-60DA-43A0-8E7B-4BF346F3247C}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{3A4132B6-60DA-43A0-8E7B-4BF346F3247C}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{3A4132B6-60DA-43A0-8E7B-4BF346F3247C}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{3A4132B6-60DA-43A0-8E7B-4BF346F3247C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{3A4132B6-60DA-43A0-8E7B-4BF346F3247C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{3A4132B6-60DA-43A0-8E7B-4BF346F3247C}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{3A4132B6-60DA-43A0-8E7B-4BF346F3247C}.Release|x64.Build.0 = Release|Any CPU
|
||||
{3A4132B6-60DA-43A0-8E7B-4BF346F3247C}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{3A4132B6-60DA-43A0-8E7B-4BF346F3247C}.Release|x86.Build.0 = Release|Any CPU
|
||||
{ED210157-461B-45BB-9D86-B81A62792C30}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{ED210157-461B-45BB-9D86-B81A62792C30}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{ED210157-461B-45BB-9D86-B81A62792C30}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
|
|
@ -1548,7 +1534,6 @@ Global
|
|||
{04262990-929C-42BF-85A9-21C25FA95617} = {2FC10057-7A0A-4E34-8302-879925BC0102}
|
||||
{DC47C40A-FC38-44E4-94A4-ADE794E76309} = {2FC10057-7A0A-4E34-8302-879925BC0102}
|
||||
{9088E4E4-B855-457F-AE9E-D86709A5E1F4} = {7260DED9-22A9-4E9D-92F4-5E8A4404DEAF}
|
||||
{3A4132B6-60DA-43A0-8E7B-4BF346F3247C} = {2FC10057-7A0A-4E34-8302-879925BC0102}
|
||||
{ED210157-461B-45BB-9D86-B81A62792C30} = {2FC10057-7A0A-4E34-8302-879925BC0102}
|
||||
{DA137BD4-F7F1-4D53-855F-5EC40CEA36B0} = {2FC10057-7A0A-4E34-8302-879925BC0102}
|
||||
{0CDAB70B-71DC-43BE-ACB7-AD2EE3541FFB} = {2FC10057-7A0A-4E34-8302-879925BC0102}
|
||||
|
|
|
|||
|
|
@ -266,16 +266,6 @@ namespace Microsoft.AspNetCore.Components
|
|||
{
|
||||
public InjectAttribute() { }
|
||||
}
|
||||
public partial interface IUriHelper
|
||||
{
|
||||
event System.EventHandler<Microsoft.AspNetCore.Components.Routing.LocationChangedEventArgs> OnLocationChanged;
|
||||
string GetAbsoluteUri();
|
||||
string GetBaseUri();
|
||||
void NavigateTo(string uri);
|
||||
void NavigateTo(string uri, bool forceLoad);
|
||||
System.Uri ToAbsoluteUri(string href);
|
||||
string ToBaseRelativePath(string baseUri, string locationAbsolute);
|
||||
}
|
||||
[System.AttributeUsageAttribute(System.AttributeTargets.Class, AllowMultiple=false, Inherited=true)]
|
||||
public sealed partial class LayoutAttribute : System.Attribute
|
||||
{
|
||||
|
|
@ -288,6 +278,10 @@ namespace Microsoft.AspNetCore.Components
|
|||
[Microsoft.AspNetCore.Components.ParameterAttribute]
|
||||
public Microsoft.AspNetCore.Components.RenderFragment Body { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
|
||||
}
|
||||
public sealed partial class LocationChangeException : System.Exception
|
||||
{
|
||||
public LocationChangeException(string message, System.Exception innerException) { }
|
||||
}
|
||||
[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
|
||||
public readonly partial struct MarkupString
|
||||
{
|
||||
|
|
@ -302,6 +296,33 @@ namespace Microsoft.AspNetCore.Components
|
|||
public NavigationException(string uri) { }
|
||||
public string Location { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } }
|
||||
}
|
||||
public abstract partial class NavigationManager
|
||||
{
|
||||
protected NavigationManager() { }
|
||||
public string BaseUri { get { throw null; } protected set { } }
|
||||
public string Uri { get { throw null; } protected set { } }
|
||||
public event System.EventHandler<Microsoft.AspNetCore.Components.Routing.LocationChangedEventArgs> LocationChanged { add { } remove { } }
|
||||
protected virtual void EnsureInitialized() { }
|
||||
protected void Initialize(string baseUri, string uri) { }
|
||||
public void NavigateTo(string uri, bool forceLoad = false) { }
|
||||
protected abstract void NavigateToCore(string uri, bool forceLoad);
|
||||
protected void NotifyLocationChanged(bool isInterceptedLink) { }
|
||||
public System.Uri ToAbsoluteUri(string relativeUri) { throw null; }
|
||||
public string ToBaseRelativePath(string uri) { throw null; }
|
||||
}
|
||||
public abstract partial class OwningComponentBase : Microsoft.AspNetCore.Components.ComponentBase, System.IDisposable
|
||||
{
|
||||
protected OwningComponentBase() { }
|
||||
protected bool IsDisposed { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } }
|
||||
protected System.IServiceProvider ScopedServices { get { throw null; } }
|
||||
protected virtual void Dispose(bool disposing) { }
|
||||
void System.IDisposable.Dispose() { }
|
||||
}
|
||||
public abstract partial class OwningComponentBase<TService> : Microsoft.AspNetCore.Components.OwningComponentBase, System.IDisposable
|
||||
{
|
||||
protected OwningComponentBase() { }
|
||||
protected TService Service { get { throw null; } }
|
||||
}
|
||||
public partial class PageDisplay : Microsoft.AspNetCore.Components.IComponent
|
||||
{
|
||||
public PageDisplay() { }
|
||||
|
|
@ -370,23 +391,6 @@ namespace Microsoft.AspNetCore.Components
|
|||
public RouteAttribute(string template) { }
|
||||
public string Template { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } }
|
||||
}
|
||||
public abstract partial class UriHelperBase : Microsoft.AspNetCore.Components.IUriHelper
|
||||
{
|
||||
protected UriHelperBase() { }
|
||||
public event System.EventHandler<Microsoft.AspNetCore.Components.Routing.LocationChangedEventArgs> OnLocationChanged { add { } remove { } }
|
||||
protected virtual void EnsureInitialized() { }
|
||||
public string GetAbsoluteUri() { throw null; }
|
||||
public virtual string GetBaseUri() { throw null; }
|
||||
public virtual void InitializeState(string uriAbsolute, string baseUriAbsolute) { }
|
||||
public void NavigateTo(string uri) { }
|
||||
public void NavigateTo(string uri, bool forceLoad) { }
|
||||
protected abstract void NavigateToCore(string uri, bool forceLoad);
|
||||
protected void SetAbsoluteBaseUri(string baseUri) { }
|
||||
protected void SetAbsoluteUri(string uri) { }
|
||||
public System.Uri ToAbsoluteUri(string href) { throw null; }
|
||||
public string ToBaseRelativePath(string baseUri, string locationAbsolute) { throw null; }
|
||||
protected void TriggerOnLocationChanged(bool isinterceptedLink) { }
|
||||
}
|
||||
}
|
||||
namespace Microsoft.AspNetCore.Components.CompilerServices
|
||||
{
|
||||
|
|
@ -624,16 +628,17 @@ namespace Microsoft.AspNetCore.Components.RenderTree
|
|||
}
|
||||
namespace Microsoft.AspNetCore.Components.Routing
|
||||
{
|
||||
public partial interface IHostEnvironmentNavigationManager
|
||||
{
|
||||
void Initialize(string baseUri, string uri);
|
||||
}
|
||||
public partial interface INavigationInterception
|
||||
{
|
||||
System.Threading.Tasks.Task EnableNavigationInterceptionAsync();
|
||||
}
|
||||
[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
|
||||
public readonly partial struct LocationChangedEventArgs
|
||||
public partial class LocationChangedEventArgs : System.EventArgs
|
||||
{
|
||||
private readonly object _dummy;
|
||||
private readonly int _dummyPrimitive;
|
||||
public LocationChangedEventArgs(string location, bool isNavigationIntercepted) { throw null; }
|
||||
public LocationChangedEventArgs(string location, bool isNavigationIntercepted) { }
|
||||
public bool IsNavigationIntercepted { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } }
|
||||
public string Location { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,64 +0,0 @@
|
|||
// 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 Microsoft.AspNetCore.Components.Routing;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Helpers for working with URIs and navigation state.
|
||||
/// </summary>
|
||||
public interface IUriHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the current absolute URI.
|
||||
/// </summary>
|
||||
/// <returns>The current absolute URI.</returns>
|
||||
string GetAbsoluteUri();
|
||||
|
||||
/// <summary>
|
||||
/// An event that fires when the navigation location has changed.
|
||||
/// </summary>
|
||||
event EventHandler<LocationChangedEventArgs> OnLocationChanged;
|
||||
|
||||
/// <summary>
|
||||
/// Converts a relative URI into an absolute one (by resolving it
|
||||
/// relative to the current absolute URI).
|
||||
/// </summary>
|
||||
/// <param name="href">The relative URI.</param>
|
||||
/// <returns>The absolute URI.</returns>
|
||||
Uri ToAbsoluteUri(string href);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the base URI (with trailing slash) that can be prepended before relative URI paths to produce an absolute URI.
|
||||
/// Typically this corresponds to the 'href' attribute on the document's <base> element.
|
||||
/// </summary>
|
||||
/// <returns>The URI prefix, which has a trailing slash.</returns>
|
||||
string GetBaseUri();
|
||||
|
||||
/// <summary>
|
||||
/// Given a base URI (e.g., one previously returned by <see cref="GetBaseUri"/>),
|
||||
/// converts an absolute URI into one relative to the base URI prefix.
|
||||
/// </summary>
|
||||
/// <param name="baseUri">The base URI prefix (e.g., previously returned by <see cref="GetBaseUri"/>).</param>
|
||||
/// <param name="locationAbsolute">An absolute URI that is within the space of the base URI.</param>
|
||||
/// <returns>A relative URI path.</returns>
|
||||
string ToBaseRelativePath(string baseUri, string locationAbsolute);
|
||||
|
||||
/// <summary>
|
||||
/// Navigates to the specified URI.
|
||||
/// </summary>
|
||||
/// <param name="uri">The destination URI. This can be absolute, or relative to the base URI
|
||||
/// (as returned by <see cref="GetBaseUri"/>).</param>
|
||||
void NavigateTo(string uri);
|
||||
|
||||
/// <summary>
|
||||
/// Navigates to the specified URI.
|
||||
/// </summary>
|
||||
/// <param name="uri">The destination URI. This can be absolute, or relative to the base URI
|
||||
/// (as returned by <see cref="GetBaseUri"/>).</param>
|
||||
/// <param name="forceLoad">If true, bypasses client-side routing and forces the browser to load the new page from the server, whether or not the URI would normally be handled by the client-side router.</param>
|
||||
void NavigateTo(string uri, bool forceLoad);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
// 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;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// An exception thrown when <see cref="NavigationManager.LocationChanged"/> throws an exception.
|
||||
/// </summary>
|
||||
public sealed class LocationChangeException : Exception
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new instance of <see cref="LocationChangeException"/>.
|
||||
/// </summary>
|
||||
/// <param name="message">The exception message.</param>
|
||||
/// <param name="innerException">The inner exception.</param>
|
||||
public LocationChangeException(string message, Exception innerException)
|
||||
: base(message, innerException)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -6,7 +6,7 @@ using System;
|
|||
namespace Microsoft.AspNetCore.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Exception thrown when an <see cref="IUriHelper"/> is not able to navigate to a different url.
|
||||
/// Exception thrown when an <see cref="NavigationManager"/> is not able to navigate to a different url.
|
||||
/// </summary>
|
||||
public class NavigationException : Exception
|
||||
{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,269 @@
|
|||
// 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 Microsoft.AspNetCore.Components.Routing;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides an abstraction for querying and mananging URI navigation.
|
||||
/// </summary>
|
||||
public abstract class NavigationManager
|
||||
{
|
||||
/// <summary>
|
||||
/// An event that fires when the navigation location has changed.
|
||||
/// </summary>
|
||||
public event EventHandler<LocationChangedEventArgs> LocationChanged
|
||||
{
|
||||
add
|
||||
{
|
||||
AssertInitialized();
|
||||
_locationChanged += value;
|
||||
}
|
||||
remove
|
||||
{
|
||||
AssertInitialized();
|
||||
_locationChanged -= value;
|
||||
}
|
||||
}
|
||||
|
||||
private EventHandler<LocationChangedEventArgs> _locationChanged;
|
||||
|
||||
// For the baseUri it's worth storing as a System.Uri so we can do operations
|
||||
// on that type. System.Uri gives us access to the original string anyway.
|
||||
private Uri _baseUri;
|
||||
|
||||
// The URI. Always represented an absolute URI.
|
||||
private string _uri;
|
||||
|
||||
private bool _isInitialized;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the current base URI. The <see cref="BaseUri" /> is always represented as an absolute URI in string form with trailing slash.
|
||||
/// Typically this corresponds to the 'href' attribute on the document's <base> element.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Setting <see cref="BaseUri" /> will not trigger the <see cref="LocationChanged" /> event.
|
||||
/// </remarks>
|
||||
public string BaseUri
|
||||
{
|
||||
get
|
||||
{
|
||||
AssertInitialized();
|
||||
return _baseUri.OriginalString;
|
||||
}
|
||||
protected set
|
||||
{
|
||||
if (value != null)
|
||||
{
|
||||
value = NormalizeBaseUri(value);
|
||||
}
|
||||
|
||||
_baseUri = new Uri(value, UriKind.Absolute);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the current URI. The <see cref="Uri" /> is always represented as an absolute URI in string form.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Setting <see cref="Uri" /> will not trigger the <see cref="LocationChanged" /> event.
|
||||
/// </remarks>
|
||||
public string Uri
|
||||
{
|
||||
get
|
||||
{
|
||||
AssertInitialized();
|
||||
return _uri;
|
||||
}
|
||||
protected set
|
||||
{
|
||||
Validate(_baseUri, value);
|
||||
_uri = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Navigates to the specified URI.
|
||||
/// </summary>
|
||||
/// <param name="uri">The destination URI. This can be absolute, or relative to the base URI
|
||||
/// (as returned by <see cref="BaseUri"/>).</param>
|
||||
/// <param name="forceLoad">If true, bypasses client-side routing and forces the browser to load the new page from the server, whether or not the URI would normally be handled by the client-side router.</param>
|
||||
public void NavigateTo(string uri, bool forceLoad = false)
|
||||
{
|
||||
AssertInitialized();
|
||||
NavigateToCore(uri, forceLoad);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Navigates to the specified URI.
|
||||
/// </summary>
|
||||
/// <param name="uri">The destination URI. This can be absolute, or relative to the base URI
|
||||
/// (as returned by <see cref="BaseUri"/>).</param>
|
||||
/// <param name="forceLoad">If true, bypasses client-side routing and forces the browser to load the new page from the server, whether or not the URI would normally be handled by the client-side router.</param>
|
||||
protected abstract void NavigateToCore(string uri, bool forceLoad);
|
||||
|
||||
/// <summary>
|
||||
/// Called to initialize BaseURI and current URI before these values are used for the first time.
|
||||
/// Override <see cref="EnsureInitialized" /> and call this method to dynamically calculate these values.
|
||||
/// </summary>
|
||||
protected void Initialize(string baseUri, string uri)
|
||||
{
|
||||
// Make sure it's possible/safe to call this method from constructors of derived classes.
|
||||
if (uri == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(uri));
|
||||
}
|
||||
|
||||
if (baseUri == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(baseUri));
|
||||
}
|
||||
|
||||
if (_isInitialized)
|
||||
{
|
||||
throw new InvalidOperationException($"'{GetType().Name}' already initialized.");
|
||||
}
|
||||
|
||||
_isInitialized = true;
|
||||
|
||||
// Setting BaseUri before Uri so they get validated.
|
||||
BaseUri = baseUri;
|
||||
Uri = uri;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Allows derived classes to lazyly self-initialize. Implementations that support lazy-initialization should override
|
||||
/// this method and call <see cref="Initialize(string, string)" />.
|
||||
/// </summary>
|
||||
protected virtual void EnsureInitialized()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a relative URI into an absolute one (by resolving it
|
||||
/// relative to the current absolute URI).
|
||||
/// </summary>
|
||||
/// <param name="relativeUri">The relative URI.</param>
|
||||
/// <returns>The absolute URI.</returns>
|
||||
public Uri ToAbsoluteUri(string relativeUri)
|
||||
{
|
||||
AssertInitialized();
|
||||
return new Uri(_baseUri, relativeUri);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Given a base URI (e.g., one previously returned by <see cref="BaseUri"/>),
|
||||
/// converts an absolute URI into one relative to the base URI prefix.
|
||||
/// </summary>
|
||||
/// <param name="uri">An absolute URI that is within the space of the base URI.</param>
|
||||
/// <returns>A relative URI path.</returns>
|
||||
public string ToBaseRelativePath(string uri)
|
||||
{
|
||||
if (uri.StartsWith(_baseUri.OriginalString, StringComparison.Ordinal))
|
||||
{
|
||||
// The absolute URI must be of the form "{baseUri}something" (where
|
||||
// baseUri ends with a slash), and from that we return "something"
|
||||
return uri.Substring(_baseUri.OriginalString.Length);
|
||||
}
|
||||
|
||||
var hashIndex = uri.IndexOf('#');
|
||||
var uriWithoutHash = hashIndex < 0 ? uri : uri.Substring(0, hashIndex);
|
||||
if ($"{uriWithoutHash}/".Equals(_baseUri.OriginalString, StringComparison.Ordinal))
|
||||
{
|
||||
// Special case: for the base URI "/something/", if you're at
|
||||
// "/something" then treat it as if you were at "/something/" (i.e.,
|
||||
// with the trailing slash). It's a bit ambiguous because we don't know
|
||||
// whether the server would return the same page whether or not the
|
||||
// slash is present, but ASP.NET Core at least does by default when
|
||||
// using PathBase.
|
||||
return uri.Substring(_baseUri.OriginalString.Length - 1);
|
||||
}
|
||||
|
||||
var message = $"The URI '{uri}' is not contained by the base URI '{_baseUri}'.";
|
||||
throw new ArgumentException(message);
|
||||
}
|
||||
|
||||
internal static string NormalizeBaseUri(string baseUri)
|
||||
{
|
||||
var lastSlashIndex = baseUri.LastIndexOf('/');
|
||||
if (lastSlashIndex >= 0)
|
||||
{
|
||||
baseUri = baseUri.Substring(0, lastSlashIndex + 1);
|
||||
}
|
||||
|
||||
return baseUri;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Triggers the <see cref="LocationChanged"/> event with the current URI value.
|
||||
/// </summary>
|
||||
protected void NotifyLocationChanged(bool isInterceptedLink)
|
||||
{
|
||||
try
|
||||
{
|
||||
_locationChanged?.Invoke(this, new LocationChangedEventArgs(_uri, isInterceptedLink));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new LocationChangeException("An exception occurred while dispatching a location changed event.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void AssertInitialized()
|
||||
{
|
||||
if (!_isInitialized)
|
||||
{
|
||||
EnsureInitialized();
|
||||
}
|
||||
|
||||
if (!_isInitialized)
|
||||
{
|
||||
throw new InvalidOperationException($"'{GetType().Name}' has not been initialized.");
|
||||
}
|
||||
}
|
||||
|
||||
private static bool TryGetLengthOfBaseUriPrefix(Uri baseUri, string uri, out int length)
|
||||
{
|
||||
if (uri.StartsWith(baseUri.OriginalString, StringComparison.Ordinal))
|
||||
{
|
||||
// The absolute URI must be of the form "{baseUri}something" (where
|
||||
// baseUri ends with a slash), and from that we return "something"
|
||||
length = baseUri.OriginalString.Length;
|
||||
return true;
|
||||
}
|
||||
|
||||
var hashIndex = uri.IndexOf('#');
|
||||
var uriWithoutHash = hashIndex < 0 ? uri : uri.Substring(0, hashIndex);
|
||||
if ($"{uriWithoutHash}/".Equals(baseUri.OriginalString, StringComparison.Ordinal))
|
||||
{
|
||||
// Special case: for the base URI "/something/", if you're at
|
||||
// "/something" then treat it as if you were at "/something/" (i.e.,
|
||||
// with the trailing slash). It's a bit ambiguous because we don't know
|
||||
// whether the server would return the same page whether or not the
|
||||
// slash is present, but ASP.NET Core at least does by default when
|
||||
// using PathBase.
|
||||
length = baseUri.OriginalString.Length - 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
length = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void Validate(Uri baseUri, string uri)
|
||||
{
|
||||
if (baseUri == null || uri == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!TryGetLengthOfBaseUriPrefix(baseUri, uri, out _))
|
||||
{
|
||||
var message = $"The URI '{uri}' is not contained by the base URI '{baseUri}'.";
|
||||
throw new ArgumentException(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,100 @@
|
|||
// 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 Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// A base class that creates a service provider scope.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Use the <see cref="OwningComponentBase"/> class as a base class to author components that control
|
||||
/// the lifetime of a service provider scope. This is useful when using a transient or scoped service that
|
||||
/// requires disposal such as a repository or database abstraction. Using <see cref="OwningComponentBase"/>
|
||||
/// as a base class ensures that the service provider scope is disposed with the component.
|
||||
/// </remarks>
|
||||
public abstract class OwningComponentBase : ComponentBase, IDisposable
|
||||
{
|
||||
private IServiceScope _scope;
|
||||
|
||||
[Inject] IServiceScopeFactory ScopeFactory { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value determining if the component and associated services have been disposed.
|
||||
/// </summary>
|
||||
protected bool IsDisposed { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the scoped <see cref="IServiceProvider"/> that is associated with this component.
|
||||
/// </summary>
|
||||
protected IServiceProvider ScopedServices
|
||||
{
|
||||
get
|
||||
{
|
||||
if (ScopeFactory == null)
|
||||
{
|
||||
throw new InvalidOperationException("Services cannot be accessed before the component is initialized.");
|
||||
}
|
||||
|
||||
if (IsDisposed)
|
||||
{
|
||||
throw new ObjectDisposedException(GetType().Name);
|
||||
}
|
||||
|
||||
_scope ??= ScopeFactory.CreateScope();
|
||||
return _scope.ServiceProvider;
|
||||
}
|
||||
}
|
||||
|
||||
void IDisposable.Dispose()
|
||||
{
|
||||
if (!IsDisposed)
|
||||
{
|
||||
_scope?.Dispose();
|
||||
_scope = null;
|
||||
Dispose(disposing: true);
|
||||
IsDisposed = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A base class that creates a service provider scope, and resolves a service of type <typeparamref name="TService"/>.
|
||||
/// </summary>
|
||||
/// <typeparam name="TService">The service type.</typeparam>
|
||||
/// <remarks>
|
||||
/// Use the <see cref="OwningComponentBase{TService}"/> class as a base class to author components that control
|
||||
/// the lifetime of a service or multiple services. This is useful when using a transient or scoped service that
|
||||
/// requires disposal such as a repository or database abstraction. Using <see cref="OwningComponentBase{TService}"/>
|
||||
/// as a base class ensures that the service and relates services that share its scope are disposed with the component.
|
||||
/// </remarks>
|
||||
public abstract class OwningComponentBase<TService> : OwningComponentBase, IDisposable
|
||||
{
|
||||
private TService _item;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <typeparamref name="TService"/> that is associated with this component.
|
||||
/// </summary>
|
||||
protected TService Service
|
||||
{
|
||||
get
|
||||
{
|
||||
if (IsDisposed)
|
||||
{
|
||||
throw new ObjectDisposedException(GetType().Name);
|
||||
}
|
||||
|
||||
// We cache this because we don't know the lifetime. We have to assume that it could be transient.
|
||||
_item ??= ScopedServices.GetRequiredService<TService>();
|
||||
return _item;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -99,6 +99,10 @@ namespace Microsoft.AspNetCore.Components.RenderTree
|
|||
if (oldKey != null || newKey != null)
|
||||
{
|
||||
#region "Get diff action by matching on key"
|
||||
// Regardless of whether these two keys match, since you are using keys, we want to validate at this point that there are no clashes
|
||||
// so ensure we've built the dictionary that will be used for lookups if any don't match
|
||||
keyedItemInfos ??= BuildKeyToInfoLookup(diffContext, origOldStartIndex, oldEndIndexExcl, origNewStartIndex, newEndIndexExcl);
|
||||
|
||||
if (Equals(oldKey, newKey))
|
||||
{
|
||||
// Keys match
|
||||
|
|
@ -108,11 +112,6 @@ namespace Microsoft.AspNetCore.Components.RenderTree
|
|||
else
|
||||
{
|
||||
// Keys don't match
|
||||
if (keyedItemInfos == null)
|
||||
{
|
||||
keyedItemInfos = BuildKeyToInfoLookup(diffContext, origOldStartIndex, oldEndIndexExcl, origNewStartIndex, newEndIndexExcl);
|
||||
}
|
||||
|
||||
var oldKeyItemInfo = oldKey != null ? keyedItemInfos[oldKey] : new KeyedItemInfo(-1, -1);
|
||||
var newKeyItemInfo = newKey != null ? keyedItemInfos[newKey] : new KeyedItemInfo(-1, -1);
|
||||
var oldKeyIsInNewTree = oldKeyItemInfo.NewIndex >= 0;
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.ExceptionServices;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Components.RenderTree;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
|
@ -21,6 +22,8 @@ namespace Microsoft.AspNetCore.Components.Rendering
|
|||
"area", "base", "br", "col", "embed", "hr", "img", "input", "link", "meta", "param", "source", "track", "wbr"
|
||||
};
|
||||
|
||||
private static readonly Task CanceledRenderTask = Task.FromCanceled(new CancellationToken(canceled: true));
|
||||
|
||||
private readonly Func<string, string> _htmlEncoder;
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -40,7 +43,19 @@ namespace Microsoft.AspNetCore.Components.Rendering
|
|||
/// <inheritdoc />
|
||||
protected override Task UpdateDisplayAsync(in RenderBatch renderBatch)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
// By default we return a canceled task. This has the effect of making it so that the
|
||||
// OnAfterRenderAsync callbacks on components don't run by default.
|
||||
// This way, by default prerendering gets the correct behavior and other renderers
|
||||
// override the UpdateDisplayAsync method already, so those components can
|
||||
// either complete a task when the client acknowledges the render, or return a canceled task
|
||||
// when the renderer gets disposed.
|
||||
|
||||
// We believe that returning a canceled task is the right behavior as we expect that any class
|
||||
// that subclasses this class to provide an implementation for a given rendering scenario respects
|
||||
// the contract that OnAfterRender should only be called when the display has successfully been updated
|
||||
// and the application is interactive. (Element and component references are populated and JavaScript interop
|
||||
// is available).
|
||||
return CanceledRenderTask;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -445,8 +445,12 @@ namespace Microsoft.AspNetCore.Components.Rendering
|
|||
{
|
||||
if (updateDisplayTask.IsCanceled)
|
||||
{
|
||||
// The display update was cancelled (maybe due to a timeout on the components server-side case or due
|
||||
// to the renderer being disposed)
|
||||
// The display update was canceled.
|
||||
// This can be due to a timeout on the components server-side case, or the renderer being disposed.
|
||||
|
||||
// The latter case is normal during prerendering, as the render never fully completes (the display never
|
||||
// gets updated, no references get populated and JavaScript interop is not available) and we simply discard
|
||||
// the renderer after producing the prerendered content.
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
if (updateDisplayTask.IsFaulted)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,19 @@
|
|||
// 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.
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.Routing
|
||||
{
|
||||
/// <summary>
|
||||
/// An optional interface for <see cref="NavigationManager" /> implementations that must be initialized
|
||||
/// by the host.
|
||||
/// </summary>
|
||||
public interface IHostEnvironmentNavigationManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes the <see cref="NavigationManager" />.
|
||||
/// </summary>
|
||||
/// <param name="baseUri">The base URI.</param>
|
||||
/// <param name="uri">The absolute URI.</param>
|
||||
void Initialize(string baseUri, string uri);
|
||||
}
|
||||
}
|
||||
|
|
@ -6,9 +6,9 @@ using System;
|
|||
namespace Microsoft.AspNetCore.Components.Routing
|
||||
{
|
||||
/// <summary>
|
||||
/// <see cref="EventArgs" /> for <see cref="IUriHelper.OnLocationChanged" />.
|
||||
/// <see cref="EventArgs" /> for <see cref="NavigationManager.LocationChanged" />.
|
||||
/// </summary>
|
||||
public readonly struct LocationChangedEventArgs
|
||||
public class LocationChangedEventArgs : EventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="LocationChangedEventArgs" />.
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ namespace Microsoft.AspNetCore.Components.Routing
|
|||
bool _navigationInterceptionEnabled;
|
||||
ILogger<Router> _logger;
|
||||
|
||||
[Inject] private IUriHelper UriHelper { get; set; }
|
||||
[Inject] private NavigationManager NavigationManager { get; set; }
|
||||
|
||||
[Inject] private INavigationInterception NavigationInterception { get; set; }
|
||||
|
||||
|
|
@ -60,9 +60,9 @@ namespace Microsoft.AspNetCore.Components.Routing
|
|||
{
|
||||
_logger = LoggerFactory.CreateLogger<Router>();
|
||||
_renderHandle = renderHandle;
|
||||
_baseUri = UriHelper.GetBaseUri();
|
||||
_locationAbsolute = UriHelper.GetAbsoluteUri();
|
||||
UriHelper.OnLocationChanged += OnLocationChanged;
|
||||
_baseUri = NavigationManager.BaseUri;
|
||||
_locationAbsolute = NavigationManager.Uri;
|
||||
NavigationManager.LocationChanged += OnLocationChanged;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
|
@ -77,7 +77,7 @@ namespace Microsoft.AspNetCore.Components.Routing
|
|||
/// <inheritdoc />
|
||||
public void Dispose()
|
||||
{
|
||||
UriHelper.OnLocationChanged -= OnLocationChanged;
|
||||
NavigationManager.LocationChanged -= OnLocationChanged;
|
||||
}
|
||||
|
||||
private string StringUntilAny(string str, char[] chars)
|
||||
|
|
@ -101,7 +101,7 @@ namespace Microsoft.AspNetCore.Components.Routing
|
|||
|
||||
private void Refresh(bool isNavigationIntercepted)
|
||||
{
|
||||
var locationPath = UriHelper.ToBaseRelativePath(_baseUri, _locationAbsolute);
|
||||
var locationPath = NavigationManager.ToBaseRelativePath(_locationAbsolute);
|
||||
locationPath = StringUntilAny(locationPath, _queryOrHashStartChar);
|
||||
var context = new RouteContext(locationPath);
|
||||
Routes.Route(context);
|
||||
|
|
@ -132,7 +132,7 @@ namespace Microsoft.AspNetCore.Components.Routing
|
|||
else
|
||||
{
|
||||
Log.NavigatingToExternalUri(_logger, _locationAbsolute, locationPath, _baseUri);
|
||||
UriHelper.NavigateTo(_locationAbsolute, forceLoad: true);
|
||||
NavigationManager.NavigateTo(_locationAbsolute, forceLoad: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,230 +0,0 @@
|
|||
// 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 Microsoft.AspNetCore.Components.Routing;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// A base class for <see cref="IUriHelper"/> implementations.
|
||||
/// </summary>
|
||||
public abstract class UriHelperBase : IUriHelper
|
||||
{
|
||||
private EventHandler<LocationChangedEventArgs> _onLocationChanged;
|
||||
|
||||
/// <summary>
|
||||
/// An event that fires when the navigation location has changed.
|
||||
/// </summary>
|
||||
public event EventHandler<LocationChangedEventArgs> OnLocationChanged
|
||||
{
|
||||
add
|
||||
{
|
||||
AssertInitialized();
|
||||
_onLocationChanged += value;
|
||||
}
|
||||
remove
|
||||
{
|
||||
_onLocationChanged -= value;
|
||||
}
|
||||
}
|
||||
|
||||
// For the baseUri it's worth storing both the string form and Uri form and
|
||||
// keeping them in sync. These are always represented as absolute URIs with
|
||||
// a trailing slash.
|
||||
private Uri _baseUri;
|
||||
private string _baseUriString;
|
||||
|
||||
// The URI. Always represented an absolute URI.
|
||||
private string _uri;
|
||||
|
||||
private bool _isInitialized;
|
||||
|
||||
/// <summary>
|
||||
/// Navigates to the specified URI.
|
||||
/// </summary>
|
||||
/// <param name="uri">The destination URI. This can be absolute, or relative to the base URI
|
||||
/// (as returned by <see cref="GetBaseUri"/>).</param>
|
||||
public void NavigateTo(string uri)
|
||||
{
|
||||
NavigateTo(uri, forceLoad: false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Navigates to the specified URI.
|
||||
/// </summary>
|
||||
/// <param name="uri">The destination URI. This can be absolute, or relative to the base URI
|
||||
/// (as returned by <see cref="GetBaseUri"/>).</param>
|
||||
/// <param name="forceLoad">If true, bypasses client-side routing and forces the browser to load the new page from the server, whether or not the URI would normally be handled by the client-side router.</param>
|
||||
public void NavigateTo(string uri, bool forceLoad)
|
||||
{
|
||||
AssertInitialized();
|
||||
NavigateToCore(uri, forceLoad);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Navigates to the specified URI.
|
||||
/// </summary>
|
||||
/// <param name="uri">The destination URI. This can be absolute, or relative to the base URI
|
||||
/// (as returned by <see cref="GetBaseUri"/>).</param>
|
||||
/// <param name="forceLoad">If true, bypasses client-side routing and forces the browser to load the new page from the server, whether or not the URI would normally be handled by the client-side router.</param>
|
||||
protected abstract void NavigateToCore(string uri, bool forceLoad);
|
||||
|
||||
/// <summary>
|
||||
/// Called to initialize BaseURI and current URI before these values are used for the first time.
|
||||
/// Override this method to dynamically calculate these values.
|
||||
/// </summary>
|
||||
public virtual void InitializeState(string uriAbsolute, string baseUriAbsolute)
|
||||
{
|
||||
if (uriAbsolute == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(uriAbsolute));
|
||||
}
|
||||
|
||||
if (baseUriAbsolute == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(baseUriAbsolute));
|
||||
}
|
||||
|
||||
if (_isInitialized)
|
||||
{
|
||||
throw new InvalidOperationException($"'{typeof(UriHelperBase).Name}' already initialized.");
|
||||
}
|
||||
_isInitialized = true;
|
||||
|
||||
SetAbsoluteUri(uriAbsolute);
|
||||
SetAbsoluteBaseUri(baseUriAbsolute);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Allows derived classes to lazyly self initialize. It does nothing unless overriden.
|
||||
/// </summary>
|
||||
protected virtual void EnsureInitialized()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current absolute URI.
|
||||
/// </summary>
|
||||
/// <returns>The current absolute URI.</returns>
|
||||
public string GetAbsoluteUri()
|
||||
{
|
||||
AssertInitialized();
|
||||
return _uri;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the base URI (with trailing slash) that can be prepended before relative URI paths to
|
||||
/// produce an absolute URI. Typically this corresponds to the 'href' attribute on the
|
||||
/// document's <base> element.
|
||||
/// </summary>
|
||||
/// <returns>The URI prefix, which has a trailing slash.</returns>
|
||||
public virtual string GetBaseUri()
|
||||
{
|
||||
AssertInitialized();
|
||||
return _baseUriString;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a relative URI into an absolute one (by resolving it
|
||||
/// relative to the current absolute URI).
|
||||
/// </summary>
|
||||
/// <param name="href">The relative URI.</param>
|
||||
/// <returns>The absolute URI.</returns>
|
||||
public Uri ToAbsoluteUri(string href)
|
||||
{
|
||||
AssertInitialized();
|
||||
return new Uri(_baseUri, href);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Given a base URI (e.g., one previously returned by <see cref="GetBaseUri"/>),
|
||||
/// converts an absolute URI into one relative to the base URI prefix.
|
||||
/// </summary>
|
||||
/// <param name="baseUri">
|
||||
/// The base URI prefix (e.g., previously returned by <see cref="GetBaseUri"/>).
|
||||
/// </param>
|
||||
/// <param name="locationAbsolute">An absolute URI that is within the space of the base URI.</param>
|
||||
/// <returns>A relative URI path.</returns>
|
||||
public string ToBaseRelativePath(string baseUri, string locationAbsolute)
|
||||
{
|
||||
if (locationAbsolute.StartsWith(baseUri, StringComparison.Ordinal))
|
||||
{
|
||||
// The absolute URI must be of the form "{baseUri}something" (where
|
||||
// baseUri ends with a slash), and from that we return "something"
|
||||
return locationAbsolute.Substring(baseUri.Length);
|
||||
}
|
||||
|
||||
var hashIndex = locationAbsolute.IndexOf('#');
|
||||
var locationAbsoluteNoHash = hashIndex < 0 ? locationAbsolute : locationAbsolute.Substring(0, hashIndex);
|
||||
if ($"{locationAbsoluteNoHash}/".Equals(baseUri, StringComparison.Ordinal))
|
||||
{
|
||||
// Special case: for the base URI "/something/", if you're at
|
||||
// "/something" then treat it as if you were at "/something/" (i.e.,
|
||||
// with the trailing slash). It's a bit ambiguous because we don't know
|
||||
// whether the server would return the same page whether or not the
|
||||
// slash is present, but ASP.NET Core at least does by default when
|
||||
// using PathBase.
|
||||
return locationAbsolute.Substring(baseUri.Length - 1);
|
||||
}
|
||||
|
||||
var message = $"The URI '{locationAbsolute}' is not contained by the base URI '{baseUri}'.";
|
||||
throw new ArgumentException(message);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the URI to the provided value.
|
||||
/// </summary>
|
||||
/// <param name="uri">The URI. Must be an absolute URI.</param>
|
||||
/// <remarks>
|
||||
/// Calling <see cref="SetAbsoluteUri(string)"/> does not trigger <see cref="OnLocationChanged"/>.
|
||||
/// </remarks>
|
||||
protected void SetAbsoluteUri(string uri)
|
||||
{
|
||||
_uri = uri;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the base URI to the provided value (after normalization).
|
||||
/// </summary>
|
||||
/// <param name="baseUri">The base URI. Must be an absolute URI.</param>
|
||||
/// <remarks>
|
||||
/// Calling <see cref="SetAbsoluteBaseUri(string)"/> does not trigger <see cref="OnLocationChanged"/>.
|
||||
/// </remarks>
|
||||
protected void SetAbsoluteBaseUri(string baseUri)
|
||||
{
|
||||
if (baseUri != null)
|
||||
{
|
||||
var lastSlashIndex = baseUri.LastIndexOf('/');
|
||||
if (lastSlashIndex >= 0)
|
||||
{
|
||||
baseUri = baseUri.Substring(0, lastSlashIndex + 1);
|
||||
}
|
||||
}
|
||||
|
||||
_baseUriString = baseUri ?? "/";
|
||||
_baseUri = new Uri(_baseUriString);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Triggers the <see cref="OnLocationChanged"/> event with the current URI value.
|
||||
/// </summary>
|
||||
protected void TriggerOnLocationChanged(bool isinterceptedLink)
|
||||
{
|
||||
_onLocationChanged?.Invoke(this, new LocationChangedEventArgs(_uri, isinterceptedLink));
|
||||
}
|
||||
|
||||
private void AssertInitialized()
|
||||
{
|
||||
if (!_isInitialized)
|
||||
{
|
||||
EnsureInitialized();
|
||||
}
|
||||
|
||||
if (!_isInitialized)
|
||||
{
|
||||
throw new InvalidOperationException($"'{GetType().Name}' has not been initialized.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,117 @@
|
|||
// 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 Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components
|
||||
{
|
||||
public class NavigationManagerTest
|
||||
{
|
||||
[Theory]
|
||||
[InlineData("scheme://host/", "scheme://host/")]
|
||||
[InlineData("scheme://host:123/", "scheme://host:123/")]
|
||||
[InlineData("scheme://host/path", "scheme://host/")]
|
||||
[InlineData("scheme://host/path/", "scheme://host/path/")]
|
||||
[InlineData("scheme://host/path/page?query=string&another=here", "scheme://host/path/")]
|
||||
public void ComputesCorrectBaseUri(string baseUri, string expectedResult)
|
||||
{
|
||||
var actualResult = NavigationManager.NormalizeBaseUri(baseUri);
|
||||
Assert.Equal(expectedResult, actualResult);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("scheme://host/", "scheme://host", "")]
|
||||
[InlineData("scheme://host/", "scheme://host/", "")]
|
||||
[InlineData("scheme://host/", "scheme://host/path", "path")]
|
||||
[InlineData("scheme://host/path/", "scheme://host/path/", "")]
|
||||
[InlineData("scheme://host/path/", "scheme://host/path/more", "more")]
|
||||
[InlineData("scheme://host/path/", "scheme://host/path", "")]
|
||||
[InlineData("scheme://host/path/", "scheme://host/path#hash", "#hash")]
|
||||
[InlineData("scheme://host/path/", "scheme://host/path/#hash", "#hash")]
|
||||
[InlineData("scheme://host/path/", "scheme://host/path/more#hash", "more#hash")]
|
||||
public void ComputesCorrectValidBaseRelativePaths(string baseUri, string uri, string expectedResult)
|
||||
{
|
||||
var navigationManager = new TestNavigationManager(baseUri);
|
||||
|
||||
var actualResult = navigationManager.ToBaseRelativePath(uri);
|
||||
Assert.Equal(expectedResult, actualResult);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("scheme://host/", "otherscheme://host/")]
|
||||
[InlineData("scheme://host/", "scheme://otherhost/")]
|
||||
[InlineData("scheme://host/path/", "scheme://host/")]
|
||||
public void Initialize_ThrowsForInvalidBaseRelativePaths(string baseUri, string absoluteUri)
|
||||
{
|
||||
var navigationManager = new TestNavigationManager();
|
||||
|
||||
var ex = Assert.Throws<ArgumentException>(() =>
|
||||
{
|
||||
navigationManager.Initialize(baseUri, absoluteUri);
|
||||
});
|
||||
|
||||
Assert.Equal(
|
||||
$"The URI '{absoluteUri}' is not contained by the base URI '{baseUri}'.",
|
||||
ex.Message);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("scheme://host/", "otherscheme://host/")]
|
||||
[InlineData("scheme://host/", "scheme://otherhost/")]
|
||||
[InlineData("scheme://host/path/", "scheme://host/")]
|
||||
public void Uri_ThrowsForInvalidBaseRelativePaths(string baseUri, string absoluteUri)
|
||||
{
|
||||
var navigationManager = new TestNavigationManager(baseUri);
|
||||
|
||||
var ex = Assert.Throws<ArgumentException>(() =>
|
||||
{
|
||||
navigationManager.ToBaseRelativePath(absoluteUri);
|
||||
});
|
||||
|
||||
Assert.Equal(
|
||||
$"The URI '{absoluteUri}' is not contained by the base URI '{baseUri}'.",
|
||||
ex.Message);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("scheme://host/", "otherscheme://host/")]
|
||||
[InlineData("scheme://host/", "scheme://otherhost/")]
|
||||
[InlineData("scheme://host/path/", "scheme://host/")]
|
||||
public void ToBaseRelativePath_ThrowsForInvalidBaseRelativePaths(string baseUri, string absoluteUri)
|
||||
{
|
||||
var navigationManager = new TestNavigationManager(baseUri);
|
||||
|
||||
var ex = Assert.Throws<ArgumentException>(() =>
|
||||
{
|
||||
navigationManager.ToBaseRelativePath(absoluteUri);
|
||||
});
|
||||
|
||||
Assert.Equal(
|
||||
$"The URI '{absoluteUri}' is not contained by the base URI '{baseUri}'.",
|
||||
ex.Message);
|
||||
}
|
||||
|
||||
private class TestNavigationManager : NavigationManager
|
||||
{
|
||||
public TestNavigationManager()
|
||||
{
|
||||
}
|
||||
|
||||
public TestNavigationManager(string baseUri = null, string uri = null)
|
||||
{
|
||||
Initialize(baseUri ?? "http://example.com/", uri ?? baseUri ?? "http://example.com/welcome-page");
|
||||
}
|
||||
|
||||
public new void Initialize(string baseUri, string uri)
|
||||
{
|
||||
base.Initialize(baseUri, uri);
|
||||
}
|
||||
|
||||
protected override void NavigateToCore(string uri, bool forceLoad)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
// 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.Dynamic;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Components.RenderTree;
|
||||
using Microsoft.AspNetCore.Components.Test.Helpers;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components
|
||||
{
|
||||
public class OwningComponentBaseTest
|
||||
{
|
||||
[Fact]
|
||||
public void CreatesScopeAndService()
|
||||
{
|
||||
var services = new ServiceCollection();
|
||||
services.AddSingleton<Counter>();
|
||||
services.AddTransient<MyService>();
|
||||
var serviceProvider = services.BuildServiceProvider();
|
||||
|
||||
var counter = serviceProvider.GetRequiredService<Counter>();
|
||||
var renderer = new TestRenderer(serviceProvider);
|
||||
var component1 = renderer.InstantiateComponent<MyOwningComponent>();
|
||||
|
||||
Assert.NotNull(component1.MyService);
|
||||
Assert.Equal(1, counter.CreatedCount);
|
||||
Assert.Equal(0, counter.DisposedCount);
|
||||
|
||||
((IDisposable)component1).Dispose();
|
||||
Assert.Equal(1, counter.CreatedCount);
|
||||
Assert.Equal(1, counter.DisposedCount);
|
||||
}
|
||||
|
||||
private class Counter
|
||||
{
|
||||
public int CreatedCount { get; set; }
|
||||
public int DisposedCount { get; set; }
|
||||
}
|
||||
|
||||
private class MyService : IDisposable
|
||||
{
|
||||
public MyService(Counter counter)
|
||||
{
|
||||
Counter = counter;
|
||||
Counter.CreatedCount++;
|
||||
}
|
||||
|
||||
public Counter Counter { get; }
|
||||
|
||||
void IDisposable.Dispose() => Counter.DisposedCount++;
|
||||
}
|
||||
|
||||
private class MyOwningComponent : OwningComponentBase<MyService>
|
||||
{
|
||||
public MyService MyService => Service;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -360,6 +360,23 @@ namespace Microsoft.AspNetCore.Components.Test
|
|||
Assert.Equal("More than one sibling has the same key value, 'key1'. Key values must be unique.", ex.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RejectsClashingKeysEvenIfAllPairsMatch()
|
||||
{
|
||||
// This sort of scenario would happen if you accidentally used a constant value for @key
|
||||
|
||||
// Arrange
|
||||
AddWithKey(oldTree, "key1", "attrib1a");
|
||||
AddWithKey(oldTree, "key1", "attrib1b");
|
||||
|
||||
AddWithKey(newTree, "key1", "attrib1a");
|
||||
AddWithKey(newTree, "key1", "attrib1b");
|
||||
|
||||
// Act/Assert
|
||||
var ex = Assert.Throws<InvalidOperationException>(() => GetSingleUpdatedComponent());
|
||||
Assert.Equal("More than one sibling has the same key value, 'key1'. Key values must be unique.", ex.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void HandlesInsertionOfUnkeyedItemsAroundKey()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -14,8 +14,6 @@ namespace Microsoft.AspNetCore.Builder
|
|||
}
|
||||
public static partial class ComponentEndpointRouteBuilderExtensions
|
||||
{
|
||||
public static Microsoft.AspNetCore.Builder.ComponentEndpointConventionBuilder MapBlazorHub(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints) { throw null; }
|
||||
public static Microsoft.AspNetCore.Builder.ComponentEndpointConventionBuilder MapBlazorHub(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints, System.Action<Microsoft.AspNetCore.Http.Connections.HttpConnectionDispatcherOptions> configureOptions) { throw null; }
|
||||
public static Microsoft.AspNetCore.Builder.ComponentEndpointConventionBuilder MapBlazorHub(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints, System.Type type, string selector) { throw null; }
|
||||
public static Microsoft.AspNetCore.Builder.ComponentEndpointConventionBuilder MapBlazorHub(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints, System.Type type, string selector, System.Action<Microsoft.AspNetCore.Http.Connections.HttpConnectionDispatcherOptions> configureOptions) { throw null; }
|
||||
public static Microsoft.AspNetCore.Builder.ComponentEndpointConventionBuilder MapBlazorHub(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints, System.Type componentType, string selector, string path) { throw null; }
|
||||
|
|
@ -36,22 +34,6 @@ namespace Microsoft.AspNetCore.Components.Server
|
|||
public System.TimeSpan DisconnectedCircuitRetentionPeriod { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
|
||||
public System.TimeSpan JSInteropDefaultCallTimeout { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
|
||||
}
|
||||
public partial class ComponentPrerenderingContext
|
||||
{
|
||||
public ComponentPrerenderingContext() { }
|
||||
public System.Type ComponentType { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
|
||||
public Microsoft.AspNetCore.Http.HttpContext Context { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
|
||||
public Microsoft.AspNetCore.Components.ParameterView Parameters { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
|
||||
}
|
||||
public sealed partial class ComponentPrerenderResult
|
||||
{
|
||||
internal ComponentPrerenderResult() { }
|
||||
public void WriteTo(System.IO.TextWriter writer) { }
|
||||
}
|
||||
public partial interface IComponentPrerenderer
|
||||
{
|
||||
System.Threading.Tasks.Task<Microsoft.AspNetCore.Components.Server.ComponentPrerenderResult> PrerenderComponentAsync(Microsoft.AspNetCore.Components.Server.ComponentPrerenderingContext context);
|
||||
}
|
||||
}
|
||||
namespace Microsoft.AspNetCore.Components.Server.Circuits
|
||||
{
|
||||
|
|
@ -69,15 +51,6 @@ namespace Microsoft.AspNetCore.Components.Server.Circuits
|
|||
public virtual System.Threading.Tasks.Task OnConnectionDownAsync(Microsoft.AspNetCore.Components.Server.Circuits.Circuit circuit, System.Threading.CancellationToken cancellationToken) { throw null; }
|
||||
public virtual System.Threading.Tasks.Task OnConnectionUpAsync(Microsoft.AspNetCore.Components.Server.Circuits.Circuit circuit, System.Threading.CancellationToken cancellationToken) { throw null; }
|
||||
}
|
||||
public partial class RemoteUriHelper : Microsoft.AspNetCore.Components.UriHelperBase
|
||||
{
|
||||
public RemoteUriHelper(Microsoft.Extensions.Logging.ILogger<Microsoft.AspNetCore.Components.Server.Circuits.RemoteUriHelper> logger) { }
|
||||
public bool HasAttachedJSRuntime { get { throw null; } }
|
||||
public override void InitializeState(string uriAbsolute, string baseUriAbsolute) { }
|
||||
protected override void NavigateToCore(string uri, bool forceLoad) { }
|
||||
[Microsoft.JSInterop.JSInvokableAttribute("NotifyLocationChanged")]
|
||||
public static void NotifyLocationChanged(string uriAbsolute, bool isInterceptedLink) { }
|
||||
}
|
||||
}
|
||||
namespace Microsoft.Extensions.DependencyInjection
|
||||
{
|
||||
|
|
|
|||
|
|
@ -15,42 +15,6 @@ namespace Microsoft.AspNetCore.Builder
|
|||
/// </summary>
|
||||
public static class ComponentEndpointRouteBuilderExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Maps the Blazor <see cref="Hub" /> to the default path.
|
||||
/// </summary>
|
||||
/// <param name="endpoints">The <see cref="IEndpointRouteBuilder"/>.</param>
|
||||
/// <returns>The <see cref="ComponentEndpointConventionBuilder"/>.</returns>
|
||||
public static ComponentEndpointConventionBuilder MapBlazorHub(this IEndpointRouteBuilder endpoints)
|
||||
{
|
||||
if (endpoints == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(endpoints));
|
||||
}
|
||||
|
||||
return endpoints.MapBlazorHub(configureOptions: _ => { });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Maps the Blazor <see cref="Hub" /> to the default path.
|
||||
/// </summary>
|
||||
/// <param name="endpoints">The <see cref="IEndpointRouteBuilder"/>.</param>
|
||||
/// <param name="configureOptions">A callback to configure dispatcher options.</param>
|
||||
/// <returns>The <see cref="ComponentEndpointConventionBuilder"/>.</returns>
|
||||
public static ComponentEndpointConventionBuilder MapBlazorHub(this IEndpointRouteBuilder endpoints, Action<HttpConnectionDispatcherOptions> configureOptions)
|
||||
{
|
||||
if (endpoints == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(endpoints));
|
||||
}
|
||||
|
||||
if (configureOptions == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(configureOptions));
|
||||
}
|
||||
|
||||
return new ComponentEndpointConventionBuilder(endpoints.MapHub<ComponentHub>(ComponentHub.DefaultPath, configureOptions));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///Maps the Blazor <see cref="Hub" /> to the default path and associates
|
||||
/// the component <typeparamref name="TComponent"/> to this hub instance as the given DOM <paramref name="selector"/>.
|
||||
|
|
|
|||
|
|
@ -11,8 +11,8 @@ namespace Microsoft.AspNetCore.Components.Server.Circuits
|
|||
public abstract CircuitHost CreateCircuitHost(
|
||||
HttpContext httpContext,
|
||||
CircuitClientProxy client,
|
||||
string uriAbsolute,
|
||||
string baseUriAbsolute,
|
||||
string baseUri,
|
||||
string uri,
|
||||
ClaimsPrincipal user);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,8 +7,6 @@ using System.Security.Claims;
|
|||
using System.Text.Json;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Components.Rendering;
|
||||
using Microsoft.AspNetCore.Components.Routing;
|
||||
using Microsoft.AspNetCore.Components.Web;
|
||||
using Microsoft.AspNetCore.Components.Web.Rendering;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
|
@ -19,31 +17,28 @@ namespace Microsoft.AspNetCore.Components.Server.Circuits
|
|||
{
|
||||
internal class CircuitHost : IAsyncDisposable
|
||||
{
|
||||
private static readonly AsyncLocal<CircuitHost> _current = new AsyncLocal<CircuitHost>();
|
||||
private readonly SemaphoreSlim HandlerLock = new SemaphoreSlim(1);
|
||||
private readonly IServiceScope _scope;
|
||||
private readonly CircuitHandler[] _circuitHandlers;
|
||||
private readonly ILogger _logger;
|
||||
private bool _initialized;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current <see cref="Circuit"/>, if any.
|
||||
/// </summary>
|
||||
public static CircuitHost Current => _current.Value;
|
||||
|
||||
/// <summary>
|
||||
/// Sets the current <see cref="Circuits.Circuit"/>.
|
||||
/// </summary>
|
||||
/// <param name="circuitHost">The <see cref="Circuits.Circuit"/>.</param>
|
||||
/// <remarks>
|
||||
/// Calling <see cref="SetCurrentCircuitHost(CircuitHost)"/> will store the circuit
|
||||
/// and other related values such as the <see cref="IJSRuntime"/> and <see cref="Renderer"/>
|
||||
/// Calling <see cref="SetCurrentCircuitHost(CircuitHost)"/> will store related values such as the
|
||||
/// <see cref="IJSRuntime"/> and <see cref="Renderer"/>
|
||||
/// in the local execution context. Application code should not need to call this method,
|
||||
/// it is primarily used by the Server-Side Components infrastructure.
|
||||
/// </remarks>
|
||||
public static void SetCurrentCircuitHost(CircuitHost circuitHost)
|
||||
{
|
||||
_current.Value = circuitHost ?? throw new ArgumentNullException(nameof(circuitHost));
|
||||
if (circuitHost is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(circuitHost));
|
||||
}
|
||||
|
||||
JSInterop.JSRuntime.SetCurrentJSRuntime(circuitHost.JSRuntime);
|
||||
RendererRegistry.SetCurrentRendererRegistry(circuitHost.RendererRegistry);
|
||||
|
|
@ -57,7 +52,7 @@ namespace Microsoft.AspNetCore.Components.Server.Circuits
|
|||
CircuitClientProxy client,
|
||||
RendererRegistry rendererRegistry,
|
||||
RemoteRenderer renderer,
|
||||
IList<ComponentDescriptor> descriptors,
|
||||
IReadOnlyList<ComponentDescriptor> descriptors,
|
||||
RemoteJSRuntime jsRuntime,
|
||||
CircuitHandler[] circuitHandlers,
|
||||
ILogger logger)
|
||||
|
|
@ -92,24 +87,10 @@ namespace Microsoft.AspNetCore.Components.Server.Circuits
|
|||
|
||||
public RendererRegistry RendererRegistry { get; }
|
||||
|
||||
public IList<ComponentDescriptor> Descriptors { get; }
|
||||
public IReadOnlyList<ComponentDescriptor> Descriptors { get; }
|
||||
|
||||
public IServiceProvider Services { get; }
|
||||
|
||||
public Task<ComponentRenderedText> PrerenderComponentAsync(Type componentType, ParameterView parameters)
|
||||
{
|
||||
return Renderer.Dispatcher.InvokeAsync(async () =>
|
||||
{
|
||||
var result = await Renderer.RenderComponentAsync(componentType, parameters);
|
||||
|
||||
// When we prerender we start the circuit in a disconnected state. As such, we only call
|
||||
// OnCircuitOpenenedAsync here and when the client reconnects we run OnConnectionUpAsync
|
||||
await OnCircuitOpenedAsync(CancellationToken.None);
|
||||
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
public void SetCircuitUser(ClaimsPrincipal user)
|
||||
{
|
||||
var authenticationStateProvider = Services.GetService<AuthenticationStateProvider>() as IHostEnvironmentAuthenticationStateProvider;
|
||||
|
|
@ -120,26 +101,6 @@ namespace Microsoft.AspNetCore.Components.Server.Circuits
|
|||
}
|
||||
}
|
||||
|
||||
internal void InitializeCircuitAfterPrerender(UnhandledExceptionEventHandler unhandledException)
|
||||
{
|
||||
if (!_initialized)
|
||||
{
|
||||
_initialized = true;
|
||||
UnhandledException += unhandledException;
|
||||
var uriHelper = (RemoteUriHelper)Services.GetRequiredService<IUriHelper>();
|
||||
if (!uriHelper.HasAttachedJSRuntime)
|
||||
{
|
||||
uriHelper.AttachJsRuntime(JSRuntime);
|
||||
}
|
||||
|
||||
var navigationInterception = (RemoteNavigationInterception)Services.GetRequiredService<INavigationInterception>();
|
||||
if (!navigationInterception.HasAttachedJSRuntime)
|
||||
{
|
||||
navigationInterception.AttachJSRuntime(JSRuntime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal void SendPendingBatches()
|
||||
{
|
||||
// Dispatch any buffered renders we accumulated during a disconnect.
|
||||
|
|
@ -188,7 +149,6 @@ namespace Microsoft.AspNetCore.Components.Server.Circuits
|
|||
return;
|
||||
}
|
||||
|
||||
|
||||
await Renderer.Dispatcher.InvokeAsync(() =>
|
||||
{
|
||||
SetCurrentCircuitHost(this);
|
||||
|
|
@ -233,13 +193,11 @@ namespace Microsoft.AspNetCore.Components.Server.Circuits
|
|||
// That's because AddComponentAsync waits for quiescence, which can take
|
||||
// arbitrarily long. In the meantime we might need to be receiving and
|
||||
// processing incoming JSInterop calls or similar.
|
||||
for (var i = 0; i < Descriptors.Count; i++)
|
||||
var count = Descriptors.Count;
|
||||
for (var i = 0; i < count; i++)
|
||||
{
|
||||
var (componentType, domElementSelector, prerendered) = Descriptors[i];
|
||||
if (!prerendered)
|
||||
{
|
||||
await Renderer.AddComponentAsync(componentType, domElementSelector);
|
||||
}
|
||||
var (componentType, domElementSelector) = Descriptors[i];
|
||||
await Renderer.AddComponentAsync(componentType, domElementSelector);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
|
@ -256,7 +214,7 @@ namespace Microsoft.AspNetCore.Components.Server.Circuits
|
|||
try
|
||||
{
|
||||
AssertInitialized();
|
||||
if(assemblyName == "Microsoft.AspNetCore.Components.Web" && methodIdentifier == "DispatchEvent")
|
||||
if (assemblyName == "Microsoft.AspNetCore.Components.Web" && methodIdentifier == "DispatchEvent")
|
||||
{
|
||||
Log.DispatchEventTroughJSInterop(_logger);
|
||||
return;
|
||||
|
|
@ -271,6 +229,38 @@ namespace Microsoft.AspNetCore.Components.Server.Circuits
|
|||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// We don't expect any of this code to actually throw, because DotNetDispatcher.BeginInvoke doesn't throw
|
||||
// however, we still want this to get logged if we do.
|
||||
UnhandledException?.Invoke(this, new UnhandledExceptionEventArgs(ex, isTerminating: false));
|
||||
}
|
||||
}
|
||||
|
||||
public async Task OnLocationChangedAsync(string uri, bool intercepted)
|
||||
{
|
||||
try
|
||||
{
|
||||
AssertInitialized();
|
||||
await Renderer.Dispatcher.InvokeAsync(() =>
|
||||
{
|
||||
SetCurrentCircuitHost(this);
|
||||
Log.LocationChange(_logger, CircuitId, uri);
|
||||
var navigationManager = (RemoteNavigationManager)Services.GetRequiredService<NavigationManager>();
|
||||
navigationManager.NotifyLocationChanged(uri, intercepted);
|
||||
Log.LocationChangeSucceeded(_logger, CircuitId, uri);
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// It's up to the NavigationManager implementation to validate the URI.
|
||||
//
|
||||
// Note that it's also possible that setting the URI could cause a failure in code that listens
|
||||
// to NavigationManager.LocationChanged.
|
||||
//
|
||||
// In either case, a well-behaved client will not send invalid URIs, and we don't really
|
||||
// want to continue processing with the circuit if setting the URI failed inside application
|
||||
// code. The safest thing to do is consider it a critical failure since URI is global state,
|
||||
// and a failure means that an update to global state was partially applied.
|
||||
Log.LocationChangeFailed(_logger, CircuitId, uri, ex);
|
||||
UnhandledException?.Invoke(this, new UnhandledExceptionEventArgs(ex, isTerminating: false));
|
||||
}
|
||||
}
|
||||
|
|
@ -423,6 +413,9 @@ namespace Microsoft.AspNetCore.Components.Server.Circuits
|
|||
private static readonly Action<ILogger, Exception> _dispatchEventFailedToParseEventDescriptor;
|
||||
private static readonly Action<ILogger, string, Exception> _dispatchEventFailedToDispatchEvent;
|
||||
private static readonly Action<ILogger, Exception> _dispatchEventThroughJSInterop;
|
||||
private static readonly Action<ILogger, string, string, Exception> _locationChange;
|
||||
private static readonly Action<ILogger, string, string, Exception> _locationChangeSucceeded;
|
||||
private static readonly Action<ILogger, string, string, Exception> _locationChangeFailed;
|
||||
|
||||
private static class EventIds
|
||||
{
|
||||
|
|
@ -440,6 +433,9 @@ namespace Microsoft.AspNetCore.Components.Server.Circuits
|
|||
public static readonly EventId EndInvokeJSFailed = new EventId(111, "EndInvokeJSFailed");
|
||||
public static readonly EventId EndInvokeJSSucceeded = new EventId(112, "EndInvokeJSSucceeded");
|
||||
public static readonly EventId DispatchEventThroughJSInterop = new EventId(113, "DispatchEventThroughJSInterop");
|
||||
public static readonly EventId LocationChange = new EventId(114, "LocationChange");
|
||||
public static readonly EventId LocationChangeSucceded = new EventId(115, "LocationChangeSucceeded");
|
||||
public static readonly EventId LocationChangeFailed = new EventId(116, "LocationChangeFailed");
|
||||
}
|
||||
|
||||
static Log()
|
||||
|
|
@ -513,6 +509,21 @@ namespace Microsoft.AspNetCore.Components.Server.Circuits
|
|||
LogLevel.Debug,
|
||||
EventIds.DispatchEventThroughJSInterop,
|
||||
"There was an intent to dispatch a browser event through JS interop.");
|
||||
|
||||
_locationChange = LoggerMessage.Define<string, string>(
|
||||
LogLevel.Debug,
|
||||
EventIds.LocationChange,
|
||||
"Location changing to {URI} in {CircuitId}.");
|
||||
|
||||
_locationChangeSucceeded = LoggerMessage.Define<string, string>(
|
||||
LogLevel.Debug,
|
||||
EventIds.LocationChangeSucceded,
|
||||
"Location change to {URI} in {CircuitId} succeded.");
|
||||
|
||||
_locationChangeFailed = LoggerMessage.Define<string, string>(
|
||||
LogLevel.Debug,
|
||||
EventIds.LocationChangeFailed,
|
||||
"Location change to {URI} in {CircuitId} failed.");
|
||||
}
|
||||
|
||||
public static void UnhandledExceptionInvokingCircuitHandler(ILogger logger, CircuitHandler handler, string handlerMethod, Exception exception)
|
||||
|
|
@ -560,8 +571,13 @@ namespace Microsoft.AspNetCore.Components.Server.Circuits
|
|||
}
|
||||
}
|
||||
|
||||
public static void DispatchEventTroughJSInterop(ILogger logger) =>
|
||||
_dispatchEventThroughJSInterop(logger, null);
|
||||
public static void DispatchEventTroughJSInterop(ILogger logger) => _dispatchEventThroughJSInterop(logger, null);
|
||||
|
||||
public static void LocationChange(ILogger logger, string circuitId, string uri) => _locationChange(logger, circuitId, uri, null);
|
||||
|
||||
public static void LocationChangeSucceeded(ILogger logger, string circuitId, string uri) => _locationChangeSucceeded(logger, circuitId, uri, null);
|
||||
|
||||
public static void LocationChangeFailed(ILogger logger, string circuitId, string uri, Exception exception) => _locationChangeFailed(logger, circuitId, uri, exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,207 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Runtime.ExceptionServices;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Components.Rendering;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Http.Extensions;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.Server.Circuits
|
||||
{
|
||||
internal class CircuitPrerenderer : IComponentPrerenderer
|
||||
{
|
||||
private static object CircuitHostKey = new object();
|
||||
private static object CancellationStatusKey = new object();
|
||||
private static readonly JsonSerializerOptions _jsonSerializationOptions =
|
||||
new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase };
|
||||
|
||||
private readonly CircuitFactory _circuitFactory;
|
||||
private readonly CircuitRegistry _registry;
|
||||
|
||||
public CircuitPrerenderer(
|
||||
CircuitFactory circuitFactory,
|
||||
CircuitRegistry registry)
|
||||
{
|
||||
_circuitFactory = circuitFactory;
|
||||
_registry = registry;
|
||||
}
|
||||
|
||||
public async Task<ComponentPrerenderResult> PrerenderComponentAsync(ComponentPrerenderingContext prerenderingContext)
|
||||
{
|
||||
var context = prerenderingContext.Context;
|
||||
var cancellationStatus = GetOrCreateCancellationStatus(context);
|
||||
if (cancellationStatus.Canceled)
|
||||
{
|
||||
// Avoid creating a circuit host if other component earlier in the pipeline already triggered
|
||||
// cancellation (e.g., by navigating or throwing). Instead render nothing.
|
||||
return new ComponentPrerenderResult(Array.Empty<string>());
|
||||
}
|
||||
var circuitHost = GetOrCreateCircuitHost(context, cancellationStatus);
|
||||
ComponentRenderedText renderResult;
|
||||
try
|
||||
{
|
||||
renderResult = await circuitHost.PrerenderComponentAsync(
|
||||
prerenderingContext.ComponentType,
|
||||
prerenderingContext.Parameters);
|
||||
}
|
||||
catch (NavigationException navigationException)
|
||||
{
|
||||
// Cleanup the state as we won't need it any longer.
|
||||
// Signal callbacks that we don't have to register the circuit.
|
||||
await CleanupCircuitState(context, cancellationStatus, circuitHost);
|
||||
|
||||
// Navigation was attempted during prerendering.
|
||||
if (prerenderingContext.Context.Response.HasStarted)
|
||||
{
|
||||
// We can't perform a redirect as the server already started sending the response.
|
||||
// This is considered an application error as the developer should buffer the response until
|
||||
// all components have rendered.
|
||||
throw new InvalidOperationException("A navigation command was attempted during prerendering after the server already started sending the response. " +
|
||||
"Navigation commands can not be issued during server-side prerendering after the response from the server has started. Applications must buffer the" +
|
||||
"reponse and avoid using features like FlushAsync() before all components on the page have been rendered to prevent failed navigation commands.", navigationException);
|
||||
}
|
||||
|
||||
context.Response.Redirect(navigationException.Location);
|
||||
return new ComponentPrerenderResult(Array.Empty<string>());
|
||||
}
|
||||
catch
|
||||
{
|
||||
// If prerendering any component fails, cancel prerendering entirely and dispose the DI scope
|
||||
await CleanupCircuitState(context, cancellationStatus, circuitHost);
|
||||
throw;
|
||||
}
|
||||
|
||||
circuitHost.Descriptors.Add(new ComponentDescriptor
|
||||
{
|
||||
ComponentType = prerenderingContext.ComponentType,
|
||||
Prerendered = true
|
||||
});
|
||||
|
||||
var record = JsonSerializer.Serialize(new PrerenderedComponentRecord(
|
||||
// We need to do this due to the fact that -- is not allowed within HTML comments and HTML doesn't encode '-'.
|
||||
// We will never have '..' sequences because we Base64UrlEncode the circuit id
|
||||
circuitHost.CircuitId.Replace("--", ".."),
|
||||
circuitHost.Renderer.Id,
|
||||
renderResult.ComponentId),
|
||||
_jsonSerializationOptions);
|
||||
|
||||
var result = (new[] {
|
||||
$"<!-- M.A.C.Component: {record} -->",
|
||||
}).Concat(renderResult.Tokens).Concat(
|
||||
new[] {
|
||||
$"<!-- M.A.C.Component: {renderResult.ComponentId} -->"
|
||||
});
|
||||
|
||||
return new ComponentPrerenderResult(result);
|
||||
}
|
||||
|
||||
private PrerenderingCancellationStatus GetOrCreateCancellationStatus(HttpContext context)
|
||||
{
|
||||
if (context.Items.TryGetValue(CancellationStatusKey, out var existingValue))
|
||||
{
|
||||
return (PrerenderingCancellationStatus)existingValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
var cancellationStatus = new PrerenderingCancellationStatus();
|
||||
context.Items[CancellationStatusKey] = cancellationStatus;
|
||||
return cancellationStatus;
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task CleanupCircuitState(HttpContext context, PrerenderingCancellationStatus cancellationStatus, CircuitHost circuitHost)
|
||||
{
|
||||
cancellationStatus.Canceled = true;
|
||||
context.Items.Remove(CircuitHostKey);
|
||||
await circuitHost.DisposeAsync();
|
||||
}
|
||||
|
||||
private CircuitHost GetOrCreateCircuitHost(HttpContext context, PrerenderingCancellationStatus cancellationStatus)
|
||||
{
|
||||
if (context.Items.TryGetValue(CircuitHostKey, out var existingHost))
|
||||
{
|
||||
return (CircuitHost)existingHost;
|
||||
}
|
||||
else
|
||||
{
|
||||
var result = _circuitFactory.CreateCircuitHost(
|
||||
context,
|
||||
client: new CircuitClientProxy(), // This creates an "offline" client.
|
||||
GetFullUri(context.Request),
|
||||
GetFullBaseUri(context.Request),
|
||||
context.User);
|
||||
|
||||
result.UnhandledException += CircuitHost_UnhandledException;
|
||||
context.Response.OnCompleted(() =>
|
||||
{
|
||||
result.UnhandledException -= CircuitHost_UnhandledException;
|
||||
if (!cancellationStatus.Canceled)
|
||||
{
|
||||
_registry.RegisterDisconnectedCircuit(result);
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
});
|
||||
context.Items.Add(CircuitHostKey, result);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
private void CircuitHost_UnhandledException(object sender, UnhandledExceptionEventArgs e)
|
||||
{
|
||||
// Throw all exceptions encountered during pre-rendering so the default developer
|
||||
// error page can respond.
|
||||
ExceptionDispatchInfo.Capture((Exception)e.ExceptionObject).Throw();
|
||||
}
|
||||
|
||||
private string GetFullUri(HttpRequest request)
|
||||
{
|
||||
return UriHelper.BuildAbsolute(
|
||||
request.Scheme,
|
||||
request.Host,
|
||||
request.PathBase,
|
||||
request.Path,
|
||||
request.QueryString);
|
||||
}
|
||||
|
||||
private string GetFullBaseUri(HttpRequest request)
|
||||
{
|
||||
var result = UriHelper.BuildAbsolute(request.Scheme, request.Host, request.PathBase);
|
||||
|
||||
// PathBase may be "/" or "/some/thing", but to be a well-formed base URI
|
||||
// it has to end with a trailing slash
|
||||
if (!result.EndsWith('/'))
|
||||
{
|
||||
result += '/';
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private readonly struct PrerenderedComponentRecord
|
||||
{
|
||||
public PrerenderedComponentRecord(string circuitId, int rendererId, int componentId)
|
||||
{
|
||||
CircuitId = circuitId;
|
||||
RendererId = rendererId;
|
||||
ComponentId = componentId;
|
||||
}
|
||||
|
||||
public string CircuitId { get; }
|
||||
|
||||
public int RendererId { get; }
|
||||
|
||||
public int ComponentId { get; }
|
||||
}
|
||||
|
||||
private class PrerenderingCancellationStatus
|
||||
{
|
||||
public bool Canceled { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -14,6 +14,7 @@ using Microsoft.AspNetCore.Http.Features;
|
|||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.JSInterop;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.Server.Circuits
|
||||
{
|
||||
|
|
@ -38,10 +39,12 @@ namespace Microsoft.AspNetCore.Components.Server.Circuits
|
|||
public override CircuitHost CreateCircuitHost(
|
||||
HttpContext httpContext,
|
||||
CircuitClientProxy client,
|
||||
string uriAbsolute,
|
||||
string baseUriAbsolute,
|
||||
string baseUri,
|
||||
string uri,
|
||||
ClaimsPrincipal user)
|
||||
{
|
||||
// We do as much intialization as possible eagerly in this method, which makes the error handling
|
||||
// story much simpler. If we throw from here, it's handled inside the initial hub method.
|
||||
var components = ResolveComponentMetadata(httpContext, client);
|
||||
|
||||
var scope = _scopeFactory.CreateScope();
|
||||
|
|
@ -51,20 +54,25 @@ namespace Microsoft.AspNetCore.Components.Server.Circuits
|
|||
jsRuntime.Initialize(client);
|
||||
componentContext.Initialize(client);
|
||||
|
||||
var uriHelper = (RemoteUriHelper)scope.ServiceProvider.GetRequiredService<IUriHelper>();
|
||||
var authenticationStateProvider = scope.ServiceProvider.GetService<AuthenticationStateProvider>() as IHostEnvironmentAuthenticationStateProvider;
|
||||
if (authenticationStateProvider != null)
|
||||
{
|
||||
var authenticationState = new AuthenticationState(httpContext.User); // TODO: Get this from the hub connection context instead
|
||||
authenticationStateProvider.SetAuthenticationState(Task.FromResult(authenticationState));
|
||||
}
|
||||
|
||||
var navigationManager = (RemoteNavigationManager)scope.ServiceProvider.GetRequiredService<NavigationManager>();
|
||||
var navigationInterception = (RemoteNavigationInterception)scope.ServiceProvider.GetRequiredService<INavigationInterception>();
|
||||
if (client.Connected)
|
||||
{
|
||||
uriHelper.AttachJsRuntime(jsRuntime);
|
||||
uriHelper.InitializeState(
|
||||
uriAbsolute,
|
||||
baseUriAbsolute);
|
||||
navigationManager.AttachJsRuntime(jsRuntime);
|
||||
navigationManager.Initialize(baseUri, uri);
|
||||
|
||||
navigationInterception.AttachJSRuntime(jsRuntime);
|
||||
}
|
||||
else
|
||||
{
|
||||
uriHelper.InitializeState(uriAbsolute, baseUriAbsolute);
|
||||
navigationManager.Initialize(baseUri, uri);
|
||||
}
|
||||
|
||||
var rendererRegistry = new RendererRegistry();
|
||||
|
|
@ -100,7 +108,7 @@ namespace Microsoft.AspNetCore.Components.Server.Circuits
|
|||
return circuitHost;
|
||||
}
|
||||
|
||||
internal static IList<ComponentDescriptor> ResolveComponentMetadata(HttpContext httpContext, CircuitClientProxy client)
|
||||
internal static List<ComponentDescriptor> ResolveComponentMetadata(HttpContext httpContext, CircuitClientProxy client)
|
||||
{
|
||||
if (!client.Connected)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ using System;
|
|||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Components.Routing;
|
||||
using Microsoft.JSInterop;
|
||||
using Interop = Microsoft.AspNetCore.Components.Web.BrowserUriHelperInterop;
|
||||
using Interop = Microsoft.AspNetCore.Components.Web.BrowserNavigationManagerInterop;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.Server.Circuits
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2,26 +2,26 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.AspNetCore.Components.Routing;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.JSInterop;
|
||||
using Interop = Microsoft.AspNetCore.Components.Web.BrowserUriHelperInterop;
|
||||
using Interop = Microsoft.AspNetCore.Components.Web.BrowserNavigationManagerInterop;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.Server.Circuits
|
||||
{
|
||||
/// <summary>
|
||||
/// A Server-Side Components implementation of <see cref="IUriHelper"/>.
|
||||
/// A Server-Side Blazor implementation of <see cref="NavigationManager"/>.
|
||||
/// </summary>
|
||||
public class RemoteUriHelper : UriHelperBase
|
||||
internal class RemoteNavigationManager : NavigationManager, IHostEnvironmentNavigationManager
|
||||
{
|
||||
private readonly ILogger<RemoteUriHelper> _logger;
|
||||
private readonly ILogger<RemoteNavigationManager> _logger;
|
||||
private IJSRuntime _jsRuntime;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="RemoteUriHelper"/> instance.
|
||||
/// Creates a new <see cref="RemoteNavigationManager"/> instance.
|
||||
/// </summary>
|
||||
/// <param name="logger">The <see cref="ILogger{TCategoryName}"/>.</param>
|
||||
public RemoteUriHelper(ILogger<RemoteUriHelper> logger)
|
||||
public RemoteNavigationManager(ILogger<RemoteNavigationManager> logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
|
|
@ -32,21 +32,21 @@ namespace Microsoft.AspNetCore.Components.Server.Circuits
|
|||
public bool HasAttachedJSRuntime => _jsRuntime != null;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the <see cref="RemoteUriHelper"/>.
|
||||
/// Initializes the <see cref="NavigationManager" />.
|
||||
/// </summary>
|
||||
/// <param name="uriAbsolute">The absolute URI of the current page.</param>
|
||||
/// <param name="baseUriAbsolute">The absolute base URI of the current page.</param>
|
||||
public override void InitializeState(string uriAbsolute, string baseUriAbsolute)
|
||||
/// <param name="baseUri">The base URI.</param>
|
||||
/// <param name="uri">The absolute URI.</param>
|
||||
public new void Initialize(string baseUri, string uri)
|
||||
{
|
||||
base.InitializeState(uriAbsolute, baseUriAbsolute);
|
||||
TriggerOnLocationChanged(isinterceptedLink: false);
|
||||
base.Initialize(baseUri, uri);
|
||||
NotifyLocationChanged(isInterceptedLink: false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the <see cref="RemoteUriHelper"/>.
|
||||
/// Initializes the <see cref="RemoteNavigationManager"/>.
|
||||
/// </summary>
|
||||
/// <param name="jsRuntime">The <see cref="IJSRuntime"/> to use for interoperability.</param>
|
||||
internal void AttachJsRuntime(IJSRuntime jsRuntime)
|
||||
public void AttachJsRuntime(IJSRuntime jsRuntime)
|
||||
{
|
||||
if (_jsRuntime != null)
|
||||
{
|
||||
|
|
@ -54,31 +54,14 @@ namespace Microsoft.AspNetCore.Components.Server.Circuits
|
|||
}
|
||||
|
||||
_jsRuntime = jsRuntime;
|
||||
|
||||
_jsRuntime.InvokeAsync<object>(
|
||||
Interop.ListenForNavigationEvents,
|
||||
typeof(RemoteUriHelper).Assembly.GetName().Name,
|
||||
nameof(NotifyLocationChanged));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// For framework use only.
|
||||
/// </summary>
|
||||
[JSInvokable(nameof(NotifyLocationChanged))]
|
||||
public static void NotifyLocationChanged(string uriAbsolute, bool isInterceptedLink)
|
||||
public void NotifyLocationChanged(string uri, bool intercepted)
|
||||
{
|
||||
var circuit = CircuitHost.Current;
|
||||
if (circuit == null)
|
||||
{
|
||||
var message = $"{nameof(NotifyLocationChanged)} called without a circuit.";
|
||||
throw new InvalidOperationException(message);
|
||||
}
|
||||
Log.ReceivedLocationChangedNotification(_logger, uri, intercepted);
|
||||
|
||||
var uriHelper = (RemoteUriHelper)circuit.Services.GetRequiredService<IUriHelper>();
|
||||
Log.ReceivedLocationChangedNotification(uriHelper._logger, uriAbsolute, isInterceptedLink);
|
||||
|
||||
uriHelper.SetAbsoluteUri(uriAbsolute);
|
||||
uriHelper.TriggerOnLocationChanged(isInterceptedLink);
|
||||
Uri = uri;
|
||||
NotifyLocationChanged(intercepted);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
|
@ -11,13 +11,10 @@ namespace Microsoft.AspNetCore.Components.Server
|
|||
|
||||
public string Selector { get; set; }
|
||||
|
||||
public bool Prerendered { get; set; }
|
||||
|
||||
public void Deconstruct(out Type componentType, out string selector, out bool prerendered)
|
||||
public void Deconstruct(out Type componentType, out string selector)
|
||||
{
|
||||
componentType = ComponentType;
|
||||
selector = Selector;
|
||||
prerendered = Prerendered;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -48,6 +48,9 @@ namespace Microsoft.AspNetCore.Components.Server
|
|||
/// <summary>
|
||||
/// For unit testing only.
|
||||
/// </summary>
|
||||
// We store the circuit host in Context.Items which is tied to the lifetime of the underlying
|
||||
// SignalR connection. There's no need to clean this up, it's a non-owning reference and it
|
||||
// will go away when the connection does.
|
||||
internal CircuitHost CircuitHost
|
||||
{
|
||||
get => (CircuitHost)Context.Items[CircuitKey];
|
||||
|
|
@ -65,7 +68,6 @@ namespace Microsoft.AspNetCore.Components.Server
|
|||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
CircuitHost = null;
|
||||
if (exception != null)
|
||||
{
|
||||
return _circuitRegistry.DisconnectAsync(circuitHost, Context.ConnectionId);
|
||||
|
|
@ -92,12 +94,14 @@ namespace Microsoft.AspNetCore.Components.Server
|
|||
{
|
||||
Log.UnhandledExceptionInCircuit(_logger, circuitHost.CircuitId, e);
|
||||
}
|
||||
|
||||
await _circuitRegistry.DisconnectAsync(circuitHost, Context.ConnectionId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Intended for framework use only. Applications should not call this method directly.
|
||||
/// </summary>
|
||||
public string StartCircuit(string uriAbsolute, string baseUriAbsolute)
|
||||
public string StartCircuit(string baseUri, string uri)
|
||||
{
|
||||
if (CircuitHost != null)
|
||||
{
|
||||
|
|
@ -106,6 +110,18 @@ namespace Microsoft.AspNetCore.Components.Server
|
|||
return null;
|
||||
}
|
||||
|
||||
if (baseUri == null ||
|
||||
uri == null ||
|
||||
!Uri.IsWellFormedUriString(baseUri, UriKind.Absolute) ||
|
||||
!Uri.IsWellFormedUriString(uri, UriKind.Absolute))
|
||||
{
|
||||
// We do some really minimal validation here to prevent obviously wrong data from getting in
|
||||
// without duplicating too much logic.
|
||||
Log.InvalidInputData(_logger);
|
||||
_ = NotifyClientError(Clients.Caller, $"The uris provided are invalid.");
|
||||
return null;
|
||||
}
|
||||
|
||||
var circuitClient = new CircuitClientProxy(Clients.Caller, Context.ConnectionId);
|
||||
if (DefaultCircuitFactory.ResolveComponentMetadata(Context.GetHttpContext(), circuitClient).Count == 0)
|
||||
{
|
||||
|
|
@ -118,26 +134,35 @@ namespace Microsoft.AspNetCore.Components.Server
|
|||
return null;
|
||||
}
|
||||
|
||||
var circuitHost = _circuitFactory.CreateCircuitHost(
|
||||
Context.GetHttpContext(),
|
||||
circuitClient,
|
||||
uriAbsolute,
|
||||
baseUriAbsolute,
|
||||
Context.User);
|
||||
try
|
||||
{
|
||||
var circuitHost = _circuitFactory.CreateCircuitHost(
|
||||
Context.GetHttpContext(),
|
||||
circuitClient,
|
||||
baseUri,
|
||||
uri,
|
||||
Context.User);
|
||||
|
||||
circuitHost.UnhandledException += CircuitHost_UnhandledException;
|
||||
circuitHost.UnhandledException += CircuitHost_UnhandledException;
|
||||
|
||||
// Fire-and-forget the initialization process, because we can't block the
|
||||
// SignalR message loop (we'd get a deadlock if any of the initialization
|
||||
// logic relied on receiving a subsequent message from SignalR), and it will
|
||||
// take care of its own errors anyway.
|
||||
_ = circuitHost.InitializeAsync(Context.ConnectionAborted);
|
||||
// Fire-and-forget the initialization process, because we can't block the
|
||||
// SignalR message loop (we'd get a deadlock if any of the initialization
|
||||
// logic relied on receiving a subsequent message from SignalR), and it will
|
||||
// take care of its own errors anyway.
|
||||
_ = circuitHost.InitializeAsync(Context.ConnectionAborted);
|
||||
|
||||
_circuitRegistry.Register(circuitHost);
|
||||
|
||||
CircuitHost = circuitHost;
|
||||
|
||||
return circuitHost.CircuitId;
|
||||
// It's safe to *publish* the circuit now because nothing will be able
|
||||
// to run inside it until after InitializeAsync completes.
|
||||
_circuitRegistry.Register(circuitHost);
|
||||
CircuitHost = circuitHost;
|
||||
return circuitHost.CircuitId;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.CircuitInitializationFailed(_logger, ex);
|
||||
NotifyClientError(Clients.Caller, "The circuit failed to initialize.");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -149,8 +174,8 @@ namespace Microsoft.AspNetCore.Components.Server
|
|||
if (circuitHost != null)
|
||||
{
|
||||
CircuitHost = circuitHost;
|
||||
CircuitHost.UnhandledException += CircuitHost_UnhandledException;
|
||||
|
||||
circuitHost.InitializeCircuitAfterPrerender(CircuitHost_UnhandledException);
|
||||
circuitHost.SetCircuitUser(Context.User);
|
||||
circuitHost.SendPendingBatches();
|
||||
return true;
|
||||
|
|
@ -220,6 +245,18 @@ namespace Microsoft.AspNetCore.Components.Server
|
|||
CircuitHost.Renderer.OnRenderCompleted(renderId, errorMessageOrNull);
|
||||
}
|
||||
|
||||
public void OnLocationChanged(string uri, bool intercepted)
|
||||
{
|
||||
if (CircuitHost == null)
|
||||
{
|
||||
Log.CircuitHostNotInitialized(_logger);
|
||||
NotifyClientError(Clients.Caller, "Circuit not initialized.");
|
||||
return;
|
||||
}
|
||||
|
||||
_ = CircuitHost.OnLocationChangedAsync(uri, intercepted);
|
||||
}
|
||||
|
||||
private async void CircuitHost_UnhandledException(object sender, UnhandledExceptionEventArgs e)
|
||||
{
|
||||
var circuitHost = (CircuitHost)sender;
|
||||
|
|
@ -271,10 +308,16 @@ namespace Microsoft.AspNetCore.Components.Server
|
|||
LoggerMessage.Define<string>(LogLevel.Debug, new EventId(5, "CircuitAlreadyInitialized"), "The circuit host '{CircuitId}' has already been initialized");
|
||||
|
||||
private static readonly Action<ILogger, string, Exception> _circuitHostNotInitialized =
|
||||
LoggerMessage.Define<string>(LogLevel.Debug, new EventId(6, "CircuitHostNotInitialized"), "Call to '{CallSite}' received before the circuit host initialization.");
|
||||
LoggerMessage.Define<string>(LogLevel.Debug, new EventId(6, "CircuitHostNotInitialized"), "Call to '{CallSite}' received before the circuit host initialization");
|
||||
|
||||
private static readonly Action<ILogger, string, Exception> _circuitTerminatedGracefully =
|
||||
LoggerMessage.Define<string>(LogLevel.Debug, new EventId(7, "CircuitTerminatedGracefully"), "Circuit '{CircuitId}' terminated gracefully.");
|
||||
LoggerMessage.Define<string>(LogLevel.Debug, new EventId(7, "CircuitTerminatedGracefully"), "Circuit '{CircuitId}' terminated gracefully");
|
||||
|
||||
private static readonly Action<ILogger, string, Exception> _invalidInputData =
|
||||
LoggerMessage.Define<string>(LogLevel.Debug, new EventId(8, "InvalidInputData"), "Call to '{CallSite}' received invalid input data");
|
||||
|
||||
private static readonly Action<ILogger, Exception> _circuitInitializationFailed =
|
||||
LoggerMessage.Define(LogLevel.Debug, new EventId(9, "CircuitInitializationFailed"), "Circuit initialization failed");
|
||||
|
||||
public static void NoComponentsRegisteredInEndpoint(ILogger logger, string endpointDisplayName)
|
||||
{
|
||||
|
|
@ -301,6 +344,10 @@ namespace Microsoft.AspNetCore.Components.Server
|
|||
public static void CircuitHostNotInitialized(ILogger logger, [CallerMemberName] string callSite = "") => _circuitHostNotInitialized(logger, callSite, null);
|
||||
|
||||
public static void CircuitTerminatedGracefully(ILogger logger, string circuitId) => _circuitTerminatedGracefully(logger, circuitId, null);
|
||||
|
||||
public static void InvalidInputData(ILogger logger, [CallerMemberName] string callSite = "") => _invalidInputData(logger, callSite, null);
|
||||
|
||||
public static void CircuitInitializationFailed(ILogger logger, Exception exception) => _circuitInitializationFailed(logger, exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -63,16 +63,10 @@ namespace Microsoft.Extensions.DependencyInjection
|
|||
|
||||
services.TryAddSingleton<CircuitRegistry>();
|
||||
|
||||
// We explicitly take over the prerendering and components services here.
|
||||
// We can't have two separate component implementations coexisting at the
|
||||
// same time, so when you register components (Circuits) it takes over
|
||||
// all the abstractions.
|
||||
services.AddScoped<IComponentPrerenderer, CircuitPrerenderer>();
|
||||
|
||||
// Standard razor component services implementations
|
||||
// Standard blazor hosting services implementations
|
||||
//
|
||||
// These intentionally replace the non-interactive versions included in MVC.
|
||||
services.AddScoped<IUriHelper, RemoteUriHelper>();
|
||||
services.AddScoped<NavigationManager, RemoteNavigationManager>();
|
||||
services.AddScoped<IJSRuntime, RemoteJSRuntime>();
|
||||
services.AddScoped<INavigationInterception, RemoteNavigationInterception>();
|
||||
services.AddScoped<IComponentContext, RemoteComponentContext>();
|
||||
|
|
|
|||
|
|
@ -1,33 +0,0 @@
|
|||
// 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.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.Server
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the result of a prerendering an <see cref="IComponent"/>.
|
||||
/// </summary>
|
||||
public sealed class ComponentPrerenderResult
|
||||
{
|
||||
private readonly IEnumerable<string> _result;
|
||||
|
||||
internal ComponentPrerenderResult(IEnumerable<string> result)
|
||||
{
|
||||
_result = result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes the prerendering result to the given <paramref name="writer"/>.
|
||||
/// </summary>
|
||||
/// <param name="writer">The <see cref="TextWriter"/> the results will be written to.</param>
|
||||
public void WriteTo(TextWriter writer)
|
||||
{
|
||||
foreach (var element in _result)
|
||||
{
|
||||
writer.Write(element);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
// 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 Microsoft.AspNetCore.Http;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.Server
|
||||
{
|
||||
/// <summary>
|
||||
/// The context for prerendering a component.
|
||||
/// </summary>
|
||||
public class ComponentPrerenderingContext
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the component type.
|
||||
/// </summary>
|
||||
public Type ComponentType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the parameters for the component.
|
||||
/// </summary>
|
||||
public ParameterView Parameters { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the <see cref="HttpContext"/> in which the prerendering has been initiated.
|
||||
/// </summary>
|
||||
public HttpContext Context { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
// 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.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.Server
|
||||
{
|
||||
/// <summary>
|
||||
/// Prerrenders <see cref="IComponent"/> instances.
|
||||
/// </summary>
|
||||
public interface IComponentPrerenderer
|
||||
{
|
||||
/// <summary>
|
||||
/// Prerrenders the component <see cref="ComponentPrerenderingContext.ComponentType"/>.
|
||||
/// </summary>
|
||||
/// <param name="context">The context in which the prerrendering is happening.</param>
|
||||
/// <returns><see cref="Task{TResult}"/> that will complete when the prerendering is done.</returns>
|
||||
Task<ComponentPrerenderResult> PrerenderComponentAsync(ComponentPrerenderingContext context);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,253 +0,0 @@
|
|||
// 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.IO;
|
||||
using System.Security.Claims;
|
||||
using System.Text.Json;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Components.Server.Circuits;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.Server.Tests.Circuits
|
||||
{
|
||||
public class CircuitPrerendererTest
|
||||
{
|
||||
private static readonly Regex ContentWrapperRegex = new Regex(
|
||||
"<!-- M.A.C.Component: {\"circuitId\":\"[^\"]+\",\"rendererId\":0,\"componentId\":0} -->(?<content>.*)<!-- M.A.C.Component: 0 -->",
|
||||
RegexOptions.Compiled | RegexOptions.Singleline, TimeSpan.FromSeconds(1)); // Treat the entire input string as a single line
|
||||
|
||||
private static readonly Regex CircuitInfoRegex = new Regex(
|
||||
"<!-- M.A.C.Component: (?<info>.*?) -->.*",
|
||||
RegexOptions.Compiled | RegexOptions.Singleline, TimeSpan.FromSeconds(1)); // Treat the entire input string as a single line
|
||||
|
||||
// Because CircuitPrerenderer is a point of integration with HttpContext,
|
||||
// it's not a good candidate for unit testing. The majority of prerendering
|
||||
// unit tests should be elsewhere in HtmlRendererTests inside the
|
||||
// Microsoft.AspNetCore.Components.Tests projects.
|
||||
//
|
||||
// The only unit tests added here should specifically be about how we're
|
||||
// interacting with the HttpContext for configuring the prerenderer.
|
||||
|
||||
[Fact]
|
||||
public async Task ExtractsUriFromHttpContext_EmptyPathBase()
|
||||
{
|
||||
// Arrange
|
||||
var circuitFactory = new TestCircuitFactory();
|
||||
var circuitRegistry = new CircuitRegistry(
|
||||
Options.Create(new CircuitOptions()),
|
||||
Mock.Of<ILogger<CircuitRegistry>>(),
|
||||
TestCircuitIdFactory.CreateTestFactory());
|
||||
var circuitPrerenderer = new CircuitPrerenderer(circuitFactory, circuitRegistry);
|
||||
var httpContext = new DefaultHttpContext();
|
||||
var httpRequest = httpContext.Request;
|
||||
httpRequest.Scheme = "https";
|
||||
httpRequest.Host = new HostString("example.com", 1234);
|
||||
httpRequest.Path = "/some/path";
|
||||
|
||||
var prerenderingContext = new ComponentPrerenderingContext
|
||||
{
|
||||
ComponentType = typeof(UriDisplayComponent),
|
||||
Parameters = ParameterView.Empty,
|
||||
Context = httpContext
|
||||
};
|
||||
|
||||
// Act
|
||||
var result = await circuitPrerenderer.PrerenderComponentAsync(prerenderingContext);
|
||||
// Assert
|
||||
Assert.Equal(string.Join("", new[]
|
||||
{
|
||||
"The current URI is ",
|
||||
"https://example.com:1234/some/path",
|
||||
" within base URI ",
|
||||
"https://example.com:1234/"
|
||||
}), GetUnwrappedContent(result));
|
||||
}
|
||||
|
||||
private string GetUnwrappedContent(ComponentPrerenderResult rawResult)
|
||||
{
|
||||
var writer = new StringWriter();
|
||||
rawResult.WriteTo(writer);
|
||||
return ContentWrapperRegex.Match(writer.ToString())
|
||||
.Groups["content"].Value
|
||||
.Replace("\r\n","\n");
|
||||
}
|
||||
|
||||
private JsonDocument GetUnwrappedCircuitInfo(ComponentPrerenderResult rawResult)
|
||||
{
|
||||
var writer = new StringWriter();
|
||||
rawResult.WriteTo(writer);
|
||||
var circuitInfo = CircuitInfoRegex.Match(writer.ToString()).Groups["info"].Value;
|
||||
|
||||
return JsonDocument.Parse(circuitInfo);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ExtractsUriFromHttpContext_NonemptyPathBase()
|
||||
{
|
||||
// Arrange
|
||||
var circuitFactory = new TestCircuitFactory();
|
||||
var circuitRegistry = new CircuitRegistry(
|
||||
Options.Create(new CircuitOptions()),
|
||||
Mock.Of<ILogger<CircuitRegistry>>(),
|
||||
TestCircuitIdFactory.CreateTestFactory());
|
||||
var circuitPrerenderer = new CircuitPrerenderer(circuitFactory, circuitRegistry);
|
||||
var httpContext = new DefaultHttpContext();
|
||||
var httpRequest = httpContext.Request;
|
||||
httpRequest.Scheme = "https";
|
||||
httpRequest.Host = new HostString("example.com", 1234);
|
||||
httpRequest.PathBase = "/my/dir";
|
||||
httpRequest.Path = "/some/path";
|
||||
|
||||
var prerenderingContext = new ComponentPrerenderingContext
|
||||
{
|
||||
ComponentType = typeof(UriDisplayComponent),
|
||||
Parameters = ParameterView.Empty,
|
||||
Context = httpContext
|
||||
};
|
||||
|
||||
// Act
|
||||
var result = await circuitPrerenderer.PrerenderComponentAsync(prerenderingContext);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(string.Join("", new[]
|
||||
{
|
||||
"The current URI is ",
|
||||
"https://example.com:1234/my/dir/some/path",
|
||||
" within base URI ",
|
||||
"https://example.com:1234/my/dir/"
|
||||
}), GetUnwrappedContent(result));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ReplacesDashesWithDots_WhenTheyAppearInPairs()
|
||||
{
|
||||
// Arrange
|
||||
var circuitFactory = new TestCircuitFactory(() => "--1234--");
|
||||
var circuitRegistry = new CircuitRegistry(
|
||||
Options.Create(new CircuitOptions()),
|
||||
Mock.Of<ILogger<CircuitRegistry>>(),
|
||||
TestCircuitIdFactory.CreateTestFactory());
|
||||
var circuitPrerenderer = new CircuitPrerenderer(circuitFactory, circuitRegistry);
|
||||
var httpContext = new DefaultHttpContext();
|
||||
var httpRequest = httpContext.Request;
|
||||
httpRequest.Scheme = "https";
|
||||
httpRequest.Host = new HostString("example.com", 1234);
|
||||
httpRequest.Path = "/some/path";
|
||||
|
||||
var prerenderingContext = new ComponentPrerenderingContext
|
||||
{
|
||||
ComponentType = typeof(UriDisplayComponent),
|
||||
Parameters = ParameterView.Empty,
|
||||
Context = httpContext
|
||||
};
|
||||
|
||||
// Act
|
||||
var result = await circuitPrerenderer.PrerenderComponentAsync(prerenderingContext);
|
||||
|
||||
// Assert
|
||||
Assert.Equal("..1234..", GetUnwrappedCircuitInfo(result).RootElement.GetProperty("circuitId").GetString());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task DisposesCircuitScopeEvenIfPrerenderingThrows()
|
||||
{
|
||||
// Arrange
|
||||
var circuitFactory = new MockServiceScopeCircuitFactory();
|
||||
var circuitRegistry = new CircuitRegistry(
|
||||
Options.Create(new CircuitOptions()),
|
||||
Mock.Of<ILogger<CircuitRegistry>>(),
|
||||
TestCircuitIdFactory.CreateTestFactory());
|
||||
var httpContext = new DefaultHttpContext();
|
||||
var prerenderer = new CircuitPrerenderer(circuitFactory, circuitRegistry);
|
||||
var prerenderingContext = new ComponentPrerenderingContext
|
||||
{
|
||||
ComponentType = typeof(ThrowExceptionComponent),
|
||||
Parameters = ParameterView.Empty,
|
||||
Context = httpContext
|
||||
};
|
||||
|
||||
// Act
|
||||
await Assert.ThrowsAsync<InvalidTimeZoneException>(async () =>
|
||||
await prerenderer.PrerenderComponentAsync(prerenderingContext));
|
||||
|
||||
// Assert
|
||||
circuitFactory.MockServiceScope.Verify(scope => scope.Dispose(), Times.Once());
|
||||
}
|
||||
|
||||
class TestCircuitFactory : CircuitFactory
|
||||
{
|
||||
private readonly Func<string> _circuitIdFactory;
|
||||
|
||||
public TestCircuitFactory(Func<string> circuitIdFactory = null)
|
||||
{
|
||||
_circuitIdFactory = circuitIdFactory ?? (() => Guid.NewGuid().ToString());
|
||||
}
|
||||
|
||||
public override CircuitHost CreateCircuitHost(HttpContext httpContext, CircuitClientProxy client, string uriAbsolute, string baseUriAbsolute, ClaimsPrincipal user)
|
||||
{
|
||||
var serviceCollection = new ServiceCollection();
|
||||
serviceCollection.AddScoped<IUriHelper>(_ =>
|
||||
{
|
||||
var uriHelper = new RemoteUriHelper(NullLogger<RemoteUriHelper>.Instance);
|
||||
uriHelper.InitializeState(uriAbsolute, baseUriAbsolute);
|
||||
return uriHelper;
|
||||
});
|
||||
var serviceScope = serviceCollection.BuildServiceProvider().CreateScope();
|
||||
return TestCircuitHost.Create(_circuitIdFactory(), serviceScope);
|
||||
}
|
||||
}
|
||||
|
||||
class MockServiceScopeCircuitFactory : CircuitFactory
|
||||
{
|
||||
public Mock<IServiceScope> MockServiceScope { get; }
|
||||
= new Mock<IServiceScope>();
|
||||
|
||||
public override CircuitHost CreateCircuitHost(HttpContext httpContext, CircuitClientProxy client, string uriAbsolute, string baseUriAbsolute, ClaimsPrincipal user)
|
||||
{
|
||||
return TestCircuitHost.Create(Guid.NewGuid().ToString(), MockServiceScope.Object);
|
||||
}
|
||||
}
|
||||
|
||||
class UriDisplayComponent : IComponent
|
||||
{
|
||||
private RenderHandle _renderHandle;
|
||||
|
||||
[Inject] IUriHelper UriHelper { get; set; }
|
||||
|
||||
public void Attach(RenderHandle renderHandle)
|
||||
{
|
||||
_renderHandle = renderHandle;
|
||||
}
|
||||
|
||||
public Task SetParametersAsync(ParameterView parameters)
|
||||
{
|
||||
_renderHandle.Render(builder =>
|
||||
{
|
||||
builder.AddContent(0, "The current URI is ");
|
||||
builder.AddContent(1, UriHelper.GetAbsoluteUri());
|
||||
builder.AddContent(2, " within base URI ");
|
||||
builder.AddContent(3, UriHelper.GetBaseUri());
|
||||
});
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
|
||||
class ThrowExceptionComponent : IComponent
|
||||
{
|
||||
public void Attach(RenderHandle renderHandle)
|
||||
=> throw new InvalidTimeZoneException();
|
||||
|
||||
public Task SetParametersAsync(ParameterView parameters)
|
||||
=> Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -11,7 +11,6 @@ using Microsoft.AspNetCore.SignalR;
|
|||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Microsoft.Extensions.Logging.Testing;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Moq;
|
||||
|
||||
|
|
@ -19,7 +18,7 @@ namespace Microsoft.AspNetCore.Components.Server.Circuits
|
|||
{
|
||||
internal class TestCircuitHost : CircuitHost
|
||||
{
|
||||
private TestCircuitHost(string circuitId, IServiceScope scope, CircuitClientProxy client, RendererRegistry rendererRegistry, RemoteRenderer renderer, IList<ComponentDescriptor> descriptors, RemoteJSRuntime jsRuntime, CircuitHandler[] circuitHandlers, ILogger logger)
|
||||
private TestCircuitHost(string circuitId, IServiceScope scope, CircuitClientProxy client, RendererRegistry rendererRegistry, RemoteRenderer renderer, IReadOnlyList<ComponentDescriptor> descriptors, RemoteJSRuntime jsRuntime, CircuitHandler[] circuitHandlers, ILogger logger)
|
||||
: base(circuitId, scope, client, rendererRegistry, renderer, descriptors, jsRuntime, circuitHandlers, logger)
|
||||
{
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Diagnostics;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Moq;
|
||||
|
|
@ -25,7 +25,7 @@ namespace Microsoft.AspNetCore.Components.Server.Tests
|
|||
.UseRouting()
|
||||
.UseEndpoints(endpoints =>
|
||||
{
|
||||
endpoints.MapBlazorHub(dispatchOptions => called = true);
|
||||
endpoints.MapBlazorHub<MyComponent>("app", dispatchOptions => called = true);
|
||||
}).Build();
|
||||
|
||||
// Assert
|
||||
|
|
@ -68,5 +68,18 @@ namespace Microsoft.AspNetCore.Components.Server.Tests
|
|||
|
||||
return new ApplicationBuilder(serviceProvder);
|
||||
}
|
||||
|
||||
private class MyComponent : IComponent
|
||||
{
|
||||
public void Attach(RenderHandle renderHandle)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
public Task SetParametersAsync(ParameterView parameters)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -6,7 +6,7 @@ import { shouldAutoStart } from './BootCommon';
|
|||
import { RenderQueue } from './Platform/Circuits/RenderQueue';
|
||||
import { ConsoleLogger } from './Platform/Logging/Loggers';
|
||||
import { LogLevel, Logger } from './Platform/Logging/Logger';
|
||||
import { discoverPrerenderedCircuits, startCircuit } from './Platform/Circuits/CircuitManager';
|
||||
import { startCircuit } from './Platform/Circuits/CircuitManager';
|
||||
import { setEventDispatcher } from './Rendering/RendererEventDispatcher';
|
||||
import { resolveOptions, BlazorOptions } from './Platform/Circuits/BlazorOptions';
|
||||
import { DefaultReconnectionHandler } from './Platform/Circuits/DefaultReconnectionHandler';
|
||||
|
|
@ -27,32 +27,18 @@ async function boot(userOptions?: Partial<BlazorOptions>): Promise<void> {
|
|||
options.reconnectionHandler = options.reconnectionHandler || window['Blazor'].defaultReconnectionHandler;
|
||||
logger.log(LogLevel.Information, 'Starting up blazor server-side application.');
|
||||
|
||||
// Initialize statefully prerendered circuits and their components
|
||||
// Note: This will all be removed soon
|
||||
const initialConnection = await initializeConnection(options, logger);
|
||||
const circuits = discoverPrerenderedCircuits(document);
|
||||
for (let i = 0; i < circuits.length; i++) {
|
||||
const circuit = circuits[i];
|
||||
for (let j = 0; j < circuit.components.length; j++) {
|
||||
const component = circuit.components[j];
|
||||
component.initialize();
|
||||
}
|
||||
}
|
||||
|
||||
const circuit = await startCircuit(initialConnection);
|
||||
if (!circuit) {
|
||||
logger.log(LogLevel.Information, 'No preregistered components to render.');
|
||||
}
|
||||
|
||||
const reconnect = async (existingConnection?: signalR.HubConnection): Promise<boolean> => {
|
||||
if (renderingFailed) {
|
||||
// We can't reconnect after a failure, so exit early.
|
||||
return false;
|
||||
}
|
||||
const reconnection = existingConnection || await initializeConnection(options, logger);
|
||||
const results = await Promise.all(circuits.map(circuit => circuit.reconnect(reconnection)));
|
||||
|
||||
if (reconnectionFailed(results)) {
|
||||
const reconnection = existingConnection || await initializeConnection(options, logger);
|
||||
if (!(await circuit.reconnect(reconnection))) {
|
||||
logger.log(LogLevel.Information, 'Reconnection attempt failed.');
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -63,19 +49,7 @@ async function boot(userOptions?: Partial<BlazorOptions>): Promise<void> {
|
|||
|
||||
window['Blazor'].reconnect = reconnect;
|
||||
|
||||
const reconnectTask = reconnect(initialConnection);
|
||||
|
||||
if (circuit) {
|
||||
circuits.push(circuit);
|
||||
}
|
||||
|
||||
await reconnectTask;
|
||||
|
||||
logger.log(LogLevel.Information, 'Blazor server-side application started.');
|
||||
|
||||
function reconnectionFailed(results: boolean[]): boolean {
|
||||
return !results.reduce((current, next) => current && next, true);
|
||||
}
|
||||
}
|
||||
|
||||
async function initializeConnection(options: BlazorOptions, logger: Logger): Promise<signalR.HubConnection> {
|
||||
|
|
@ -94,6 +68,11 @@ async function initializeConnection(options: BlazorOptions, logger: Logger): Pro
|
|||
return connection.send('DispatchBrowserEvent', JSON.stringify(descriptor), JSON.stringify(args));
|
||||
});
|
||||
|
||||
// Configure navigation via SignalR
|
||||
window['Blazor']._internal.navigationManager.listenForNavigationEvents((uri: string, intercepted: boolean): Promise<void> => {
|
||||
return connection.send('OnLocationChanged', uri, intercepted);
|
||||
});
|
||||
|
||||
connection.on('JS.BeginInvokeJS', DotNet.jsCallDispatcher.beginInvokeJSFromDotNet);
|
||||
connection.on('JS.EndInvokeDotNet', (args: string) => DotNet.jsCallDispatcher.endInvokeDotNetFromJS(...(JSON.parse(args) as [string, boolean, unknown])));
|
||||
connection.on('JS.RenderBatch', (browserRendererId: number, batchId: number, batchData: Uint8Array) => {
|
||||
|
|
|
|||
|
|
@ -27,6 +27,16 @@ async function boot(options?: any): Promise<void> {
|
|||
renderBatch(browserRendererId, new SharedMemoryRenderBatch(batchAddress));
|
||||
};
|
||||
|
||||
// Configure navigation via JS Interop
|
||||
window['Blazor']._internal.navigationManager.listenForNavigationEvents(async (uri: string, intercepted: boolean): Promise<void> => {
|
||||
await DotNet.invokeMethodAsync(
|
||||
'Microsoft.AspNetCore.Blazor',
|
||||
'NotifyLocationChanged',
|
||||
uri,
|
||||
intercepted
|
||||
);
|
||||
});
|
||||
|
||||
// Fetch the boot JSON file
|
||||
const bootConfig = await fetchBootConfigAsync();
|
||||
const embeddedResourcesPromise = loadEmbeddedResourcesAsync(bootConfig);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { navigateTo, internalFunctions as uriHelperInternalFunctions } from './Services/UriHelper';
|
||||
import { navigateTo, internalFunctions as navigationManagerInternalFunctions } from './Services/NavigationManager';
|
||||
import { internalFunctions as httpInternalFunctions } from './Services/Http';
|
||||
import { attachRootComponentToElement } from './Rendering/Renderer';
|
||||
|
||||
|
|
@ -9,6 +9,6 @@ window['Blazor'] = {
|
|||
_internal: {
|
||||
attachRootComponentToElement,
|
||||
http: httpInternalFunctions,
|
||||
uriHelper: uriHelperInternalFunctions,
|
||||
navigationManager: navigationManagerInternalFunctions,
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,14 +1,10 @@
|
|||
import { internalFunctions as uriHelperFunctions } from '../../Services/UriHelper';
|
||||
import { ComponentDescriptor, MarkupRegistrationTags, StartComponentComment, EndComponentComment } from './ComponentDescriptor';
|
||||
import { internalFunctions as navigationManagerFunctions } from '../../Services/NavigationManager';
|
||||
|
||||
export class CircuitDescriptor {
|
||||
public circuitId: string;
|
||||
|
||||
public components: ComponentDescriptor[];
|
||||
|
||||
public constructor(circuitId: string, components: ComponentDescriptor[]) {
|
||||
public constructor(circuitId: string) {
|
||||
this.circuitId = circuitId;
|
||||
this.components = components;
|
||||
}
|
||||
|
||||
public reconnect(reconnection: signalR.HubConnection): Promise<boolean> {
|
||||
|
|
@ -16,115 +12,11 @@ export class CircuitDescriptor {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
export function discoverPrerenderedCircuits(document: Document): CircuitDescriptor[] {
|
||||
const commentPairs = resolveCommentPairs(document);
|
||||
const discoveredCircuits = new Map<string, ComponentDescriptor[]>();
|
||||
for (let i = 0; i < commentPairs.length; i++) {
|
||||
const pair = commentPairs[i];
|
||||
// We replace '--' on the server with '..' when we prerender due to the fact that this
|
||||
// is not allowed in HTML comments and doesn't get encoded by default.
|
||||
const circuitId = pair.start.circuitId.replace('..', '--');
|
||||
let circuit = discoveredCircuits.get(circuitId);
|
||||
if (!circuit) {
|
||||
circuit = [];
|
||||
discoveredCircuits.set(circuitId, circuit);
|
||||
}
|
||||
const entry = new ComponentDescriptor(pair.start.componentId, circuitId, pair.start.rendererId, pair);
|
||||
circuit.push(entry);
|
||||
}
|
||||
const circuits: CircuitDescriptor[] = [];
|
||||
for (const [key, values] of discoveredCircuits) {
|
||||
circuits.push(new CircuitDescriptor(key, values));
|
||||
}
|
||||
return circuits;
|
||||
}
|
||||
|
||||
export async function startCircuit(connection: signalR.HubConnection): Promise<CircuitDescriptor | undefined> {
|
||||
const result = await connection.invoke<string>('StartCircuit', uriHelperFunctions.getLocationHref(), uriHelperFunctions.getBaseURI());
|
||||
export async function startCircuit(connection: signalR.HubConnection): Promise<CircuitDescriptor> {
|
||||
const result = await connection.invoke<string>('StartCircuit', navigationManagerFunctions.getBaseURI(), navigationManagerFunctions.getLocationHref());
|
||||
if (result) {
|
||||
return new CircuitDescriptor(result, []);
|
||||
return new CircuitDescriptor(result);
|
||||
} else {
|
||||
return undefined;
|
||||
throw new Error('Circuit failed to start');
|
||||
}
|
||||
}
|
||||
|
||||
function resolveCommentPairs(node: Node): MarkupRegistrationTags[] {
|
||||
if (!node.hasChildNodes()) {
|
||||
return [];
|
||||
}
|
||||
const result: MarkupRegistrationTags[] = [];
|
||||
const children = node.childNodes;
|
||||
let i = 0;
|
||||
const childrenLength = children.length;
|
||||
while (i < childrenLength) {
|
||||
const currentChildNode = children[i];
|
||||
const startComponent = getComponentStartComment(currentChildNode);
|
||||
if (!startComponent) {
|
||||
i++;
|
||||
const childResults = resolveCommentPairs(currentChildNode);
|
||||
for (let j = 0; j < childResults.length; j++) {
|
||||
const childResult = childResults[j];
|
||||
result.push(childResult);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
const endComponent = getComponentEndComment(startComponent, children, i + 1, childrenLength);
|
||||
result.push({ start: startComponent, end: endComponent });
|
||||
i = endComponent.index + 1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
function getComponentStartComment(node: Node): StartComponentComment | undefined {
|
||||
if (node.nodeType !== Node.COMMENT_NODE) {
|
||||
return;
|
||||
}
|
||||
if (node.textContent) {
|
||||
const componentStartComment = /\W+M.A.C.Component:[^{]*(.*)$/;
|
||||
const definition = componentStartComment.exec(node.textContent);
|
||||
const json = definition && definition[1];
|
||||
if (json) {
|
||||
try {
|
||||
const { componentId, rendererId, circuitId } = JSON.parse(json);
|
||||
const allComponents = componentId !== undefined && rendererId !== undefined && !!circuitId;
|
||||
if (allComponents) {
|
||||
return {
|
||||
node: node as Comment,
|
||||
circuitId,
|
||||
rendererId: rendererId,
|
||||
componentId: componentId,
|
||||
};
|
||||
}
|
||||
} catch (error) {
|
||||
}
|
||||
throw new Error(`Found malformed start component comment at ${node.textContent}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
function getComponentEndComment(component: StartComponentComment, children: NodeList, index: number, end: number): EndComponentComment {
|
||||
for (let i = index; i < end; i++) {
|
||||
const node = children[i];
|
||||
if (node.nodeType !== Node.COMMENT_NODE) {
|
||||
continue;
|
||||
}
|
||||
if (!node.textContent) {
|
||||
continue;
|
||||
}
|
||||
const componentEndComment = /\W+M.A.C.Component:\W+(\d+)\W+$/;
|
||||
const definition = componentEndComment.exec(node.textContent);
|
||||
const json = definition && definition[1];
|
||||
if (!json) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
// The value is expected to be a JSON encoded number
|
||||
const componentId = JSON.parse(json);
|
||||
if (componentId === component.componentId) {
|
||||
return { componentId, node: node as Comment, index: i };
|
||||
}
|
||||
} catch (error) {
|
||||
}
|
||||
throw new Error(`Found malformed end component comment at ${node.textContent}`);
|
||||
}
|
||||
throw new Error(`End component comment not found for ${component.node}`);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,46 +0,0 @@
|
|||
import { attachRootComponentToLogicalElement } from '../../Rendering/Renderer';
|
||||
import { toLogicalRootCommentElement } from '../../Rendering/LogicalElements';
|
||||
|
||||
export interface EndComponentComment {
|
||||
componentId: number;
|
||||
node: Comment;
|
||||
index: number;
|
||||
}
|
||||
|
||||
export interface StartComponentComment {
|
||||
node: Comment;
|
||||
rendererId: number;
|
||||
componentId: number;
|
||||
circuitId: string;
|
||||
}
|
||||
|
||||
// Represent pairs of start end comments indicating a component that was registered
|
||||
// in markup (such as a prerendered component)
|
||||
export interface MarkupRegistrationTags {
|
||||
start: StartComponentComment;
|
||||
end: EndComponentComment;
|
||||
}
|
||||
|
||||
export class ComponentDescriptor {
|
||||
public registrationTags: MarkupRegistrationTags;
|
||||
|
||||
public componentId: number;
|
||||
|
||||
public circuitId: string;
|
||||
|
||||
public rendererId: number;
|
||||
|
||||
public constructor(componentId: number, circuitId: string, rendererId: number, descriptor: MarkupRegistrationTags) {
|
||||
this.componentId = componentId;
|
||||
this.circuitId = circuitId;
|
||||
this.rendererId = rendererId;
|
||||
this.registrationTags = descriptor;
|
||||
}
|
||||
|
||||
public initialize(): void {
|
||||
const startEndPair = { start: this.registrationTags.start.node, end: this.registrationTags.end.node };
|
||||
|
||||
const logicalElement = toLogicalRootCommentElement(startEndPair.start, startEndPair.end);
|
||||
attachRootComponentToLogicalElement(this.rendererId, logicalElement, this.componentId);
|
||||
}
|
||||
}
|
||||
|
|
@ -5,7 +5,7 @@ let hasRegisteredNavigationInterception = false;
|
|||
let hasRegisteredNavigationEventListeners = false;
|
||||
|
||||
// Will be initialized once someone registers
|
||||
let notifyLocationChangedCallback: { assemblyName: string; functionName: string } | null = null;
|
||||
let notifyLocationChangedCallback: ((uri: string, intercepted: boolean) => Promise<void>) | null = null;
|
||||
|
||||
// These are the functions we're making available for invocation from .NET
|
||||
export const internalFunctions = {
|
||||
|
|
@ -16,12 +16,12 @@ export const internalFunctions = {
|
|||
getLocationHref: () => location.href,
|
||||
};
|
||||
|
||||
function listenForNavigationEvents(assemblyName: string, functionName: string) {
|
||||
function listenForNavigationEvents(callback: (uri: string, intercepted: boolean) => Promise<void>) {
|
||||
if (hasRegisteredNavigationEventListeners) {
|
||||
return;
|
||||
}
|
||||
|
||||
notifyLocationChangedCallback = { assemblyName, functionName };
|
||||
notifyLocationChangedCallback = callback;
|
||||
|
||||
hasRegisteredNavigationEventListeners = true;
|
||||
window.addEventListener('popstate', () => notifyLocationChanged(false));
|
||||
|
|
@ -95,12 +95,7 @@ function performInternalNavigation(absoluteInternalHref: string, interceptedLink
|
|||
|
||||
async function notifyLocationChanged(interceptedLink: boolean) {
|
||||
if (notifyLocationChangedCallback) {
|
||||
await DotNet.invokeMethodAsync(
|
||||
notifyLocationChangedCallback.assemblyName,
|
||||
notifyLocationChangedCallback.functionName,
|
||||
location.href,
|
||||
interceptedLink
|
||||
);
|
||||
await notifyLocationChangedCallback(location.href, interceptedLink);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,146 +0,0 @@
|
|||
(global as any).DotNet = { attachReviver: jest.fn() };
|
||||
|
||||
import { discoverPrerenderedCircuits } from '../src/Platform/Circuits/CircuitManager';
|
||||
import { JSDOM } from 'jsdom';
|
||||
|
||||
describe('CircuitManager', () => {
|
||||
|
||||
it('discoverPrerenderedCircuits returns discovered prerendered circuits', () => {
|
||||
const dom = new JSDOM(`<!doctype HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Page</title>
|
||||
</head>
|
||||
<body>
|
||||
<header>Preamble</header>
|
||||
<!-- M.A.C.Component: {"circuitId":"1234","rendererId":2,"componentId":1} -->
|
||||
<p>Prerendered content</p>
|
||||
<!-- M.A.C.Component: 1 -->
|
||||
<footer></footer>
|
||||
</body>
|
||||
</html>`);
|
||||
|
||||
const results = discoverPrerenderedCircuits(dom.window.document);
|
||||
|
||||
expect(results.length).toEqual(1);
|
||||
expect(results[0].components.length).toEqual(1);
|
||||
const result = results[0].components[0];
|
||||
expect(result.circuitId).toEqual("1234");
|
||||
expect(result.rendererId).toEqual(2);
|
||||
expect(result.componentId).toEqual(1);
|
||||
|
||||
});
|
||||
|
||||
it('discoverPrerenderedCircuits returns discovers multiple prerendered circuits', () => {
|
||||
const dom = new JSDOM(`<!doctype HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Page</title>
|
||||
</head>
|
||||
<body>
|
||||
<header>Preamble</header>
|
||||
<!-- M.A.C.Component: {"circuitId":"1234","rendererId":2,"componentId":1} -->
|
||||
<p>Prerendered content</p>
|
||||
<!-- M.A.C.Component: 1 -->
|
||||
<footer>
|
||||
<!-- M.A.C.Component: {"circuitId":"1234","rendererId":2,"componentId":2} -->
|
||||
<p>Prerendered content</p>
|
||||
<!-- M.A.C.Component: 2 -->
|
||||
</footer>
|
||||
</body>
|
||||
</html>`);
|
||||
|
||||
const results = discoverPrerenderedCircuits(dom.window.document);
|
||||
|
||||
expect(results.length).toEqual(1);
|
||||
expect(results[0].components.length).toEqual(2);
|
||||
const first = results[0].components[0];
|
||||
expect(first.circuitId).toEqual("1234");
|
||||
expect(first.rendererId).toEqual(2);
|
||||
expect(first.componentId).toEqual(1);
|
||||
|
||||
const second = results[0].components[1];
|
||||
expect(second.circuitId).toEqual("1234");
|
||||
expect(second.rendererId).toEqual(2);
|
||||
expect(second.componentId).toEqual(2);
|
||||
});
|
||||
|
||||
it('discoverPrerenderedCircuits throws for malformed circuits - improper nesting', () => {
|
||||
const dom = new JSDOM(`<!doctype HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Page</title>
|
||||
</head>
|
||||
<body>
|
||||
<header>Preamble</header>
|
||||
<!-- M.A.C.Component: {"circuitId":"1234","rendererId":2,"componentId":1} -->
|
||||
<p>Prerendered content</p>
|
||||
<!-- M.A.C.Component: 2 -->
|
||||
<footer>
|
||||
<!-- M.A.C.Component: {"circuitId":"1234","rendererId":2,"componentId":2} -->
|
||||
<p>Prerendered content</p>
|
||||
<!-- M.A.C.Component: 1 -->
|
||||
</footer>
|
||||
</body>
|
||||
</html>`);
|
||||
|
||||
expect(() => discoverPrerenderedCircuits(dom.window.document))
|
||||
.toThrow();
|
||||
});
|
||||
|
||||
|
||||
it('discoverPrerenderedCircuits throws for malformed circuits - mixed string and int', () => {
|
||||
const dom = new JSDOM(`<!doctype HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Page</title>
|
||||
</head>
|
||||
<body>
|
||||
<header>Preamble</header>
|
||||
<!-- M.A.C.Component: {"circuitId":"1234","rendererId":"2","componentId":"1"} -->
|
||||
<p>Prerendered content</p>
|
||||
<!-- M.A.C.Component: 1 -->
|
||||
<footer>
|
||||
<!-- M.A.C.Component: {"circuitId":"1234","rendererId":2,"componentId":2} -->
|
||||
<p>Prerendered content</p>
|
||||
<!-- M.A.C.Component: 2 -->
|
||||
</footer>
|
||||
</body>
|
||||
</html>`);
|
||||
|
||||
expect(() => discoverPrerenderedCircuits(dom.window.document))
|
||||
.toThrow();
|
||||
});
|
||||
|
||||
it('discoverPrerenderedCircuits initializes circuits', () => {
|
||||
const dom = new JSDOM(`<!doctype HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Page</title>
|
||||
</head>
|
||||
<body>
|
||||
<header>Preamble</header>
|
||||
<!-- M.A.C.Component: {"circuitId":"1234","rendererId":2,"componentId":1} -->
|
||||
<p>Prerendered content</p>
|
||||
<!-- M.A.C.Component: 1 -->
|
||||
<footer>
|
||||
<!-- M.A.C.Component: {"circuitId":"1234","rendererId":2,"componentId":2} -->
|
||||
<p>Prerendered content</p>
|
||||
<!-- M.A.C.Component: 2 -->
|
||||
</footer>
|
||||
</body>
|
||||
</html>`);
|
||||
|
||||
const results = discoverPrerenderedCircuits(dom.window.document);
|
||||
|
||||
for (let i = 0; i < results.length; i++) {
|
||||
const result = results[i];
|
||||
for (let j = 0; j < result.components.length; j++) {
|
||||
const component = result.components[j];
|
||||
component.initialize();
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
|
@ -4,11 +4,9 @@
|
|||
namespace Microsoft.AspNetCore.Components.Web
|
||||
{
|
||||
// Shared interop constants
|
||||
internal static class BrowserUriHelperInterop
|
||||
internal static class BrowserNavigationManagerInterop
|
||||
{
|
||||
private static readonly string Prefix = "Blazor._internal.uriHelper.";
|
||||
|
||||
public static readonly string ListenForNavigationEvents = Prefix + "listenForNavigationEvents";
|
||||
private static readonly string Prefix = "Blazor._internal.navigationManager.";
|
||||
|
||||
public static readonly string EnableNavigationInterception = Prefix + "enableNavigationInterception";
|
||||
|
||||
|
|
@ -51,13 +51,13 @@ namespace Microsoft.AspNetCore.Components.Routing
|
|||
[Parameter]
|
||||
public NavLinkMatch Match { get; set; }
|
||||
|
||||
[Inject] private IUriHelper UriHelper { get; set; }
|
||||
[Inject] private NavigationManager NavigationManger { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
// We'll consider re-rendering on each location change
|
||||
UriHelper.OnLocationChanged += OnLocationChanged;
|
||||
NavigationManger.LocationChanged += OnLocationChanged;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
|
@ -70,8 +70,8 @@ namespace Microsoft.AspNetCore.Components.Routing
|
|||
href = Convert.ToString(obj);
|
||||
}
|
||||
|
||||
_hrefAbsolute = href == null ? null : UriHelper.ToAbsoluteUri(href).AbsoluteUri;
|
||||
_isActive = ShouldMatch(UriHelper.GetAbsoluteUri());
|
||||
_hrefAbsolute = href == null ? null : NavigationManger.ToAbsoluteUri(href).AbsoluteUri;
|
||||
_isActive = ShouldMatch(NavigationManger.Uri);
|
||||
|
||||
_class = (string)null;
|
||||
if (AdditionalAttributes != null && AdditionalAttributes.TryGetValue("class", out obj))
|
||||
|
|
@ -86,7 +86,7 @@ namespace Microsoft.AspNetCore.Components.Routing
|
|||
public void Dispose()
|
||||
{
|
||||
// To avoid leaking memory, it's important to detach any event handlers in Dispose()
|
||||
UriHelper.OnLocationChanged -= OnLocationChanged;
|
||||
NavigationManger.LocationChanged -= OnLocationChanged;
|
||||
}
|
||||
|
||||
private void UpdateCssClass()
|
||||
|
|
|
|||
|
|
@ -1,13 +1,12 @@
|
|||
// 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.Linq;
|
||||
using BasicTestApp;
|
||||
using Microsoft.AspNetCore.Components.E2ETest.Infrastructure.ServerFixtures;
|
||||
using Microsoft.AspNetCore.E2ETesting;
|
||||
using OpenQA.Selenium;
|
||||
using OpenQA.Selenium.Support.UI;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.E2ETest.Infrastructure
|
||||
|
|
@ -38,18 +37,10 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Infrastructure
|
|||
protected SelectElement WaitUntilTestSelectorReady()
|
||||
{
|
||||
var elemToFind = By.CssSelector("#test-selector > select");
|
||||
WaitUntilExists(elemToFind, timeoutSeconds: 30);
|
||||
WaitUntilExists(elemToFind, timeoutSeconds: 30, throwOnError: true);
|
||||
return new SelectElement(Browser.FindElement(elemToFind));
|
||||
}
|
||||
|
||||
protected IWebElement WaitUntilExists(By findBy, int timeoutSeconds = 10)
|
||||
{
|
||||
IWebElement result = null;
|
||||
new WebDriverWait(Browser, TimeSpan.FromSeconds(timeoutSeconds))
|
||||
.Until(driver => (result = driver.FindElement(findBy)) != null);
|
||||
return result;
|
||||
}
|
||||
|
||||
protected void SignInAs(string usernameOrNull, string rolesOrNull, bool useSeparateTab = false)
|
||||
{
|
||||
const string authenticationPageUrl = "/Authentication";
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ using System.Collections.Generic;
|
|||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.ExceptionServices;
|
||||
using System.Threading;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.E2ETest.Infrastructure.ServerFixtures
|
||||
|
|
@ -52,13 +53,30 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Infrastructure.ServerFixtures
|
|||
{
|
||||
var isDone = new ManualResetEvent(false);
|
||||
|
||||
ExceptionDispatchInfo edi = null;
|
||||
new Thread(() =>
|
||||
{
|
||||
action();
|
||||
try
|
||||
{
|
||||
action();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
edi = ExceptionDispatchInfo.Capture(ex);
|
||||
}
|
||||
|
||||
isDone.Set();
|
||||
}).Start();
|
||||
|
||||
isDone.WaitOne();
|
||||
if (!isDone.WaitOne(TimeSpan.FromSeconds(10)))
|
||||
{
|
||||
throw new TimeoutException("Timed out waiting for: " + action);
|
||||
}
|
||||
|
||||
if (edi != null)
|
||||
{
|
||||
throw edi.SourceException;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Infrastructure.ServerFixtures
|
|||
{
|
||||
// This can be null if creating the webhost throws, we don't want to throw here and hide
|
||||
// the original exception.
|
||||
Host?.Dispose();
|
||||
Host?.StopAsync();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,12 +7,16 @@
|
|||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||
<TestGroupName>Components.E2ETests</TestGroupName>
|
||||
|
||||
<SkipTests Condition="$(ContinuousIntegrationBuild) == 'true'" >true</SkipTests>
|
||||
<!-- https://github.com/aspnet/AspNetCore/issues/6857 -->
|
||||
<BuildHelixPayload>false</BuildHelixPayload>
|
||||
|
||||
<!-- Run on platforms where we support Selenium -->
|
||||
<SkipTests Condition="'$(SeleniumE2ETestsSupported)' != 'true'">true</SkipTests>
|
||||
|
||||
<!-- Tests do not work on Helix or when bin/ directory is not in project directory due to undeclared dependency on test content. -->
|
||||
<BaseOutputPath />
|
||||
|
||||
|
||||
<OutputPath />
|
||||
|
||||
</PropertyGroup>
|
||||
|
|
|
|||
|
|
@ -5,10 +5,8 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using BasicTestApp;
|
||||
using Castle.DynamicProxy.Contributors;
|
||||
using Microsoft.AspNetCore.Components.E2ETest.Infrastructure;
|
||||
using Microsoft.AspNetCore.Components.E2ETest.Infrastructure.ServerFixtures;
|
||||
using Microsoft.AspNetCore.Components.E2ETest.ServerExecutionTests;
|
||||
using Microsoft.AspNetCore.E2ETesting;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging.Testing;
|
||||
|
|
@ -16,7 +14,7 @@ using OpenQA.Selenium;
|
|||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.E2ETests.ServerExecutionTests
|
||||
namespace Microsoft.AspNetCore.Components.E2ETest.ServerExecutionTests
|
||||
{
|
||||
public class CircuitGracefulTerminationTests : BasicTestAppTestBase, IDisposable
|
||||
{
|
||||
|
|
|
|||
|
|
@ -60,8 +60,66 @@ namespace Microsoft.AspNetCore.Components.E2ETest.ServerExecutionTests
|
|||
// Act
|
||||
await Client.ExpectCircuitError(() => Client.HubConnection.SendAsync(
|
||||
"StartCircuit",
|
||||
baseUri.GetLeftPart(UriPartial.Authority),
|
||||
baseUri));
|
||||
baseUri,
|
||||
baseUri + "/home"));
|
||||
|
||||
// Assert
|
||||
var actualError = Assert.Single(Errors);
|
||||
Assert.Matches(expectedError, actualError);
|
||||
Assert.DoesNotContain(Logs, l => l.LogLevel > LogLevel.Information);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CannotStartCircuitWithNullData()
|
||||
{
|
||||
// Arrange
|
||||
var expectedError = "The uris provided are invalid.";
|
||||
var rootUri = _serverFixture.RootUri;
|
||||
var uri = new Uri(rootUri, "/subdir");
|
||||
Assert.True(await Client.ConnectAsync(uri, prerendered: false, connectAutomatically: false), "Couldn't connect to the app");
|
||||
|
||||
// Act
|
||||
await Client.ExpectCircuitError(() => Client.HubConnection.SendAsync("StartCircuit", null, null));
|
||||
|
||||
// Assert
|
||||
var actualError = Assert.Single(Errors);
|
||||
Assert.Matches(expectedError, actualError);
|
||||
Assert.DoesNotContain(Logs, l => l.LogLevel > LogLevel.Information);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CannotStartCircuitWithInvalidUris()
|
||||
{
|
||||
// Arrange
|
||||
var expectedError = "The uris provided are invalid.";
|
||||
var rootUri = _serverFixture.RootUri;
|
||||
var uri = new Uri(rootUri, "/subdir");
|
||||
Assert.True(await Client.ConnectAsync(uri, prerendered: false, connectAutomatically: false), "Couldn't connect to the app");
|
||||
|
||||
// Act
|
||||
await Client.ExpectCircuitError(() => Client.HubConnection.SendAsync("StartCircuit", uri.AbsoluteUri, "/foo"));
|
||||
|
||||
// Assert
|
||||
var actualError = Assert.Single(Errors);
|
||||
Assert.Matches(expectedError, actualError);
|
||||
Assert.DoesNotContain(Logs, l => l.LogLevel > LogLevel.Information);
|
||||
}
|
||||
|
||||
// This is a hand-chosen example of something that will cause an exception in creating the circuit host.
|
||||
// We want to test this case so that we know what happens when creating the circuit host blows up.
|
||||
[Fact]
|
||||
public async Task StartCircuitCausesInitializationError()
|
||||
{
|
||||
// Arrange
|
||||
var expectedError = "The circuit failed to initialize.";
|
||||
var rootUri = _serverFixture.RootUri;
|
||||
var uri = new Uri(rootUri, "/subdir");
|
||||
Assert.True(await Client.ConnectAsync(uri, prerendered: false, connectAutomatically: false), "Couldn't connect to the app");
|
||||
|
||||
// Act
|
||||
//
|
||||
// These are valid URIs by the BaseUri doesn't contain the Uri - so it fails to initialize.
|
||||
await Client.ExpectCircuitError(() => Client.HubConnection.SendAsync("StartCircuit", uri, "http://example.com"), TimeSpan.FromHours(1));
|
||||
|
||||
// Assert
|
||||
var actualError = Assert.Single(Errors);
|
||||
|
|
@ -92,7 +150,7 @@ namespace Microsoft.AspNetCore.Components.E2ETest.ServerExecutionTests
|
|||
var actualError = Assert.Single(Errors);
|
||||
Assert.Equal(expectedError, actualError);
|
||||
Assert.DoesNotContain(Logs, l => l.LogLevel > LogLevel.Information);
|
||||
Assert.Contains(Logs, l => (l.LogLevel, l.Message) == (LogLevel.Debug, "Call to 'BeginInvokeDotNetFromJS' received before the circuit host initialization."));
|
||||
Assert.Contains(Logs, l => (l.LogLevel, l.Message) == (LogLevel.Debug, "Call to 'BeginInvokeDotNetFromJS' received before the circuit host initialization"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -116,7 +174,7 @@ namespace Microsoft.AspNetCore.Components.E2ETest.ServerExecutionTests
|
|||
var actualError = Assert.Single(Errors);
|
||||
Assert.Equal(expectedError, actualError);
|
||||
Assert.DoesNotContain(Logs, l => l.LogLevel > LogLevel.Information);
|
||||
Assert.Contains(Logs, l => (l.LogLevel, l.Message) == (LogLevel.Debug, "Call to 'EndInvokeJSFromDotNet' received before the circuit host initialization."));
|
||||
Assert.Contains(Logs, l => (l.LogLevel, l.Message) == (LogLevel.Debug, "Call to 'EndInvokeJSFromDotNet' received before the circuit host initialization"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -139,7 +197,7 @@ namespace Microsoft.AspNetCore.Components.E2ETest.ServerExecutionTests
|
|||
var actualError = Assert.Single(Errors);
|
||||
Assert.Equal(expectedError, actualError);
|
||||
Assert.DoesNotContain(Logs, l => l.LogLevel > LogLevel.Information);
|
||||
Assert.Contains(Logs, l => (l.LogLevel, l.Message) == (LogLevel.Debug, "Call to 'DispatchBrowserEvent' received before the circuit host initialization."));
|
||||
Assert.Contains(Logs, l => (l.LogLevel, l.Message) == (LogLevel.Debug, "Call to 'DispatchBrowserEvent' received before the circuit host initialization"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -162,7 +220,30 @@ namespace Microsoft.AspNetCore.Components.E2ETest.ServerExecutionTests
|
|||
var actualError = Assert.Single(Errors);
|
||||
Assert.Equal(expectedError, actualError);
|
||||
Assert.DoesNotContain(Logs, l => l.LogLevel > LogLevel.Information);
|
||||
Assert.Contains(Logs, l => (l.LogLevel, l.Message) == (LogLevel.Debug, "Call to 'OnRenderCompleted' received before the circuit host initialization."));
|
||||
Assert.Contains(Logs, l => (l.LogLevel, l.Message) == (LogLevel.Debug, "Call to 'OnRenderCompleted' received before the circuit host initialization"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CannotInvokeOnLocationChangedBeforeInitialization()
|
||||
{
|
||||
// Arrange
|
||||
var expectedError = "Circuit not initialized.";
|
||||
var rootUri = _serverFixture.RootUri;
|
||||
var baseUri = new Uri(rootUri, "/subdir");
|
||||
Assert.True(await Client.ConnectAsync(baseUri, prerendered: false, connectAutomatically: false));
|
||||
Assert.Empty(Batches);
|
||||
|
||||
// Act
|
||||
await Client.ExpectCircuitError(() => Client.HubConnection.SendAsync(
|
||||
"OnLocationChanged",
|
||||
baseUri.AbsoluteUri,
|
||||
false));
|
||||
|
||||
// Assert
|
||||
var actualError = Assert.Single(Errors);
|
||||
Assert.Equal(expectedError, actualError);
|
||||
Assert.DoesNotContain(Logs, l => l.LogLevel > LogLevel.Information);
|
||||
Assert.Contains(Logs, l => (l.LogLevel, l.Message) == (LogLevel.Debug, "Call to 'OnLocationChanged' received before the circuit host initialization"));
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
|
|
|
|||
|
|
@ -239,13 +239,15 @@ namespace Microsoft.AspNetCore.Components.E2ETest.ServerExecutionTests
|
|||
// Act
|
||||
await Client.ClickAsync("triggerjsinterop-malformed");
|
||||
|
||||
Assert.Single(interopCalls, (4, "sendMalformedCallbackReturn", (string)null));
|
||||
var call = interopCalls.FirstOrDefault(call => call.identifier == "sendMalformedCallbackReturn");
|
||||
Assert.NotEqual(default, call);
|
||||
|
||||
var id = call.id;
|
||||
await Client.HubConnection.InvokeAsync(
|
||||
"EndInvokeJSFromDotNet",
|
||||
4,
|
||||
id,
|
||||
true,
|
||||
"[4, true, \"{\"]");
|
||||
$"[{id}, true, \"{{\"]");
|
||||
|
||||
var text = Assert.Single(
|
||||
Client.FindElementById("errormessage-malformed").Children.OfType<TextNode>(),
|
||||
|
|
@ -264,16 +266,19 @@ namespace Microsoft.AspNetCore.Components.E2ETest.ServerExecutionTests
|
|||
var sink = _serverFixture.Host.Services.GetRequiredService<TestSink>();
|
||||
var logEvents = new List<(LogLevel logLevel, string)>();
|
||||
sink.MessageLogged += (wc) => logEvents.Add((wc.LogLevel, wc.EventId.Name));
|
||||
|
||||
// Act
|
||||
await Client.ClickAsync("triggerjsinterop-malformed");
|
||||
|
||||
Assert.Single(interopCalls, (4, "sendMalformedCallbackReturn", (string)null));
|
||||
var call = interopCalls.FirstOrDefault(call => call.identifier == "sendMalformedCallbackReturn");
|
||||
Assert.NotEqual(default, call);
|
||||
|
||||
var id = call.id;
|
||||
await Client.HubConnection.InvokeAsync(
|
||||
"EndInvokeJSFromDotNet",
|
||||
4,
|
||||
id,
|
||||
true,
|
||||
"[4, true, }");
|
||||
$"[{id}, true, }}");
|
||||
|
||||
// A completely malformed payload like the one above never gets to the application.
|
||||
Assert.Single(
|
||||
|
|
@ -285,9 +290,9 @@ namespace Microsoft.AspNetCore.Components.E2ETest.ServerExecutionTests
|
|||
await Client.ClickAsync("triggerjsinterop-success");
|
||||
await Client.HubConnection.InvokeAsync(
|
||||
"EndInvokeJSFromDotNet",
|
||||
5,
|
||||
id++,
|
||||
true,
|
||||
"[5, true, null]");
|
||||
$"[{id}, true, null]");
|
||||
|
||||
Assert.Single(
|
||||
Client.FindElementById("errormessage-success").Children.OfType<TextNode>(),
|
||||
|
|
@ -298,9 +303,9 @@ namespace Microsoft.AspNetCore.Components.E2ETest.ServerExecutionTests
|
|||
await Client.ClickAsync("triggerjsinterop-failure");
|
||||
await Client.HubConnection.InvokeAsync(
|
||||
"EndInvokeJSFromDotNet",
|
||||
6,
|
||||
id++,
|
||||
false,
|
||||
"[6, false, \"There was an error invoking sendFailureCallbackReturn\"]");
|
||||
$"[{id}, false, \"There was an error invoking sendFailureCallbackReturn\"]");
|
||||
|
||||
Assert.Single(
|
||||
Client.FindElementById("errormessage-failure").Children.OfType<TextNode>(),
|
||||
|
|
@ -534,7 +539,7 @@ namespace Microsoft.AspNetCore.Components.E2ETest.ServerExecutionTests
|
|||
Assert.Equal(2, batches.Count);
|
||||
}
|
||||
|
||||
private (List<(int, string, string)>, List<string>, List<(int, int, byte[])>) ConfigureClient()
|
||||
private (List<(int id, string identifier, string args)>, List<string>, List<(int, int, byte[])>) ConfigureClient()
|
||||
{
|
||||
var interopCalls = new List<(int, string, string)>();
|
||||
Client.JSInterop += (int arg1, string arg2, string arg3) => interopCalls.Add((arg1, arg2, arg3));
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ namespace Microsoft.AspNetCore.Components.E2ETest.ServerExecutionTests
|
|||
{
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[Theory(Skip = "https://github.com/aspnet/AspNetCore/issues/12788")]
|
||||
[InlineData(null, null)]
|
||||
[InlineData(null, "Someone")]
|
||||
[InlineData("Someone", null)]
|
||||
|
|
|
|||
|
|
@ -138,7 +138,7 @@ namespace Microsoft.AspNetCore.Components.E2ETest.ServerExecutionTests
|
|||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Fact(Skip = "https://github.com/aspnet/AspNetCore/issues/12788")]
|
||||
public void ReconnectUI()
|
||||
{
|
||||
Browser.FindElement(By.LinkText("Counter")).Click();
|
||||
|
|
@ -155,7 +155,7 @@ namespace Microsoft.AspNetCore.Components.E2ETest.ServerExecutionTests
|
|||
.Until(driver => reconnectionDialog.GetCssValue("display") == "none");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Fact(Skip = "https://github.com/aspnet/AspNetCore/issues/12788")]
|
||||
public void RendersContinueAfterReconnect()
|
||||
{
|
||||
Browser.FindElement(By.LinkText("Ticker")).Click();
|
||||
|
|
@ -184,11 +184,14 @@ namespace Microsoft.AspNetCore.Components.E2ETest.ServerExecutionTests
|
|||
_ => element.Text != currentValue);
|
||||
}
|
||||
|
||||
// Since we've removed stateful prerendering, the name which is passed in
|
||||
// during prerendering cannot be retained. The first interactive render
|
||||
// will remove it.
|
||||
[Fact]
|
||||
public void RendersContinueAfterPrerendering()
|
||||
public void RendersDoNotPreserveState()
|
||||
{
|
||||
Browser.FindElement(By.LinkText("Greeter")).Click();
|
||||
Browser.Equal("Hello Guest", () => Browser.FindElement(By.ClassName("greeting")).Text);
|
||||
Browser.Equal("Hello", () => Browser.FindElement(By.ClassName("greeting")).Text);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
|
|||
|
|
@ -369,9 +369,9 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Tests
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void UsingUriHelperWithoutRouterWorks()
|
||||
public void UsingNavigationManagerWithoutRouterWorks()
|
||||
{
|
||||
var app = MountTestComponent<UriHelperComponent>();
|
||||
var app = MountTestComponent<NavigationManagerComponent>();
|
||||
var initialUrl = Browser.Url;
|
||||
|
||||
Browser.Equal(Browser.Url, () => app.FindElement(By.Id("test-info")).Text);
|
||||
|
|
@ -387,7 +387,7 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Tests
|
|||
[Fact]
|
||||
public void UriHelperCanReadAbsoluteUriIncludingHash()
|
||||
{
|
||||
var app = MountTestComponent<UriHelperComponent>();
|
||||
var app = MountTestComponent<NavigationManagerComponent>();
|
||||
Browser.Equal(Browser.Url, () => app.FindElement(By.Id("test-info")).Text);
|
||||
|
||||
var uri = "/mytestpath?my=query&another#some/hash?tokens";
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
@using Microsoft.AspNetCore.Components.Routing
|
||||
@inject IUriHelper UriHelper
|
||||
@inject NavigationManager NavigationManager
|
||||
|
||||
@*
|
||||
This router is independent of any other router that may exist within the same project.
|
||||
|
|
@ -27,11 +27,11 @@
|
|||
{
|
||||
// Start at AuthHome, not at any other component in the same app that happens to
|
||||
// register itself for the route ""
|
||||
var absoluteUriPath = new Uri(UriHelper.GetAbsoluteUri()).GetLeftPart(UriPartial.Path);
|
||||
var relativeUri = UriHelper.ToBaseRelativePath(UriHelper.GetBaseUri(), absoluteUriPath);
|
||||
var absoluteUriPath = new Uri(NavigationManager.Uri).GetLeftPart(UriPartial.Path);
|
||||
var relativeUri = NavigationManager.ToBaseRelativePath(absoluteUriPath);
|
||||
if (relativeUri == string.Empty)
|
||||
{
|
||||
UriHelper.NavigateTo("AuthHome");
|
||||
NavigationManager.NavigateTo("AuthHome");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
@inject IUriHelper UriHelper
|
||||
@inject NavigationManager NavigationManager
|
||||
|
||||
<h3>Select your language</h3>
|
||||
<select @onchange="@OnSelected" id="culture-selector">
|
||||
|
|
@ -11,8 +11,8 @@
|
|||
void OnSelected(ChangeEventArgs e)
|
||||
{
|
||||
// Included fragment to preserve choice of Blazor client or server.
|
||||
var redirect = new Uri(UriHelper.GetAbsoluteUri()).GetComponents(UriComponents.PathAndQuery | UriComponents.Fragment, UriFormat.UriEscaped);
|
||||
var redirect = new Uri(NavigationManager.Uri).GetComponents(UriComponents.PathAndQuery | UriComponents.Fragment, UriFormat.UriEscaped);
|
||||
var query = $"?culture={Uri.EscapeDataString((string)e.Value)}&redirectUri={redirect}";
|
||||
UriHelper.NavigateTo("/Culture/SetCulture" + query, forceLoad: true);
|
||||
NavigationManager.NavigateTo("/Culture/SetCulture" + query, forceLoad: true);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,12 +2,12 @@
|
|||
<DuplicateAttributesOnElementChildComponent
|
||||
BoolAttributeBefore="true"
|
||||
StringAttributeBefore="original-text"
|
||||
UnmatchedValues="@elementValues"/>
|
||||
UnmatchedValues="elementValues"/>
|
||||
</div>
|
||||
|
||||
<div id="duplicate-on-element-override">
|
||||
<DuplicateAttributesOnElementChildComponent
|
||||
UnmatchedValues="@elementValues"
|
||||
UnmatchedValues="elementValues"
|
||||
BoolAttributeAfter="false"
|
||||
StringAttributeAfter="other-text" />
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -14,10 +14,10 @@ else
|
|||
}
|
||||
|
||||
@code {
|
||||
[Parameter] public string StringAttributeBefore { get; private set; }
|
||||
[Parameter] public bool BoolAttributeBefore { get; private set; }
|
||||
[Parameter] public string StringAttributeAfter { get; private set; }
|
||||
[Parameter] public bool? BoolAttributeAfter { get; private set; }
|
||||
[Parameter] public string StringAttributeBefore { get; set; }
|
||||
[Parameter] public bool BoolAttributeBefore { get; set; }
|
||||
[Parameter] public string StringAttributeAfter { get; set; }
|
||||
[Parameter] public bool? BoolAttributeAfter { get; set; }
|
||||
|
||||
[Parameter(CaptureUnmatchedValues = true)] public Dictionary<string, object> UnmatchedValues { get; private set; }
|
||||
[Parameter(CaptureUnmatchedValues = true)] public Dictionary<string, object> UnmatchedValues { get; set; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,8 +57,8 @@
|
|||
<option value="BasicTestApp.ReliabilityComponent">Server reliability component</option>
|
||||
<option value="BasicTestApp.RenderFragmentToggler">Render fragment renderer</option>
|
||||
<option value="BasicTestApp.ReorderingFocusComponent">Reordering focus retention</option>
|
||||
<option value="BasicTestApp.RouterTest.NavigationManagerComponent">NavigationManager Test</option>
|
||||
<option value="BasicTestApp.RouterTest.TestRouter">Router</option>
|
||||
<option value="BasicTestApp.RouterTest.UriHelperComponent">UriHelper Test</option>
|
||||
<option value="BasicTestApp.SvgComponent">SVG</option>
|
||||
<option value="BasicTestApp.SvgWithChildComponent">SVG with child component</option>
|
||||
<option value="BasicTestApp.TextOnlyComponent">Plain text</option>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
@page "/prerendered-redirection"
|
||||
@inject IUriHelper UriHelper
|
||||
@inject NavigationManager NavigationManager
|
||||
|
||||
@{
|
||||
throw new InvalidOperationException("The rendering logic should never be executed");
|
||||
|
|
@ -8,9 +8,9 @@
|
|||
@code {
|
||||
protected override Task OnInitializedAsync()
|
||||
{
|
||||
var uri = UriHelper.GetAbsoluteUri();
|
||||
var uri = NavigationManager.Uri;
|
||||
var destination = uri.Substring(uri.IndexOf("?destination=") + 13);
|
||||
UriHelper.NavigateTo(destination);
|
||||
NavigationManager.NavigateTo(destination);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
@using Microsoft.AspNetCore.Components.Routing
|
||||
@inject Microsoft.AspNetCore.Components.IUriHelper uriHelper
|
||||
@inject NavigationManager NavigationManager
|
||||
<style type="text/css">
|
||||
a.active {
|
||||
background-color: yellow;
|
||||
|
|
@ -22,11 +22,11 @@
|
|||
<li><NavLink href="/subdir/LongPage2">Long page 2</NavLink></li>
|
||||
</ul>
|
||||
|
||||
<button id="do-navigation" @onclick=@(x => uriHelper.NavigateTo("Other"))>
|
||||
<button id="do-navigation" @onclick=@(x => NavigationManager.NavigateTo("Other"))>
|
||||
Programmatic navigation
|
||||
</button>
|
||||
|
||||
<button id="do-navigation-forced" @onclick=@(x => uriHelper.NavigateTo("Other", true))>
|
||||
<button id="do-navigation-forced" @onclick=@(x => NavigationManager.NavigateTo("Other", true))>
|
||||
Programmatic navigation with force-load
|
||||
</button>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
@page "/LongPage1"
|
||||
@inject IUriHelper UriHelper
|
||||
@inject NavigationManager NavigationManager
|
||||
<div id="test-info">This is a long page you can scroll.</div>
|
||||
|
||||
<div style="border: 2px dashed red; margin: 1rem; padding: 1rem; height: 1500px;">
|
||||
Scroll past me to find the links
|
||||
</div>
|
||||
|
||||
<button id="go-to-longpage2" @onclick="@(() => UriHelper.NavigateTo("LongPage2"))">
|
||||
<button id="go-to-longpage2" @onclick="@(() => NavigationManager.NavigateTo("LongPage2"))">
|
||||
Navigate programmatically to long page 2
|
||||
</button>
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,35 @@
|
|||
@inject NavigationManager NavigationManager
|
||||
@inject Microsoft.JSInterop.IJSRuntime JSRuntime
|
||||
@using Microsoft.AspNetCore.Components.Routing
|
||||
@implements IDisposable
|
||||
|
||||
<button @onclick="Navigate">Navigate</button>
|
||||
|
||||
<span id="test-info">@UrlLocation</span>
|
||||
|
||||
@code{
|
||||
string UrlLocation;
|
||||
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
UrlLocation = NavigationManager.Uri;
|
||||
NavigationManager.LocationChanged += OnLocationChanged;
|
||||
}
|
||||
|
||||
void IDisposable.Dispose()
|
||||
{
|
||||
NavigationManager.LocationChanged -= OnLocationChanged;
|
||||
}
|
||||
|
||||
void OnLocationChanged(object sender, LocationChangedEventArgs e)
|
||||
{
|
||||
UrlLocation = NavigationManager.Uri;
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
async Task Navigate()
|
||||
{
|
||||
await JSRuntime.InvokeAsync<object>("navigationManagerNavigate");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
@inject IUriHelper UriHelper
|
||||
@inject Microsoft.JSInterop.IJSRuntime JSRuntime
|
||||
|
||||
<button @onclick="Navigate">Navigate</button>
|
||||
|
||||
<span id="test-info">@UrlLocation</span>
|
||||
|
||||
@code{
|
||||
string UrlLocation;
|
||||
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
UrlLocation = UriHelper.GetAbsoluteUri();
|
||||
UriHelper.OnLocationChanged += (_, __) =>
|
||||
{
|
||||
UrlLocation = UriHelper.GetAbsoluteUri();
|
||||
StateHasChanged();
|
||||
};
|
||||
}
|
||||
|
||||
async Task Navigate()
|
||||
{
|
||||
await JSRuntime.InvokeAsync<object>("uriHelperNavigate");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,3 +1,3 @@
|
|||
@page "/show-uri"
|
||||
@inject IUriHelper UriHelper
|
||||
The current URL is <strong>@UriHelper.GetAbsoluteUri()</strong>
|
||||
@inject NavigationManager NavigationManager
|
||||
The current URL is <strong>@NavigationManager.Uri</strong>
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
return element.value;
|
||||
}
|
||||
|
||||
function uriHelperNavigate() {
|
||||
function navigationManagerNavigate() {
|
||||
Blazor.navigateTo('/subdir/some-path');
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@
|
|||
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.AspNetCore" />
|
||||
<Reference Include="Microsoft.AspNetCore.Mvc.Components.Prerendering" />
|
||||
<Reference Include="Microsoft.AspNetCore.Components.Server" />
|
||||
<Reference Include="Microsoft.AspNetCore.Mvc" />
|
||||
<Reference Include="Newtonsoft.Json" />
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Components.Server;
|
||||
using Microsoft.AspNetCore.Components.Server.Circuits;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
|
@ -40,8 +39,8 @@ namespace ComponentsApp.Server
|
|||
{
|
||||
endpoints.MapRazorPages();
|
||||
endpoints.MapControllers();
|
||||
endpoints.MapBlazorHub();
|
||||
endpoints.MapFallbackToPage("/Index");
|
||||
endpoints.MapBlazorHub<ComponentsApp.App.App>("app");
|
||||
endpoints.MapFallbackToPage("/_Host");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -76,38 +76,38 @@ namespace Ignitor
|
|||
return NextBatchReceived.Completion.Task;
|
||||
}
|
||||
|
||||
public Task PrepareForNextJSInterop()
|
||||
public Task PrepareForNextJSInterop(TimeSpan? timeout)
|
||||
{
|
||||
if (NextJSInteropReceived?.Completion != null)
|
||||
{
|
||||
throw new InvalidOperationException("Invalid state previous task not completed");
|
||||
}
|
||||
|
||||
NextJSInteropReceived = new CancellableOperation(DefaultLatencyTimeout);
|
||||
NextJSInteropReceived = new CancellableOperation(timeout);
|
||||
|
||||
return NextJSInteropReceived.Completion.Task;
|
||||
}
|
||||
|
||||
public Task PrepareForNextDotNetInterop()
|
||||
public Task PrepareForNextDotNetInterop(TimeSpan? timeout)
|
||||
{
|
||||
if (NextDotNetInteropCompletionReceived?.Completion != null)
|
||||
{
|
||||
throw new InvalidOperationException("Invalid state previous task not completed");
|
||||
}
|
||||
|
||||
NextDotNetInteropCompletionReceived = new CancellableOperation(DefaultLatencyTimeout);
|
||||
NextDotNetInteropCompletionReceived = new CancellableOperation(timeout);
|
||||
|
||||
return NextDotNetInteropCompletionReceived.Completion.Task;
|
||||
}
|
||||
|
||||
public Task PrepareForNextCircuitError()
|
||||
public Task PrepareForNextCircuitError(TimeSpan? timeout)
|
||||
{
|
||||
if (NextErrorReceived?.Completion != null)
|
||||
{
|
||||
throw new InvalidOperationException("Invalid state previous task not completed");
|
||||
}
|
||||
|
||||
NextErrorReceived = new CancellableOperation(DefaultLatencyTimeout);
|
||||
NextErrorReceived = new CancellableOperation(timeout);
|
||||
|
||||
return NextErrorReceived.Completion.Task;
|
||||
}
|
||||
|
|
@ -139,23 +139,23 @@ namespace Ignitor
|
|||
await task;
|
||||
}
|
||||
|
||||
public async Task ExpectJSInterop(Func<Task> action)
|
||||
public async Task ExpectJSInterop(Func<Task> action, TimeSpan? timeout = null)
|
||||
{
|
||||
var task = WaitForJSInterop();
|
||||
var task = WaitForJSInterop(timeout);
|
||||
await action();
|
||||
await task;
|
||||
}
|
||||
|
||||
public async Task ExpectDotNetInterop(Func<Task> action)
|
||||
public async Task ExpectDotNetInterop(Func<Task> action, TimeSpan? timeout = null)
|
||||
{
|
||||
var task = WaitForDotNetInterop();
|
||||
var task = WaitForDotNetInterop(timeout);
|
||||
await action();
|
||||
await task;
|
||||
}
|
||||
|
||||
public async Task ExpectCircuitError(Func<Task> action)
|
||||
public async Task ExpectCircuitError(Func<Task> action, TimeSpan? timeout = null)
|
||||
{
|
||||
var task = WaitForCircuitError();
|
||||
var task = WaitForCircuitError(timeout);
|
||||
await action();
|
||||
await task;
|
||||
}
|
||||
|
|
@ -175,42 +175,42 @@ namespace Ignitor
|
|||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private async Task WaitForJSInterop()
|
||||
private async Task WaitForJSInterop(TimeSpan? timeout = null)
|
||||
{
|
||||
if (ImplicitWait)
|
||||
{
|
||||
if (DefaultLatencyTimeout == null)
|
||||
if (DefaultLatencyTimeout == null && timeout == null)
|
||||
{
|
||||
throw new InvalidOperationException("Implicit wait without DefaultLatencyTimeout is not allowed.");
|
||||
}
|
||||
|
||||
await PrepareForNextJSInterop();
|
||||
await PrepareForNextJSInterop(timeout ?? DefaultLatencyTimeout);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task WaitForDotNetInterop()
|
||||
private async Task WaitForDotNetInterop(TimeSpan? timeout = null)
|
||||
{
|
||||
if (ImplicitWait)
|
||||
{
|
||||
if (DefaultLatencyTimeout == null)
|
||||
if (DefaultLatencyTimeout == null && timeout == null)
|
||||
{
|
||||
throw new InvalidOperationException("Implicit wait without DefaultLatencyTimeout is not allowed.");
|
||||
}
|
||||
|
||||
await PrepareForNextDotNetInterop();
|
||||
await PrepareForNextDotNetInterop(timeout ?? DefaultLatencyTimeout);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task WaitForCircuitError()
|
||||
private async Task WaitForCircuitError(TimeSpan? timeout = null)
|
||||
{
|
||||
if (ImplicitWait)
|
||||
{
|
||||
if (DefaultLatencyTimeout == null)
|
||||
if (DefaultLatencyTimeout == null && timeout == null)
|
||||
{
|
||||
throw new InvalidOperationException("Implicit wait without DefaultLatencyTimeout is not allowed.");
|
||||
}
|
||||
|
||||
await PrepareForNextCircuitError();
|
||||
await PrepareForNextCircuitError(timeout ?? DefaultLatencyTimeout);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -246,7 +246,7 @@ namespace Ignitor
|
|||
else
|
||||
{
|
||||
await ExpectRenderBatch(
|
||||
async () => CircuitId = await HubConnection.InvokeAsync<string>("StartCircuit", new Uri(uri.GetLeftPart(UriPartial.Authority)), uri),
|
||||
async () => CircuitId = await HubConnection.InvokeAsync<string>("StartCircuit", uri, uri),
|
||||
TimeSpan.FromSeconds(10));
|
||||
return CircuitId != null;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text.Json;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
|
|
@ -75,8 +76,6 @@ namespace Ignitor
|
|||
|
||||
public async Task ExecuteAsync(Uri uri)
|
||||
{
|
||||
string circuitId = await GetPrerenderedCircuitId(uri);
|
||||
|
||||
var builder = new HubConnectionBuilder();
|
||||
builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<IHubProtocol, IgnitorMessagePackHubProtocol>());
|
||||
builder.WithUrl(new Uri(uri, "_blazor/"));
|
||||
|
|
@ -93,7 +92,7 @@ namespace Ignitor
|
|||
connection.Closed += OnClosedAsync;
|
||||
|
||||
// Now everything is registered so we can start the circuit.
|
||||
var success = await connection.InvokeAsync<bool>("ConnectCircuit", circuitId);
|
||||
var success = await connection.InvokeAsync<bool>("StartCircuit", uri.AbsoluteUri, uri.GetLeftPart(UriPartial.Authority));
|
||||
|
||||
await TaskCompletionSource.Task;
|
||||
|
||||
|
|
@ -131,19 +130,6 @@ namespace Ignitor
|
|||
}
|
||||
}
|
||||
|
||||
private static async Task<string> GetPrerenderedCircuitId(Uri uri)
|
||||
{
|
||||
var httpClient = new HttpClient();
|
||||
var response = await httpClient.GetAsync(uri);
|
||||
var content = await response.Content.ReadAsStringAsync();
|
||||
|
||||
// <!-- M.A.C.Component:{"circuitId":"CfDJ8KZCIaqnXmdF...PVd6VVzfnmc1","rendererId":"0","componentId":"0"} -->
|
||||
var match = Regex.Match(content, $"{Regex.Escape("<!-- M.A.C.Component:")}(.+?){Regex.Escape(" -->")}");
|
||||
var json = JsonDocument.Parse(match.Groups[1].Value);
|
||||
var circuitId = json.RootElement.GetProperty("circuitId").GetString();
|
||||
return circuitId;
|
||||
}
|
||||
|
||||
private static async Task ClickAsync(string id, ElementHive hive, HubConnection connection)
|
||||
{
|
||||
if (!hive.TryFindElementById(id, out var elementNode))
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||
|
|
@ -8,11 +8,11 @@
|
|||
<Reference Include="Microsoft.AspNetCore" />
|
||||
<Reference Include="Microsoft.AspNetCore.Authentication.Cookies" />
|
||||
<Reference Include="Microsoft.AspNetCore.Blazor.Server" />
|
||||
<Reference Include="Microsoft.AspNetCore.Components.Server" />
|
||||
<Reference Include="Microsoft.AspNetCore.Cors" />
|
||||
<Reference Include="Microsoft.AspNetCore.Mvc" />
|
||||
<Reference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" />
|
||||
<Reference Include="Microsoft.AspNetCore.Components.Server" />
|
||||
<Reference Include="Microsoft.AspNetCore.Mvc.Components.Prerendering" />
|
||||
<Reference Include="Microsoft.AspNetCore.Mvc.ViewFeatures" />
|
||||
<Reference Include="Microsoft.Extensions.Logging.Testing" />
|
||||
</ItemGroup>
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
<base href="~/" />
|
||||
</head>
|
||||
<body>
|
||||
<app>@(await Html.RenderStaticComponentAsync<TestRouter>())</app>
|
||||
<app>@(await Html.RenderComponentAsync<TestRouter>())</app>
|
||||
|
||||
@*
|
||||
So that E2E tests can make assertions about both the prerendered and
|
||||
|
|
|
|||
|
|
@ -13,8 +13,8 @@ namespace Microsoft.AspNetCore.WebUtilities.Performance
|
|||
public class FormPipeReaderInternalsBenchmark
|
||||
{
|
||||
private byte[] _singleUtf8 = Encoding.UTF8.GetBytes("foo=bar&baz=boo&haha=hehe&lol=temp");
|
||||
private byte[] _firstUtf8 = Encoding.UTF8.GetBytes("foo=bar&baz=boo");
|
||||
private byte[] _secondUtf8 = Encoding.UTF8.GetBytes("&haha=hehe&lol=temp");
|
||||
private byte[] _firstUtf8 = Encoding.UTF8.GetBytes("foo=bar&baz=bo");
|
||||
private byte[] _secondUtf8 = Encoding.UTF8.GetBytes("o&haha=hehe&lol=temp");
|
||||
private FormPipeReader _formPipeReader;
|
||||
|
||||
[IterationSetup]
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
using System;
|
||||
using System.Buffers;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.IO.Pipelines;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
|
@ -139,74 +140,78 @@ namespace Microsoft.AspNetCore.WebUtilities
|
|||
bool isFinalBlock,
|
||||
out int consumed)
|
||||
{
|
||||
ReadOnlySpan<byte> key = default;
|
||||
ReadOnlySpan<byte> value = default;
|
||||
ReadOnlySpan<byte> key;
|
||||
ReadOnlySpan<byte> value;
|
||||
consumed = 0;
|
||||
var equalsDelimiter = GetEqualsForEncoding();
|
||||
var andDelimiter = GetAndForEncoding();
|
||||
|
||||
while (span.Length > 0)
|
||||
{
|
||||
var equals = span.IndexOf(equalsDelimiter);
|
||||
|
||||
if (equals == -1)
|
||||
{
|
||||
if (span.Length > KeyLengthLimit)
|
||||
{
|
||||
ThrowKeyTooLargeException();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (equals > KeyLengthLimit)
|
||||
{
|
||||
ThrowKeyTooLargeException();
|
||||
}
|
||||
|
||||
key = span.Slice(0, equals);
|
||||
|
||||
span = span.Slice(key.Length + equalsDelimiter.Length);
|
||||
value = span;
|
||||
|
||||
// Find the end of the key=value pair.
|
||||
var ampersand = span.IndexOf(andDelimiter);
|
||||
ReadOnlySpan<byte> keyValuePair;
|
||||
int equals;
|
||||
var foundAmpersand = ampersand != -1;
|
||||
|
||||
if (ampersand == -1)
|
||||
if (foundAmpersand)
|
||||
{
|
||||
if (span.Length > ValueLengthLimit)
|
||||
{
|
||||
ThrowValueTooLargeException();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isFinalBlock)
|
||||
{
|
||||
// We can't know that what is currently read is the end of the form value, that's only the case if this is the final block
|
||||
// If we're not in the final block, then consume nothing
|
||||
break;
|
||||
}
|
||||
|
||||
// If we are on the final block, the remaining content in value is what we want to add to the KVAccumulator.
|
||||
// Clear out the remaining span such that the loop will exit.
|
||||
span = Span<byte>.Empty;
|
||||
keyValuePair = span.Slice(0, ampersand);
|
||||
span = span.Slice(keyValuePair.Length + andDelimiter.Length);
|
||||
consumed += keyValuePair.Length + andDelimiter.Length;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ampersand > ValueLengthLimit)
|
||||
// We can't know that what is currently read is the end of the form value, that's only the case if this is the final block
|
||||
// If we're not in the final block, then consume nothing
|
||||
if (!isFinalBlock)
|
||||
{
|
||||
// Don't buffer indefinately
|
||||
if (span.Length > KeyLengthLimit + ValueLengthLimit)
|
||||
{
|
||||
ThrowKeyOrValueTooLargeException();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
keyValuePair = span;
|
||||
span = default;
|
||||
consumed += keyValuePair.Length;
|
||||
}
|
||||
|
||||
equals = keyValuePair.IndexOf(equalsDelimiter);
|
||||
|
||||
if (equals == -1)
|
||||
{
|
||||
// Too long for the whole segment to be a key.
|
||||
if (keyValuePair.Length > KeyLengthLimit)
|
||||
{
|
||||
ThrowKeyTooLargeException();
|
||||
}
|
||||
|
||||
// There is no more data, this segment must be "key" with no equals or value.
|
||||
key = keyValuePair;
|
||||
value = default;
|
||||
}
|
||||
else
|
||||
{
|
||||
key = keyValuePair.Slice(0, equals);
|
||||
if (key.Length > KeyLengthLimit)
|
||||
{
|
||||
ThrowKeyTooLargeException();
|
||||
}
|
||||
|
||||
value = keyValuePair.Slice(equals + equalsDelimiter.Length);
|
||||
if (value.Length > ValueLengthLimit)
|
||||
{
|
||||
ThrowValueTooLargeException();
|
||||
}
|
||||
|
||||
value = span.Slice(0, ampersand);
|
||||
span = span.Slice(ampersand + andDelimiter.Length);
|
||||
}
|
||||
|
||||
var decodedKey = GetDecodedString(key);
|
||||
var decodedValue = GetDecodedString(value);
|
||||
|
||||
AppendAndVerify(ref accumulator, decodedKey, decodedValue);
|
||||
|
||||
// Cover case where we don't have an ampersand at the end.
|
||||
consumed += key.Length + value.Length + (ampersand == -1 ? equalsDelimiter.Length : equalsDelimiter.Length + andDelimiter.Length);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -217,6 +222,8 @@ namespace Microsoft.AspNetCore.WebUtilities
|
|||
bool isFinalBlock)
|
||||
{
|
||||
var sequenceReader = new SequenceReader<byte>(buffer);
|
||||
ReadOnlySequence<byte> keyValuePair;
|
||||
|
||||
var consumed = sequenceReader.Position;
|
||||
var consumedBytes = default(long);
|
||||
var equalsDelimiter = GetEqualsForEncoding();
|
||||
|
|
@ -224,46 +231,59 @@ namespace Microsoft.AspNetCore.WebUtilities
|
|||
|
||||
while (!sequenceReader.End)
|
||||
{
|
||||
// TODO seems there is a bug with TryReadTo (advancePastDelimiter: true). It isn't advancing past the delimiter on second read.
|
||||
if (!sequenceReader.TryReadTo(out ReadOnlySequence<byte> key, equalsDelimiter, advancePastDelimiter: false) ||
|
||||
!sequenceReader.IsNext(equalsDelimiter, true))
|
||||
{
|
||||
if ((sequenceReader.Consumed - consumedBytes) > KeyLengthLimit)
|
||||
{
|
||||
ThrowKeyTooLargeException();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (key.Length > KeyLengthLimit)
|
||||
{
|
||||
ThrowKeyTooLargeException();
|
||||
}
|
||||
|
||||
if (!sequenceReader.TryReadTo(out ReadOnlySequence<byte> value, andDelimiter, false) ||
|
||||
!sequenceReader.IsNext(andDelimiter, true))
|
||||
if (!sequenceReader.TryReadTo(out keyValuePair, andDelimiter))
|
||||
{
|
||||
if (!isFinalBlock)
|
||||
{
|
||||
if ((sequenceReader.Consumed - consumedBytes - key.Length) > ValueLengthLimit)
|
||||
// Don't buffer indefinately
|
||||
if ((sequenceReader.Consumed - consumedBytes) > KeyLengthLimit + ValueLengthLimit)
|
||||
{
|
||||
ThrowValueTooLargeException();
|
||||
ThrowKeyOrValueTooLargeException();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
value = buffer.Slice(sequenceReader.Position);
|
||||
|
||||
sequenceReader.Advance(value.Length);
|
||||
// This must be the final key=value pair
|
||||
keyValuePair = buffer.Slice(sequenceReader.Position);
|
||||
sequenceReader.Advance(keyValuePair.Length);
|
||||
}
|
||||
|
||||
if (value.Length > ValueLengthLimit)
|
||||
if (keyValuePair.IsSingleSegment)
|
||||
{
|
||||
ThrowValueTooLargeException();
|
||||
ParseFormValuesFast(keyValuePair.FirstSpan, ref accumulator, isFinalBlock: true, out var segmentConsumed);
|
||||
Debug.Assert(segmentConsumed == keyValuePair.FirstSpan.Length);
|
||||
continue;
|
||||
}
|
||||
|
||||
var keyValueReader = new SequenceReader<byte>(keyValuePair);
|
||||
ReadOnlySequence<byte> value;
|
||||
|
||||
if (keyValueReader.TryReadTo(out var key, equalsDelimiter))
|
||||
{
|
||||
if (key.Length > KeyLengthLimit)
|
||||
{
|
||||
ThrowKeyTooLargeException();
|
||||
}
|
||||
|
||||
value = keyValuePair.Slice(keyValueReader.Position);
|
||||
if (value.Length > ValueLengthLimit)
|
||||
{
|
||||
ThrowValueTooLargeException();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Too long for the whole segment to be a key.
|
||||
if (keyValuePair.Length > KeyLengthLimit)
|
||||
{
|
||||
ThrowKeyTooLargeException();
|
||||
}
|
||||
|
||||
// There is no more data, this segment must be "key" with no equals or value.
|
||||
key = keyValuePair;
|
||||
value = default;
|
||||
}
|
||||
|
||||
// Need to call ToArray if the key/value spans multiple segments
|
||||
var decodedKey = GetDecodedStringFromReadOnlySequence(key);
|
||||
var decodedValue = GetDecodedStringFromReadOnlySequence(value);
|
||||
|
||||
|
|
@ -276,6 +296,11 @@ namespace Microsoft.AspNetCore.WebUtilities
|
|||
buffer = buffer.Slice(consumed);
|
||||
}
|
||||
|
||||
private void ThrowKeyOrValueTooLargeException()
|
||||
{
|
||||
throw new InvalidDataException($"Form key length limit {KeyLengthLimit} or value length limit {ValueLengthLimit} exceeded.");
|
||||
}
|
||||
|
||||
private void ThrowKeyTooLargeException()
|
||||
{
|
||||
throw new InvalidDataException($"Form key length limit {KeyLengthLimit} exceeded.");
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ namespace Microsoft.AspNetCore.WebUtilities
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ReadFormAsync_EmptyValuedAtEndAllowed()
|
||||
public async Task ReadFormAsync_EmptyValueAtEndAllowed()
|
||||
{
|
||||
var bodyPipe = await MakePipeReader("foo=");
|
||||
|
||||
|
|
@ -47,7 +47,17 @@ namespace Microsoft.AspNetCore.WebUtilities
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ReadFormAsync_EmptyValuedWithAdditionalEntryAllowed()
|
||||
public async Task ReadFormAsync_EmptyValueWithoutEqualsAtEndAllowed()
|
||||
{
|
||||
var bodyPipe = await MakePipeReader("foo");
|
||||
|
||||
var formCollection = await ReadFormAsync(new FormPipeReader(bodyPipe));
|
||||
|
||||
Assert.Equal("", formCollection["foo"].ToString());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ReadFormAsync_EmptyValueWithAdditionalEntryAllowed()
|
||||
{
|
||||
var bodyPipe = await MakePipeReader("foo=&baz=2");
|
||||
|
||||
|
|
@ -57,6 +67,17 @@ namespace Microsoft.AspNetCore.WebUtilities
|
|||
Assert.Equal("2", formCollection["baz"].ToString());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ReadFormAsync_EmptyValueWithoutEqualsWithAdditionalEntryAllowed()
|
||||
{
|
||||
var bodyPipe = await MakePipeReader("foo&baz=2");
|
||||
|
||||
var formCollection = await ReadFormAsync(new FormPipeReader(bodyPipe));
|
||||
|
||||
Assert.Equal("", formCollection["foo"].ToString());
|
||||
Assert.Equal("2", formCollection["baz"].ToString());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ReadFormAsync_ValueCountLimitMet_Success()
|
||||
{
|
||||
|
|
@ -172,7 +193,7 @@ namespace Microsoft.AspNetCore.WebUtilities
|
|||
|
||||
[Theory]
|
||||
[MemberData(nameof(Encodings))]
|
||||
public void TryParseFormValues_MultiSegmentWorks(Encoding encoding)
|
||||
public void TryParseFormValues_Works(Encoding encoding)
|
||||
{
|
||||
var readOnlySequence = ReadOnlySequenceFactory.SingleSegmentFactory.CreateWithContent(encoding.GetBytes("foo=bar&baz=boo&t="));
|
||||
|
||||
|
|
@ -190,9 +211,9 @@ namespace Microsoft.AspNetCore.WebUtilities
|
|||
|
||||
[Theory]
|
||||
[MemberData(nameof(Encodings))]
|
||||
public void TryParseFormValues_MultiSegmentSplitAcrossSegmentsWorks(Encoding encoding)
|
||||
public void TryParseFormValues_SplitAcrossSegmentsWorks(Encoding encoding)
|
||||
{
|
||||
var readOnlySequence = ReadOnlySequenceFactory.SingleSegmentFactory.CreateWithContent(encoding.GetBytes("foo=bar&baz=boo&t="));
|
||||
var readOnlySequence = ReadOnlySequenceFactory.SegmentPerByteFactory.CreateWithContent(encoding.GetBytes("foo=bar&baz=boo&t="));
|
||||
|
||||
KeyValueAccumulator accumulator = default;
|
||||
|
||||
|
|
@ -210,7 +231,7 @@ namespace Microsoft.AspNetCore.WebUtilities
|
|||
[MemberData(nameof(Encodings))]
|
||||
public void TryParseFormValues_MultiSegmentWithArrayPoolAcrossSegmentsWorks(Encoding encoding)
|
||||
{
|
||||
var readOnlySequence = ReadOnlySequenceFactory.SingleSegmentFactory.CreateWithContent(encoding.GetBytes("foo=bar&baz=bo" + new string('a', 128)));
|
||||
var readOnlySequence = ReadOnlySequenceFactory.SegmentPerByteFactory.CreateWithContent(encoding.GetBytes("foo=bar&baz=bo" + new string('a', 128)));
|
||||
|
||||
KeyValueAccumulator accumulator = default;
|
||||
|
||||
|
|
@ -227,7 +248,7 @@ namespace Microsoft.AspNetCore.WebUtilities
|
|||
[MemberData(nameof(Encodings))]
|
||||
public void TryParseFormValues_MultiSegmentSplitAcrossSegmentsWithPlusesWorks(Encoding encoding)
|
||||
{
|
||||
var readOnlySequence = ReadOnlySequenceFactory.SingleSegmentFactory.CreateWithContent(encoding.GetBytes("+++=+++&++++=++++&+="));
|
||||
var readOnlySequence = ReadOnlySequenceFactory.SegmentPerByteFactory.CreateWithContent(encoding.GetBytes("+++=+++&++++=++++&+="));
|
||||
|
||||
KeyValueAccumulator accumulator = default;
|
||||
|
||||
|
|
@ -261,9 +282,9 @@ namespace Microsoft.AspNetCore.WebUtilities
|
|||
|
||||
[Theory]
|
||||
[MemberData(nameof(Encodings))]
|
||||
public void TryParseFormValues_MultiSegmentSplitAcrossSegmentsThatNeedDecodingWorks(Encoding encoding)
|
||||
public void TryParseFormValues_SplitAcrossSegmentsThatNeedDecodingWorks(Encoding encoding)
|
||||
{
|
||||
var readOnlySequence = ReadOnlySequenceFactory.SingleSegmentFactory.CreateWithContent(encoding.GetBytes("\"%-.<>\\^_`{|}~=\"%-.<>\\^_`{|}~&\"%-.<>\\^_`{|}=wow"));
|
||||
var readOnlySequence = ReadOnlySequenceFactory.SegmentPerByteFactory.CreateWithContent(encoding.GetBytes("\"%-.<>\\^_`{|}~=\"%-.<>\\^_`{|}~&\"%-.<>\\^_`{|}=wow"));
|
||||
|
||||
KeyValueAccumulator accumulator = default;
|
||||
|
||||
|
|
@ -277,7 +298,7 @@ namespace Microsoft.AspNetCore.WebUtilities
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void TryParseFormValues_MultiSegmentExceedKeyLengthThrows()
|
||||
public void TryParseFormValues_ExceedKeyLengthThrows()
|
||||
{
|
||||
var readOnlySequence = ReadOnlySequenceFactory.SingleSegmentFactory.CreateWithContent(Encoding.UTF8.GetBytes("foo=bar&baz=boo&t="));
|
||||
|
||||
|
|
@ -291,7 +312,7 @@ namespace Microsoft.AspNetCore.WebUtilities
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void TryParseFormValues_MultiSegmentExceedKeyLengthThrowsInSplitSegment()
|
||||
public void TryParseFormValues_ExceedKeyLengthThrowsInSplitSegment()
|
||||
{
|
||||
var readOnlySequence = ReadOnlySequenceFactory.CreateSegments(Encoding.UTF8.GetBytes("fo=bar&ba"), Encoding.UTF8.GetBytes("z=boo&t="));
|
||||
|
||||
|
|
@ -305,9 +326,9 @@ namespace Microsoft.AspNetCore.WebUtilities
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void TryParseFormValues_MultiSegmentExceedValueLengthThrows()
|
||||
public void TryParseFormValues_ExceedValueLengthThrows()
|
||||
{
|
||||
var readOnlySequence = ReadOnlySequenceFactory.CreateSegments(Encoding.UTF8.GetBytes("foo=bar&baz=bo"), Encoding.UTF8.GetBytes("o&t="));
|
||||
var readOnlySequence = ReadOnlySequenceFactory.CreateSegments(Encoding.UTF8.GetBytes("foo=bar&baz=boo&t="));
|
||||
|
||||
KeyValueAccumulator accumulator = default;
|
||||
|
||||
|
|
@ -319,7 +340,7 @@ namespace Microsoft.AspNetCore.WebUtilities
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void TryParseFormValues_MultiSegmentExceedValueLengthThrowsInSplitSegment()
|
||||
public void TryParseFormValues_ExceedValueLengthThrowsInSplitSegment()
|
||||
{
|
||||
var readOnlySequence = ReadOnlySequenceFactory.CreateSegments(Encoding.UTF8.GetBytes("foo=ba&baz=bo"), Encoding.UTF8.GetBytes("o&t="));
|
||||
|
||||
|
|
@ -333,7 +354,7 @@ namespace Microsoft.AspNetCore.WebUtilities
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void TryParseFormValues_MultiSegmentExceedKeLengthThrowsInSplitSegmentEnd()
|
||||
public void TryParseFormValues_ExceedKeyLengthThrowsInSplitSegmentEnd()
|
||||
{
|
||||
var readOnlySequence = ReadOnlySequenceFactory.CreateSegments(Encoding.UTF8.GetBytes("foo=ba&baz=bo"), Encoding.UTF8.GetBytes("o&asdfasdfasd="));
|
||||
|
||||
|
|
@ -347,7 +368,7 @@ namespace Microsoft.AspNetCore.WebUtilities
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void TryParseFormValues_MultiSegmentExceedValueLengthThrowsInSplitSegmentEnd()
|
||||
public void TryParseFormValues_ExceedValueLengthThrowsInSplitSegmentEnd()
|
||||
{
|
||||
var readOnlySequence = ReadOnlySequenceFactory.CreateSegments(Encoding.UTF8.GetBytes("foo=ba&baz=bo"), Encoding.UTF8.GetBytes("o&t=asdfasdfasd"));
|
||||
|
||||
|
|
@ -389,12 +410,13 @@ namespace Microsoft.AspNetCore.WebUtilities
|
|||
KeyLengthLimit = 3
|
||||
};
|
||||
|
||||
formReader.ParseFormValues(ref readOnlySequence, ref accumulator, isFinalBlock: false);
|
||||
formReader.ParseFormValues(ref readOnlySequence, ref accumulator, isFinalBlock: true);
|
||||
|
||||
IDictionary<string, StringValues> values = accumulator.GetResults();
|
||||
Assert.Single(values);
|
||||
Assert.Contains("fo", values);
|
||||
Assert.Equal("bar", values["fo"]);
|
||||
Assert.Contains("ba", values);
|
||||
Assert.Equal("", values["ba"]);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
|
@ -408,12 +430,13 @@ namespace Microsoft.AspNetCore.WebUtilities
|
|||
ValueLengthLimit = 3
|
||||
};
|
||||
|
||||
formReader.ParseFormValues(ref readOnlySequence, ref accumulator, isFinalBlock: false);
|
||||
formReader.ParseFormValues(ref readOnlySequence, ref accumulator, isFinalBlock: true);
|
||||
|
||||
IDictionary<string, StringValues> values = accumulator.GetResults();
|
||||
Assert.Single(values);
|
||||
Assert.Contains("fo", values);
|
||||
Assert.Equal("bar", values["fo"]);
|
||||
Assert.Contains("b", values);
|
||||
Assert.Equal("", values["b"]);
|
||||
}
|
||||
|
||||
public static TheoryData<ReadOnlySequence<byte>> IncompleteFormKeys =>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
<Project>
|
||||
<PropertyGroup Condition=" '$(OpenApiGenerateDocuments)' == '' ">
|
||||
<OpenApiGenerateDocuments
|
||||
Condition=" '$(TargetFrameworkIdentifier)' == '.NETCoreApp' AND '$(TargetFrameworkVersion.TrimStart('vV'))' < '2.1' ">false</OpenApiGenerateDocuments>
|
||||
Condition=" '$(TargetFrameworkIdentifier)' == '.NETCoreApp' AND '$(TargetFrameworkVersion.TrimStart("vV"))' < '2.1' ">false</OpenApiGenerateDocuments>
|
||||
<OpenApiGenerateDocuments Condition=" '$(OpenApiGenerateDocuments)' == '' ">true</OpenApiGenerateDocuments>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
|
|
@ -16,7 +16,7 @@
|
|||
</ItemGroup>
|
||||
|
||||
<Target Name="OpenApiGetDocuments" Returns="@(_OpenApiProjectDocuments)">
|
||||
<Error Text="OpenAPI document generation is disabled. Add '<OpenApiGenerateDocuments>true</OpenApiGenerateDocuments>' to the project."
|
||||
<Error Text="OpenAPI document generation is disabled. Add '<OpenApiGenerateDocuments>true</OpenApiGenerateDocuments>' to the project."
|
||||
Condition=" '$(OpenApiGenerateDocuments)' != 'true' " />
|
||||
|
||||
<ReadLinesFromFile File="$(_OpenApiDocumentsCache)">
|
||||
|
|
@ -32,7 +32,7 @@
|
|||
Inputs="$(TargetPath)"
|
||||
Outputs="$(_OpenApiDocumentsCache)">
|
||||
<Error Text="OpenAPI document generation is not supported when targeting netcoreapp2.0 or earlier. Disable the feature or move to a later target framework."
|
||||
Condition=" '$(TargetFrameworkIdentifier)' == '.NETCoreApp' AND '$(TargetFrameworkVersion.TrimStart('vV'))' < '2.1' " />
|
||||
Condition=" '$(TargetFrameworkIdentifier)' == '.NETCoreApp' AND '$(TargetFrameworkVersion.TrimStart("vV"))' < '2.1' " />
|
||||
|
||||
<PropertyGroup>
|
||||
<_Command>dotnet "$(MSBuildThisFileDirectory)/../tools/dotnet-getdocument.dll" --assembly "$(TargetPath)"</_Command>
|
||||
|
|
|
|||
|
|
@ -1,11 +0,0 @@
|
|||
<!-- This file is automatically generated. -->
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>netcoreapp3.0</TargetFrameworks>
|
||||
</PropertyGroup>
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp3.0'">
|
||||
<Compile Include="Microsoft.AspNetCore.Mvc.Components.Prerendering.netcoreapp3.0.cs" />
|
||||
<Reference Include="Microsoft.AspNetCore.Mvc.ViewFeatures" />
|
||||
<Reference Include="Microsoft.AspNetCore.Components.Server" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
// 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.
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.Rendering
|
||||
{
|
||||
public static partial class HtmlHelperComponentPrerenderingExtensions
|
||||
{
|
||||
public static System.Threading.Tasks.Task<Microsoft.AspNetCore.Html.IHtmlContent> RenderComponentAsync<TComponent>(this Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper htmlHelper) where TComponent : Microsoft.AspNetCore.Components.IComponent { throw null; }
|
||||
[System.Diagnostics.DebuggerStepThroughAttribute]
|
||||
public static System.Threading.Tasks.Task<Microsoft.AspNetCore.Html.IHtmlContent> RenderComponentAsync<TComponent>(this Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper htmlHelper, object parameters) where TComponent : Microsoft.AspNetCore.Components.IComponent { throw null; }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.IO;
|
||||
using System.Text.Encodings.Web;
|
||||
using Microsoft.AspNetCore.Components.Server;
|
||||
using Microsoft.AspNetCore.Html;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.ViewFeatures
|
||||
{
|
||||
internal class HtmlContentPrerenderComponentResultAdapter : IHtmlContent
|
||||
{
|
||||
private ComponentPrerenderResult _result;
|
||||
|
||||
public HtmlContentPrerenderComponentResultAdapter(ComponentPrerenderResult result)
|
||||
{
|
||||
_result = result;
|
||||
}
|
||||
|
||||
public void WriteTo(TextWriter writer, HtmlEncoder encoder)
|
||||
{
|
||||
_result.WriteTo(writer);
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue