Merge branch 'release/3.0'
This commit is contained in:
commit
0193983327
|
|
@ -29,7 +29,9 @@ variables:
|
|||
- ${{ if or(eq(variables['System.TeamProject'], 'public'), in(variables['Build.Reason'], 'PullRequest')) }}:
|
||||
- name: _BuildArgs
|
||||
value: ''
|
||||
|
||||
jobs:
|
||||
# Code check
|
||||
- template: jobs/default-build.yml
|
||||
parameters:
|
||||
jobName: Code_check
|
||||
|
|
@ -38,6 +40,10 @@ jobs:
|
|||
steps:
|
||||
- powershell: ./eng/scripts/CodeCheck.ps1 -ci
|
||||
displayName: Run eng/scripts/CodeCheck.ps1
|
||||
artifacts:
|
||||
- name: Code_Check_Logs
|
||||
path: artifacts/log/
|
||||
publishOnError: true
|
||||
|
||||
# Build Windows (x64/x86)
|
||||
- template: jobs/default-build.yml
|
||||
|
|
@ -171,6 +177,7 @@ jobs:
|
|||
-bl:artifacts/log/build.macos.binlog
|
||||
$(_BuildArgs)
|
||||
installNodeJs: false
|
||||
installJdk: false
|
||||
artifacts:
|
||||
- name: MacOS_x64_Packages
|
||||
path: artifacts/packages/
|
||||
|
|
@ -191,7 +198,6 @@ jobs:
|
|||
jobName: Linux_x64_build
|
||||
jobDisplayName: "Build: Linux x64"
|
||||
agentOs: Linux
|
||||
installNodeJs: false
|
||||
steps:
|
||||
- script: ./build.sh
|
||||
--ci
|
||||
|
|
@ -211,6 +217,7 @@ jobs:
|
|||
--arch x64 \
|
||||
--build-installers \
|
||||
--no-build-deps \
|
||||
--no-build-nodejs \
|
||||
-p:OnlyPackPlatformSpecificPackages=true \
|
||||
-p:BuildRuntimeArchive=false \
|
||||
-p:LinuxInstallerType=deb \
|
||||
|
|
@ -224,12 +231,15 @@ jobs:
|
|||
--arch x64 \
|
||||
--build-installers \
|
||||
--no-build-deps \
|
||||
--no-build-nodejs \
|
||||
-p:OnlyPackPlatformSpecificPackages=true \
|
||||
-p:BuildRuntimeArchive=false \
|
||||
-p:LinuxInstallerType=rpm \
|
||||
-bl:artifacts/log/build.rpm.binlog \
|
||||
$(_BuildArgs)
|
||||
displayName: Build RPM installers
|
||||
installNodeJs: false
|
||||
installJdk: false
|
||||
artifacts:
|
||||
- name: Linux_x64_Packages
|
||||
path: artifacts/packages/
|
||||
|
|
@ -260,6 +270,7 @@ jobs:
|
|||
-bl:artifacts/log/build.linux-arm.binlog
|
||||
$(_BuildArgs)
|
||||
installNodeJs: false
|
||||
installJdk: false
|
||||
artifacts:
|
||||
- name: Linux_arm_Packages
|
||||
path: artifacts/packages/
|
||||
|
|
@ -290,6 +301,7 @@ jobs:
|
|||
-bl:artifacts/log/build.arm64.binlog
|
||||
$(_BuildArgs)
|
||||
installNodeJs: false
|
||||
installJdk: false
|
||||
artifacts:
|
||||
- name: Linux_arm64_Packages
|
||||
path: artifacts/packages/
|
||||
|
|
@ -323,6 +335,7 @@ jobs:
|
|||
-bl:artifacts/log/build.musl.binlog
|
||||
$(_BuildArgs)
|
||||
installNodeJs: false
|
||||
installJdk: false
|
||||
artifacts:
|
||||
- name: Linux_musl_x64_Packages
|
||||
path: artifacts/packages/
|
||||
|
|
@ -337,7 +350,7 @@ jobs:
|
|||
parameters:
|
||||
inputName: Linux_musl_x64
|
||||
|
||||
# Build Linux Musl arm64
|
||||
# Build Linux Musl ARM64
|
||||
- template: jobs/default-build.yml
|
||||
parameters:
|
||||
jobName: Linux_musl_arm64_build
|
||||
|
|
@ -356,6 +369,7 @@ jobs:
|
|||
-bl:artifacts/log/build.musl.binlog
|
||||
$(_BuildArgs)
|
||||
installNodeJs: false
|
||||
installJdk: false
|
||||
artifacts:
|
||||
- name: Linux_musl_arm64_Packages
|
||||
path: artifacts/packages/
|
||||
|
|
@ -499,7 +513,7 @@ jobs:
|
|||
version: 3.0.x
|
||||
installationPath: $(DotNetCoreSdkDir)
|
||||
includePreviewVersions: true
|
||||
- script: ./eng/scripts/ci-source-build.sh --ci --configuration Release /p:BuildManaged=true
|
||||
- script: ./eng/scripts/ci-source-build.sh --ci --configuration Release /p:BuildManaged=true /p:BuildNodeJs=false
|
||||
displayName: Run ci-source-build.sh
|
||||
- task: PublishBuildArtifacts@1
|
||||
displayName: Upload logs
|
||||
|
|
|
|||
|
|
@ -1,13 +1,18 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Keep this file in sync with src/ProjectTemplates/test/Infrastructure/NuGet.config.in. -->
|
||||
<configuration>
|
||||
<packageSources>
|
||||
<clear />
|
||||
<add key="dotnet-core" value="https://dotnetfeed.blob.core.windows.net/dotnet-core/index.json" />
|
||||
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
|
||||
<add key="aspnet-blazor" value="https://dotnetfeed.blob.core.windows.net/aspnet-blazor/index.json" />
|
||||
<add key="aspnet-extensions" value="https://dotnetfeed.blob.core.windows.net/aspnet-extensions/index.json" />
|
||||
<add key="aspnet-entityframeworkcore" value="https://dotnetfeed.blob.core.windows.net/aspnet-entityframeworkcore/index.json" />
|
||||
<add key="aspnet-aspnetcore-tooling" value="https://dotnetfeed.blob.core.windows.net/aspnet-aspnetcore-tooling/index.json" />
|
||||
<add key="grpc-nuget-dev" value="https://grpc.jfrog.io/grpc/api/nuget/v3/grpc-nuget-dev" />
|
||||
<add key="roslyn" value="https://dotnet.myget.org/F/roslyn/api/v3/index.json" />
|
||||
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
|
||||
<add key="aspnetcore-dev" value="https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json" />
|
||||
<add key="aspnetcore-tools" value="https://dotnet.myget.org/F/aspnetcore-tools/api/v3/index.json" />
|
||||
<add key="roslyn-tools" value="https://dotnet.myget.org/F/roslyn-tools/api/v3/index.json" />
|
||||
</packageSources>
|
||||
</configuration>
|
||||
|
|
|
|||
21
build.ps1
21
build.ps1
|
|
@ -183,7 +183,7 @@ elseif ($Projects) {
|
|||
}
|
||||
# When adding new sub-group build flags, add them to this check.
|
||||
elseif((-not $BuildNative) -and (-not $BuildManaged) -and (-not $BuildNodeJS) -and (-not $BuildInstallers) -and (-not $BuildJava)) {
|
||||
Write-Warning "No default group of projects was specified, so building the 'managed' subsets of projects. Run ``build.cmd -help`` for more details."
|
||||
Write-Warning "No default group of projects was specified, so building the 'managed' and its dependent subsets of projects. Run ``build.cmd -help`` for more details."
|
||||
|
||||
# This goal of this is to pick a sensible default for `build.cmd` with zero arguments.
|
||||
# Now that we support subfolder invokations of build.cmd, we will be pushing to have build.cmd build everything (-all) by default
|
||||
|
|
@ -191,6 +191,25 @@ elseif((-not $BuildNative) -and (-not $BuildManaged) -and (-not $BuildNodeJS) -a
|
|||
$BuildManaged = $true
|
||||
}
|
||||
|
||||
if ($BuildManaged -or ($All -and (-not $NoBuildManaged))) {
|
||||
if ((-not $BuildNodeJS) -and (-not $NoBuildNodeJS)) {
|
||||
$node = Get-Command node -ErrorAction Ignore -CommandType Application
|
||||
|
||||
if ($node) {
|
||||
$nodeHome = Split-Path -Parent (Split-Path -Parent $node.Path)
|
||||
Write-Host -f Magenta "Building of C# project is enabled and has dependencies on NodeJS projects. Building of NodeJS projects is enabled since node is detected in $nodeHome."
|
||||
}
|
||||
else {
|
||||
Write-Host -f Magenta "Building of NodeJS projects is disabled since node is not detected on Path and no BuildNodeJs or NoBuildNodeJs setting is set explicitly."
|
||||
$NoBuildNodeJS = $true
|
||||
}
|
||||
}
|
||||
|
||||
if ($NoBuildNodeJS){
|
||||
Write-Warning "Some managed projects depend on NodeJS projects. Building NodeJS is disabled so the managed projects will fallback to using the output from previous builds. The output may not be correct or up to date."
|
||||
}
|
||||
}
|
||||
|
||||
if ($BuildInstallers) { $MSBuildArguments += "/p:BuildInstallers=true" }
|
||||
if ($BuildManaged) { $MSBuildArguments += "/p:BuildManaged=true" }
|
||||
if ($BuildNative) { $MSBuildArguments += "/p:BuildNative=true" }
|
||||
|
|
|
|||
17
build.sh
17
build.sh
|
|
@ -213,7 +213,7 @@ elif [ ! -z "$build_projects" ]; then
|
|||
elif [ -z "$build_managed" ] && [ -z "$build_nodejs" ] && [ -z "$build_java" ] && [ -z "$build_native" ] && [ -z "$build_installers" ]; then
|
||||
# This goal of this is to pick a sensible default for `build.sh` with zero arguments.
|
||||
# We believe the most common thing our contributors will work on is C#, so if no other build group was picked, build the C# projects.
|
||||
__warn "No default group of projects was specified, so building the 'managed' subset of projects. Run ``build.sh --help`` for more details."
|
||||
__warn "No default group of projects was specified, so building the 'managed' and its dependent subset of projects. Run ``build.sh --help`` for more details."
|
||||
build_managed=true
|
||||
fi
|
||||
|
||||
|
|
@ -221,6 +221,21 @@ if [ "$build_deps" = false ]; then
|
|||
msbuild_args[${#msbuild_args[*]}]="-p:BuildProjectReferences=false"
|
||||
fi
|
||||
|
||||
if [ "$build_managed" = true ] || (["$build_all" = true ] && [ "$build_managed" != false ]); then
|
||||
if [ -z "$build_nodejs" ]; then
|
||||
if [ -x "$(command -v node)" ]; then
|
||||
__warn "Building of C# project is enabled and has dependencies on NodeJS projects. Building of NodeJS projects is enabled since node is detected on PATH."
|
||||
else
|
||||
__warn "Building of NodeJS projects is disabled since node is not detected on Path and no BuildNodeJs or NoBuildNodeJs setting is set explicitly."
|
||||
build_nodejs=false
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$build_nodejs" = false ]; then
|
||||
__warn "Some managed projects depend on NodeJS projects. Building NodeJS is disabled so the managed projects will fallback to using the output from previous builds. The output may not be correct or up to date."
|
||||
fi
|
||||
fi
|
||||
|
||||
# Only set these MSBuild properties if they were explicitly set by build parameters.
|
||||
[ ! -z "$build_java" ] && msbuild_args[${#msbuild_args[*]}]="-p:BuildJava=$build_java"
|
||||
[ ! -z "$build_native" ] && msbuild_args[${#msbuild_args[*]}]="-p:BuildNative=$build_native"
|
||||
|
|
|
|||
|
|
@ -97,14 +97,14 @@ The cause of this problem is that the solution you are using does not include th
|
|||
```
|
||||
|
||||
### Common error: Unable to locate the .NET Core SDK
|
||||
|
||||
|
||||
Executing `.\restore.cmd` or `.\build.cmd` may produce these errors:
|
||||
|
||||
> error : Unable to locate the .NET Core SDK. Check that it is installed and that the version specified in global.json (if any) matches the installed version.
|
||||
> error MSB4236: The SDK 'Microsoft.NET.Sdk' specified could not be found.
|
||||
|
||||
In most cases, this is because the option _Use previews of the .NET Core SDK_ in VS2019 is not checked. Start Visual Studio, go to _Tools > Options_ and check _Use previews of the .NET Core SDK_ under _Environment > Preview Features_.
|
||||
|
||||
|
||||
## Building with Visual Studio Code
|
||||
|
||||
Using Visual Studio Code with this repo requires setting environment variables on command line first.
|
||||
|
|
@ -138,6 +138,8 @@ On macOS/Linux:
|
|||
./build.sh
|
||||
```
|
||||
|
||||
By default, all of the C# projects are built. Some C# projects requires NodeJS to be installed to compile JavaScript assets which are then checked in as source. If NodeJS is detected on the path, the NodeJS projects will be compiled as part of building C# projects. If NodeJS is not detected on the path, the JavaScript assets checked in previously will be used instead. To disable building NodeJS projects, specify /p:BuildNodeJs=false on the command line.
|
||||
|
||||
### Using `dotnet` on command line in this repo
|
||||
|
||||
Because we are using pre-release versions of .NET Core, you have to set a handful of environment variables
|
||||
|
|
|
|||
|
|
@ -4,14 +4,16 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition=" '$(BuildAllProjects)' == 'true' ">
|
||||
<BuildNative>true</BuildNative>
|
||||
<BuildManaged>true</BuildManaged>
|
||||
<BuildNodeJS>true</BuildNodeJS>
|
||||
<BuildJava>true</BuildJava>
|
||||
<BuildNative Condition="'$(BuildNative)' == ''">true</BuildNative>
|
||||
<BuildManaged Condition="'$(BuildManaged)' == ''">true</BuildManaged>
|
||||
<BuildNodeJS Condition="'$(BuildNodeJS)' == ''">true</BuildNodeJS>
|
||||
<BuildJava Condition="'$(BuildJava)' == ''">true</BuildJava>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- These projects are always excluded, even when -projects is specified on command line. -->
|
||||
<ItemGroup>
|
||||
<!-- Explicitly excluded projects -->
|
||||
<ProjectToExclude Include="$(ProjectToExclude)" />
|
||||
|
||||
<!-- These projects use 'legacy' csproj, which is not supported by dotnet-msbuild. -->
|
||||
<ProjectToExclude Include="
|
||||
|
|
@ -31,6 +33,7 @@
|
|||
$(RepoRoot)src\submodules\**\*.*proj;
|
||||
$(RepoRoot)src\Installers\**\*.*proj;
|
||||
$(RepoRoot)src\SignalR\clients\ts\**\node_modules\**\*.*proj;
|
||||
$(RepoRoot)src\Components\Web.JS\node_modules\**\*.*proj;
|
||||
$(RepoRoot)src\Components\Blazor\Templates\src\content\**\*.*proj;
|
||||
$(RepoRoot)src\ProjectTemplates\Web.ProjectTemplates\content\**\*.csproj;
|
||||
$(RepoRoot)src\ProjectTemplates\Web.ProjectTemplates\content\**\*.fsproj;
|
||||
|
|
@ -43,7 +46,6 @@
|
|||
$(RepoRoot)src\Servers\Kestrel\perf\PlatformBenchmarks\**\*.csproj;
|
||||
$(RepoRoot)src\SignalR\perf\benchmarkapps\**\*.csproj;
|
||||
" />
|
||||
|
||||
</ItemGroup>
|
||||
|
||||
<Choose>
|
||||
|
|
@ -102,6 +104,7 @@
|
|||
<ProjectToExclude Condition=" '$(BuildNative)' != 'true'" Include="@(NativeProjects)" />
|
||||
|
||||
<NodeJsProjects Include="
|
||||
$(RepoRoot)src\Components\Web.JS\Microsoft.AspNetCore.Components.Web.JS.npmproj;
|
||||
$(RepoRoot)src\SignalR\**\*.npmproj;
|
||||
$(RepoRoot)src\Middleware\**\*.npmproj;
|
||||
"
|
||||
|
|
|
|||
|
|
@ -29,269 +29,269 @@
|
|||
<Uri>https://github.com/aspnet/AspNetCore-Tooling</Uri>
|
||||
<Sha>448a88e86d20fd9315901f663318d64c9c6841bf</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="dotnet-ef" Version="3.0.0-preview9.19402.9">
|
||||
<Dependency Name="dotnet-ef" Version="3.0.0-preview9.19405.13">
|
||||
<Uri>https://github.com/aspnet/EntityFrameworkCore</Uri>
|
||||
<Sha>49f9f7632c742108e5652f182922cc35c19c9162</Sha>
|
||||
<Sha>07ed34e80585ca9575ea0265921d42a203193b21</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.EntityFrameworkCore.InMemory" Version="3.0.0-preview9.19402.9">
|
||||
<Dependency Name="Microsoft.EntityFrameworkCore.InMemory" Version="3.0.0-preview9.19405.13">
|
||||
<Uri>https://github.com/aspnet/EntityFrameworkCore</Uri>
|
||||
<Sha>49f9f7632c742108e5652f182922cc35c19c9162</Sha>
|
||||
<Sha>07ed34e80585ca9575ea0265921d42a203193b21</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.EntityFrameworkCore.Relational" Version="3.0.0-preview9.19402.9">
|
||||
<Dependency Name="Microsoft.EntityFrameworkCore.Relational" Version="3.0.0-preview9.19405.13">
|
||||
<Uri>https://github.com/aspnet/EntityFrameworkCore</Uri>
|
||||
<Sha>49f9f7632c742108e5652f182922cc35c19c9162</Sha>
|
||||
<Sha>07ed34e80585ca9575ea0265921d42a203193b21</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.EntityFrameworkCore.Sqlite" Version="3.0.0-preview9.19402.9">
|
||||
<Dependency Name="Microsoft.EntityFrameworkCore.Sqlite" Version="3.0.0-preview9.19405.13">
|
||||
<Uri>https://github.com/aspnet/EntityFrameworkCore</Uri>
|
||||
<Sha>49f9f7632c742108e5652f182922cc35c19c9162</Sha>
|
||||
<Sha>07ed34e80585ca9575ea0265921d42a203193b21</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.EntityFrameworkCore.SqlServer" Version="3.0.0-preview9.19402.9">
|
||||
<Dependency Name="Microsoft.EntityFrameworkCore.SqlServer" Version="3.0.0-preview9.19405.13">
|
||||
<Uri>https://github.com/aspnet/EntityFrameworkCore</Uri>
|
||||
<Sha>49f9f7632c742108e5652f182922cc35c19c9162</Sha>
|
||||
<Sha>07ed34e80585ca9575ea0265921d42a203193b21</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.EntityFrameworkCore.Tools" Version="3.0.0-preview9.19402.9">
|
||||
<Dependency Name="Microsoft.EntityFrameworkCore.Tools" Version="3.0.0-preview9.19405.13">
|
||||
<Uri>https://github.com/aspnet/EntityFrameworkCore</Uri>
|
||||
<Sha>49f9f7632c742108e5652f182922cc35c19c9162</Sha>
|
||||
<Sha>07ed34e80585ca9575ea0265921d42a203193b21</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.EntityFrameworkCore" Version="3.0.0-preview9.19402.9">
|
||||
<Dependency Name="Microsoft.EntityFrameworkCore" Version="3.0.0-preview9.19405.13">
|
||||
<Uri>https://github.com/aspnet/EntityFrameworkCore</Uri>
|
||||
<Sha>49f9f7632c742108e5652f182922cc35c19c9162</Sha>
|
||||
<Sha>07ed34e80585ca9575ea0265921d42a203193b21</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.AspNetCore.Analyzer.Testing" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.AspNetCore.Analyzer.Testing" Version="3.0.0-preview9.19405.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
<Sha>86469ee35cf718e0122f16f52b486303dcfbb1fe</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.AspNetCore.BenchmarkRunner.Sources" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.AspNetCore.BenchmarkRunner.Sources" Version="3.0.0-preview9.19405.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
<Sha>86469ee35cf718e0122f16f52b486303dcfbb1fe</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.ActivatorUtilities.Sources" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.ActivatorUtilities.Sources" Version="3.0.0-preview9.19405.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
<Sha>86469ee35cf718e0122f16f52b486303dcfbb1fe</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Caching.Abstractions" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.Caching.Abstractions" Version="3.0.0-preview9.19405.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
<Sha>86469ee35cf718e0122f16f52b486303dcfbb1fe</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Caching.Memory" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.Caching.Memory" Version="3.0.0-preview9.19405.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
<Sha>86469ee35cf718e0122f16f52b486303dcfbb1fe</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Caching.SqlServer" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.Caching.SqlServer" Version="3.0.0-preview9.19405.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
<Sha>86469ee35cf718e0122f16f52b486303dcfbb1fe</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Caching.StackExchangeRedis" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.Caching.StackExchangeRedis" Version="3.0.0-preview9.19405.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
<Sha>86469ee35cf718e0122f16f52b486303dcfbb1fe</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.CommandLineUtils.Sources" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.CommandLineUtils.Sources" Version="3.0.0-preview9.19405.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
<Sha>86469ee35cf718e0122f16f52b486303dcfbb1fe</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Configuration.Abstractions" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.Configuration.Abstractions" Version="3.0.0-preview9.19405.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
<Sha>86469ee35cf718e0122f16f52b486303dcfbb1fe</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Configuration.AzureKeyVault" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.Configuration.AzureKeyVault" Version="3.0.0-preview9.19405.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
<Sha>86469ee35cf718e0122f16f52b486303dcfbb1fe</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Configuration.Binder" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.Configuration.Binder" Version="3.0.0-preview9.19405.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
<Sha>86469ee35cf718e0122f16f52b486303dcfbb1fe</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Configuration.CommandLine" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.Configuration.CommandLine" Version="3.0.0-preview9.19405.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
<Sha>86469ee35cf718e0122f16f52b486303dcfbb1fe</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="3.0.0-preview9.19405.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
<Sha>86469ee35cf718e0122f16f52b486303dcfbb1fe</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Configuration.FileExtensions" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.Configuration.FileExtensions" Version="3.0.0-preview9.19405.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
<Sha>86469ee35cf718e0122f16f52b486303dcfbb1fe</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Configuration.Ini" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.Configuration.Ini" Version="3.0.0-preview9.19405.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
<Sha>86469ee35cf718e0122f16f52b486303dcfbb1fe</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Configuration.Json" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.Configuration.Json" Version="3.0.0-preview9.19405.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
<Sha>86469ee35cf718e0122f16f52b486303dcfbb1fe</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Configuration.KeyPerFile" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.Configuration.KeyPerFile" Version="3.0.0-preview9.19405.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
<Sha>86469ee35cf718e0122f16f52b486303dcfbb1fe</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Configuration.UserSecrets" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.Configuration.UserSecrets" Version="3.0.0-preview9.19405.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
<Sha>86469ee35cf718e0122f16f52b486303dcfbb1fe</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Configuration.Xml" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.Configuration.Xml" Version="3.0.0-preview9.19405.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
<Sha>86469ee35cf718e0122f16f52b486303dcfbb1fe</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Configuration" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.Configuration" Version="3.0.0-preview9.19405.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
<Sha>86469ee35cf718e0122f16f52b486303dcfbb1fe</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.DependencyInjection.Abstractions" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.DependencyInjection.Abstractions" Version="3.0.0-preview9.19405.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
<Sha>86469ee35cf718e0122f16f52b486303dcfbb1fe</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.DependencyInjection" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.DependencyInjection" Version="3.0.0-preview9.19405.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
<Sha>86469ee35cf718e0122f16f52b486303dcfbb1fe</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.DiagnosticAdapter" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.DiagnosticAdapter" Version="3.0.0-preview9.19405.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
<Sha>86469ee35cf718e0122f16f52b486303dcfbb1fe</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions" Version="3.0.0-preview9.19405.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
<Sha>86469ee35cf718e0122f16f52b486303dcfbb1fe</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Diagnostics.HealthChecks" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.Diagnostics.HealthChecks" Version="3.0.0-preview9.19405.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
<Sha>86469ee35cf718e0122f16f52b486303dcfbb1fe</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.FileProviders.Abstractions" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.FileProviders.Abstractions" Version="3.0.0-preview9.19405.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
<Sha>86469ee35cf718e0122f16f52b486303dcfbb1fe</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.FileProviders.Composite" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.FileProviders.Composite" Version="3.0.0-preview9.19405.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
<Sha>86469ee35cf718e0122f16f52b486303dcfbb1fe</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.FileProviders.Embedded" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.FileProviders.Embedded" Version="3.0.0-preview9.19405.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
<Sha>86469ee35cf718e0122f16f52b486303dcfbb1fe</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.FileProviders.Physical" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.FileProviders.Physical" Version="3.0.0-preview9.19405.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
<Sha>86469ee35cf718e0122f16f52b486303dcfbb1fe</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.FileSystemGlobbing" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.FileSystemGlobbing" Version="3.0.0-preview9.19405.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
<Sha>86469ee35cf718e0122f16f52b486303dcfbb1fe</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.HashCodeCombiner.Sources" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.HashCodeCombiner.Sources" Version="3.0.0-preview9.19405.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
<Sha>86469ee35cf718e0122f16f52b486303dcfbb1fe</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Hosting.Abstractions" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.Hosting.Abstractions" Version="3.0.0-preview9.19405.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
<Sha>86469ee35cf718e0122f16f52b486303dcfbb1fe</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Hosting" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.Hosting" Version="3.0.0-preview9.19405.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
<Sha>86469ee35cf718e0122f16f52b486303dcfbb1fe</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.HostFactoryResolver.Sources" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.HostFactoryResolver.Sources" Version="3.0.0-preview9.19405.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
<Sha>86469ee35cf718e0122f16f52b486303dcfbb1fe</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Http" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.Http" Version="3.0.0-preview9.19405.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
<Sha>86469ee35cf718e0122f16f52b486303dcfbb1fe</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Localization.Abstractions" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.Localization.Abstractions" Version="3.0.0-preview9.19405.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
<Sha>86469ee35cf718e0122f16f52b486303dcfbb1fe</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Localization" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.Localization" Version="3.0.0-preview9.19405.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
<Sha>86469ee35cf718e0122f16f52b486303dcfbb1fe</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Logging.Abstractions" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.Logging.Abstractions" Version="3.0.0-preview9.19405.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
<Sha>86469ee35cf718e0122f16f52b486303dcfbb1fe</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Logging.AzureAppServices" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.Logging.AzureAppServices" Version="3.0.0-preview9.19405.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
<Sha>86469ee35cf718e0122f16f52b486303dcfbb1fe</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Logging.Configuration" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.Logging.Configuration" Version="3.0.0-preview9.19405.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
<Sha>86469ee35cf718e0122f16f52b486303dcfbb1fe</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Logging.Console" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.Logging.Console" Version="3.0.0-preview9.19405.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
<Sha>86469ee35cf718e0122f16f52b486303dcfbb1fe</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Logging.Debug" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.Logging.Debug" Version="3.0.0-preview9.19405.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
<Sha>86469ee35cf718e0122f16f52b486303dcfbb1fe</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Logging.EventSource" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.Logging.EventSource" Version="3.0.0-preview9.19405.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
<Sha>86469ee35cf718e0122f16f52b486303dcfbb1fe</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Logging.EventLog" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.Logging.EventLog" Version="3.0.0-preview9.19405.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
<Sha>86469ee35cf718e0122f16f52b486303dcfbb1fe</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Logging.TraceSource" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.Logging.TraceSource" Version="3.0.0-preview9.19405.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
<Sha>86469ee35cf718e0122f16f52b486303dcfbb1fe</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Logging.Testing" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.Logging.Testing" Version="3.0.0-preview9.19405.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
<Sha>86469ee35cf718e0122f16f52b486303dcfbb1fe</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Logging" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.Logging" Version="3.0.0-preview9.19405.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
<Sha>86469ee35cf718e0122f16f52b486303dcfbb1fe</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.ObjectPool" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.ObjectPool" Version="3.0.0-preview9.19405.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
<Sha>86469ee35cf718e0122f16f52b486303dcfbb1fe</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Options.ConfigurationExtensions" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.Options.ConfigurationExtensions" Version="3.0.0-preview9.19405.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
<Sha>86469ee35cf718e0122f16f52b486303dcfbb1fe</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Options.DataAnnotations" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.Options.DataAnnotations" Version="3.0.0-preview9.19405.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
<Sha>86469ee35cf718e0122f16f52b486303dcfbb1fe</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Options" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.Options" Version="3.0.0-preview9.19405.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
<Sha>86469ee35cf718e0122f16f52b486303dcfbb1fe</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.ParameterDefaultValue.Sources" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.ParameterDefaultValue.Sources" Version="3.0.0-preview9.19405.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
<Sha>86469ee35cf718e0122f16f52b486303dcfbb1fe</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Primitives" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.Primitives" Version="3.0.0-preview9.19405.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
<Sha>86469ee35cf718e0122f16f52b486303dcfbb1fe</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.TypeNameHelper.Sources" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.TypeNameHelper.Sources" Version="3.0.0-preview9.19405.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
<Sha>86469ee35cf718e0122f16f52b486303dcfbb1fe</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.ValueStopwatch.Sources" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.ValueStopwatch.Sources" Version="3.0.0-preview9.19405.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
<Sha>86469ee35cf718e0122f16f52b486303dcfbb1fe</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.WebEncoders" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Extensions.WebEncoders" Version="3.0.0-preview9.19405.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
<Sha>86469ee35cf718e0122f16f52b486303dcfbb1fe</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Internal.Extensions.Refs" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.Internal.Extensions.Refs" Version="3.0.0-preview9.19405.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
<Sha>86469ee35cf718e0122f16f52b486303dcfbb1fe</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.JSInterop" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.JSInterop" Version="3.0.0-preview9.19405.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
<Sha>86469ee35cf718e0122f16f52b486303dcfbb1fe</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Mono.WebAssembly.Interop" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Mono.WebAssembly.Interop" Version="3.0.0-preview9.19405.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
<Sha>86469ee35cf718e0122f16f52b486303dcfbb1fe</Sha>
|
||||
</Dependency>
|
||||
<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>
|
||||
|
|
@ -412,25 +412,25 @@
|
|||
<Uri>https://github.com/dotnet/corefx</Uri>
|
||||
<Sha>80f411d58df8338ccd9430900b541a037a9cb383</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Internal.AspNetCore.Analyzers" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Internal.AspNetCore.Analyzers" Version="3.0.0-preview9.19405.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
<Sha>86469ee35cf718e0122f16f52b486303dcfbb1fe</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.DotNet.GenAPI" Version="1.0.0-beta.19369.2">
|
||||
<Dependency Name="Microsoft.DotNet.GenAPI" Version="1.0.0-beta.19404.1">
|
||||
<Uri>https://github.com/dotnet/arcade</Uri>
|
||||
<Sha>a190d4865fe3c86a168ec49c4fc61c90c96ae051</Sha>
|
||||
<Sha>b1c2f33f0cef32d1df6e7f388017fd6761d3fcad</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.DotNet.Arcade.Sdk" Version="1.0.0-beta.19369.2">
|
||||
<Dependency Name="Microsoft.DotNet.Arcade.Sdk" Version="1.0.0-beta.19404.1">
|
||||
<Uri>https://github.com/dotnet/arcade</Uri>
|
||||
<Sha>a190d4865fe3c86a168ec49c4fc61c90c96ae051</Sha>
|
||||
<Sha>b1c2f33f0cef32d1df6e7f388017fd6761d3fcad</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.DotNet.Helix.Sdk" Version="2.0.0-beta.19369.2">
|
||||
<Dependency Name="Microsoft.DotNet.Helix.Sdk" Version="2.0.0-beta.19404.1">
|
||||
<Uri>https://github.com/dotnet/arcade</Uri>
|
||||
<Sha>a190d4865fe3c86a168ec49c4fc61c90c96ae051</Sha>
|
||||
<Sha>b1c2f33f0cef32d1df6e7f388017fd6761d3fcad</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.AspNetCore.Testing" Version="3.0.0-preview9.19401.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Dependency Name="Microsoft.AspNetCore.Testing" Version="3.0.0-preview9.19405.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
|
||||
<Uri>https://github.com/aspnet/Extensions</Uri>
|
||||
<Sha>54d000fda95c2c1f05b13a2e910fc91994da8eb8</Sha>
|
||||
<Sha>86469ee35cf718e0122f16f52b486303dcfbb1fe</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Net.Compilers.Toolset" Version="3.3.0-beta3-19401-01" CoherentParentDependency="Microsoft.Extensions.Logging">
|
||||
<Uri>https://github.com/dotnet/roslyn</Uri>
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@
|
|||
-->
|
||||
<PropertyGroup Label="Automated">
|
||||
<!-- Packages from dotnet/arcade -->
|
||||
<MicrosoftDotNetGenAPIPackageVersion>1.0.0-beta.19369.2</MicrosoftDotNetGenAPIPackageVersion>
|
||||
<MicrosoftDotNetGenAPIPackageVersion>1.0.0-beta.19404.1</MicrosoftDotNetGenAPIPackageVersion>
|
||||
<!-- Packages from dotnet/roslyn -->
|
||||
<MicrosoftNetCompilersToolsetPackageVersion>3.3.0-beta3-19401-01</MicrosoftNetCompilersToolsetPackageVersion>
|
||||
<!-- Packages from dotnet/core-setup -->
|
||||
|
|
@ -92,80 +92,87 @@
|
|||
<!-- Packages from aspnet/Blazor -->
|
||||
<MicrosoftAspNetCoreBlazorMonoPackageVersion>5.0.0-alpha1.19405.2</MicrosoftAspNetCoreBlazorMonoPackageVersion>
|
||||
<!-- Packages from aspnet/Extensions -->
|
||||
<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>
|
||||
<InternalAspNetCoreAnalyzersPackageVersion>3.0.0-preview9.19405.2</InternalAspNetCoreAnalyzersPackageVersion>
|
||||
<MicrosoftAspNetCoreAnalyzerTestingPackageVersion>3.0.0-preview9.19405.2</MicrosoftAspNetCoreAnalyzerTestingPackageVersion>
|
||||
<MicrosoftAspNetCoreBenchmarkRunnerSourcesPackageVersion>3.0.0-preview9.19405.2</MicrosoftAspNetCoreBenchmarkRunnerSourcesPackageVersion>
|
||||
<MicrosoftAspNetCoreTestingPackageVersion>3.0.0-preview9.19405.2</MicrosoftAspNetCoreTestingPackageVersion>
|
||||
<MicrosoftExtensionsActivatorUtilitiesSourcesPackageVersion>3.0.0-preview9.19405.2</MicrosoftExtensionsActivatorUtilitiesSourcesPackageVersion>
|
||||
<MicrosoftExtensionsCachingAbstractionsPackageVersion>3.0.0-preview9.19405.2</MicrosoftExtensionsCachingAbstractionsPackageVersion>
|
||||
<MicrosoftExtensionsCachingMemoryPackageVersion>3.0.0-preview9.19405.2</MicrosoftExtensionsCachingMemoryPackageVersion>
|
||||
<MicrosoftExtensionsCachingSqlServerPackageVersion>3.0.0-preview9.19405.2</MicrosoftExtensionsCachingSqlServerPackageVersion>
|
||||
<MicrosoftExtensionsCachingStackExchangeRedisPackageVersion>3.0.0-preview9.19405.2</MicrosoftExtensionsCachingStackExchangeRedisPackageVersion>
|
||||
<MicrosoftExtensionsCommandLineUtilsSourcesPackageVersion>3.0.0-preview9.19405.2</MicrosoftExtensionsCommandLineUtilsSourcesPackageVersion>
|
||||
<MicrosoftExtensionsConfigurationAbstractionsPackageVersion>3.0.0-preview9.19405.2</MicrosoftExtensionsConfigurationAbstractionsPackageVersion>
|
||||
<MicrosoftExtensionsConfigurationAzureKeyVaultPackageVersion>3.0.0-preview9.19405.2</MicrosoftExtensionsConfigurationAzureKeyVaultPackageVersion>
|
||||
<MicrosoftExtensionsConfigurationBinderPackageVersion>3.0.0-preview9.19405.2</MicrosoftExtensionsConfigurationBinderPackageVersion>
|
||||
<MicrosoftExtensionsConfigurationCommandLinePackageVersion>3.0.0-preview9.19405.2</MicrosoftExtensionsConfigurationCommandLinePackageVersion>
|
||||
<MicrosoftExtensionsConfigurationEnvironmentVariablesPackageVersion>3.0.0-preview9.19405.2</MicrosoftExtensionsConfigurationEnvironmentVariablesPackageVersion>
|
||||
<MicrosoftExtensionsConfigurationFileExtensionsPackageVersion>3.0.0-preview9.19405.2</MicrosoftExtensionsConfigurationFileExtensionsPackageVersion>
|
||||
<MicrosoftExtensionsConfigurationIniPackageVersion>3.0.0-preview9.19405.2</MicrosoftExtensionsConfigurationIniPackageVersion>
|
||||
<MicrosoftExtensionsConfigurationJsonPackageVersion>3.0.0-preview9.19405.2</MicrosoftExtensionsConfigurationJsonPackageVersion>
|
||||
<MicrosoftExtensionsConfigurationKeyPerFilePackageVersion>3.0.0-preview9.19405.2</MicrosoftExtensionsConfigurationKeyPerFilePackageVersion>
|
||||
<MicrosoftExtensionsConfigurationPackageVersion>3.0.0-preview9.19405.2</MicrosoftExtensionsConfigurationPackageVersion>
|
||||
<MicrosoftExtensionsConfigurationUserSecretsPackageVersion>3.0.0-preview9.19405.2</MicrosoftExtensionsConfigurationUserSecretsPackageVersion>
|
||||
<MicrosoftExtensionsConfigurationXmlPackageVersion>3.0.0-preview9.19405.2</MicrosoftExtensionsConfigurationXmlPackageVersion>
|
||||
<MicrosoftExtensionsDependencyInjectionAbstractionsPackageVersion>3.0.0-preview9.19405.2</MicrosoftExtensionsDependencyInjectionAbstractionsPackageVersion>
|
||||
<MicrosoftExtensionsDependencyInjectionPackageVersion>3.0.0-preview9.19405.2</MicrosoftExtensionsDependencyInjectionPackageVersion>
|
||||
<MicrosoftExtensionsDiagnosticAdapterPackageVersion>3.0.0-preview9.19405.2</MicrosoftExtensionsDiagnosticAdapterPackageVersion>
|
||||
<MicrosoftExtensionsDiagnosticsHealthChecksAbstractionsPackageVersion>3.0.0-preview9.19405.2</MicrosoftExtensionsDiagnosticsHealthChecksAbstractionsPackageVersion>
|
||||
<MicrosoftExtensionsDiagnosticsHealthChecksPackageVersion>3.0.0-preview9.19405.2</MicrosoftExtensionsDiagnosticsHealthChecksPackageVersion>
|
||||
<MicrosoftExtensionsFileProvidersAbstractionsPackageVersion>3.0.0-preview9.19405.2</MicrosoftExtensionsFileProvidersAbstractionsPackageVersion>
|
||||
<MicrosoftExtensionsFileProvidersCompositePackageVersion>3.0.0-preview9.19405.2</MicrosoftExtensionsFileProvidersCompositePackageVersion>
|
||||
<MicrosoftExtensionsFileProvidersEmbeddedPackageVersion>3.0.0-preview9.19405.2</MicrosoftExtensionsFileProvidersEmbeddedPackageVersion>
|
||||
<MicrosoftExtensionsFileProvidersPhysicalPackageVersion>3.0.0-preview9.19405.2</MicrosoftExtensionsFileProvidersPhysicalPackageVersion>
|
||||
<MicrosoftExtensionsFileSystemGlobbingPackageVersion>3.0.0-preview9.19405.2</MicrosoftExtensionsFileSystemGlobbingPackageVersion>
|
||||
<MicrosoftExtensionsHashCodeCombinerSourcesPackageVersion>3.0.0-preview9.19405.2</MicrosoftExtensionsHashCodeCombinerSourcesPackageVersion>
|
||||
<MicrosoftExtensionsHostingAbstractionsPackageVersion>3.0.0-preview9.19405.2</MicrosoftExtensionsHostingAbstractionsPackageVersion>
|
||||
<MicrosoftExtensionsHostingPackageVersion>3.0.0-preview9.19405.2</MicrosoftExtensionsHostingPackageVersion>
|
||||
<MicrosoftExtensionsHostFactoryResolverSourcesPackageVersion>3.0.0-preview9.19405.2</MicrosoftExtensionsHostFactoryResolverSourcesPackageVersion>
|
||||
<MicrosoftExtensionsHttpPackageVersion>3.0.0-preview9.19405.2</MicrosoftExtensionsHttpPackageVersion>
|
||||
<MicrosoftExtensionsLocalizationAbstractionsPackageVersion>3.0.0-preview9.19405.2</MicrosoftExtensionsLocalizationAbstractionsPackageVersion>
|
||||
<MicrosoftExtensionsLocalizationPackageVersion>3.0.0-preview9.19405.2</MicrosoftExtensionsLocalizationPackageVersion>
|
||||
<MicrosoftExtensionsLoggingAbstractionsPackageVersion>3.0.0-preview9.19405.2</MicrosoftExtensionsLoggingAbstractionsPackageVersion>
|
||||
<MicrosoftExtensionsLoggingAzureAppServicesPackageVersion>3.0.0-preview9.19405.2</MicrosoftExtensionsLoggingAzureAppServicesPackageVersion>
|
||||
<MicrosoftExtensionsLoggingConfigurationPackageVersion>3.0.0-preview9.19405.2</MicrosoftExtensionsLoggingConfigurationPackageVersion>
|
||||
<MicrosoftExtensionsLoggingConsolePackageVersion>3.0.0-preview9.19405.2</MicrosoftExtensionsLoggingConsolePackageVersion>
|
||||
<MicrosoftExtensionsLoggingDebugPackageVersion>3.0.0-preview9.19405.2</MicrosoftExtensionsLoggingDebugPackageVersion>
|
||||
<MicrosoftExtensionsLoggingEventSourcePackageVersion>3.0.0-preview9.19405.2</MicrosoftExtensionsLoggingEventSourcePackageVersion>
|
||||
<MicrosoftExtensionsLoggingEventLogPackageVersion>3.0.0-preview9.19405.2</MicrosoftExtensionsLoggingEventLogPackageVersion>
|
||||
<MicrosoftExtensionsLoggingPackageVersion>3.0.0-preview9.19405.2</MicrosoftExtensionsLoggingPackageVersion>
|
||||
<MicrosoftExtensionsLoggingTestingPackageVersion>3.0.0-preview9.19405.2</MicrosoftExtensionsLoggingTestingPackageVersion>
|
||||
<MicrosoftExtensionsLoggingTraceSourcePackageVersion>3.0.0-preview9.19405.2</MicrosoftExtensionsLoggingTraceSourcePackageVersion>
|
||||
<MicrosoftExtensionsObjectPoolPackageVersion>3.0.0-preview9.19405.2</MicrosoftExtensionsObjectPoolPackageVersion>
|
||||
<MicrosoftExtensionsOptionsConfigurationExtensionsPackageVersion>3.0.0-preview9.19405.2</MicrosoftExtensionsOptionsConfigurationExtensionsPackageVersion>
|
||||
<MicrosoftExtensionsOptionsDataAnnotationsPackageVersion>3.0.0-preview9.19405.2</MicrosoftExtensionsOptionsDataAnnotationsPackageVersion>
|
||||
<MicrosoftExtensionsOptionsPackageVersion>3.0.0-preview9.19405.2</MicrosoftExtensionsOptionsPackageVersion>
|
||||
<MicrosoftExtensionsParameterDefaultValueSourcesPackageVersion>3.0.0-preview9.19405.2</MicrosoftExtensionsParameterDefaultValueSourcesPackageVersion>
|
||||
<MicrosoftExtensionsPrimitivesPackageVersion>3.0.0-preview9.19405.2</MicrosoftExtensionsPrimitivesPackageVersion>
|
||||
<MicrosoftExtensionsTypeNameHelperSourcesPackageVersion>3.0.0-preview9.19405.2</MicrosoftExtensionsTypeNameHelperSourcesPackageVersion>
|
||||
<MicrosoftExtensionsValueStopwatchSourcesPackageVersion>3.0.0-preview9.19405.2</MicrosoftExtensionsValueStopwatchSourcesPackageVersion>
|
||||
<MicrosoftExtensionsWebEncodersPackageVersion>3.0.0-preview9.19405.2</MicrosoftExtensionsWebEncodersPackageVersion>
|
||||
<MicrosoftInternalExtensionsRefsPackageVersion>3.0.0-preview9.19405.2</MicrosoftInternalExtensionsRefsPackageVersion>
|
||||
<MicrosoftJSInteropPackageVersion>3.0.0-preview9.19405.2</MicrosoftJSInteropPackageVersion>
|
||||
<MonoWebAssemblyInteropPackageVersion>3.0.0-preview9.19405.2</MonoWebAssemblyInteropPackageVersion>
|
||||
<!-- Packages from aspnet/EntityFrameworkCore -->
|
||||
<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>
|
||||
<dotnetefPackageVersion>3.0.0-preview9.19405.13</dotnetefPackageVersion>
|
||||
<MicrosoftEntityFrameworkCoreInMemoryPackageVersion>3.0.0-preview9.19405.13</MicrosoftEntityFrameworkCoreInMemoryPackageVersion>
|
||||
<MicrosoftEntityFrameworkCoreRelationalPackageVersion>3.0.0-preview9.19405.13</MicrosoftEntityFrameworkCoreRelationalPackageVersion>
|
||||
<MicrosoftEntityFrameworkCoreSqlitePackageVersion>3.0.0-preview9.19405.13</MicrosoftEntityFrameworkCoreSqlitePackageVersion>
|
||||
<MicrosoftEntityFrameworkCoreSqlServerPackageVersion>3.0.0-preview9.19405.13</MicrosoftEntityFrameworkCoreSqlServerPackageVersion>
|
||||
<MicrosoftEntityFrameworkCoreToolsPackageVersion>3.0.0-preview9.19405.13</MicrosoftEntityFrameworkCoreToolsPackageVersion>
|
||||
<MicrosoftEntityFrameworkCorePackageVersion>3.0.0-preview9.19405.13</MicrosoftEntityFrameworkCorePackageVersion>
|
||||
<!-- Packages from aspnet/AspNetCore-Tooling -->
|
||||
<<<<<<< HEAD
|
||||
<MicrosoftAspNetCoreMvcRazorExtensionsPackageVersion>5.0.0-alpha1.19407.1</MicrosoftAspNetCoreMvcRazorExtensionsPackageVersion>
|
||||
<MicrosoftAspNetCoreRazorLanguagePackageVersion>5.0.0-alpha1.19407.1</MicrosoftAspNetCoreRazorLanguagePackageVersion>
|
||||
<MicrosoftCodeAnalysisRazorPackageVersion>5.0.0-alpha1.19407.1</MicrosoftCodeAnalysisRazorPackageVersion>
|
||||
<MicrosoftNETSdkRazorPackageVersion>5.0.0-alpha1.19407.1</MicrosoftNETSdkRazorPackageVersion>
|
||||
=======
|
||||
<MicrosoftAspNetCoreMvcRazorExtensionsPackageVersion>3.0.0-preview9.19405.6</MicrosoftAspNetCoreMvcRazorExtensionsPackageVersion>
|
||||
<MicrosoftAspNetCoreRazorLanguagePackageVersion>3.0.0-preview9.19405.6</MicrosoftAspNetCoreRazorLanguagePackageVersion>
|
||||
<MicrosoftCodeAnalysisRazorPackageVersion>3.0.0-preview9.19405.6</MicrosoftCodeAnalysisRazorPackageVersion>
|
||||
<MicrosoftNETSdkRazorPackageVersion>3.0.0-preview9.19405.6</MicrosoftNETSdkRazorPackageVersion>
|
||||
>>>>>>> release/3.0
|
||||
</PropertyGroup>
|
||||
<!--
|
||||
|
||||
|
|
@ -255,25 +262,7 @@
|
|||
</PropertyGroup>
|
||||
<!-- Restore feeds -->
|
||||
<PropertyGroup Label="Restore feeds">
|
||||
<RestoreSources Condition=" '$(DotNetBuildOffline)' != 'true' ">
|
||||
$(RestoreSources);
|
||||
https://dotnetfeed.blob.core.windows.net/dotnet-core/index.json;
|
||||
https://dotnetfeed.blob.core.windows.net/aspnet-blazor/index.json;
|
||||
https://dotnetfeed.blob.core.windows.net/aspnet-extensions/index.json;
|
||||
https://dotnetfeed.blob.core.windows.net/aspnet-entityframeworkcore/index.json;
|
||||
https://dotnetfeed.blob.core.windows.net/aspnet-aspnetcore-tooling/index.json;
|
||||
https://grpc.jfrog.io/grpc/api/nuget/v3/grpc-nuget-dev;
|
||||
</RestoreSources>
|
||||
<RestoreSources Condition="'$(DotNetBuildOffline)' != 'true' AND $(MicrosoftNetCompilersToolsetPackageVersion.Contains('-')) ">
|
||||
$(RestoreSources);
|
||||
https://dotnet.myget.org/F/roslyn/api/v3/index.json;
|
||||
</RestoreSources>
|
||||
<!-- TODO remove this once we move Microsoft.Internal.AspNetCore.H2Spec.All to a non-myget feed -->
|
||||
<RestoreSources>
|
||||
$(RestoreSources);
|
||||
https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json;
|
||||
</RestoreSources>
|
||||
<!-- In an orchestrated build, this may be overriden to other Azure feeds. -->
|
||||
<!-- In an orchestrated build, this may be overridden to other Azure feeds. -->
|
||||
<DotNetAssetRootUrl Condition="'$(DotNetAssetRootUrl)'==''">https://dotnetcli.blob.core.windows.net/dotnet/</DotNetAssetRootUrl>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -8,25 +8,6 @@
|
|||
<DebugType>portable</DebugType>
|
||||
</PropertyGroup>
|
||||
|
||||
<!--
|
||||
Workaround for error when running build.cmd from subfolders. It appears RepoRoot is not set correctly.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\CommonExtensions\Microsoft\NuGet\NuGet.targets(523,5): error : File 'C:\src\aspnet\AspNetCore\src\..NuGet.config' does not exist.
|
||||
-->
|
||||
<PropertyGroup>
|
||||
<RestoreConfigFile>$(RepoRoot)NuGet.config</RestoreConfigFile>
|
||||
</PropertyGroup>
|
||||
|
||||
<!--
|
||||
Required to restore the RoslynTools.ModifyVsixManifest package.
|
||||
This isn't auto-detected by Arcade like other feeds are.
|
||||
-->
|
||||
<PropertyGroup>
|
||||
<RestoreSources>
|
||||
$(RestoreSources);
|
||||
https://dotnet.myget.org/F/roslyn-tools/api/v3/index.json;
|
||||
</RestoreSources>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- Prevent pdb2pdb.exe from running because it is currently causing build failures in Blazor. -->
|
||||
<PropertyGroup>
|
||||
<PublishWindowsPdb>false</PublishWindowsPdb>
|
||||
|
|
|
|||
|
|
@ -29,12 +29,6 @@
|
|||
<ItemGroup>
|
||||
<PackageReference Include="Internal.AspNetCore.BuildTasks" PrivateAssets="All" Version="$(InternalAspNetCoreBuildTasksPackageVersion)" IsImplicitlyDefined="true" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
<RestoreSources>
|
||||
$(RestoreSources);
|
||||
https://dotnet.myget.org/F/aspnetcore-tools/api/v3/index.json;
|
||||
</RestoreSources>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- Workaround for netstandard2.1 projects until we can get a preview 8 SDK containing https://github.com/dotnet/sdk/pull/3463 fix. -->
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -98,12 +98,18 @@ try {
|
|||
}
|
||||
|
||||
Write-Verbose "Installing $ToolName version $ToolVersion"
|
||||
Write-Verbose "Executing '$InstallerPath $LocalInstallerArguments'"
|
||||
Write-Verbose "Executing '$InstallerPath $($LocalInstallerArguments.Keys.ForEach({"-$_ '$($LocalInstallerArguments.$_)'"}) -join ' ')'"
|
||||
& $InstallerPath @LocalInstallerArguments
|
||||
if ($LASTEXITCODE -Ne "0") {
|
||||
$errMsg = "$ToolName installation failed"
|
||||
if ((Get-Variable 'DoNotAbortNativeToolsInstallationOnFailure' -ErrorAction 'SilentlyContinue') -and $DoNotAbortNativeToolsInstallationOnFailure) {
|
||||
Write-Warning $errMsg
|
||||
$showNativeToolsWarning = $true
|
||||
if ((Get-Variable 'DoNotDisplayNativeToolsInstallationWarnings' -ErrorAction 'SilentlyContinue') -and $DoNotDisplayNativeToolsInstallationWarnings) {
|
||||
$showNativeToolsWarning = $false
|
||||
}
|
||||
if ($showNativeToolsWarning) {
|
||||
Write-Warning $errMsg
|
||||
}
|
||||
$toolInstallationFailure = $true
|
||||
} else {
|
||||
Write-Error $errMsg
|
||||
|
|
|
|||
|
|
@ -70,8 +70,7 @@ function ReadGlobalJsonNativeTools {
|
|||
# Only extract the contents of the object.
|
||||
local native_tools_list=$(echo $native_tools_section | awk -F"[{}]" '{print $2}')
|
||||
native_tools_list=${native_tools_list//[\" ]/}
|
||||
native_tools_list=${native_tools_list//,/$'\n'}
|
||||
native_tools_list="$(echo -e "${native_tools_list}" | tr -d '[[:space:]]')"
|
||||
native_tools_list=$( echo "$native_tools_list" | sed 's/\s//g' | sed 's/,/\n/g' )
|
||||
|
||||
local old_IFS=$IFS
|
||||
while read -r line; do
|
||||
|
|
@ -108,6 +107,7 @@ else
|
|||
installer_command+=" --baseuri $base_uri"
|
||||
installer_command+=" --installpath $install_bin"
|
||||
installer_command+=" --version $tool_version"
|
||||
echo $installer_command
|
||||
|
||||
if [[ $force = true ]]; then
|
||||
installer_command+=" --force"
|
||||
|
|
|
|||
|
|
@ -59,9 +59,38 @@ function DownloadAndExtract {
|
|||
-Verbose:$Verbose
|
||||
|
||||
if ($UnzipStatus -Eq $False) {
|
||||
Write-Error "Unzip failed"
|
||||
return $False
|
||||
# Retry Download one more time with Force=true
|
||||
$DownloadRetryStatus = CommonLibrary\Get-File -Uri $Uri `
|
||||
-Path $TempToolPath `
|
||||
-DownloadRetries 1 `
|
||||
-RetryWaitTimeInSeconds $RetryWaitTimeInSeconds `
|
||||
-Force:$True `
|
||||
-Verbose:$Verbose
|
||||
|
||||
if ($DownloadRetryStatus -Eq $False) {
|
||||
Write-Error "Last attempt of download failed as well"
|
||||
return $False
|
||||
}
|
||||
|
||||
# Retry unzip again one more time with Force=true
|
||||
$UnzipRetryStatus = CommonLibrary\Expand-Zip -ZipPath $TempToolPath `
|
||||
-OutputDirectory $InstallDirectory `
|
||||
-Force:$True `
|
||||
-Verbose:$Verbose
|
||||
if ($UnzipRetryStatus -Eq $False)
|
||||
{
|
||||
Write-Error "Last attempt of unzip failed as well"
|
||||
# Clean up partial zips and extracts
|
||||
if (Test-Path $TempToolPath) {
|
||||
Remove-Item $TempToolPath -Force
|
||||
}
|
||||
if (Test-Path $InstallDirectory) {
|
||||
Remove-Item $InstallDirectory -Force -Recurse
|
||||
}
|
||||
return $False
|
||||
}
|
||||
}
|
||||
|
||||
return $True
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,117 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
source="${BASH_SOURCE[0]}"
|
||||
scriptroot="$( cd -P "$( dirname "$source" )" && pwd )"
|
||||
|
||||
. $scriptroot/common-library.sh
|
||||
|
||||
base_uri=
|
||||
install_path=
|
||||
version=
|
||||
clean=false
|
||||
force=false
|
||||
download_retries=5
|
||||
retry_wait_time_seconds=30
|
||||
|
||||
while (($# > 0)); do
|
||||
lowerI="$(echo $1 | awk '{print tolower($0)}')"
|
||||
case $lowerI in
|
||||
--baseuri)
|
||||
base_uri=$2
|
||||
shift 2
|
||||
;;
|
||||
--installpath)
|
||||
install_path=$2
|
||||
shift 2
|
||||
;;
|
||||
--version)
|
||||
version=$2
|
||||
shift 2
|
||||
;;
|
||||
--clean)
|
||||
clean=true
|
||||
shift 1
|
||||
;;
|
||||
--force)
|
||||
force=true
|
||||
shift 1
|
||||
;;
|
||||
--downloadretries)
|
||||
download_retries=$2
|
||||
shift 2
|
||||
;;
|
||||
--retrywaittimeseconds)
|
||||
retry_wait_time_seconds=$2
|
||||
shift 2
|
||||
;;
|
||||
--help)
|
||||
echo "Common settings:"
|
||||
echo " --baseuri <value> Base file directory or Url wrom which to acquire tool archives"
|
||||
echo " --installpath <value> Base directory to install native tool to"
|
||||
echo " --clean Don't install the tool, just clean up the current install of the tool"
|
||||
echo " --force Force install of tools even if they previously exist"
|
||||
echo " --help Print help and exit"
|
||||
echo ""
|
||||
echo "Advanced settings:"
|
||||
echo " --downloadretries Total number of retry attempts"
|
||||
echo " --retrywaittimeseconds Wait time between retry attempts in seconds"
|
||||
echo ""
|
||||
exit 0
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
tool_name="cmake-test"
|
||||
tool_os=$(GetCurrentOS)
|
||||
tool_folder=$(echo $tool_os | awk '{print tolower($0)}')
|
||||
tool_arch="x86_64"
|
||||
tool_name_moniker="$tool_name-$version-$tool_os-$tool_arch"
|
||||
tool_install_directory="$install_path/$tool_name/$version"
|
||||
tool_file_path="$tool_install_directory/$tool_name_moniker/bin/$tool_name"
|
||||
shim_path="$install_path/$tool_name.sh"
|
||||
uri="${base_uri}/$tool_folder/$tool_name/$tool_name_moniker.tar.gz"
|
||||
|
||||
# Clean up tool and installers
|
||||
if [[ $clean = true ]]; then
|
||||
echo "Cleaning $tool_install_directory"
|
||||
if [[ -d $tool_install_directory ]]; then
|
||||
rm -rf $tool_install_directory
|
||||
fi
|
||||
|
||||
echo "Cleaning $shim_path"
|
||||
if [[ -f $shim_path ]]; then
|
||||
rm -rf $shim_path
|
||||
fi
|
||||
|
||||
tool_temp_path=$(GetTempPathFileName $uri)
|
||||
echo "Cleaning $tool_temp_path"
|
||||
if [[ -f $tool_temp_path ]]; then
|
||||
rm -rf $tool_temp_path
|
||||
fi
|
||||
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Install tool
|
||||
if [[ -f $tool_file_path ]] && [[ $force = false ]]; then
|
||||
echo "$tool_name ($version) already exists, skipping install"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
DownloadAndExtract $uri $tool_install_directory $force $download_retries $retry_wait_time_seconds
|
||||
|
||||
if [[ $? != 0 ]]; then
|
||||
echo "Installation failed" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Generate Shim
|
||||
# Always rewrite shims so that we are referencing the expected version
|
||||
NewScriptShim $shim_path $tool_file_path true
|
||||
|
||||
if [[ $? != 0 ]]; then
|
||||
echo "Shim generation failed" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
exit 0
|
||||
|
|
@ -69,7 +69,7 @@ tool_name_moniker="$tool_name-$version-$tool_os-$tool_arch"
|
|||
tool_install_directory="$install_path/$tool_name/$version"
|
||||
tool_file_path="$tool_install_directory/$tool_name_moniker/bin/$tool_name"
|
||||
shim_path="$install_path/$tool_name.sh"
|
||||
uri="${base_uri}/$tool_folder/cmake/$tool_name_moniker.tar.gz"
|
||||
uri="${base_uri}/$tool_folder/$tool_name/$tool_name_moniker.tar.gz"
|
||||
|
||||
# Clean up tool and installers
|
||||
if [[ $clean = true ]]; then
|
||||
|
|
|
|||
|
|
@ -0,0 +1,35 @@
|
|||
param(
|
||||
[Parameter(Mandatory=$true)][int] $BarBuildId, # ID of the build which assets should be downloaded
|
||||
[Parameter(Mandatory=$true)][string] $DropLocation, # Where the assets should be downloaded to
|
||||
[Parameter(Mandatory=$true)][string] $MaestroApiAccessToken, # Token used to access Maestro API
|
||||
[Parameter(Mandatory=$false)][string] $MaestroApiEndPoint = "https://maestro-prod.westus2.cloudapp.azure.com", # Maestro API URL
|
||||
[Parameter(Mandatory=$false)][string] $MaestroApiVersion = "2019-01-16" # Version of Maestro API to use
|
||||
)
|
||||
|
||||
. $PSScriptRoot\post-build-utils.ps1
|
||||
|
||||
try {
|
||||
Write-Host "Installing DARC ..."
|
||||
|
||||
. $PSScriptRoot\..\darc-init.ps1
|
||||
$exitCode = $LASTEXITCODE
|
||||
|
||||
if ($exitCode -ne 0) {
|
||||
Write-PipelineTaskError "Something failed while running 'darc-init.ps1'. Check for errors above. Exiting now..."
|
||||
ExitWithExitCode $exitCode
|
||||
}
|
||||
|
||||
darc gather-drop --non-shipping `
|
||||
--continue-on-error `
|
||||
--id $BarBuildId `
|
||||
--output-dir $DropLocation `
|
||||
--bar-uri $MaestroApiEndpoint `
|
||||
--password $MaestroApiAccessToken `
|
||||
--latest-location
|
||||
}
|
||||
catch {
|
||||
Write-Host $_
|
||||
Write-Host $_.Exception
|
||||
Write-Host $_.ScriptStackTrace
|
||||
ExitWithExitCode 1
|
||||
}
|
||||
|
|
@ -6,10 +6,7 @@ param(
|
|||
[Parameter(Mandatory=$true)][string] $ToolDestinationPath # Where the validation tool should be downloaded to
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
Set-StrictMode -Version 2.0
|
||||
|
||||
. $PSScriptRoot\..\tools.ps1
|
||||
. $PSScriptRoot\post-build-utils.ps1
|
||||
|
||||
try {
|
||||
$url = "https://raw.githubusercontent.com/NuGet/NuGetGallery/jver-verify/src/VerifyMicrosoftPackage/verify.ps1"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,90 @@
|
|||
# Most of the functions in this file require the variables `MaestroApiEndPoint`,
|
||||
# `MaestroApiVersion` and `MaestroApiAccessToken` to be globally available.
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
Set-StrictMode -Version 2.0
|
||||
|
||||
# `tools.ps1` checks $ci to perform some actions. Since the post-build
|
||||
# scripts don't necessarily execute in the same agent that run the
|
||||
# build.ps1/sh script this variable isn't automatically set.
|
||||
$ci = $true
|
||||
. $PSScriptRoot\..\tools.ps1
|
||||
|
||||
function Create-MaestroApiRequestHeaders([string]$ContentType = "application/json") {
|
||||
Validate-MaestroVars
|
||||
|
||||
$headers = New-Object 'System.Collections.Generic.Dictionary[[String],[String]]'
|
||||
$headers.Add('Accept', $ContentType)
|
||||
$headers.Add('Authorization',"Bearer $MaestroApiAccessToken")
|
||||
return $headers
|
||||
}
|
||||
|
||||
function Get-MaestroChannel([int]$ChannelId) {
|
||||
Validate-MaestroVars
|
||||
|
||||
$apiHeaders = Create-MaestroApiRequestHeaders
|
||||
$apiEndpoint = "$MaestroApiEndPoint/api/channels/${ChannelId}?api-version=$MaestroApiVersion"
|
||||
|
||||
$result = try { Invoke-WebRequest -Method Get -Uri $apiEndpoint -Headers $apiHeaders | ConvertFrom-Json } catch { Write-Host "Error: $_" }
|
||||
return $result
|
||||
}
|
||||
|
||||
function Get-MaestroBuild([int]$BuildId) {
|
||||
Validate-MaestroVars
|
||||
|
||||
$apiHeaders = Create-MaestroApiRequestHeaders -AuthToken $MaestroApiAccessToken
|
||||
$apiEndpoint = "$MaestroApiEndPoint/api/builds/${BuildId}?api-version=$MaestroApiVersion"
|
||||
|
||||
$result = try { return Invoke-WebRequest -Method Get -Uri $apiEndpoint -Headers $apiHeaders | ConvertFrom-Json } catch { Write-Host "Error: $_" }
|
||||
return $result
|
||||
}
|
||||
|
||||
function Get-MaestroSubscriptions([string]$SourceRepository, [int]$ChannelId) {
|
||||
Validate-MaestroVars
|
||||
|
||||
$SourceRepository = [System.Web.HttpUtility]::UrlEncode($SourceRepository)
|
||||
$apiHeaders = Create-MaestroApiRequestHeaders -AuthToken $MaestroApiAccessToken
|
||||
$apiEndpoint = "$MaestroApiEndPoint/api/subscriptions?sourceRepository=$SourceRepository&channelId=$ChannelId&api-version=$MaestroApiVersion"
|
||||
|
||||
$result = try { Invoke-WebRequest -Method Get -Uri $apiEndpoint -Headers $apiHeaders | ConvertFrom-Json } catch { Write-Host "Error: $_" }
|
||||
return $result
|
||||
}
|
||||
|
||||
function Trigger-Subscription([string]$SubscriptionId) {
|
||||
Validate-MaestroVars
|
||||
|
||||
$apiHeaders = Create-MaestroApiRequestHeaders -AuthToken $MaestroApiAccessToken
|
||||
$apiEndpoint = "$MaestroApiEndPoint/api/subscriptions/$SubscriptionId/trigger?api-version=$MaestroApiVersion"
|
||||
Invoke-WebRequest -Uri $apiEndpoint -Headers $apiHeaders -Method Post | Out-Null
|
||||
}
|
||||
|
||||
function Assign-BuildToChannel([int]$BuildId, [int]$ChannelId) {
|
||||
Validate-MaestroVars
|
||||
|
||||
$apiHeaders = Create-MaestroApiRequestHeaders -AuthToken $MaestroApiAccessToken
|
||||
$apiEndpoint = "$MaestroApiEndPoint/api/channels/${ChannelId}/builds/${BuildId}?api-version=$MaestroApiVersion"
|
||||
Invoke-WebRequest -Method Post -Uri $apiEndpoint -Headers $apiHeaders | Out-Null
|
||||
}
|
||||
|
||||
function Validate-MaestroVars {
|
||||
try {
|
||||
Get-Variable MaestroApiEndPoint -Scope Global | Out-Null
|
||||
Get-Variable MaestroApiVersion -Scope Global | Out-Null
|
||||
Get-Variable MaestroApiAccessToken -Scope Global | Out-Null
|
||||
|
||||
if (!($MaestroApiEndPoint -Match "^http[s]?://maestro-(int|prod).westus2.cloudapp.azure.com$")) {
|
||||
Write-PipelineTaskError "MaestroApiEndPoint is not a valid Maestro URL. '$MaestroApiEndPoint'"
|
||||
ExitWithExitCode 1
|
||||
}
|
||||
|
||||
if (!($MaestroApiVersion -Match "^[0-9]{4}-[0-9]{2}-[0-9]{2}$")) {
|
||||
Write-PipelineTaskError "MaestroApiVersion does not match a version string in the format yyyy-MM-DD. '$MaestroApiVersion'"
|
||||
ExitWithExitCode 1
|
||||
}
|
||||
}
|
||||
catch {
|
||||
Write-PipelineTaskError "Error: Variables `MaestroApiEndPoint`, `MaestroApiVersion` and `MaestroApiAccessToken` are required while using this script."
|
||||
Write-Host $_
|
||||
ExitWithExitCode 1
|
||||
}
|
||||
}
|
||||
|
|
@ -1,30 +1,25 @@
|
|||
param(
|
||||
[Parameter(Mandatory=$true)][int] $BuildId,
|
||||
[Parameter(Mandatory=$true)][int] $ChannelId,
|
||||
[Parameter(Mandatory=$true)][string] $BarToken,
|
||||
[string] $MaestroEndpoint = "https://maestro-prod.westus2.cloudapp.azure.com",
|
||||
[string] $ApiVersion = "2019-01-16"
|
||||
[Parameter(Mandatory=$true)][string] $MaestroApiAccessToken,
|
||||
[Parameter(Mandatory=$false)][string] $MaestroApiEndPoint = "https://maestro-prod.westus2.cloudapp.azure.com",
|
||||
[Parameter(Mandatory=$false)][string] $MaestroApiVersion = "2019-01-16"
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
Set-StrictMode -Version 2.0
|
||||
|
||||
. $PSScriptRoot\..\tools.ps1
|
||||
|
||||
function Get-Headers([string]$accept, [string]$barToken) {
|
||||
$headers = New-Object 'System.Collections.Generic.Dictionary[[String],[String]]'
|
||||
$headers.Add('Accept',$accept)
|
||||
$headers.Add('Authorization',"Bearer $barToken")
|
||||
return $headers
|
||||
}
|
||||
. $PSScriptRoot\post-build-utils.ps1
|
||||
|
||||
try {
|
||||
$maestroHeaders = Get-Headers 'application/json' $BarToken
|
||||
# Check that the channel we are going to promote the build to exist
|
||||
$channelInfo = Get-MaestroChannel -ChannelId $ChannelId
|
||||
|
||||
if (!$channelInfo) {
|
||||
Write-Host "Channel with BAR ID $ChannelId was not found in BAR!"
|
||||
ExitWithExitCode 1
|
||||
}
|
||||
|
||||
# Get info about which channels the build has already been promoted to
|
||||
$getBuildApiEndpoint = "$MaestroEndpoint/api/builds/${BuildId}?api-version=$ApiVersion"
|
||||
$buildInfo = Invoke-WebRequest -Method Get -Uri $getBuildApiEndpoint -Headers $maestroHeaders | ConvertFrom-Json
|
||||
|
||||
$buildInfo = Get-MaestroBuild -BuildId $BuildId
|
||||
|
||||
if (!$buildInfo) {
|
||||
Write-Host "Build with BAR ID $BuildId was not found in BAR!"
|
||||
ExitWithExitCode 1
|
||||
|
|
@ -40,10 +35,10 @@ try {
|
|||
}
|
||||
}
|
||||
|
||||
Write-Host "Build not present in channel $ChannelId. Promoting build ... "
|
||||
Write-Host "Promoting build '$BuildId' to channel '$ChannelId'."
|
||||
|
||||
Assign-BuildToChannel -BuildId $BuildId -ChannelId $ChannelId
|
||||
|
||||
$promoteBuildApiEndpoint = "$maestroEndpoint/api/channels/${ChannelId}/builds/${BuildId}?api-version=$ApiVersion"
|
||||
Invoke-WebRequest -Method Post -Uri $promoteBuildApiEndpoint -Headers $maestroHeaders
|
||||
Write-Host "done."
|
||||
}
|
||||
catch {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,26 @@
|
|||
param(
|
||||
[Parameter(Mandatory=$true)][string] $ReleaseConfigsPath # Full path to ReleaseConfigs.txt asset
|
||||
)
|
||||
|
||||
. $PSScriptRoot\post-build-utils.ps1
|
||||
|
||||
try {
|
||||
$Content = Get-Content $ReleaseConfigsPath
|
||||
|
||||
$BarId = $Content | Select -Index 0
|
||||
|
||||
$Channels = ""
|
||||
$Content | Select -Index 1 | ForEach-Object { $Channels += "$_ ," }
|
||||
|
||||
$IsStableBuild = $Content | Select -Index 2
|
||||
|
||||
Write-PipelineSetVariable -Name 'BARBuildId' -Value $BarId
|
||||
Write-PipelineSetVariable -Name 'InitialChannels' -Value "$Channels"
|
||||
Write-PipelineSetVariable -Name 'IsStableBuild' -Value $IsStableBuild
|
||||
}
|
||||
catch {
|
||||
Write-Host $_
|
||||
Write-Host $_.Exception
|
||||
Write-Host $_.ScriptStackTrace
|
||||
ExitWithExitCode 1
|
||||
}
|
||||
|
|
@ -6,10 +6,7 @@ param(
|
|||
[Parameter(Mandatory=$true)][string] $SourcelinkCliVersion # Version of SourceLink CLI to use
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
Set-StrictMode -Version 2.0
|
||||
|
||||
. $PSScriptRoot\..\tools.ps1
|
||||
. $PSScriptRoot\post-build-utils.ps1
|
||||
|
||||
# Cache/HashMap (File -> Exist flag) used to consult whether a file exist
|
||||
# in the repository at a specific commit point. This is populated by inserting
|
||||
|
|
@ -200,21 +197,27 @@ function ValidateSourceLinkLinks {
|
|||
}
|
||||
}
|
||||
|
||||
function CheckExitCode ([string]$stage) {
|
||||
$exitCode = $LASTEXITCODE
|
||||
if ($exitCode -ne 0) {
|
||||
Write-PipelineTaskError "Something failed while '$stage'. Check for errors above. Exiting now..."
|
||||
ExitWithExitCode $exitCode
|
||||
function InstallSourcelinkCli {
|
||||
$sourcelinkCliPackageName = "sourcelink"
|
||||
|
||||
$dotnetRoot = InitializeDotNetCli -install:$true
|
||||
$dotnet = "$dotnetRoot\dotnet.exe"
|
||||
$toolList = & "$dotnet" tool list --global
|
||||
|
||||
if (($toolList -like "*$sourcelinkCliPackageName*") -and ($toolList -like "*$sourcelinkCliVersion*")) {
|
||||
Write-Host "SourceLink CLI version $sourcelinkCliVersion is already installed."
|
||||
}
|
||||
else {
|
||||
Write-Host "Installing SourceLink CLI version $sourcelinkCliVersion..."
|
||||
Write-Host "You may need to restart your command window if this is the first dotnet tool you have installed."
|
||||
& "$dotnet" tool install $sourcelinkCliPackageName --version $sourcelinkCliVersion --verbosity "minimal" --global
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
Write-Host "Installing SourceLink CLI..."
|
||||
Get-Location
|
||||
. $PSScriptRoot\sourcelink-cli-init.ps1 -sourcelinkCliVersion $SourcelinkCliVersion
|
||||
CheckExitCode "Running sourcelink-cli-init"
|
||||
InstallSourcelinkCli
|
||||
|
||||
Measure-Command { ValidateSourceLinkLinks }
|
||||
ValidateSourceLinkLinks
|
||||
}
|
||||
catch {
|
||||
Write-Host $_
|
||||
|
|
|
|||
|
|
@ -4,10 +4,7 @@ param(
|
|||
[Parameter(Mandatory=$true)][string] $DotnetSymbolVersion # Version of dotnet symbol to use
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
Set-StrictMode -Version 2.0
|
||||
|
||||
. $PSScriptRoot\..\tools.ps1
|
||||
. $PSScriptRoot\post-build-utils.ps1
|
||||
|
||||
Add-Type -AssemblyName System.IO.Compression.FileSystem
|
||||
|
||||
|
|
@ -162,19 +159,25 @@ function CheckSymbolsAvailable {
|
|||
}
|
||||
}
|
||||
|
||||
function CheckExitCode ([string]$stage) {
|
||||
$exitCode = $LASTEXITCODE
|
||||
if ($exitCode -ne 0) {
|
||||
Write-PipelineTaskError "Something failed while '$stage'. Check for errors above. Exiting now..."
|
||||
ExitWithExitCode $exitCode
|
||||
function Installdotnetsymbol {
|
||||
$dotnetsymbolPackageName = "dotnet-symbol"
|
||||
|
||||
$dotnetRoot = InitializeDotNetCli -install:$true
|
||||
$dotnet = "$dotnetRoot\dotnet.exe"
|
||||
$toolList = & "$dotnet" tool list --global
|
||||
|
||||
if (($toolList -like "*$dotnetsymbolPackageName*") -and ($toolList -like "*$dotnetsymbolVersion*")) {
|
||||
Write-Host "dotnet-symbol version $dotnetsymbolVersion is already installed."
|
||||
}
|
||||
else {
|
||||
Write-Host "Installing dotnet-symbol version $dotnetsymbolVersion..."
|
||||
Write-Host "You may need to restart your command window if this is the first dotnet tool you have installed."
|
||||
& "$dotnet" tool install $dotnetsymbolPackageName --version $dotnetsymbolVersion --verbosity "minimal" --global
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
Write-Host "Installing dotnet symbol ..."
|
||||
Get-Location
|
||||
. $PSScriptRoot\dotnetsymbol-init.ps1 -dotnetsymbolVersion $DotnetSymbolVersion
|
||||
CheckExitCode "Running dotnetsymbol-init"
|
||||
Installdotnetsymbol
|
||||
|
||||
CheckSymbolsAvailable
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,33 +1,20 @@
|
|||
param(
|
||||
param(
|
||||
[Parameter(Mandatory=$true)][string] $SourceRepo,
|
||||
[Parameter(Mandatory=$true)][int] $ChannelId,
|
||||
[string] $MaestroEndpoint = "https://maestro-prod.westus2.cloudapp.azure.com",
|
||||
[string] $BarToken,
|
||||
[string] $ApiVersion = "2019-01-16"
|
||||
[Parameter(Mandatory=$true)][string] $MaestroApiAccessToken,
|
||||
[Parameter(Mandatory=$false)][string] $MaestroApiEndPoint = "https://maestro-prod.westus2.cloudapp.azure.com",
|
||||
[Parameter(Mandatory=$false)][string] $MaestroApiVersion = "2019-01-16"
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
Set-StrictMode -Version 2.0
|
||||
|
||||
. $PSScriptRoot\..\tools.ps1
|
||||
|
||||
function Get-Headers([string]$accept, [string]$barToken) {
|
||||
$headers = New-Object 'System.Collections.Generic.Dictionary[[String],[String]]'
|
||||
$headers.Add('Accept',$accept)
|
||||
$headers.Add('Authorization',"Bearer $barToken")
|
||||
return $headers
|
||||
}
|
||||
. $PSScriptRoot\post-build-utils.ps1
|
||||
|
||||
# Get all the $SourceRepo subscriptions
|
||||
$normalizedSourceRepo = $SourceRepo.Replace('dnceng@', '')
|
||||
$getSubscriptionsApiEndpoint = "$maestroEndpoint/api/subscriptions?sourceRepository=$normalizedSourceRepo&api-version=$apiVersion"
|
||||
$headers = Get-Headers 'application/json' $barToken
|
||||
|
||||
$subscriptions = Invoke-WebRequest -Uri $getSubscriptionsApiEndpoint -Headers $headers | ConvertFrom-Json
|
||||
$subscriptions = Get-MaestroSubscriptions -SourceRepository $normalizedSourceRepo -ChannelId $ChannelId
|
||||
|
||||
if (!$subscriptions) {
|
||||
Write-Host "No subscriptions found for source repo '$normalizedSourceRepo' in channel '$ChannelId'"
|
||||
return
|
||||
ExitWithExitCode 0
|
||||
}
|
||||
|
||||
$subscriptionsToTrigger = New-Object System.Collections.Generic.List[string]
|
||||
|
|
@ -36,21 +23,18 @@ $failedTriggeredSubscription = $false
|
|||
# Get all enabled subscriptions that need dependency flow on 'everyBuild'
|
||||
foreach ($subscription in $subscriptions) {
|
||||
if ($subscription.enabled -and $subscription.policy.updateFrequency -like 'everyBuild' -and $subscription.channel.id -eq $ChannelId) {
|
||||
Write-Host "$subscription.id"
|
||||
Write-Host "Should trigger this subscription: $subscription.id"
|
||||
[void]$subscriptionsToTrigger.Add($subscription.id)
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($subscriptionToTrigger in $subscriptionsToTrigger) {
|
||||
try {
|
||||
$triggerSubscriptionApiEndpoint = "$maestroEndpoint/api/subscriptions/$subscriptionToTrigger/trigger?api-version=$apiVersion"
|
||||
$headers = Get-Headers 'application/json' $BarToken
|
||||
|
||||
Write-Host "Triggering subscription '$subscriptionToTrigger'..."
|
||||
Write-Host "Triggering subscription '$subscriptionToTrigger'."
|
||||
|
||||
Invoke-WebRequest -Uri $triggerSubscriptionApiEndpoint -Headers $headers -Method Post
|
||||
Trigger-Subscription -SubscriptionId $subscriptionToTrigger
|
||||
|
||||
Write-Host "Subscription '$subscriptionToTrigger' triggered!"
|
||||
Write-Host "done."
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
|
@ -61,9 +45,13 @@ foreach ($subscriptionToTrigger in $subscriptionsToTrigger) {
|
|||
}
|
||||
}
|
||||
|
||||
if ($failedTriggeredSubscription) {
|
||||
if ($subscriptionsToTrigger.Count -eq 0) {
|
||||
Write-Host "No subscription matched source repo '$normalizedSourceRepo' and channel ID '$ChannelId'."
|
||||
}
|
||||
elseif ($failedTriggeredSubscription) {
|
||||
Write-Host "At least one subscription failed to be triggered..."
|
||||
ExitWithExitCode 1
|
||||
}
|
||||
|
||||
Write-Host "All subscriptions were triggered successfully!"
|
||||
else {
|
||||
Write-Host "All subscriptions were triggered successfully!"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Microsoft.Guardian.Cli" version="0.6.0"/>
|
||||
<package id="Microsoft.Guardian.Cli" version="0.7.1"/>
|
||||
</packages>
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ jobs:
|
|||
continueOnError: ${{ parameters.continueOnError }}
|
||||
- ${{ if eq(parameters.overrideParameters, '') }}:
|
||||
- powershell: eng/common/sdl/execute-all-sdl-tools.ps1
|
||||
-GuardianPackageName Microsoft.Guardian.Cli.0.6.0
|
||||
-GuardianPackageName Microsoft.Guardian.Cli.0.7.1
|
||||
-NugetPackageDirectory $(Build.SourcesDirectory)\.packages
|
||||
-AzureDevOpsAccessToken $(dn-bot-dotnet-build-rw-code-rw)
|
||||
${{ parameters.additionalParameters }}
|
||||
|
|
|
|||
|
|
@ -37,6 +37,9 @@ parameters:
|
|||
# Optional: Enable publishing to the build asset registry
|
||||
enablePublishBuildAssets: false
|
||||
|
||||
# Optional: Prevent gather/push manifest from executing when using publishing pipelines
|
||||
enablePublishUsingPipelines: false
|
||||
|
||||
# Optional: Include PublishTestResults task
|
||||
enablePublishTestResults: false
|
||||
|
||||
|
|
@ -187,7 +190,7 @@ jobs:
|
|||
continueOnError: true
|
||||
condition: always()
|
||||
|
||||
- ${{ if and(eq(parameters.enablePublishBuildAssets, true), ne(variables['_PublishUsingPipelines'], 'true'), eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}:
|
||||
- ${{ if and(eq(parameters.enablePublishBuildAssets, true), ne(parameters.enablePublishUsingPipelines, 'true'), eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}:
|
||||
- task: CopyFiles@2
|
||||
displayName: Gather Asset Manifests
|
||||
inputs:
|
||||
|
|
@ -195,6 +198,7 @@ jobs:
|
|||
TargetFolder: '$(Build.StagingDirectory)/AssetManifests'
|
||||
continueOnError: ${{ parameters.continueOnError }}
|
||||
condition: and(succeeded(), eq(variables['_DotNetPublishToBlobFeed'], 'true'))
|
||||
|
||||
- task: PublishBuildArtifacts@1
|
||||
displayName: Push Asset Manifests
|
||||
inputs:
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ stages:
|
|||
- job:
|
||||
displayName: Symbol Publishing
|
||||
dependsOn: setupMaestroVars
|
||||
condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], variables.InternalServicing_30_Channel_Id)
|
||||
condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', variables.InternalServicing_30_Channel_Id))
|
||||
variables:
|
||||
- group: DotNet-Symbol-Server-Pats
|
||||
pool:
|
||||
|
|
@ -41,13 +41,12 @@ stages:
|
|||
dependsOn: setupMaestroVars
|
||||
variables:
|
||||
- group: DotNet-Blob-Feed
|
||||
- group: Publish-Build-Assets
|
||||
- group: AzureDevOps-Artifact-Feeds-Pats
|
||||
- name: BARBuildId
|
||||
value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.BARBuildId'] ]
|
||||
- name: IsStableBuild
|
||||
value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.IsStableBuild'] ]
|
||||
condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], variables.InternalServicing_30_Channel_Id)
|
||||
condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', variables.InternalServicing_30_Channel_Id))
|
||||
pool:
|
||||
vmImage: 'windows-2019'
|
||||
steps:
|
||||
|
|
@ -87,8 +86,8 @@ stages:
|
|||
/p:StaticInternalFeed=$(dotnetfeed-internal-nonstable-feed-url)
|
||||
/p:NugetPath=$(Agent.BuildDirectory)\Nuget\NuGet.exe
|
||||
/p:BARBuildId=$(BARBuildId)
|
||||
/p:MaestroApiEndpoint='https://maestro-prod.westus2.cloudapp.azure.com'
|
||||
/p:BuildAssetRegistryToken='$(MaestroAccessToken)'
|
||||
/p:MaestroApiEndpoint='$(MaestroApiEndPoint)'
|
||||
/p:BuildAssetRegistryToken='$(MaestroApiAccessToken)'
|
||||
/p:ManifestsBasePath='$(Build.ArtifactStagingDirectory)/AssetManifests/'
|
||||
/p:BlobBasePath='$(Build.ArtifactStagingDirectory)\BlobArtifacts'
|
||||
/p:PackageBasePath='$(Build.ArtifactStagingDirectory)\PackageArtifacts'
|
||||
|
|
@ -127,7 +126,7 @@ stages:
|
|||
- job:
|
||||
displayName: Symbol Availability
|
||||
dependsOn: setupMaestroVars
|
||||
condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], variables.InternalServicing_30_Channel_Id)
|
||||
condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', variables.InternalServicing_30_Channel_Id))
|
||||
pool:
|
||||
vmImage: 'windows-2019'
|
||||
steps:
|
||||
|
|
@ -143,29 +142,6 @@ stages:
|
|||
filePath: $(Build.SourcesDirectory)/eng/common/post-build/symbols-validation.ps1
|
||||
arguments: -InputPath $(Build.ArtifactStagingDirectory)/PackageArtifacts/ -ExtractPath $(Agent.BuildDirectory)/Temp/ -DotnetSymbolVersion $(SymbolToolVersion)
|
||||
|
||||
- job:
|
||||
displayName: Gather Drop
|
||||
dependsOn: setupMaestroVars
|
||||
variables:
|
||||
BARBuildId: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.BARBuildId'] ]
|
||||
condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], variables.InternalServicing_30_Channel_Id)
|
||||
pool:
|
||||
vmImage: 'windows-2019'
|
||||
steps:
|
||||
- task: PowerShell@2
|
||||
displayName: Setup Darc CLI
|
||||
inputs:
|
||||
targetType: filePath
|
||||
filePath: '$(Build.SourcesDirectory)/eng/common/darc-init.ps1'
|
||||
|
||||
- task: PowerShell@2
|
||||
displayName: Run Darc gather-drop
|
||||
inputs:
|
||||
targetType: inline
|
||||
script: |
|
||||
darc gather-drop --non-shipping --continue-on-error --id $(BARBuildId) --output-dir $(Agent.BuildDirectory)/Temp/Drop/ --bar-uri https://maestro-prod.westus2.cloudapp.azure.com/ --password $(MaestroAccessToken) --latest-location
|
||||
enabled: false
|
||||
|
||||
- template: ../promote-build.yml
|
||||
parameters:
|
||||
ChannelId: ${{ variables.InternalServicing_30_Channel_Id }}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,148 @@
|
|||
parameters:
|
||||
enableSymbolValidation: true
|
||||
|
||||
stages:
|
||||
- stage: NetCore_Dev5_Publish
|
||||
dependsOn: validate
|
||||
variables:
|
||||
- template: ../common-variables.yml
|
||||
displayName: .NET Core 5 Dev Channel
|
||||
jobs:
|
||||
- template: ../setup-maestro-vars.yml
|
||||
|
||||
- job:
|
||||
displayName: Symbol Publishing
|
||||
dependsOn: setupMaestroVars
|
||||
condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', variables.NetCore_5_Dev_Channel_Id))
|
||||
variables:
|
||||
- group: DotNet-Symbol-Server-Pats
|
||||
pool:
|
||||
vmImage: 'windows-2019'
|
||||
steps:
|
||||
- task: DownloadBuildArtifacts@0
|
||||
displayName: Download Artifacts
|
||||
inputs:
|
||||
downloadType: specific files
|
||||
matchingPattern: "*Artifacts*"
|
||||
|
||||
- task: PowerShell@2
|
||||
displayName: Publish
|
||||
inputs:
|
||||
filePath: eng\common\sdk-task.ps1
|
||||
arguments: -task PublishToSymbolServers -restore -msbuildEngine dotnet
|
||||
/p:DotNetSymbolServerTokenMsdl=$(microsoft-symbol-server-pat)
|
||||
/p:DotNetSymbolServerTokenSymWeb=$(symweb-symbol-server-pat)
|
||||
/p:PDBArtifactsDirectory='$(Build.ArtifactStagingDirectory)/PDBArtifacts/'
|
||||
/p:BlobBasePath='$(Build.ArtifactStagingDirectory)/BlobArtifacts/'
|
||||
/p:Configuration=Release
|
||||
|
||||
- job:
|
||||
displayName: Publish Assets
|
||||
dependsOn: setupMaestroVars
|
||||
variables:
|
||||
- group: DotNet-Blob-Feed
|
||||
- group: AzureDevOps-Artifact-Feeds-Pats
|
||||
- name: BARBuildId
|
||||
value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.BARBuildId'] ]
|
||||
- name: IsStableBuild
|
||||
value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.IsStableBuild'] ]
|
||||
condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', variables.NetCore_5_Dev_Channel_Id))
|
||||
pool:
|
||||
vmImage: 'windows-2019'
|
||||
steps:
|
||||
- task: DownloadBuildArtifacts@0
|
||||
displayName: Download Package Artifacts
|
||||
inputs:
|
||||
buildType: current
|
||||
artifactName: PackageArtifacts
|
||||
|
||||
- task: DownloadBuildArtifacts@0
|
||||
displayName: Download Blob Artifacts
|
||||
inputs:
|
||||
buildType: current
|
||||
artifactName: BlobArtifacts
|
||||
|
||||
- task: DownloadBuildArtifacts@0
|
||||
displayName: Download Asset Manifests
|
||||
inputs:
|
||||
buildType: current
|
||||
artifactName: AssetManifests
|
||||
|
||||
- task: PowerShell@2
|
||||
displayName: Add Assets Location
|
||||
env:
|
||||
AZURE_DEVOPS_EXT_PAT: $(dn-bot-dnceng-unviersal-packages-rw)
|
||||
inputs:
|
||||
filePath: eng\common\sdk-task.ps1
|
||||
arguments: -task PublishArtifactsInManifest -restore -msbuildEngine dotnet
|
||||
/p:ChannelId=$(NetCore_5_Dev_Channel_Id)
|
||||
/p:ArtifactsCategory=$(_DotNetArtifactsCategory)
|
||||
/p:IsStableBuild=$(IsStableBuild)
|
||||
/p:IsInternalBuild=$(IsInternalBuild)
|
||||
/p:RepositoryName=$(Build.Repository.Name)
|
||||
/p:CommitSha=$(Build.SourceVersion)
|
||||
/p:NugetPath=$(Agent.BuildDirectory)\Nuget\NuGet.exe
|
||||
/p:AzdoTargetFeedPAT='$(dn-bot-dnceng-unviersal-packages-rw)'
|
||||
/p:TargetFeedPAT='$(dn-bot-dnceng-unviersal-packages-rw)'
|
||||
/p:AzureStorageTargetFeedPAT='$(dotnetfeed-storage-access-key-1)'
|
||||
/p:BARBuildId=$(BARBuildId)
|
||||
/p:MaestroApiEndpoint='$(MaestroApiEndPoint)'
|
||||
/p:BuildAssetRegistryToken='$(MaestroApiAccessToken)'
|
||||
/p:ManifestsBasePath='$(Build.ArtifactStagingDirectory)/AssetManifests/'
|
||||
/p:BlobBasePath='$(Build.ArtifactStagingDirectory)/BlobArtifacts/'
|
||||
/p:PackageBasePath='$(Build.ArtifactStagingDirectory)/PackageArtifacts/'
|
||||
/p:Configuration=Release
|
||||
|
||||
- task: NuGetCommand@2
|
||||
displayName: Publish Packages to AzDO Feed
|
||||
condition: contains(variables['TargetAzDOFeed'], 'pkgs.visualstudio.com')
|
||||
inputs:
|
||||
command: push
|
||||
vstsFeed: $(AzDoFeedName)
|
||||
packagesToPush: $(Build.ArtifactStagingDirectory)\PackageArtifacts\*.nupkg
|
||||
publishVstsFeed: $(AzDoFeedName)
|
||||
|
||||
- task: PowerShell@2
|
||||
displayName: Publish Blobs to AzDO Feed
|
||||
inputs:
|
||||
filePath: $(Build.SourcesDirectory)/eng/common/post-build/publish-blobs-to-azdo.ps1
|
||||
arguments: -FeedName $(AzDoFeedName)
|
||||
-SourceFolderCollection $(Build.ArtifactStagingDirectory)/BlobArtifacts/
|
||||
-PersonalAccessToken $(dn-bot-dnceng-unviersal-packages-rw)
|
||||
enabled: false
|
||||
|
||||
|
||||
- stage: NetCore_Dev5_PublishValidation
|
||||
displayName: Publish Validation
|
||||
variables:
|
||||
- template: ../common-variables.yml
|
||||
jobs:
|
||||
- template: ../setup-maestro-vars.yml
|
||||
|
||||
- ${{ if eq(parameters.enableSymbolValidation, 'true') }}:
|
||||
- job:
|
||||
displayName: Symbol Availability
|
||||
dependsOn: setupMaestroVars
|
||||
condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', variables.NetCore_5_Dev_Channel_Id))
|
||||
pool:
|
||||
vmImage: 'windows-2019'
|
||||
steps:
|
||||
- task: DownloadBuildArtifacts@0
|
||||
displayName: Download Package Artifacts
|
||||
inputs:
|
||||
buildType: current
|
||||
artifactName: PackageArtifacts
|
||||
|
||||
- task: PowerShell@2
|
||||
displayName: Check Symbol Availability
|
||||
inputs:
|
||||
filePath: $(Build.SourcesDirectory)/eng/common/post-build/symbols-validation.ps1
|
||||
arguments: -InputPath $(Build.ArtifactStagingDirectory)/PackageArtifacts/ -ExtractPath $(Agent.BuildDirectory)/Temp/ -DotnetSymbolVersion $(SymbolToolVersion)
|
||||
|
||||
- template: ../darc-gather-drop.yml
|
||||
parameters:
|
||||
ChannelId: ${{ variables.NetCore_5_Dev_Channel_Id }}
|
||||
|
||||
- template: ../promote-build.yml
|
||||
parameters:
|
||||
ChannelId: ${{ variables.NetCore_5_Dev_Channel_Id }}
|
||||
|
|
@ -0,0 +1,148 @@
|
|||
parameters:
|
||||
enableSymbolValidation: true
|
||||
|
||||
stages:
|
||||
- stage: NetCore_Tools_Latest_Publish
|
||||
dependsOn: validate
|
||||
variables:
|
||||
- template: ../common-variables.yml
|
||||
displayName: .NET Tools - Latest
|
||||
jobs:
|
||||
- template: ../setup-maestro-vars.yml
|
||||
|
||||
- job:
|
||||
displayName: Symbol Publishing
|
||||
dependsOn: setupMaestroVars
|
||||
condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', variables.NetCore_Tools_Latest_Channel_Id))
|
||||
variables:
|
||||
- group: DotNet-Symbol-Server-Pats
|
||||
pool:
|
||||
vmImage: 'windows-2019'
|
||||
steps:
|
||||
- task: DownloadBuildArtifacts@0
|
||||
displayName: Download Artifacts
|
||||
inputs:
|
||||
downloadType: specific files
|
||||
matchingPattern: "*Artifacts*"
|
||||
|
||||
- task: PowerShell@2
|
||||
displayName: Publish
|
||||
inputs:
|
||||
filePath: eng\common\sdk-task.ps1
|
||||
arguments: -task PublishToSymbolServers -restore -msbuildEngine dotnet
|
||||
/p:DotNetSymbolServerTokenMsdl=$(microsoft-symbol-server-pat)
|
||||
/p:DotNetSymbolServerTokenSymWeb=$(symweb-symbol-server-pat)
|
||||
/p:PDBArtifactsDirectory='$(Build.ArtifactStagingDirectory)/PDBArtifacts/'
|
||||
/p:BlobBasePath='$(Build.ArtifactStagingDirectory)/BlobArtifacts/'
|
||||
/p:Configuration=Release
|
||||
|
||||
- job:
|
||||
displayName: Publish Assets
|
||||
dependsOn: setupMaestroVars
|
||||
variables:
|
||||
- group: DotNet-Blob-Feed
|
||||
- group: AzureDevOps-Artifact-Feeds-Pats
|
||||
- name: BARBuildId
|
||||
value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.BARBuildId'] ]
|
||||
- name: IsStableBuild
|
||||
value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.IsStableBuild'] ]
|
||||
condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', variables.NetCore_Tools_Latest_Channel_Id))
|
||||
pool:
|
||||
vmImage: 'windows-2019'
|
||||
steps:
|
||||
- task: DownloadBuildArtifacts@0
|
||||
displayName: Download Package Artifacts
|
||||
inputs:
|
||||
buildType: current
|
||||
artifactName: PackageArtifacts
|
||||
|
||||
- task: DownloadBuildArtifacts@0
|
||||
displayName: Download Blob Artifacts
|
||||
inputs:
|
||||
buildType: current
|
||||
artifactName: BlobArtifacts
|
||||
|
||||
- task: DownloadBuildArtifacts@0
|
||||
displayName: Download Asset Manifests
|
||||
inputs:
|
||||
buildType: current
|
||||
artifactName: AssetManifests
|
||||
|
||||
- task: PowerShell@2
|
||||
displayName: Add Assets Location
|
||||
env:
|
||||
AZURE_DEVOPS_EXT_PAT: $(dn-bot-dnceng-unviersal-packages-rw)
|
||||
inputs:
|
||||
filePath: eng\common\sdk-task.ps1
|
||||
arguments: -task PublishArtifactsInManifest -restore -msbuildEngine dotnet
|
||||
/p:ChannelId=$(NetCore_Tools_Latest_Channel_Id)
|
||||
/p:ArtifactsCategory=$(_DotNetArtifactsCategory)
|
||||
/p:IsStableBuild=$(IsStableBuild)
|
||||
/p:IsInternalBuild=$(IsInternalBuild)
|
||||
/p:RepositoryName=$(Build.Repository.Name)
|
||||
/p:CommitSha=$(Build.SourceVersion)
|
||||
/p:NugetPath=$(Agent.BuildDirectory)\Nuget\NuGet.exe
|
||||
/p:AzdoTargetFeedPAT='$(dn-bot-dnceng-unviersal-packages-rw)'
|
||||
/p:TargetFeedPAT='$(dn-bot-dnceng-unviersal-packages-rw)'
|
||||
/p:AzureStorageTargetFeedPAT='$(dotnetfeed-storage-access-key-1)'
|
||||
/p:BARBuildId=$(BARBuildId)
|
||||
/p:MaestroApiEndpoint='$(MaestroApiEndPoint)'
|
||||
/p:BuildAssetRegistryToken='$(MaestroApiAccessToken)'
|
||||
/p:ManifestsBasePath='$(Build.ArtifactStagingDirectory)/AssetManifests/'
|
||||
/p:BlobBasePath='$(Build.ArtifactStagingDirectory)/BlobArtifacts/'
|
||||
/p:PackageBasePath='$(Build.ArtifactStagingDirectory)/PackageArtifacts/'
|
||||
/p:Configuration=Release
|
||||
|
||||
- task: NuGetCommand@2
|
||||
displayName: Publish Packages to AzDO Feed
|
||||
condition: contains(variables['TargetAzDOFeed'], 'pkgs.visualstudio.com')
|
||||
inputs:
|
||||
command: push
|
||||
vstsFeed: $(AzDoFeedName)
|
||||
packagesToPush: $(Build.ArtifactStagingDirectory)\PackageArtifacts\*.nupkg
|
||||
publishVstsFeed: $(AzDoFeedName)
|
||||
|
||||
- task: PowerShell@2
|
||||
displayName: Publish Blobs to AzDO Feed
|
||||
inputs:
|
||||
filePath: $(Build.SourcesDirectory)/eng/common/post-build/publish-blobs-to-azdo.ps1
|
||||
arguments: -FeedName $(AzDoFeedName)
|
||||
-SourceFolderCollection $(Build.ArtifactStagingDirectory)/BlobArtifacts/
|
||||
-PersonalAccessToken $(dn-bot-dnceng-unviersal-packages-rw)
|
||||
enabled: false
|
||||
|
||||
|
||||
- stage: NetCore_Tools_Latest_PublishValidation
|
||||
displayName: Publish Validation
|
||||
variables:
|
||||
- template: ../common-variables.yml
|
||||
jobs:
|
||||
- template: ../setup-maestro-vars.yml
|
||||
|
||||
- ${{ if eq(parameters.enableSymbolValidation, 'true') }}:
|
||||
- job:
|
||||
displayName: Symbol Availability
|
||||
dependsOn: setupMaestroVars
|
||||
condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', variables.NetCore_Tools_Latest_Channel_Id))
|
||||
pool:
|
||||
vmImage: 'windows-2019'
|
||||
steps:
|
||||
- task: DownloadBuildArtifacts@0
|
||||
displayName: Download Package Artifacts
|
||||
inputs:
|
||||
buildType: current
|
||||
artifactName: PackageArtifacts
|
||||
|
||||
- task: PowerShell@2
|
||||
displayName: Check Symbol Availability
|
||||
inputs:
|
||||
filePath: $(Build.SourcesDirectory)/eng/common/post-build/symbols-validation.ps1
|
||||
arguments: -InputPath $(Build.ArtifactStagingDirectory)/PackageArtifacts/ -ExtractPath $(Agent.BuildDirectory)/Temp/ -DotnetSymbolVersion $(SymbolToolVersion)
|
||||
|
||||
- template: ../darc-gather-drop.yml
|
||||
parameters:
|
||||
ChannelId: ${{ variables.NetCore_Tools_Latest_Channel_Id }}
|
||||
|
||||
- template: ../promote-build.yml
|
||||
parameters:
|
||||
ChannelId: ${{ variables.NetCore_Tools_Latest_Channel_Id }}
|
||||
|
|
@ -13,7 +13,7 @@ stages:
|
|||
- job:
|
||||
displayName: Symbol Publishing
|
||||
dependsOn: setupMaestroVars
|
||||
condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], variables.PublicDevRelease_30_Channel_Id)
|
||||
condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', variables.PublicDevRelease_30_Channel_Id))
|
||||
variables:
|
||||
- group: DotNet-Symbol-Server-Pats
|
||||
pool:
|
||||
|
|
@ -41,13 +41,12 @@ stages:
|
|||
dependsOn: setupMaestroVars
|
||||
variables:
|
||||
- group: DotNet-Blob-Feed
|
||||
- group: Publish-Build-Assets
|
||||
- group: AzureDevOps-Artifact-Feeds-Pats
|
||||
- name: BARBuildId
|
||||
value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.BARBuildId'] ]
|
||||
- name: IsStableBuild
|
||||
value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.IsStableBuild'] ]
|
||||
condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], variables.PublicDevRelease_30_Channel_Id)
|
||||
condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', variables.PublicDevRelease_30_Channel_Id))
|
||||
pool:
|
||||
vmImage: 'windows-2019'
|
||||
steps:
|
||||
|
|
@ -77,7 +76,7 @@ stages:
|
|||
filePath: eng\common\sdk-task.ps1
|
||||
arguments: -task PublishArtifactsInManifest -restore -msbuildEngine dotnet
|
||||
/p:ChannelId=$(PublicDevRelease_30_Channel_Id)
|
||||
/p:ArtifactsCategory=.NetCore
|
||||
/p:ArtifactsCategory=$(_DotNetArtifactsCategory)
|
||||
/p:IsStableBuild=$(IsStableBuild)
|
||||
/p:IsInternalBuild=$(IsInternalBuild)
|
||||
/p:RepositoryName=$(Build.Repository.Name)
|
||||
|
|
@ -87,8 +86,8 @@ stages:
|
|||
/p:TargetFeedPAT='$(dn-bot-dnceng-unviersal-packages-rw)'
|
||||
/p:AzureStorageTargetFeedPAT='$(dotnetfeed-storage-access-key-1)'
|
||||
/p:BARBuildId=$(BARBuildId)
|
||||
/p:MaestroApiEndpoint='https://maestro-prod.westus2.cloudapp.azure.com'
|
||||
/p:BuildAssetRegistryToken='$(MaestroAccessToken)'
|
||||
/p:MaestroApiEndpoint='$(MaestroApiEndPoint)'
|
||||
/p:BuildAssetRegistryToken='$(MaestroApiAccessToken)'
|
||||
/p:ManifestsBasePath='$(Build.ArtifactStagingDirectory)/AssetManifests/'
|
||||
/p:BlobBasePath='$(Build.ArtifactStagingDirectory)/BlobArtifacts/'
|
||||
/p:PackageBasePath='$(Build.ArtifactStagingDirectory)/PackageArtifacts/'
|
||||
|
|
@ -124,7 +123,7 @@ stages:
|
|||
- job:
|
||||
displayName: Symbol Availability
|
||||
dependsOn: setupMaestroVars
|
||||
condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], variables.PublicDevRelease_30_Channel_Id)
|
||||
condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', variables.PublicDevRelease_30_Channel_Id))
|
||||
pool:
|
||||
vmImage: 'windows-2019'
|
||||
steps:
|
||||
|
|
@ -140,27 +139,9 @@ stages:
|
|||
filePath: $(Build.SourcesDirectory)/eng/common/post-build/symbols-validation.ps1
|
||||
arguments: -InputPath $(Build.ArtifactStagingDirectory)/PackageArtifacts/ -ExtractPath $(Agent.BuildDirectory)/Temp/ -DotnetSymbolVersion $(SymbolToolVersion)
|
||||
|
||||
- job:
|
||||
displayName: Gather Drop
|
||||
dependsOn: setupMaestroVars
|
||||
variables:
|
||||
BARBuildId: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.BARBuildId'] ]
|
||||
condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], variables.PublicDevRelease_30_Channel_Id)
|
||||
pool:
|
||||
vmImage: 'windows-2019'
|
||||
steps:
|
||||
- task: PowerShell@2
|
||||
displayName: Setup Darc CLI
|
||||
inputs:
|
||||
targetType: filePath
|
||||
filePath: '$(Build.SourcesDirectory)/eng/common/darc-init.ps1'
|
||||
|
||||
- task: PowerShell@2
|
||||
displayName: Run Darc gather-drop
|
||||
inputs:
|
||||
targetType: inline
|
||||
script: |
|
||||
darc gather-drop --non-shipping --continue-on-error --id $(BARBuildId) --output-dir $(Agent.BuildDirectory)/Temp/Drop/ --bar-uri https://maestro-prod.westus2.cloudapp.azure.com/ --password $(MaestroAccessToken) --latest-location
|
||||
- template: ../darc-gather-drop.yml
|
||||
parameters:
|
||||
ChannelId: ${{ variables.PublicDevRelease_30_Channel_Id }}
|
||||
|
||||
- template: ../promote-build.yml
|
||||
parameters:
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ stages:
|
|||
- job:
|
||||
displayName: Symbol Publishing
|
||||
dependsOn: setupMaestroVars
|
||||
condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], variables.PublicRelease_30_Channel_Id)
|
||||
condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', variables.PublicRelease_30_Channel_Id))
|
||||
variables:
|
||||
- group: DotNet-Symbol-Server-Pats
|
||||
pool:
|
||||
|
|
@ -41,13 +41,12 @@ stages:
|
|||
dependsOn: setupMaestroVars
|
||||
variables:
|
||||
- group: DotNet-Blob-Feed
|
||||
- group: Publish-Build-Assets
|
||||
- group: AzureDevOps-Artifact-Feeds-Pats
|
||||
- name: BARBuildId
|
||||
value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.BARBuildId'] ]
|
||||
- name: IsStableBuild
|
||||
value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.IsStableBuild'] ]
|
||||
condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], variables.PublicRelease_30_Channel_Id)
|
||||
condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', variables.PublicRelease_30_Channel_Id))
|
||||
pool:
|
||||
vmImage: 'windows-2019'
|
||||
steps:
|
||||
|
|
@ -87,8 +86,8 @@ stages:
|
|||
/p:StaticInternalFeed=$(dotnetfeed-internal-nonstable-feed-url)
|
||||
/p:NugetPath=$(Agent.BuildDirectory)\Nuget\NuGet.exe
|
||||
/p:BARBuildId=$(BARBuildId)
|
||||
/p:MaestroApiEndpoint='https://maestro-prod.westus2.cloudapp.azure.com'
|
||||
/p:BuildAssetRegistryToken='$(MaestroAccessToken)'
|
||||
/p:MaestroApiEndpoint='$(MaestroApiEndPoint)'
|
||||
/p:BuildAssetRegistryToken='$(MaestroApiAccessToken)'
|
||||
/p:ManifestsBasePath='$(Build.ArtifactStagingDirectory)/AssetManifests/'
|
||||
/p:BlobBasePath='$(Build.ArtifactStagingDirectory)\BlobArtifacts'
|
||||
/p:PackageBasePath='$(Build.ArtifactStagingDirectory)\PackageArtifacts'
|
||||
|
|
@ -127,7 +126,7 @@ stages:
|
|||
- job:
|
||||
displayName: Symbol Availability
|
||||
dependsOn: setupMaestroVars
|
||||
condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], variables.PublicRelease_30_Channel_Id)
|
||||
condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', variables.PublicRelease_30_Channel_Id))
|
||||
pool:
|
||||
vmImage: 'windows-2019'
|
||||
steps:
|
||||
|
|
@ -143,29 +142,6 @@ stages:
|
|||
filePath: $(Build.SourcesDirectory)/eng/common/post-build/symbols-validation.ps1
|
||||
arguments: -InputPath $(Build.ArtifactStagingDirectory)/PackageArtifacts/ -ExtractPath $(Agent.BuildDirectory)/Temp/ -DotnetSymbolVersion $(SymbolToolVersion)
|
||||
|
||||
- job:
|
||||
displayName: Gather Drop
|
||||
dependsOn: setupMaestroVars
|
||||
variables:
|
||||
BARBuildId: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.BARBuildId'] ]
|
||||
condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], variables.PublicRelease_30_Channel_Id)
|
||||
pool:
|
||||
vmImage: 'windows-2019'
|
||||
steps:
|
||||
- task: PowerShell@2
|
||||
displayName: Setup Darc CLI
|
||||
inputs:
|
||||
targetType: filePath
|
||||
filePath: '$(Build.SourcesDirectory)/eng/common/darc-init.ps1'
|
||||
|
||||
- task: PowerShell@2
|
||||
displayName: Run Darc gather-drop
|
||||
inputs:
|
||||
targetType: inline
|
||||
script: |
|
||||
darc gather-drop --non-shipping --continue-on-error --id $(BARBuildId) --output-dir $(Agent.BuildDirectory)/Temp/Drop/ --bar-uri https://maestro-prod.westus2.cloudapp.azure.com/ --password $(MaestroAccessToken) --latest-location
|
||||
enabled: false
|
||||
|
||||
- template: ../promote-build.yml
|
||||
parameters:
|
||||
ChannelId: ${{ variables.PublicRelease_30_Channel_Id }}
|
||||
|
|
|
|||
|
|
@ -12,13 +12,12 @@ stages:
|
|||
dependsOn: setupMaestroVars
|
||||
variables:
|
||||
- group: DotNet-Blob-Feed
|
||||
- group: Publish-Build-Assets
|
||||
- group: AzureDevOps-Artifact-Feeds-Pats
|
||||
- name: BARBuildId
|
||||
value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.BARBuildId'] ]
|
||||
- name: IsStableBuild
|
||||
value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.IsStableBuild'] ]
|
||||
condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], variables.PublicValidationRelease_30_Channel_Id)
|
||||
condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', variables.PublicValidationRelease_30_Channel_Id))
|
||||
pool:
|
||||
vmImage: 'windows-2019'
|
||||
steps:
|
||||
|
|
@ -48,7 +47,7 @@ stages:
|
|||
filePath: eng\common\sdk-task.ps1
|
||||
arguments: -task PublishArtifactsInManifest -restore -msbuildEngine dotnet
|
||||
/p:ChannelId=$(PublicValidationRelease_30_Channel_Id)
|
||||
/p:ArtifactsCategory=.NetCoreValidation
|
||||
/p:ArtifactsCategory=$(_DotNetValidationArtifactsCategory)
|
||||
/p:IsStableBuild=$(IsStableBuild)
|
||||
/p:IsInternalBuild=$(IsInternalBuild)
|
||||
/p:RepositoryName=$(Build.Repository.Name)
|
||||
|
|
@ -58,13 +57,13 @@ stages:
|
|||
/p:TargetFeedPAT='$(dn-bot-dnceng-unviersal-packages-rw)'
|
||||
/p:AzureStorageTargetFeedPAT='$(dotnetfeed-storage-access-key-1)'
|
||||
/p:BARBuildId=$(BARBuildId)
|
||||
/p:MaestroApiEndpoint='https://maestro-prod.westus2.cloudapp.azure.com'
|
||||
/p:BuildAssetRegistryToken='$(MaestroAccessToken)'
|
||||
/p:MaestroApiEndpoint='$(MaestroApiEndPoint)'
|
||||
/p:BuildAssetRegistryToken='$(MaestroApiAccessToken)'
|
||||
/p:ManifestsBasePath='$(Build.ArtifactStagingDirectory)/AssetManifests/'
|
||||
/p:BlobBasePath='$(Build.ArtifactStagingDirectory)\BlobArtifacts'
|
||||
/p:PackageBasePath='$(Build.ArtifactStagingDirectory)\PackageArtifacts'
|
||||
/p:Configuration=Release
|
||||
|
||||
|
||||
- task: NuGetCommand@2
|
||||
displayName: Publish Packages to AzDO Feed
|
||||
condition: contains(variables['TargetAzDOFeed'], 'pkgs.visualstudio.com')
|
||||
|
|
@ -91,29 +90,9 @@ stages:
|
|||
jobs:
|
||||
- template: ../setup-maestro-vars.yml
|
||||
|
||||
- job:
|
||||
displayName: Gather Drop
|
||||
dependsOn: setupMaestroVars
|
||||
condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], variables.PublicValidationRelease_30_Channel_Id)
|
||||
variables:
|
||||
- name: BARBuildId
|
||||
value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.BARBuildId'] ]
|
||||
- group: Publish-Build-Assets
|
||||
pool:
|
||||
vmImage: 'windows-2019'
|
||||
steps:
|
||||
- task: PowerShell@2
|
||||
displayName: Setup Darc CLI
|
||||
inputs:
|
||||
targetType: filePath
|
||||
filePath: '$(Build.SourcesDirectory)/eng/common/darc-init.ps1'
|
||||
|
||||
- task: PowerShell@2
|
||||
displayName: Run Darc gather-drop
|
||||
inputs:
|
||||
targetType: inline
|
||||
script: |
|
||||
darc gather-drop --non-shipping --continue-on-error --id $(BARBuildId) --output-dir $(Agent.BuildDirectory)/Temp/Drop/ --bar-uri https://maestro-prod.westus2.cloudapp.azure.com --password $(MaestroAccessToken) --latest-location
|
||||
- template: ../darc-gather-drop.yml
|
||||
parameters:
|
||||
ChannelId: ${{ variables.PublicValidationRelease_30_Channel_Id }}
|
||||
|
||||
- template: ../promote-build.yml
|
||||
parameters:
|
||||
|
|
|
|||
|
|
@ -1,21 +1,47 @@
|
|||
variables:
|
||||
- group: Publish-Build-Assets
|
||||
|
||||
# .NET Core 3 Dev
|
||||
PublicDevRelease_30_Channel_Id: 3
|
||||
- name: PublicDevRelease_30_Channel_Id
|
||||
value: 3
|
||||
|
||||
# .NET Core 5 Dev
|
||||
- name: NetCore_5_Dev_Channel_Id
|
||||
value: 131
|
||||
|
||||
# .NET Tools - Validation
|
||||
PublicValidationRelease_30_Channel_Id: 9
|
||||
- name: PublicValidationRelease_30_Channel_Id
|
||||
value: 9
|
||||
|
||||
# .NET Tools - Latest
|
||||
- name: NetCore_Tools_Latest_Channel_Id
|
||||
value: 2
|
||||
|
||||
# .NET Core 3.0 Internal Servicing
|
||||
InternalServicing_30_Channel_Id: 184
|
||||
- name: InternalServicing_30_Channel_Id
|
||||
value: 184
|
||||
|
||||
# .NET Core 3.0 Release
|
||||
PublicRelease_30_Channel_Id: 19
|
||||
- name: PublicRelease_30_Channel_Id
|
||||
value: 19
|
||||
|
||||
# Whether the build is internal or not
|
||||
IsInternalBuild: ${{ and(ne(variables['System.TeamProject'], 'public'), contains(variables['Build.SourceBranch'], 'internal')) }}
|
||||
- name: IsInternalBuild
|
||||
value: ${{ and(ne(variables['System.TeamProject'], 'public'), contains(variables['Build.SourceBranch'], 'internal')) }}
|
||||
|
||||
# Storage account name for proxy-backed feeds
|
||||
ProxyBackedFeedsAccountName: dotnetfeed
|
||||
- name: ProxyBackedFeedsAccountName
|
||||
value: dotnetfeed
|
||||
|
||||
SourceLinkCLIVersion: 3.0.0
|
||||
SymbolToolVersion: 1.0.1
|
||||
# Default Maestro++ API Endpoint and API Version
|
||||
- name: MaestroApiEndPoint
|
||||
value: "https://maestro-prod.westus2.cloudapp.azure.com"
|
||||
- name: MaestroApiAccessToken
|
||||
value: $(MaestroAccessToken)
|
||||
- name: MaestroApiVersion
|
||||
value: "2019-01-16"
|
||||
|
||||
- name: SourceLinkCLIVersion
|
||||
value: 3.0.0
|
||||
- name: SymbolToolVersion
|
||||
value: 1.0.1
|
||||
|
|
|
|||
|
|
@ -0,0 +1,23 @@
|
|||
parameters:
|
||||
ChannelId: 0
|
||||
|
||||
jobs:
|
||||
- job: gatherDrop
|
||||
displayName: Gather Drop
|
||||
dependsOn: setupMaestroVars
|
||||
condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', ${{ parameters.ChannelId }}))
|
||||
variables:
|
||||
- name: BARBuildId
|
||||
value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.BARBuildId'] ]
|
||||
pool:
|
||||
vmImage: 'windows-2019'
|
||||
steps:
|
||||
- task: PowerShell@2
|
||||
displayName: Darc gather-drop
|
||||
inputs:
|
||||
filePath: $(Build.SourcesDirectory)/eng/common/post-build/darc-gather-drop.ps1
|
||||
arguments: -BarBuildId $(BARBuildId)
|
||||
-DropLocation $(Agent.BuildDirectory)/Temp/Drop/
|
||||
-MaestroApiAccessToken $(MaestroApiAccessToken)
|
||||
-MaestroApiEndPoint $(MaestroApiEndPoint)
|
||||
-MaestroApiVersion $(MaestroApiVersion)
|
||||
|
|
@ -7,9 +7,12 @@ parameters:
|
|||
enable: false
|
||||
params: ''
|
||||
|
||||
# Which stages should finish execution before post-build stages start
|
||||
dependsOn: [build]
|
||||
|
||||
stages:
|
||||
- stage: validate
|
||||
dependsOn: build
|
||||
dependsOn: ${{ parameters.dependsOn }}
|
||||
displayName: Validate
|
||||
jobs:
|
||||
- ${{ if eq(parameters.enableNugetValidation, 'true') }}:
|
||||
|
|
@ -80,10 +83,18 @@ stages:
|
|||
parameters:
|
||||
additionalParameters: ${{ parameters.SDLValidationParameters.params }}
|
||||
|
||||
- template: \eng\common\templates\post-build\channels\netcore-dev-5.yml
|
||||
parameters:
|
||||
enableSymbolValidation: ${{ parameters.enableSymbolValidation }}
|
||||
|
||||
- template: \eng\common\templates\post-build\channels\public-dev-release.yml
|
||||
parameters:
|
||||
enableSymbolValidation: ${{ parameters.enableSymbolValidation }}
|
||||
|
||||
- template: \eng\common\templates\post-build\channels\netcore-tools-latest.yml
|
||||
parameters:
|
||||
enableSymbolValidation: ${{ parameters.enableSymbolValidation }}
|
||||
|
||||
- template: \eng\common\templates\post-build\channels\public-validation-release.yml
|
||||
|
||||
- template: \eng\common\templates\post-build\channels\public-release.yml
|
||||
|
|
|
|||
|
|
@ -5,13 +5,12 @@ jobs:
|
|||
- job:
|
||||
displayName: Promote Build
|
||||
dependsOn: setupMaestroVars
|
||||
condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], ${{ parameters.ChannelId }})
|
||||
condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', ${{ parameters.ChannelId }}))
|
||||
variables:
|
||||
- name: BARBuildId
|
||||
value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.BARBuildId'] ]
|
||||
- name: ChannelId
|
||||
value: ${{ parameters.ChannelId }}
|
||||
- group: Publish-Build-Assets
|
||||
pool:
|
||||
vmImage: 'windows-2019'
|
||||
steps:
|
||||
|
|
@ -21,4 +20,6 @@ jobs:
|
|||
filePath: $(Build.SourcesDirectory)/eng/common/post-build/promote-build.ps1
|
||||
arguments: -BuildId $(BARBuildId)
|
||||
-ChannelId $(ChannelId)
|
||||
-BarToken $(MaestroAccessToken)
|
||||
-MaestroApiAccessToken $(MaestroApiAccessToken)
|
||||
-MaestroApiEndPoint $(MaestroApiEndPoint)
|
||||
-MaestroApiVersion $(MaestroApiVersion)
|
||||
|
|
|
|||
|
|
@ -14,22 +14,5 @@ jobs:
|
|||
name: setReleaseVars
|
||||
displayName: Set Release Configs Vars
|
||||
inputs:
|
||||
targetType: inline
|
||||
script: |
|
||||
# This is needed to make Write-PipelineSetVariable works in this context
|
||||
$ci = $true
|
||||
|
||||
. "$(Build.SourcesDirectory)/eng/common/tools.ps1"
|
||||
|
||||
$Content = Get-Content "$(Build.StagingDirectory)/ReleaseConfigs/ReleaseConfigs.txt"
|
||||
|
||||
$BarId = $Content | Select -Index 0
|
||||
|
||||
$Channels = ""
|
||||
$Content | Select -Index 1 | ForEach-Object { $Channels += "$_ ," }
|
||||
|
||||
$IsStableBuild = $Content | Select -Index 2
|
||||
|
||||
Write-PipelineSetVariable -Name 'BARBuildId' -Value $BarId
|
||||
Write-PipelineSetVariable -Name 'InitialChannels' -Value "$Channels"
|
||||
Write-PipelineSetVariable -Name 'IsStableBuild' -Value $IsStableBuild
|
||||
filePath: $(Build.SourcesDirectory)/eng/common/post-build/setup-maestro-vars.ps1
|
||||
arguments: -ReleaseConfigsPath '$(Build.StagingDirectory)/ReleaseConfigs/ReleaseConfigs.txt'
|
||||
|
|
|
|||
|
|
@ -8,4 +8,6 @@ steps:
|
|||
filePath: $(Build.SourcesDirectory)/eng/common/post-build/trigger-subscriptions.ps1
|
||||
arguments: -SourceRepo $(Build.Repository.Uri)
|
||||
-ChannelId ${{ parameters.ChannelId }}
|
||||
-BarToken $(MaestroAccessTokenInt)
|
||||
-MaestroApiAccessToken $(MaestroAccessToken)
|
||||
-MaestroApiEndPoint $(MaestroApiEndPoint)
|
||||
-MaestroApiVersion $(MaestroApiVersion)
|
||||
|
|
|
|||
|
|
@ -39,6 +39,10 @@
|
|||
# installed on the machine instead of downloading one.
|
||||
[bool]$useInstalledDotNetCli = if (Test-Path variable:useInstalledDotNetCli) { $useInstalledDotNetCli } else { $true }
|
||||
|
||||
# Enable repos to use a particular version of the on-line dotnet-install scripts.
|
||||
# default URL: https://dot.net/v1/dotnet-install.ps1
|
||||
[string]$dotnetInstallScriptVersion = if (Test-Path variable:dotnetInstallScriptVersion) { $dotnetInstallScriptVersion } else { "v1" }
|
||||
|
||||
# True to use global NuGet cache instead of restoring packages to repository-local directory.
|
||||
[bool]$useGlobalNuGetCache = if (Test-Path variable:useGlobalNuGetCache) { $useGlobalNuGetCache } else { !$ci }
|
||||
|
||||
|
|
@ -159,7 +163,7 @@ function GetDotNetInstallScript([string] $dotnetRoot) {
|
|||
$installScript = Join-Path $dotnetRoot "dotnet-install.ps1"
|
||||
if (!(Test-Path $installScript)) {
|
||||
Create-Directory $dotnetRoot
|
||||
Invoke-WebRequest "https://dot.net/v1/dotnet-install.ps1" -OutFile $installScript
|
||||
Invoke-WebRequest "https://dot.net/$dotnetInstallScriptVersion/dotnet-install.ps1" -OutFile $installScript
|
||||
}
|
||||
|
||||
return $installScript
|
||||
|
|
@ -518,6 +522,9 @@ function MSBuild-Core() {
|
|||
if ($warnAsError) {
|
||||
$cmdArgs += " /warnaserror /p:TreatWarningsAsErrors=true"
|
||||
}
|
||||
else {
|
||||
$cmdArgs += " /p:TreatWarningsAsErrors=false"
|
||||
}
|
||||
|
||||
foreach ($arg in $args) {
|
||||
if ($arg -ne $null -and $arg.Trim() -ne "") {
|
||||
|
|
|
|||
|
|
@ -45,6 +45,10 @@ warn_as_error=${warn_as_error:-true}
|
|||
# installed on the machine instead of downloading one.
|
||||
use_installed_dotnet_cli=${use_installed_dotnet_cli:-true}
|
||||
|
||||
# Enable repos to use a particular version of the on-line dotnet-install scripts.
|
||||
# default URL: https://dot.net/v1/dotnet-install.sh
|
||||
dotnetInstallScriptVersion=${dotnetInstallScriptVersion:-'v1'}
|
||||
|
||||
# True to use global NuGet cache instead of restoring packages to repository-local directory.
|
||||
if [[ "$ci" == true ]]; then
|
||||
use_global_nuget_cache=${use_global_nuget_cache:-false}
|
||||
|
|
@ -77,7 +81,7 @@ function ReadGlobalVersion {
|
|||
local pattern="\"$key\" *: *\"(.*)\""
|
||||
|
||||
if [[ ! $line =~ $pattern ]]; then
|
||||
Write-PipelineTelemetryError -category 'InitializeTools' "Error: Cannot find \"$key\" in $global_json_file"
|
||||
Write-PipelineTelemetryError -category 'InitializeToolset' "Error: Cannot find \"$key\" in $global_json_file"
|
||||
ExitWithExitCode 1
|
||||
fi
|
||||
|
||||
|
|
@ -195,7 +199,7 @@ function InstallDotNet {
|
|||
function GetDotNetInstallScript {
|
||||
local root=$1
|
||||
local install_script="$root/dotnet-install.sh"
|
||||
local install_script_url="https://dot.net/v1/dotnet-install.sh"
|
||||
local install_script_url="https://dot.net/$dotnetInstallScriptVersion/dotnet-install.sh"
|
||||
|
||||
if [[ ! -a "$install_script" ]]; then
|
||||
mkdir -p "$root"
|
||||
|
|
@ -245,7 +249,7 @@ function InitializeNativeTools() {
|
|||
then
|
||||
local nativeArgs=""
|
||||
if [[ "$ci" == true ]]; then
|
||||
nativeArgs="-InstallDirectory $tools_dir"
|
||||
nativeArgs="--installDirectory $tools_dir"
|
||||
fi
|
||||
"$_script_dir/init-tools-native.sh" $nativeArgs
|
||||
fi
|
||||
|
|
|
|||
|
|
@ -166,11 +166,6 @@ try {
|
|||
& dotnet run -p "$repoRoot/eng/tools/BaselineGenerator/"
|
||||
}
|
||||
|
||||
Write-Host "Re-generating Web.JS files"
|
||||
Invoke-Block {
|
||||
& dotnet build "$repoRoot\src\Components\Web.JS\Microsoft.AspNetCore.Components.Web.JS.npmproj"
|
||||
}
|
||||
|
||||
Write-Host "Run git diff to check for pending changes"
|
||||
|
||||
# Redirect stderr to stdout because PowerShell does not consistently handle output to stderr
|
||||
|
|
|
|||
|
|
@ -11,15 +11,28 @@
|
|||
<IntermediateOutputPath>$([MSBuild]::NormalizeDirectory('$(BaseIntermediateOutputPath)'))$(Configuration)\</IntermediateOutputPath>
|
||||
<InstallArgs Condition="'$(RestoreLockedMode)' == 'true'">--frozen-lockfile</InstallArgs>
|
||||
<_BackupPackageJson>$(IntermediateOutputPath)$(MSBuildProjectName).package.json.bak</_BackupPackageJson>
|
||||
<BuildDependsOn>
|
||||
PrepareForBuild;
|
||||
ResolveProjectReferences;
|
||||
_Build;
|
||||
</BuildDependsOn>
|
||||
<NpmBuildArgs Condition="'$(NpmBuildArgs)' == ''">run build</NpmBuildArgs>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<TSFiles Include="$(MSBuildProjectDirectory)\*\*.ts" />
|
||||
<TSFiles Include="$(MSBuildProjectDirectory)\package.json" />
|
||||
<TSFiles Include="$(MSBuildProjectDirectory)\*.npmproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="_CheckForInvalidConfiguration">
|
||||
<Error Text="Missing expected property: PackageId" Condition="'$(IsPackable)' != 'false' and '$(PackageId)' == ''" />
|
||||
|
||||
<Exec ContinueOnError="true" Command="node -v">
|
||||
<Output TaskParameter="ExitCode" PropertyName="ErrorCode"/>
|
||||
</Exec>
|
||||
|
||||
<Error Text="Building *.npmproj but NodeJS was not detected on path. Ensure NodeJS is on path or disable building NodeJS projects with /p:BuildNodeJs=false. Skipping NodeJS projects will also skip managed projects depending on them, including Components, Mvc and Analysers." Condition="'$(ErrorCode)' != '0'"/>
|
||||
</Target>
|
||||
|
||||
<Target Name="Restore">
|
||||
|
|
@ -36,13 +49,13 @@
|
|||
BuildInParallel="true" />
|
||||
</Target>
|
||||
|
||||
<Target Name="Build" DependsOnTargets="PrepareForBuild;ResolveProjectReferences;_Build" />
|
||||
<Target Name="Build" DependsOnTargets="$(BuildDependsOn)" />
|
||||
|
||||
<Target Name="_Build"
|
||||
Condition="'$(IsBuildable)' != 'false'"
|
||||
Inputs="@(TSFiles)"
|
||||
Outputs="$(BaseIntermediateOutputPath)\build-sentinel" >
|
||||
<Yarn Command="run build" StandardOutputImportance="High" StandardErrorImportance="High" />
|
||||
<Yarn Command="$(NpmBuildArgs)" StandardOutputImportance="High" StandardErrorImportance="High" />
|
||||
<WriteLinesToFile Overwrite="true" File="$(BaseIntermediateOutputPath)\build-sentinel" />
|
||||
</Target>
|
||||
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@
|
|||
},
|
||||
"msbuild-sdks": {
|
||||
"Yarn.MSBuild": "1.15.2",
|
||||
"Microsoft.DotNet.Arcade.Sdk": "1.0.0-beta.19369.2",
|
||||
"Microsoft.DotNet.Helix.Sdk": "2.0.0-beta.19369.2"
|
||||
"Microsoft.DotNet.Arcade.Sdk": "1.0.0-beta.19404.1",
|
||||
"Microsoft.DotNet.Helix.Sdk": "2.0.0-beta.19404.1"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,39 @@
|
|||
// 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.Immutable;
|
||||
using Microsoft.AspNetCore.Components.Analyzers;
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.CodeAnalysis.Diagnostics;
|
||||
|
||||
namespace Microsoft.Extensions.Internal
|
||||
{
|
||||
[DiagnosticAnalyzer(LanguageNames.CSharp)]
|
||||
public class ComponentInternalUsageDiagnosticAnalyzer : DiagnosticAnalyzer
|
||||
{
|
||||
private readonly InternalUsageAnalyzer _inner;
|
||||
|
||||
public ComponentInternalUsageDiagnosticAnalyzer()
|
||||
{
|
||||
// We don't have in *internal* attribute in Blazor.
|
||||
_inner = new InternalUsageAnalyzer(IsInInternalNamespace, hasInternalAttribute: null, DiagnosticDescriptors.DoNotUseRenderTreeTypes);
|
||||
}
|
||||
|
||||
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(DiagnosticDescriptors.DoNotUseRenderTreeTypes);
|
||||
|
||||
public override void Initialize(AnalysisContext context)
|
||||
{
|
||||
_inner.Register(context);
|
||||
}
|
||||
|
||||
private static bool IsInInternalNamespace(ISymbol symbol)
|
||||
{
|
||||
if (symbol?.ContainingNamespace?.ToDisplayString() is string ns)
|
||||
{
|
||||
return string.Equals(ns, "Microsoft.AspNetCore.Components.RenderTree");
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -55,5 +55,14 @@ namespace Microsoft.AspNetCore.Components.Analyzers
|
|||
DiagnosticSeverity.Warning,
|
||||
isEnabledByDefault: true,
|
||||
description: new LocalizableResourceString(nameof(Resources.ComponentParameterShouldNotBeSetOutsideOfTheirDeclaredComponent_Description), Resources.ResourceManager, typeof(Resources)));
|
||||
|
||||
public static readonly DiagnosticDescriptor DoNotUseRenderTreeTypes = new DiagnosticDescriptor(
|
||||
"BL0006",
|
||||
new LocalizableResourceString(nameof(Resources.DoNotUseRenderTreeTypes_Title), Resources.ResourceManager, typeof(Resources)),
|
||||
new LocalizableResourceString(nameof(Resources.DoNotUseRenderTreeTypes_Description), Resources.ResourceManager, typeof(Resources)),
|
||||
"Usage",
|
||||
DiagnosticSeverity.Warning,
|
||||
isEnabledByDefault: true,
|
||||
description: new LocalizableResourceString(nameof(Resources.DoNotUseRenderTreeTypes_Description), Resources.ResourceManager, typeof(Resources)));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,126 @@
|
|||
// 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.CodeAnalysis;
|
||||
using Microsoft.CodeAnalysis.CSharp;
|
||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||
using Microsoft.CodeAnalysis.Diagnostics;
|
||||
|
||||
namespace Microsoft.Extensions.Internal
|
||||
{
|
||||
internal class InternalUsageAnalyzer
|
||||
{
|
||||
private readonly Func<ISymbol, bool> _isInternalNamespace;
|
||||
private readonly Func<ISymbol, bool> _hasInternalAttribute;
|
||||
private readonly DiagnosticDescriptor _descriptor;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of <see cref="InternalUsageAnalyzer" />. The creator should provide delegates to help determine whether
|
||||
/// a given symbol is internal or not, and a <see cref="DiagnosticDescriptor" /> to create errors.
|
||||
/// </summary>
|
||||
/// <param name="isInInternalNamespace">The delegate used to check if a symbol belongs to an internal namespace.</param>
|
||||
/// <param name="hasInternalAttribute">The delegate used to check if a symbol has an internal attribute.</param>
|
||||
/// <param name="descriptor">
|
||||
/// The <see cref="DiagnosticDescriptor" /> used to create errors. The error message should expect a single parameter
|
||||
/// used for the display name of the member.
|
||||
/// </param>
|
||||
public InternalUsageAnalyzer(Func<ISymbol, bool> isInInternalNamespace, Func<ISymbol, bool> hasInternalAttribute, DiagnosticDescriptor descriptor)
|
||||
{
|
||||
_isInternalNamespace = isInInternalNamespace ?? new Func<ISymbol, bool>((_) => false);
|
||||
_hasInternalAttribute = hasInternalAttribute ?? new Func<ISymbol, bool>((_) => false);
|
||||
_descriptor = descriptor ?? throw new ArgumentNullException(nameof(descriptor));
|
||||
}
|
||||
|
||||
public void Register(AnalysisContext context)
|
||||
{
|
||||
context.EnableConcurrentExecution();
|
||||
context.RegisterSyntaxNodeAction(AnalyzeNode,
|
||||
SyntaxKind.SimpleMemberAccessExpression,
|
||||
SyntaxKind.ObjectCreationExpression,
|
||||
SyntaxKind.ClassDeclaration,
|
||||
SyntaxKind.Parameter);
|
||||
}
|
||||
|
||||
private void AnalyzeNode(SyntaxNodeAnalysisContext context)
|
||||
{
|
||||
switch (context.Node)
|
||||
{
|
||||
case MemberAccessExpressionSyntax memberAccessSyntax:
|
||||
{
|
||||
if (context.SemanticModel.GetSymbolInfo(context.Node, context.CancellationToken).Symbol is ISymbol symbol &&
|
||||
symbol.ContainingAssembly != context.Compilation.Assembly)
|
||||
{
|
||||
var containingType = symbol.ContainingType;
|
||||
|
||||
if (HasInternalAttribute(symbol))
|
||||
{
|
||||
context.ReportDiagnostic(Diagnostic.Create(_descriptor, memberAccessSyntax.Name.GetLocation(), $"{containingType}.{symbol.Name}"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (IsInInternalNamespace(containingType) || HasInternalAttribute(containingType))
|
||||
{
|
||||
context.ReportDiagnostic(Diagnostic.Create(_descriptor, memberAccessSyntax.Name.GetLocation(), containingType));
|
||||
return;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
case ObjectCreationExpressionSyntax creationSyntax:
|
||||
{
|
||||
if (context.SemanticModel.GetSymbolInfo(context.Node, context.CancellationToken).Symbol is ISymbol symbol &&
|
||||
symbol.ContainingAssembly != context.Compilation.Assembly)
|
||||
{
|
||||
var containingType = symbol.ContainingType;
|
||||
|
||||
if (HasInternalAttribute(symbol))
|
||||
{
|
||||
context.ReportDiagnostic(Diagnostic.Create(_descriptor, creationSyntax.GetLocation(), containingType));
|
||||
return;
|
||||
}
|
||||
|
||||
if (IsInInternalNamespace(containingType) || HasInternalAttribute(containingType))
|
||||
{
|
||||
context.ReportDiagnostic(Diagnostic.Create(_descriptor, creationSyntax.Type.GetLocation(), containingType));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
case ClassDeclarationSyntax declarationSyntax:
|
||||
{
|
||||
if (context.SemanticModel.GetDeclaredSymbol(declarationSyntax)?.BaseType is ISymbol symbol &&
|
||||
symbol.ContainingAssembly != context.Compilation.Assembly &&
|
||||
(IsInInternalNamespace(symbol) || HasInternalAttribute(symbol)) &&
|
||||
declarationSyntax.BaseList?.Types.Count > 0)
|
||||
{
|
||||
context.ReportDiagnostic(Diagnostic.Create(_descriptor, declarationSyntax.BaseList.Types[0].GetLocation(), symbol));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
case ParameterSyntax parameterSyntax:
|
||||
{
|
||||
if (context.SemanticModel.GetDeclaredSymbol(parameterSyntax)?.Type is ISymbol symbol &&
|
||||
symbol.ContainingAssembly != context.Compilation.Assembly &&
|
||||
(IsInInternalNamespace(symbol) || HasInternalAttribute(symbol)))
|
||||
{
|
||||
|
||||
context.ReportDiagnostic(Diagnostic.Create(_descriptor, parameterSyntax.GetLocation(), symbol));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool HasInternalAttribute(ISymbol symbol) => _hasInternalAttribute(symbol);
|
||||
|
||||
private bool IsInInternalNamespace(ISymbol symbol) => _isInternalNamespace(symbol);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,17 +1,17 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
|
||||
Example:
|
||||
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
|
|
@ -26,36 +26,36 @@
|
|||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
|
|
@ -165,4 +165,13 @@
|
|||
<data name="ComponentParameterShouldNotBeSetOutsideOfTheirDeclaredComponent_Title" xml:space="preserve">
|
||||
<value>Component parameter should not be set outside of its component.</value>
|
||||
</data>
|
||||
<data name="DoNotUseRenderTreeTypes_Description" xml:space="preserve">
|
||||
<value>The types in 'Microsoft.AspNetCore.Components.RenderTree' are not recommended for use outside of the Blazor framework. These type definitions will change in future releases.</value>
|
||||
</data>
|
||||
<data name="DoNotUseRenderTreeTypes_Format" xml:space="preserve">
|
||||
<value>The type or member {0} is is not recommended for use outside of the Blazor frameworks. Types defined in 'Microsoft.AspNetCore.Components.RenderTree' will change in future releases.</value>
|
||||
</data>
|
||||
<data name="DoNotUseRenderTreeTypes_Title" xml:space="preserve">
|
||||
<value>Do not use RenderTree types</value>
|
||||
</data>
|
||||
</root>
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
// 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.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Analyzer.Testing;
|
||||
using Microsoft.AspNetCore.Testing;
|
||||
using Microsoft.AspNetCore.Testing.xunit;
|
||||
using Microsoft.CodeAnalysis;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.Analyzers
|
||||
{
|
||||
public abstract class AnalyzerTestBase
|
||||
{
|
||||
private static readonly string ProjectDirectory = GetProjectDirectory();
|
||||
|
||||
public TestSource Read(string source)
|
||||
{
|
||||
if (!source.EndsWith(".cs"))
|
||||
{
|
||||
source = source + ".cs";
|
||||
}
|
||||
|
||||
var filePath = Path.Combine(ProjectDirectory, "TestFiles", GetType().Name, source);
|
||||
if (!File.Exists(filePath))
|
||||
{
|
||||
throw new FileNotFoundException($"TestFile {source} could not be found at {filePath}.", filePath);
|
||||
}
|
||||
|
||||
var fileContent = File.ReadAllText(filePath);
|
||||
return TestSource.Read(fileContent);
|
||||
}
|
||||
|
||||
public Project CreateProject(string source)
|
||||
{
|
||||
if (!source.EndsWith(".cs"))
|
||||
{
|
||||
source = source + ".cs";
|
||||
}
|
||||
|
||||
var read = Read(source);
|
||||
return DiagnosticProject.Create(GetType().Assembly, new[] { read.Source, });
|
||||
}
|
||||
|
||||
public Task<Compilation> CreateCompilationAsync(string source)
|
||||
{
|
||||
return CreateProject(source).GetCompilationAsync();
|
||||
}
|
||||
|
||||
private static string GetProjectDirectory()
|
||||
{
|
||||
// On helix we use the published test files
|
||||
if (SkipOnHelixAttribute.OnHelix())
|
||||
{
|
||||
return AppContext.BaseDirectory;
|
||||
}
|
||||
|
||||
// This test code needs to be updated to support distributed testing.
|
||||
// See https://github.com/aspnet/AspNetCore/issues/10422
|
||||
#pragma warning disable 0618
|
||||
var solutionDirectory = TestPathUtilities.GetSolutionRootDirectory("Components");
|
||||
#pragma warning restore 0618
|
||||
var projectDirectory = Path.Combine(solutionDirectory, "Analyzers", "test");
|
||||
return projectDirectory;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
// 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.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Analyzer.Testing;
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.CodeAnalysis.Diagnostics;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.Analyzers
|
||||
{
|
||||
internal class ComponentAnalyzerDiagnosticAnalyzerRunner : DiagnosticAnalyzerRunner
|
||||
{
|
||||
public ComponentAnalyzerDiagnosticAnalyzerRunner(DiagnosticAnalyzer analyzer)
|
||||
{
|
||||
Analyzer = analyzer;
|
||||
}
|
||||
|
||||
public DiagnosticAnalyzer Analyzer { get; }
|
||||
|
||||
public Task<Diagnostic[]> GetDiagnosticsAsync(string source)
|
||||
{
|
||||
return GetDiagnosticsAsync(sources: new[] { source }, Analyzer, Array.Empty<string>());
|
||||
}
|
||||
|
||||
public Task<Diagnostic[]> GetDiagnosticsAsync(Project project)
|
||||
{
|
||||
return GetDiagnosticsAsync(new[] { project }, Analyzer, Array.Empty<string>());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
// 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;
|
||||
using Microsoft.AspNetCore.Analyzer.Testing;
|
||||
using Microsoft.Extensions.Internal;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.Analyzers
|
||||
{
|
||||
public class ComponentInternalUsageDiagnoticsAnalyzerTest : AnalyzerTestBase
|
||||
{
|
||||
public ComponentInternalUsageDiagnoticsAnalyzerTest()
|
||||
{
|
||||
Analyzer = new ComponentInternalUsageDiagnosticAnalyzer();
|
||||
Runner = new ComponentAnalyzerDiagnosticAnalyzerRunner(Analyzer);
|
||||
}
|
||||
|
||||
private ComponentInternalUsageDiagnosticAnalyzer Analyzer { get; }
|
||||
private ComponentAnalyzerDiagnosticAnalyzerRunner Runner { get; }
|
||||
|
||||
[Fact]
|
||||
public async Task InternalUsage_FindsUseOfRenderTreeFrameAsParameter()
|
||||
{
|
||||
// Arrange
|
||||
var source = Read("UsesRenderTreeFrameAsParameter");
|
||||
|
||||
// Act
|
||||
var diagnostics = await Runner.GetDiagnosticsAsync(source.Source);
|
||||
|
||||
// Assert
|
||||
Assert.Collection(
|
||||
diagnostics,
|
||||
diagnostic =>
|
||||
{
|
||||
Assert.Same(DiagnosticDescriptors.DoNotUseRenderTreeTypes, diagnostic.Descriptor);
|
||||
AnalyzerAssert.DiagnosticLocation(source.DefaultMarkerLocation, diagnostic.Location);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task InternalUsage_FindsUseOfRenderTreeType()
|
||||
{
|
||||
// Arrange
|
||||
var source = Read("UsesRenderTreeFrameTypeAsLocal");
|
||||
|
||||
// Act
|
||||
var diagnostics = await Runner.GetDiagnosticsAsync(source.Source);
|
||||
|
||||
// Assert
|
||||
Assert.Collection(
|
||||
diagnostics,
|
||||
diagnostic =>
|
||||
{
|
||||
Assert.Same(DiagnosticDescriptors.DoNotUseRenderTreeTypes, diagnostic.Descriptor);
|
||||
AnalyzerAssert.DiagnosticLocation(source.DefaultMarkerLocation, diagnostic.Location);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,16 +2,24 @@
|
|||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.AspNetCore.Components" />
|
||||
<Reference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" />
|
||||
</ItemGroup>
|
||||
<!-- Tests do not work on Helix or when bin/ directory is not in project directory due to undeclared dependency on test content. -->
|
||||
<!-- https://github.com/aspnet/AspNetCore/issues/10422 -->
|
||||
<BuildHelixPayload>false</BuildHelixPayload>
|
||||
<BaseOutputPath />
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<!-- This is set to a ProjectReference because analyzers cannot be referenced via Reference. -->
|
||||
<ProjectReference Include="..\src\Microsoft.AspNetCore.Components.Analyzers.csproj" />
|
||||
|
||||
<Reference Include="Microsoft.AspNetCore.Components" />
|
||||
<Reference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" />
|
||||
<Reference Include="Microsoft.AspNetCore.Analyzer.Testing" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="$(SharedSourceRoot)test\SkipOnHelixAttribute.cs" />
|
||||
<Content Include="TestFiles\**\*.*" CopyToPublishDirectory="PreserveNewest" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
using Microsoft.AspNetCore.Components.RenderTree;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.Analyzers.Tests.TestFiles.ComponentInternalUsageDiagnoticsAnalyzerTest
|
||||
{
|
||||
class UsesRenderTreeFrameAsParameter
|
||||
{
|
||||
private void Test(/*MM*/RenderTreeFrame frame)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
using System;
|
||||
using Microsoft.AspNetCore.Components.RenderTree;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.Analyzers.Tests.TestFiles.ComponentInternalUsageDiagnoticsAnalyzerTest
|
||||
{
|
||||
class UsesRenderTreeFrameTypeAsLocal
|
||||
{
|
||||
private void Test()
|
||||
{
|
||||
var test = RenderTreeFrameType./*MM*/Attribute;
|
||||
GC.KeepAlive(test);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -26,7 +26,7 @@
|
|||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Condition="'$(BuildNodeJS)' != 'false'" Include="$(RepoRoot)src\Components\Web.JS\Microsoft.AspNetCore.Components.Web.JS.npmproj" ReferenceOutputAssembly="false" />
|
||||
<ProjectReference Condition="'$(BuildNodeJS)' != 'false' and '$(BuildingInsideVisualStudio)' != 'true'" Include="$(RepoRoot)src\Components\Web.JS\Microsoft.AspNetCore.Components.Web.JS.npmproj" ReferenceOutputAssembly="false" />
|
||||
<Reference Include="Microsoft.AspNetCore.Components" />
|
||||
<Reference Include="Microsoft.Extensions.CommandLineUtils.Sources" />
|
||||
<Reference Include="Microsoft.Extensions.FileProviders.Composite" />
|
||||
|
|
|
|||
|
|
@ -1,5 +1,10 @@
|
|||
<Router AppAssembly="typeof(Program).Assembly">
|
||||
<Router AppAssembly="@typeof(Program).Assembly">
|
||||
<Found Context="routeData">
|
||||
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
|
||||
</Found>
|
||||
<NotFound>
|
||||
<p>Sorry, there's nothing at this address.</p>
|
||||
<LayoutView Layout="@typeof(MainLayout)">
|
||||
<p>Sorry, there's nothing at this address.</p>
|
||||
</LayoutView>
|
||||
</NotFound>
|
||||
</Router>
|
||||
|
|
|
|||
|
|
@ -1 +0,0 @@
|
|||
@layout MainLayout
|
||||
|
|
@ -1 +1,8 @@
|
|||
<Router AppAssembly=typeof(Program).Assembly />
|
||||
<Router AppAssembly=typeof(Program).Assembly>
|
||||
<Found Context="routeData">
|
||||
<RouteView RouteData="@routeData" />
|
||||
</Found>
|
||||
<NotFound>
|
||||
Sorry, there's nothing here.
|
||||
</NotFound>
|
||||
</Router>
|
||||
|
|
|
|||
|
|
@ -11,7 +11,4 @@
|
|||
<!-- loader.js is hard-coded to assume it can load .pdbs regardless of Debug/Release configuration -->
|
||||
<BlazorEnableDebugging>true</BlazorEnableDebugging>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,11 @@
|
|||
<!--
|
||||
Configuring this stuff here is temporary. Later we'll move the app config
|
||||
into Program.cs, and it won't be necessary to specify AppAssembly.
|
||||
-->
|
||||
<Router AppAssembly=typeof(StandaloneApp.Program).Assembly />
|
||||
<Router AppAssembly=typeof(StandaloneApp.Program).Assembly>
|
||||
<Found Context="routeData">
|
||||
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
|
||||
</Found>
|
||||
<NotFound>
|
||||
<LayoutView Layout="@typeof(MainLayout)">
|
||||
<h2>Not found</h2>
|
||||
Sorry, there's nothing at this address.
|
||||
</LayoutView>
|
||||
</NotFound>
|
||||
</Router>
|
||||
|
|
|
|||
|
|
@ -1 +0,0 @@
|
|||
@layout MainLayout
|
||||
|
|
@ -16,6 +16,15 @@ namespace Microsoft.AspNetCore.Components
|
|||
public abstract System.Threading.Tasks.Task<Microsoft.AspNetCore.Components.AuthenticationState> GetAuthenticationStateAsync();
|
||||
protected void NotifyAuthenticationStateChanged(System.Threading.Tasks.Task<Microsoft.AspNetCore.Components.AuthenticationState> task) { }
|
||||
}
|
||||
public sealed partial class AuthorizeRouteView : Microsoft.AspNetCore.Components.RouteView
|
||||
{
|
||||
public AuthorizeRouteView() { }
|
||||
[Microsoft.AspNetCore.Components.ParameterAttribute]
|
||||
public Microsoft.AspNetCore.Components.RenderFragment Authorizing { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
|
||||
[Microsoft.AspNetCore.Components.ParameterAttribute]
|
||||
public Microsoft.AspNetCore.Components.RenderFragment<Microsoft.AspNetCore.Components.AuthenticationState> NotAuthorized { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
|
||||
protected override void Render(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder builder) { }
|
||||
}
|
||||
public partial class AuthorizeView : Microsoft.AspNetCore.Components.AuthorizeViewCore
|
||||
{
|
||||
public AuthorizeView() { }
|
||||
|
|
@ -278,6 +287,16 @@ 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 partial class LayoutView : Microsoft.AspNetCore.Components.IComponent
|
||||
{
|
||||
public LayoutView() { }
|
||||
[Microsoft.AspNetCore.Components.ParameterAttribute]
|
||||
public Microsoft.AspNetCore.Components.RenderFragment ChildContent { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
|
||||
[Microsoft.AspNetCore.Components.ParameterAttribute]
|
||||
public System.Type Layout { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
|
||||
public void Attach(Microsoft.AspNetCore.Components.RenderHandle renderHandle) { }
|
||||
public System.Threading.Tasks.Task SetParametersAsync(Microsoft.AspNetCore.Components.ParameterView parameters) { throw null; }
|
||||
}
|
||||
public sealed partial class LocationChangeException : System.Exception
|
||||
{
|
||||
public LocationChangeException(string message, System.Exception innerException) { }
|
||||
|
|
@ -323,20 +342,6 @@ namespace Microsoft.AspNetCore.Components
|
|||
protected OwningComponentBase() { }
|
||||
protected TService Service { get { throw null; } }
|
||||
}
|
||||
public partial class PageDisplay : Microsoft.AspNetCore.Components.IComponent
|
||||
{
|
||||
public PageDisplay() { }
|
||||
[Microsoft.AspNetCore.Components.ParameterAttribute]
|
||||
public Microsoft.AspNetCore.Components.RenderFragment Authorizing { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
|
||||
[Microsoft.AspNetCore.Components.ParameterAttribute]
|
||||
public Microsoft.AspNetCore.Components.RenderFragment<Microsoft.AspNetCore.Components.AuthenticationState> NotAuthorized { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
|
||||
[Microsoft.AspNetCore.Components.ParameterAttribute]
|
||||
public System.Type Page { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
|
||||
[Microsoft.AspNetCore.Components.ParameterAttribute]
|
||||
public System.Collections.Generic.IDictionary<string, object> PageParameters { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
|
||||
public void Attach(Microsoft.AspNetCore.Components.RenderHandle renderHandle) { }
|
||||
public System.Threading.Tasks.Task SetParametersAsync(Microsoft.AspNetCore.Components.ParameterView parameters) { throw null; }
|
||||
}
|
||||
[System.AttributeUsageAttribute(System.AttributeTargets.Property, AllowMultiple=false, Inherited=true)]
|
||||
public sealed partial class ParameterAttribute : System.Attribute
|
||||
{
|
||||
|
|
@ -391,6 +396,23 @@ namespace Microsoft.AspNetCore.Components
|
|||
public RouteAttribute(string template) { }
|
||||
public string Template { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } }
|
||||
}
|
||||
public sealed partial class RouteData
|
||||
{
|
||||
public RouteData(System.Type pageType, System.Collections.Generic.IReadOnlyDictionary<string, object> routeValues) { }
|
||||
public System.Type PageType { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } }
|
||||
public System.Collections.Generic.IReadOnlyDictionary<string, object> RouteValues { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } }
|
||||
}
|
||||
public partial class RouteView : Microsoft.AspNetCore.Components.IComponent
|
||||
{
|
||||
public RouteView() { }
|
||||
[Microsoft.AspNetCore.Components.ParameterAttribute]
|
||||
public System.Type DefaultLayout { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
|
||||
[Microsoft.AspNetCore.Components.ParameterAttribute]
|
||||
public Microsoft.AspNetCore.Components.RouteData RouteData { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
|
||||
public void Attach(Microsoft.AspNetCore.Components.RenderHandle renderHandle) { }
|
||||
protected virtual void Render(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder builder) { }
|
||||
public System.Threading.Tasks.Task SetParametersAsync(Microsoft.AspNetCore.Components.ParameterView parameters) { throw null; }
|
||||
}
|
||||
}
|
||||
namespace Microsoft.AspNetCore.Components.CompilerServices
|
||||
{
|
||||
|
|
@ -513,13 +535,13 @@ namespace Microsoft.AspNetCore.Components.Rendering
|
|||
public Renderer(System.IServiceProvider serviceProvider, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory) { }
|
||||
public abstract Microsoft.AspNetCore.Components.Dispatcher Dispatcher { get; }
|
||||
public event System.UnhandledExceptionEventHandler UnhandledSynchronizationException { add { } remove { } }
|
||||
protected internal virtual void AddToRenderQueue(int componentId, Microsoft.AspNetCore.Components.RenderFragment renderFragment) { }
|
||||
protected internal int AssignRootComponentId(Microsoft.AspNetCore.Components.IComponent component) { throw null; }
|
||||
public virtual System.Threading.Tasks.Task DispatchEventAsync(ulong eventHandlerId, Microsoft.AspNetCore.Components.Rendering.EventFieldInfo fieldInfo, System.EventArgs eventArgs) { throw null; }
|
||||
public void Dispose() { }
|
||||
protected virtual void Dispose(bool disposing) { }
|
||||
protected abstract void HandleException(System.Exception exception);
|
||||
protected Microsoft.AspNetCore.Components.IComponent InstantiateComponent(System.Type componentType) { throw null; }
|
||||
protected virtual void ProcessPendingRender() { }
|
||||
protected System.Threading.Tasks.Task RenderRootComponentAsync(int componentId) { throw null; }
|
||||
[System.Diagnostics.DebuggerStepThroughAttribute]
|
||||
protected System.Threading.Tasks.Task RenderRootComponentAsync(int componentId, Microsoft.AspNetCore.Components.ParameterView initialParameters) { throw null; }
|
||||
|
|
@ -648,9 +670,7 @@ namespace Microsoft.AspNetCore.Components.Routing
|
|||
[Microsoft.AspNetCore.Components.ParameterAttribute]
|
||||
public System.Reflection.Assembly AppAssembly { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
|
||||
[Microsoft.AspNetCore.Components.ParameterAttribute]
|
||||
public Microsoft.AspNetCore.Components.RenderFragment Authorizing { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
|
||||
[Microsoft.AspNetCore.Components.ParameterAttribute]
|
||||
public Microsoft.AspNetCore.Components.RenderFragment<Microsoft.AspNetCore.Components.AuthenticationState> NotAuthorized { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
|
||||
public Microsoft.AspNetCore.Components.RenderFragment<Microsoft.AspNetCore.Components.RouteData> Found { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
|
||||
[Microsoft.AspNetCore.Components.ParameterAttribute]
|
||||
public Microsoft.AspNetCore.Components.RenderFragment NotFound { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
|
||||
public void Attach(Microsoft.AspNetCore.Components.RenderHandle renderHandle) { }
|
||||
|
|
|
|||
|
|
@ -0,0 +1,118 @@
|
|||
// 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;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Components.Auth;
|
||||
using Microsoft.AspNetCore.Components.Rendering;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Combines the behaviors of <see cref="AuthorizeView"/> and <see cref="RouteView"/>,
|
||||
/// so that it displays the page matching the specified route but only if the user
|
||||
/// is authorized to see it.
|
||||
///
|
||||
/// Additionally, this component supplies a cascading parameter of type <see cref="Task{AuthenticationState}"/>,
|
||||
/// which makes the user's current authentication state available to descendants.
|
||||
/// </summary>
|
||||
public sealed class AuthorizeRouteView : RouteView
|
||||
{
|
||||
// We expect applications to supply their own authorizing/not-authorized content, but
|
||||
// it's better to have defaults than to make the parameters mandatory because in some
|
||||
// cases they will never be used (e.g., "authorizing" in out-of-box server-side Blazor)
|
||||
private static readonly RenderFragment<AuthenticationState> _defaultNotAuthorizedContent
|
||||
= state => builder => builder.AddContent(0, "Not authorized");
|
||||
private static readonly RenderFragment _defaultAuthorizingContent
|
||||
= builder => builder.AddContent(0, "Authorizing...");
|
||||
|
||||
private readonly RenderFragment _renderAuthorizeRouteViewCoreDelegate;
|
||||
private readonly RenderFragment<AuthenticationState> _renderAuthorizedDelegate;
|
||||
private readonly RenderFragment<AuthenticationState> _renderNotAuthorizedDelegate;
|
||||
private readonly RenderFragment _renderAuthorizingDelegate;
|
||||
|
||||
public AuthorizeRouteView()
|
||||
{
|
||||
// Cache the rendering delegates so that we only construct new closure instances
|
||||
// when they are actually used (e.g., we never prepare a RenderFragment bound to
|
||||
// the NotAuthorized content except when you are displaying that particular state)
|
||||
RenderFragment renderBaseRouteViewDelegate = builder => base.Render(builder);
|
||||
_renderAuthorizedDelegate = authenticateState => renderBaseRouteViewDelegate;
|
||||
_renderNotAuthorizedDelegate = authenticationState => builder => RenderNotAuthorizedInDefaultLayout(builder, authenticationState);
|
||||
_renderAuthorizingDelegate = RenderAuthorizingInDefaultLayout;
|
||||
_renderAuthorizeRouteViewCoreDelegate = RenderAuthorizeRouteViewCore;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The content that will be displayed if the user is not authorized.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public RenderFragment<AuthenticationState> NotAuthorized { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The content that will be displayed while asynchronous authorization is in progress.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public RenderFragment Authorizing { get; set; }
|
||||
|
||||
[CascadingParameter]
|
||||
private Task<AuthenticationState> ExistingCascadedAuthenticationState { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Render(RenderTreeBuilder builder)
|
||||
{
|
||||
if (ExistingCascadedAuthenticationState != null)
|
||||
{
|
||||
// If this component is already wrapped in a <CascadingAuthenticationState> (or another
|
||||
// compatible provider), then don't interfere with the cascaded authentication state.
|
||||
_renderAuthorizeRouteViewCoreDelegate(builder);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Otherwise, implicitly wrap the output in a <CascadingAuthenticationState>
|
||||
builder.OpenComponent<CascadingAuthenticationState>(0);
|
||||
builder.AddAttribute(1, nameof(CascadingAuthenticationState.ChildContent), _renderAuthorizeRouteViewCoreDelegate);
|
||||
builder.CloseComponent();
|
||||
}
|
||||
}
|
||||
|
||||
private void RenderAuthorizeRouteViewCore(RenderTreeBuilder builder)
|
||||
{
|
||||
builder.OpenComponent<AuthorizeRouteViewCore>(0);
|
||||
builder.AddAttribute(1, nameof(AuthorizeRouteViewCore.RouteData), RouteData);
|
||||
builder.AddAttribute(2, nameof(AuthorizeRouteViewCore.Authorized), _renderAuthorizedDelegate);
|
||||
builder.AddAttribute(3, nameof(AuthorizeRouteViewCore.Authorizing), _renderAuthorizingDelegate);
|
||||
builder.AddAttribute(4, nameof(AuthorizeRouteViewCore.NotAuthorized), _renderNotAuthorizedDelegate);
|
||||
builder.CloseComponent();
|
||||
}
|
||||
|
||||
private void RenderContentInDefaultLayout(RenderTreeBuilder builder, RenderFragment content)
|
||||
{
|
||||
builder.OpenComponent<LayoutView>(0);
|
||||
builder.AddAttribute(1, nameof(LayoutView.Layout), DefaultLayout);
|
||||
builder.AddAttribute(2, nameof(LayoutView.ChildContent), content);
|
||||
builder.CloseComponent();
|
||||
}
|
||||
|
||||
private void RenderNotAuthorizedInDefaultLayout(RenderTreeBuilder builder, AuthenticationState authenticationState)
|
||||
{
|
||||
var content = NotAuthorized ?? _defaultNotAuthorizedContent;
|
||||
RenderContentInDefaultLayout(builder, content(authenticationState));
|
||||
}
|
||||
|
||||
private void RenderAuthorizingInDefaultLayout(RenderTreeBuilder builder)
|
||||
{
|
||||
var content = Authorizing ?? _defaultAuthorizingContent;
|
||||
RenderContentInDefaultLayout(builder, content);
|
||||
}
|
||||
|
||||
private class AuthorizeRouteViewCore : AuthorizeViewCore
|
||||
{
|
||||
[Parameter]
|
||||
public RouteData RouteData { get; set; }
|
||||
|
||||
protected override IAuthorizeData[] GetAuthorizeData()
|
||||
=> AttributeAuthorizeDataCache.GetAuthorizeDataForType(RouteData.PageType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -52,6 +52,8 @@ namespace Microsoft.AspNetCore.Components
|
|||
/// <inheritdoc />
|
||||
protected override void BuildRenderTree(RenderTreeBuilder builder)
|
||||
{
|
||||
// We're using the same sequence number for each of the content items here
|
||||
// so that we can update existing instances if they are the same shape
|
||||
if (currentAuthenticationState == null)
|
||||
{
|
||||
builder.AddContent(0, Authorizing);
|
||||
|
|
@ -59,11 +61,11 @@ namespace Microsoft.AspNetCore.Components
|
|||
else if (isAuthorized)
|
||||
{
|
||||
var authorized = Authorized ?? ChildContent;
|
||||
builder.AddContent(1, authorized?.Invoke(currentAuthenticationState));
|
||||
builder.AddContent(0, authorized?.Invoke(currentAuthenticationState));
|
||||
}
|
||||
else
|
||||
{
|
||||
builder.AddContent(2, NotAuthorized?.Invoke(currentAuthenticationState));
|
||||
builder.AddContent(0, NotAuthorized?.Invoke(currentAuthenticationState));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -102,6 +104,12 @@ namespace Microsoft.AspNetCore.Components
|
|||
private async Task<bool> IsAuthorizedAsync(ClaimsPrincipal user)
|
||||
{
|
||||
var authorizeData = GetAuthorizeData();
|
||||
if (authorizeData == null)
|
||||
{
|
||||
// No authorization applies, so no need to consult the authorization service
|
||||
return true;
|
||||
}
|
||||
|
||||
EnsureNoAuthenticationSchemeSpecified(authorizeData);
|
||||
|
||||
var policy = await AuthorizationPolicy.CombineAsync(
|
||||
|
|
|
|||
|
|
@ -171,10 +171,25 @@ namespace Microsoft.AspNetCore.Components
|
|||
_renderHandle = renderHandle;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Method invoked to apply initial or updated parameters to the component.
|
||||
/// Sets parameters supplied by the component's parent in the render tree.
|
||||
/// </summary>
|
||||
/// <param name="parameters">The parameters to apply.</param>
|
||||
/// <param name="parameters">The parameters.</param>
|
||||
/// <returns>A <see cref="Task"/> that completes when the component has finished updating and rendering itself.</returns>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// The <see cref="SetParametersAsync(ParameterView)"/> method should be passed the entire set of parameter values each
|
||||
/// time <see cref="SetParametersAsync(ParameterView)"/> is called. It not required that the caller supply a parameter
|
||||
/// value for all parameters that are logically understood by the component.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// The default implementation of <see cref="SetParametersAsync(ParameterView)"/> will set the value of each property
|
||||
/// decorated with <see cref="ParameterAttribute" /> or <see cref="CascadingParameterAttribute" /> that has
|
||||
/// a corresponding value in the <see cref="ParameterView" />. Parameters that do not have a corresponding value
|
||||
/// will be unchanged.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public virtual Task SetParametersAsync(ParameterView parameters)
|
||||
{
|
||||
parameters.SetParameterProperties(this);
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ namespace Microsoft.AspNetCore.Components
|
|||
(
|
||||
propertyName: property.Name,
|
||||
propertyType: property.PropertyType,
|
||||
setter: MemberAssignment.CreatePropertySetter(type, property)
|
||||
setter: MemberAssignment.CreatePropertySetter(type, property, cascading: false)
|
||||
)).ToArray();
|
||||
|
||||
return Initialize;
|
||||
|
|
|
|||
|
|
@ -21,6 +21,11 @@ namespace Microsoft.AspNetCore.Components
|
|||
/// </summary>
|
||||
/// <param name="parameters">The parameters.</param>
|
||||
/// <returns>A <see cref="Task"/> that completes when the component has finished updating and rendering itself.</returns>
|
||||
/// <remarks>
|
||||
/// The <see cref="SetParametersAsync(ParameterView)"/> method should be passed the entire set of parameter values each
|
||||
/// time <see cref="SetParametersAsync(ParameterView)"/> is called. It not required that the caller supply a parameter
|
||||
/// value for all parameters that are logically understood by the component.
|
||||
/// </remarks>
|
||||
Task SetParametersAsync(ParameterView parameters);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,77 @@
|
|||
// 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.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Displays the specified content inside the specified layout and any further
|
||||
/// nested layouts.
|
||||
/// </summary>
|
||||
public class LayoutView : IComponent
|
||||
{
|
||||
private static readonly RenderFragment EmptyRenderFragment = builder => { };
|
||||
|
||||
private RenderHandle _renderHandle;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the content to display.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public RenderFragment ChildContent { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the type of the layout in which to display the content.
|
||||
/// The type must implement <see cref="IComponent"/> and accept a parameter named <see cref="LayoutComponentBase.Body"/>.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public Type Layout { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Attach(RenderHandle renderHandle)
|
||||
{
|
||||
_renderHandle = renderHandle;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task SetParametersAsync(ParameterView parameters)
|
||||
{
|
||||
parameters.SetParameterProperties(this);
|
||||
Render();
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private void Render()
|
||||
{
|
||||
// In the middle goes the supplied content
|
||||
var fragment = ChildContent ?? EmptyRenderFragment;
|
||||
|
||||
// Then repeatedly wrap that in each layer of nested layout until we get
|
||||
// to a layout that has no parent
|
||||
var layoutType = Layout;
|
||||
while (layoutType != null)
|
||||
{
|
||||
fragment = WrapInLayout(layoutType, fragment);
|
||||
layoutType = GetParentLayoutType(layoutType);
|
||||
}
|
||||
|
||||
_renderHandle.Render(fragment);
|
||||
}
|
||||
|
||||
private static RenderFragment WrapInLayout(Type layoutType, RenderFragment bodyParam)
|
||||
{
|
||||
return builder =>
|
||||
{
|
||||
builder.OpenComponent(0, layoutType);
|
||||
builder.AddAttribute(1, LayoutComponentBase.BodyPropertyName, bodyParam);
|
||||
builder.CloseComponent();
|
||||
};
|
||||
}
|
||||
|
||||
private static Type GetParentLayoutType(Type type)
|
||||
=> type.GetCustomAttribute<LayoutAttribute>()?.LayoutType;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,139 +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.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Components.Auth;
|
||||
using Microsoft.AspNetCore.Components.Rendering;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Displays the specified page component, rendering it inside its layout
|
||||
/// and any further nested layouts, plus applying any authorization rules.
|
||||
/// </summary>
|
||||
public class PageDisplay : IComponent
|
||||
{
|
||||
private RenderHandle _renderHandle;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the type of the page component to display.
|
||||
/// The type must implement <see cref="IComponent"/>.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public Type Page { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the parameters to pass to the page.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public IDictionary<string, object> PageParameters { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The content that will be displayed if the user is not authorized.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public RenderFragment<AuthenticationState> NotAuthorized { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The content that will be displayed while asynchronous authorization is in progress.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public RenderFragment Authorizing { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Attach(RenderHandle renderHandle)
|
||||
{
|
||||
_renderHandle = renderHandle;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task SetParametersAsync(ParameterView parameters)
|
||||
{
|
||||
parameters.SetParameterProperties(this);
|
||||
Render();
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private void Render()
|
||||
{
|
||||
// In the middle goes the requested page
|
||||
var fragment = (RenderFragment)RenderPageWithParameters;
|
||||
|
||||
// Around that goes an AuthorizeViewCore
|
||||
fragment = WrapInAuthorizeViewCore(fragment);
|
||||
|
||||
// Then repeatedly wrap that in each layer of nested layout until we get
|
||||
// to a layout that has no parent
|
||||
Type layoutType = Page;
|
||||
while ((layoutType = GetLayoutType(layoutType)) != null)
|
||||
{
|
||||
fragment = WrapInLayout(layoutType, fragment);
|
||||
}
|
||||
|
||||
_renderHandle.Render(fragment);
|
||||
}
|
||||
|
||||
private RenderFragment WrapInLayout(Type layoutType, RenderFragment bodyParam) => builder =>
|
||||
{
|
||||
builder.OpenComponent(0, layoutType);
|
||||
builder.AddAttribute(1, LayoutComponentBase.BodyPropertyName, bodyParam);
|
||||
builder.CloseComponent();
|
||||
};
|
||||
|
||||
private void RenderPageWithParameters(RenderTreeBuilder builder)
|
||||
{
|
||||
builder.OpenComponent(0, Page);
|
||||
|
||||
if (PageParameters != null)
|
||||
{
|
||||
foreach (var kvp in PageParameters)
|
||||
{
|
||||
builder.AddAttribute(1, kvp.Key, kvp.Value);
|
||||
}
|
||||
}
|
||||
|
||||
builder.CloseComponent();
|
||||
}
|
||||
|
||||
private RenderFragment WrapInAuthorizeViewCore(RenderFragment pageFragment)
|
||||
{
|
||||
var authorizeData = AttributeAuthorizeDataCache.GetAuthorizeDataForType(Page);
|
||||
if (authorizeData == null)
|
||||
{
|
||||
// No authorization, so no need to wrap the fragment
|
||||
return pageFragment;
|
||||
}
|
||||
|
||||
// Some authorization data exists, so we do need to wrap the fragment
|
||||
RenderFragment<AuthenticationState> authorized = context => pageFragment;
|
||||
return builder =>
|
||||
{
|
||||
builder.OpenComponent<AuthorizeViewWithSuppliedData>(0);
|
||||
builder.AddAttribute(1, nameof(AuthorizeViewWithSuppliedData.AuthorizeDataParam), authorizeData);
|
||||
builder.AddAttribute(2, nameof(AuthorizeViewWithSuppliedData.Authorized), authorized);
|
||||
builder.AddAttribute(3, nameof(AuthorizeViewWithSuppliedData.NotAuthorized), NotAuthorized ?? DefaultNotAuthorized);
|
||||
builder.AddAttribute(4, nameof(AuthorizeViewWithSuppliedData.Authorizing), Authorizing);
|
||||
builder.CloseComponent();
|
||||
};
|
||||
}
|
||||
|
||||
private static Type GetLayoutType(Type type)
|
||||
=> type.GetCustomAttribute<LayoutAttribute>()?.LayoutType;
|
||||
|
||||
private class AuthorizeViewWithSuppliedData : AuthorizeViewCore
|
||||
{
|
||||
[Parameter] public IAuthorizeData[] AuthorizeDataParam { get; private set; }
|
||||
|
||||
protected override IAuthorizeData[] GetAuthorizeData() => AuthorizeDataParam;
|
||||
}
|
||||
|
||||
// There has to be some default content. If we render blank by default, developers
|
||||
// will find it hard to guess why their UI isn't appearing.
|
||||
private static RenderFragment DefaultNotAuthorized(AuthenticationState authenticationState)
|
||||
=> builder => builder.AddContent(0, "Not authorized");
|
||||
}
|
||||
}
|
||||
|
|
@ -14,6 +14,9 @@ namespace Microsoft.AspNetCore.Components.Reflection
|
|||
{
|
||||
private const BindingFlags _bindablePropertyFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.IgnoreCase;
|
||||
|
||||
// Right now it's not possible for a component to define a Parameter and a Cascading Parameter with
|
||||
// the same name. We don't give you a way to express this in code (would create duplicate properties),
|
||||
// and we don't have the ability to represent it in our data structures.
|
||||
private readonly static ConcurrentDictionary<Type, WritersForType> _cachedWritersByType
|
||||
= new ConcurrentDictionary<Type, WritersForType>();
|
||||
|
||||
|
|
@ -44,6 +47,24 @@ namespace Microsoft.AspNetCore.Components.Reflection
|
|||
ThrowForUnknownIncomingParameterName(targetType, parameterName);
|
||||
throw null; // Unreachable
|
||||
}
|
||||
else if (writer.Cascading && !parameter.Cascading)
|
||||
{
|
||||
// We don't allow you to set a cascading parameter with a non-cascading value. Put another way:
|
||||
// cascading parameters are not part of the public API of a component, so it's not reasonable
|
||||
// for someone to set it directly.
|
||||
//
|
||||
// If we find a strong reason for this to work in the future we can reverse our decision since
|
||||
// this throws today.
|
||||
ThrowForSettingCascadingParameterWithNonCascadingValue(targetType, parameterName);
|
||||
throw null; // Unreachable
|
||||
}
|
||||
else if (!writer.Cascading && parameter.Cascading)
|
||||
{
|
||||
// We're giving a more specific error here because trying to set a non-cascading parameter
|
||||
// with a cascading value is likely deliberate (but not supported), or is a bug in our code.
|
||||
ThrowForSettingParameterWithCascadingValue(targetType, parameterName);
|
||||
throw null; // Unreachable
|
||||
}
|
||||
|
||||
SetProperty(target, writer, parameterName, parameter.Value);
|
||||
}
|
||||
|
|
@ -62,7 +83,24 @@ namespace Microsoft.AspNetCore.Components.Reflection
|
|||
}
|
||||
|
||||
var isUnmatchedValue = !writers.WritersByName.TryGetValue(parameterName, out var writer);
|
||||
if (isUnmatchedValue)
|
||||
|
||||
if ((isUnmatchedValue && parameter.Cascading) || (writer != null && !writer.Cascading && parameter.Cascading))
|
||||
{
|
||||
// Don't allow an "extra" cascading value to be collected - or don't allow a non-cascading
|
||||
// parameter to be set with a cascading value.
|
||||
//
|
||||
// This is likely a bug in our infrastructure or an attempt to deliberately do something unsupported.
|
||||
ThrowForSettingParameterWithCascadingValue(targetType, parameterName);
|
||||
throw null; // Unreachable
|
||||
|
||||
}
|
||||
else if (isUnmatchedValue ||
|
||||
|
||||
// Allow unmatched parameters to collide with the names of cascading parameters. This is
|
||||
// valid because cascading parameter names are not part of the public API. There's no
|
||||
// way for the user of a component to know what the names of cascading parameters
|
||||
// are.
|
||||
(writer.Cascading && !parameter.Cascading))
|
||||
{
|
||||
unmatched ??= new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
|
||||
unmatched[parameterName] = parameter.Value;
|
||||
|
|
@ -138,6 +176,20 @@ namespace Microsoft.AspNetCore.Components.Reflection
|
|||
}
|
||||
}
|
||||
|
||||
private static void ThrowForSettingCascadingParameterWithNonCascadingValue(Type targetType, string parameterName)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
$"Object of type '{targetType.FullName}' has a property matching the name '{parameterName}', " +
|
||||
$"but it does not have [{nameof(ParameterAttribute)}] applied.");
|
||||
}
|
||||
|
||||
private static void ThrowForSettingParameterWithCascadingValue(Type targetType, string parameterName)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
$"The property '{parameterName}' on component type '{targetType.FullName}' cannot be set " +
|
||||
$"using a cascading value.");
|
||||
}
|
||||
|
||||
private static void ThrowForCaptureUnmatchedValuesConflict(Type targetType, string parameterName, Dictionary<string, object> unmatched)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
|
|
@ -179,13 +231,14 @@ namespace Microsoft.AspNetCore.Components.Reflection
|
|||
foreach (var propertyInfo in GetCandidateBindableProperties(targetType))
|
||||
{
|
||||
var parameterAttribute = propertyInfo.GetCustomAttribute<ParameterAttribute>();
|
||||
var isParameter = parameterAttribute != null || propertyInfo.IsDefined(typeof(CascadingParameterAttribute));
|
||||
var cascadingParameterAttribute = propertyInfo.GetCustomAttribute<CascadingParameterAttribute>();
|
||||
var isParameter = parameterAttribute != null || cascadingParameterAttribute != null;
|
||||
if (!isParameter)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var propertySetter = MemberAssignment.CreatePropertySetter(targetType, propertyInfo);
|
||||
var propertySetter = MemberAssignment.CreatePropertySetter(targetType, propertyInfo, cascading: cascadingParameterAttribute != null);
|
||||
|
||||
var propertyName = propertyInfo.Name;
|
||||
if (WritersByName.ContainsKey(propertyName))
|
||||
|
|
@ -213,7 +266,7 @@ namespace Microsoft.AspNetCore.Components.Reflection
|
|||
ThrowForInvalidCaptureUnmatchedValuesParameterType(targetType, propertyInfo);
|
||||
}
|
||||
|
||||
CaptureUnmatchedValuesWriter = MemberAssignment.CreatePropertySetter(targetType, propertyInfo);
|
||||
CaptureUnmatchedValuesWriter = MemberAssignment.CreatePropertySetter(targetType, propertyInfo, cascading: false);
|
||||
CaptureUnmatchedValuesPropertyName = propertyInfo.Name;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@ namespace Microsoft.AspNetCore.Components.Reflection
|
|||
{
|
||||
internal interface IPropertySetter
|
||||
{
|
||||
bool Cascading { get; }
|
||||
|
||||
void SetValue(object target, object value);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ namespace Microsoft.AspNetCore.Components.Reflection
|
|||
}
|
||||
}
|
||||
|
||||
public static IPropertySetter CreatePropertySetter(Type targetType, PropertyInfo property)
|
||||
public static IPropertySetter CreatePropertySetter(Type targetType, PropertyInfo property, bool cascading)
|
||||
{
|
||||
if (property.SetMethod == null)
|
||||
{
|
||||
|
|
@ -37,19 +37,23 @@ namespace Microsoft.AspNetCore.Components.Reflection
|
|||
|
||||
return (IPropertySetter)Activator.CreateInstance(
|
||||
typeof(PropertySetter<,>).MakeGenericType(targetType, property.PropertyType),
|
||||
property.SetMethod);
|
||||
property.SetMethod,
|
||||
cascading);
|
||||
}
|
||||
|
||||
class PropertySetter<TTarget, TValue> : IPropertySetter
|
||||
{
|
||||
private readonly Action<TTarget, TValue> _setterDelegate;
|
||||
|
||||
public PropertySetter(MethodInfo setMethod)
|
||||
public PropertySetter(MethodInfo setMethod, bool cascading)
|
||||
{
|
||||
_setterDelegate = (Action<TTarget, TValue>)Delegate.CreateDelegate(
|
||||
typeof(Action<TTarget, TValue>), setMethod);
|
||||
Cascading = cascading;
|
||||
}
|
||||
|
||||
public bool Cascading { get; }
|
||||
|
||||
public void SetValue(object target, object value)
|
||||
{
|
||||
if (value == null)
|
||||
|
|
|
|||
|
|
@ -8,9 +8,12 @@ using System.Collections.Generic;
|
|||
namespace Microsoft.AspNetCore.Components.RenderTree
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a range of elements within an instance of <see cref="ArrayBuilder{T}"/>.
|
||||
/// Types in the Microsoft.AspNetCore.Components.RenderTree are not recommended for use outside
|
||||
/// of the Blazor framework. These types will change in future release.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the elements in the array</typeparam>
|
||||
//
|
||||
// Represents a range of elements within an instance of <see cref="ArrayBuilder{T}"/>.
|
||||
public readonly struct ArrayBuilderSegment<T> : IEnumerable<T>
|
||||
{
|
||||
// The following fields are memory mapped to the WASM client. Do not re-order or use auto-properties.
|
||||
|
|
|
|||
|
|
@ -4,9 +4,12 @@
|
|||
namespace Microsoft.AspNetCore.Components.RenderTree
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a range of elements in an array that are in use.
|
||||
/// Types in the Microsoft.AspNetCore.Components.RenderTree are not recommended for use outside
|
||||
/// of the Blazor framework. These types will change in future release.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The array item type.</typeparam>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
//
|
||||
// Represents a range of elements in an array that are in use.
|
||||
public readonly struct ArrayRange<T>
|
||||
{
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -1,13 +1,14 @@
|
|||
// 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.RenderTree
|
||||
{
|
||||
/// <summary>
|
||||
/// Describes changes to a component's render tree between successive renders.
|
||||
/// Types in the Microsoft.AspNetCore.Components.RenderTree are not recommended for use outside
|
||||
/// of the Blazor framework. These types will change in future release.
|
||||
/// </summary>
|
||||
//
|
||||
// Describes changes to a component's render tree between successive renders.
|
||||
public readonly struct RenderTreeDiff
|
||||
{
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -6,8 +6,11 @@ using System.Runtime.InteropServices;
|
|||
namespace Microsoft.AspNetCore.Components.RenderTree
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a single edit operation on a component's render tree.
|
||||
/// Types in the Microsoft.AspNetCore.Components.RenderTree are not recommended for use outside
|
||||
/// of the Blazor framework. These types will change in future release.
|
||||
/// </summary>
|
||||
//
|
||||
// Represents a single edit operation on a component's render tree.
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
public readonly struct RenderTreeEdit
|
||||
{
|
||||
|
|
|
|||
|
|
@ -4,8 +4,11 @@
|
|||
namespace Microsoft.AspNetCore.Components.RenderTree
|
||||
{
|
||||
/// <summary>
|
||||
/// Describes the type of a render tree edit operation.
|
||||
/// Types in the Microsoft.AspNetCore.Components.RenderTree are not recommended for use outside
|
||||
/// of the Blazor framework. These types will change in future release.
|
||||
/// </summary>
|
||||
//
|
||||
//Describes the type of a render tree edit operation.
|
||||
public enum RenderTreeEditType: int
|
||||
{
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -8,8 +8,11 @@ using Microsoft.AspNetCore.Components.Rendering;
|
|||
namespace Microsoft.AspNetCore.Components.RenderTree
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents an entry in a tree of user interface (UI) items.
|
||||
/// Types in the Microsoft.AspNetCore.Components.RenderTree are not recommended for use outside
|
||||
/// of the Blazor framework. These types will change in future release.
|
||||
/// </summary>
|
||||
//
|
||||
// Represents an entry in a tree of user interface (UI) items.
|
||||
[StructLayout(LayoutKind.Explicit, Pack = 4)]
|
||||
public readonly struct RenderTreeFrame
|
||||
{
|
||||
|
|
|
|||
|
|
@ -4,8 +4,11 @@
|
|||
namespace Microsoft.AspNetCore.Components.RenderTree
|
||||
{
|
||||
/// <summary>
|
||||
/// Describes the type of a <see cref="RenderTreeFrame"/>.
|
||||
/// Types in the Microsoft.AspNetCore.Components.RenderTree are not recommended for use outside
|
||||
/// of the Blazor framework. These types will change in future release.
|
||||
/// </summary>
|
||||
//
|
||||
// Describes the type of a <see cref="RenderTreeFrame"/>.
|
||||
public enum RenderTreeFrameType: short
|
||||
{
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
|
|||
}
|
||||
}
|
||||
|
||||
internal static void DisposingComponent(ILogger<Renderer> logger, ComponentState componentState)
|
||||
public static void DisposingComponent(ILogger<Renderer> logger, ComponentState componentState)
|
||||
{
|
||||
if (logger.IsEnabled(LogLevel.Debug)) // This is almost always false, so skip the evaluations
|
||||
{
|
||||
|
|
@ -56,7 +56,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
|
|||
}
|
||||
}
|
||||
|
||||
internal static void HandlingEvent(ILogger<Renderer> logger, ulong eventHandlerId, EventArgs eventArgs)
|
||||
public static void HandlingEvent(ILogger<Renderer> logger, ulong eventHandlerId, EventArgs eventArgs)
|
||||
{
|
||||
_handlingEvent(logger, eventHandlerId, eventArgs?.GetType().Name ?? "null", null);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -243,7 +243,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
|
|||
|
||||
// Since the task has yielded - process any queued rendering work before we return control
|
||||
// to the caller.
|
||||
ProcessRenderQueue();
|
||||
ProcessPendingRender();
|
||||
}
|
||||
|
||||
// Task completed synchronously or is still running. We already processed all of the rendering
|
||||
|
|
@ -334,7 +334,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
|
|||
/// </summary>
|
||||
/// <param name="componentId">The ID of the component to render.</param>
|
||||
/// <param name="renderFragment">A <see cref="RenderFragment"/> that will supply the updated UI contents.</param>
|
||||
protected internal virtual void AddToRenderQueue(int componentId, RenderFragment renderFragment)
|
||||
internal void AddToRenderQueue(int componentId, RenderFragment renderFragment)
|
||||
{
|
||||
EnsureSynchronizationContext();
|
||||
|
||||
|
|
@ -351,7 +351,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
|
|||
|
||||
if (!_isBatchInProgress)
|
||||
{
|
||||
ProcessRenderQueue();
|
||||
ProcessPendingRender();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -398,13 +398,33 @@ namespace Microsoft.AspNetCore.Components.Rendering
|
|||
? componentState
|
||||
: null;
|
||||
|
||||
/// <summary>
|
||||
/// Processses pending renders requests from components if there are any.
|
||||
/// </summary>
|
||||
protected virtual void ProcessPendingRender()
|
||||
{
|
||||
ProcessRenderQueue();
|
||||
}
|
||||
|
||||
private void ProcessRenderQueue()
|
||||
{
|
||||
EnsureSynchronizationContext();
|
||||
|
||||
if (_isBatchInProgress)
|
||||
{
|
||||
throw new InvalidOperationException("Cannot start a batch when one is already in progress.");
|
||||
}
|
||||
|
||||
_isBatchInProgress = true;
|
||||
var updateDisplayTask = Task.CompletedTask;
|
||||
|
||||
try
|
||||
{
|
||||
if (_batchBuilder.ComponentRenderQueue.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Process render queue until empty
|
||||
while (_batchBuilder.ComponentRenderQueue.Count > 0)
|
||||
{
|
||||
|
|
@ -423,6 +443,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
|
|||
{
|
||||
// Ensure we catch errors while running the render functions of the components.
|
||||
HandleException(e);
|
||||
return;
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,90 @@
|
|||
// 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.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Components.Rendering;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Displays the specified page component, rendering it inside its layout
|
||||
/// and any further nested layouts.
|
||||
/// </summary>
|
||||
public class RouteView : IComponent
|
||||
{
|
||||
private readonly RenderFragment _renderDelegate;
|
||||
private readonly RenderFragment _renderPageWithParametersDelegate;
|
||||
private RenderHandle _renderHandle;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the route data. This determines the page that will be
|
||||
/// displayed and the parameter values that will be supplied to the page.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public RouteData RouteData { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the type of a layout to be used if the page does not
|
||||
/// declare any layout. If specified, the type must implement <see cref="IComponent"/>
|
||||
/// and accept a parameter named <see cref="LayoutComponentBase.Body"/>.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public Type DefaultLayout { get; set; }
|
||||
|
||||
public RouteView()
|
||||
{
|
||||
// Cache the delegate instances
|
||||
_renderDelegate = Render;
|
||||
_renderPageWithParametersDelegate = RenderPageWithParameters;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Attach(RenderHandle renderHandle)
|
||||
{
|
||||
_renderHandle = renderHandle;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task SetParametersAsync(ParameterView parameters)
|
||||
{
|
||||
parameters.SetParameterProperties(this);
|
||||
|
||||
if (RouteData == null)
|
||||
{
|
||||
throw new InvalidOperationException($"The {nameof(RouteView)} component requires a non-null value for the parameter {nameof(RouteData)}.");
|
||||
}
|
||||
|
||||
_renderHandle.Render(_renderDelegate);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Renders the component.
|
||||
/// </summary>
|
||||
/// <param name="builder">The <see cref="RenderTreeBuilder"/>.</param>
|
||||
protected virtual void Render(RenderTreeBuilder builder)
|
||||
{
|
||||
var pageLayoutType = RouteData.PageType.GetCustomAttribute<LayoutAttribute>()?.LayoutType
|
||||
?? DefaultLayout;
|
||||
|
||||
builder.OpenComponent<LayoutView>(0);
|
||||
builder.AddAttribute(1, nameof(LayoutView.Layout), pageLayoutType);
|
||||
builder.AddAttribute(2, nameof(LayoutView.ChildContent), _renderPageWithParametersDelegate);
|
||||
builder.CloseComponent();
|
||||
}
|
||||
|
||||
private void RenderPageWithParameters(RenderTreeBuilder builder)
|
||||
{
|
||||
builder.OpenComponent(0, RouteData.PageType);
|
||||
|
||||
foreach (var kvp in RouteData.RouteValues)
|
||||
{
|
||||
builder.AddAttribute(1, kvp.Key, kvp.Value);
|
||||
}
|
||||
|
||||
builder.CloseComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -26,6 +26,6 @@ namespace Microsoft.AspNetCore.Components.Routing
|
|||
|
||||
public Type Handler { get; set; }
|
||||
|
||||
public IDictionary<string, object> Parameters { get; set; }
|
||||
public IReadOnlyDictionary<string, object> Parameters { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,46 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Describes information determined during routing that specifies
|
||||
/// the page to be displayed.
|
||||
/// </summary>
|
||||
public sealed class RouteData
|
||||
{
|
||||
/// <summary>
|
||||
/// Constructs an instance of <see cref="RouteData"/>.
|
||||
/// </summary>
|
||||
/// <param name="pageType">The type of the page matching the route, which must implement <see cref="IComponent"/>.</param>
|
||||
/// <param name="routeValues">The route parameter values extracted from the matched route.</param>
|
||||
public RouteData(Type pageType, IReadOnlyDictionary<string, object> routeValues)
|
||||
{
|
||||
if (pageType == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(pageType));
|
||||
}
|
||||
|
||||
if (!typeof(IComponent).IsAssignableFrom(pageType))
|
||||
{
|
||||
throw new ArgumentException($"The value must implement {nameof(IComponent)}.", nameof(pageType));
|
||||
}
|
||||
|
||||
PageType = pageType;
|
||||
RouteValues = routeValues ?? throw new ArgumentNullException(nameof(routeValues));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type of the page matching the route.
|
||||
/// </summary>
|
||||
public Type PageType { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets route parameter values extracted from the matched route.
|
||||
/// </summary>
|
||||
public IReadOnlyDictionary<string, object> RouteValues { get; }
|
||||
}
|
||||
}
|
||||
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Components.Rendering;
|
||||
|
|
@ -11,12 +12,13 @@ using Microsoft.Extensions.Logging;
|
|||
namespace Microsoft.AspNetCore.Components.Routing
|
||||
{
|
||||
/// <summary>
|
||||
/// A component that displays whichever other component corresponds to the
|
||||
/// current navigation location.
|
||||
/// A component that supplies route data corresponding to the current navigation state.
|
||||
/// </summary>
|
||||
public class Router : IComponent, IHandleAfterRender, IDisposable
|
||||
{
|
||||
static readonly char[] _queryOrHashStartChar = new[] { '?', '#' };
|
||||
static readonly ReadOnlyDictionary<string, object> _emptyParametersDictionary
|
||||
= new ReadOnlyDictionary<string, object>(new Dictionary<string, object>());
|
||||
|
||||
RenderHandle _renderHandle;
|
||||
string _baseUri;
|
||||
|
|
@ -33,25 +35,19 @@ namespace Microsoft.AspNetCore.Components.Routing
|
|||
[Inject] private ILoggerFactory LoggerFactory { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the assembly that should be searched, along with its referenced
|
||||
/// assemblies, for components matching the URI.
|
||||
/// Gets or sets the assembly that should be searched for components matching the URI.
|
||||
/// </summary>
|
||||
[Parameter] public Assembly AppAssembly { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the type of the component that should be used as a fallback when no match is found for the requested route.
|
||||
/// Gets or sets the content to display when no match is found for the requested route.
|
||||
/// </summary>
|
||||
[Parameter] public RenderFragment NotFound { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The content that will be displayed if the user is not authorized.
|
||||
/// Gets or sets the content to display when a match is found for the requested route.
|
||||
/// </summary>
|
||||
[Parameter] public RenderFragment<AuthenticationState> NotAuthorized { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The content that will be displayed while asynchronous authorization is in progress.
|
||||
/// </summary>
|
||||
[Parameter] public RenderFragment Authorizing { get; set; }
|
||||
[Parameter] public RenderFragment<RouteData> Found { get; set; }
|
||||
|
||||
private RouteTable Routes { get; set; }
|
||||
|
||||
|
|
@ -69,6 +65,22 @@ namespace Microsoft.AspNetCore.Components.Routing
|
|||
public Task SetParametersAsync(ParameterView parameters)
|
||||
{
|
||||
parameters.SetParameterProperties(this);
|
||||
|
||||
// Found content is mandatory, because even though we could use something like <RouteView ...> as a
|
||||
// reasonable default, if it's not declared explicitly in the template then people will have no way
|
||||
// to discover how to customize this (e.g., to add authorization).
|
||||
if (Found == null)
|
||||
{
|
||||
throw new InvalidOperationException($"The {nameof(Router)} component requires a value for the parameter {nameof(Found)}.");
|
||||
}
|
||||
|
||||
// NotFound content is mandatory, because even though we could display a default message like "Not found",
|
||||
// it has to be specified explicitly so that it can also be wrapped in a specific layout
|
||||
if (NotFound == null)
|
||||
{
|
||||
throw new InvalidOperationException($"The {nameof(Router)} component requires a value for the parameter {nameof(NotFound)}.");
|
||||
}
|
||||
|
||||
Routes = RouteTableFactory.Create(AppAssembly);
|
||||
Refresh(isNavigationIntercepted: false);
|
||||
return Task.CompletedTask;
|
||||
|
|
@ -80,7 +92,7 @@ namespace Microsoft.AspNetCore.Components.Routing
|
|||
NavigationManager.LocationChanged -= OnLocationChanged;
|
||||
}
|
||||
|
||||
private string StringUntilAny(string str, char[] chars)
|
||||
private static string StringUntilAny(string str, char[] chars)
|
||||
{
|
||||
var firstIndex = str.IndexOfAny(chars);
|
||||
return firstIndex < 0
|
||||
|
|
@ -88,17 +100,6 @@ namespace Microsoft.AspNetCore.Components.Routing
|
|||
: str.Substring(0, firstIndex);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected virtual void Render(RenderTreeBuilder builder, Type handler, IDictionary<string, object> parameters)
|
||||
{
|
||||
builder.OpenComponent(0, typeof(PageDisplay));
|
||||
builder.AddAttribute(1, nameof(PageDisplay.Page), handler);
|
||||
builder.AddAttribute(2, nameof(PageDisplay.PageParameters), parameters);
|
||||
builder.AddAttribute(3, nameof(PageDisplay.NotAuthorized), NotAuthorized);
|
||||
builder.AddAttribute(4, nameof(PageDisplay.Authorizing), Authorizing);
|
||||
builder.CloseComponent();
|
||||
}
|
||||
|
||||
private void Refresh(bool isNavigationIntercepted)
|
||||
{
|
||||
var locationPath = NavigationManager.ToBaseRelativePath(_locationAbsolute);
|
||||
|
|
@ -116,16 +117,19 @@ namespace Microsoft.AspNetCore.Components.Routing
|
|||
|
||||
Log.NavigatingToComponent(_logger, context.Handler, locationPath, _baseUri);
|
||||
|
||||
_renderHandle.Render(builder => Render(builder, context.Handler, context.Parameters));
|
||||
var routeData = new RouteData(
|
||||
context.Handler,
|
||||
context.Parameters ?? _emptyParametersDictionary);
|
||||
_renderHandle.Render(Found(routeData));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!isNavigationIntercepted && NotFound != null)
|
||||
if (!isNavigationIntercepted)
|
||||
{
|
||||
Log.DisplayingNotFound(_logger, locationPath, _baseUri);
|
||||
|
||||
// We did not find a Component that matches the route.
|
||||
// Only show the NotFound if the application developer programatically got us here i.e we did not
|
||||
// Only show the NotFound content if the application developer programatically got us here i.e we did not
|
||||
// intercept the navigation. In all other cases, force a browser navigation since this could be non-Blazor content.
|
||||
_renderHandle.Render(NotFound);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,356 @@
|
|||
// 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.Linq;
|
||||
using System.Security.Claims;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Components.Rendering;
|
||||
using Microsoft.AspNetCore.Components.RenderTree;
|
||||
using Microsoft.AspNetCore.Components.Test.Helpers;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components
|
||||
{
|
||||
public class AuthorizeRouteViewTest
|
||||
{
|
||||
private readonly static IReadOnlyDictionary<string, object> EmptyParametersDictionary = new Dictionary<string, object>();
|
||||
private readonly TestAuthenticationStateProvider _authenticationStateProvider;
|
||||
private readonly TestRenderer _renderer;
|
||||
private readonly RouteView _authorizeRouteViewComponent;
|
||||
private readonly int _authorizeRouteViewComponentId;
|
||||
private readonly TestAuthorizationService _testAuthorizationService;
|
||||
|
||||
public AuthorizeRouteViewTest()
|
||||
{
|
||||
_authenticationStateProvider = new TestAuthenticationStateProvider();
|
||||
_authenticationStateProvider.CurrentAuthStateTask = Task.FromResult(
|
||||
new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity())));
|
||||
|
||||
_testAuthorizationService = new TestAuthorizationService();
|
||||
|
||||
var serviceCollection = new ServiceCollection();
|
||||
serviceCollection.AddSingleton<AuthenticationStateProvider>(_authenticationStateProvider);
|
||||
serviceCollection.AddSingleton<IAuthorizationPolicyProvider, TestAuthorizationPolicyProvider>();
|
||||
serviceCollection.AddSingleton<IAuthorizationService>(_testAuthorizationService);
|
||||
|
||||
_renderer = new TestRenderer(serviceCollection.BuildServiceProvider());
|
||||
_authorizeRouteViewComponent = new AuthorizeRouteView();
|
||||
_authorizeRouteViewComponentId = _renderer.AssignRootComponentId(_authorizeRouteViewComponent);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void WhenAuthorized_RendersPageInsideLayout()
|
||||
{
|
||||
// Arrange
|
||||
var routeData = new RouteData(typeof(TestPageRequiringAuthorization), new Dictionary<string, object>
|
||||
{
|
||||
{ nameof(TestPageRequiringAuthorization.Message), "Hello, world!" }
|
||||
});
|
||||
_testAuthorizationService.NextResult = AuthorizationResult.Success();
|
||||
|
||||
// Act
|
||||
_renderer.RenderRootComponent(_authorizeRouteViewComponentId, ParameterView.FromDictionary(new Dictionary<string, object>
|
||||
{
|
||||
{ nameof(AuthorizeRouteView.RouteData), routeData },
|
||||
{ nameof(AuthorizeRouteView.DefaultLayout), typeof(TestLayout) },
|
||||
}));
|
||||
|
||||
// Assert: renders layout
|
||||
var batch = _renderer.Batches.Single();
|
||||
var layoutDiff = batch.GetComponentDiffs<TestLayout>().Single();
|
||||
Assert.Collection(layoutDiff.Edits,
|
||||
edit => AssertPrependText(batch, edit, "Layout starts here"),
|
||||
edit =>
|
||||
{
|
||||
Assert.Equal(RenderTreeEditType.PrependFrame, edit.Type);
|
||||
AssertFrame.Component<TestPageRequiringAuthorization>(batch.ReferenceFrames[edit.ReferenceFrameIndex]);
|
||||
},
|
||||
edit => AssertPrependText(batch, edit, "Layout ends here"));
|
||||
|
||||
// Assert: renders page
|
||||
var pageDiff = batch.GetComponentDiffs<TestPageRequiringAuthorization>().Single();
|
||||
Assert.Collection(pageDiff.Edits,
|
||||
edit => AssertPrependText(batch, edit, "Hello from the page with message: Hello, world!"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void WhenNotAuthorized_RendersDefaultNotAuthorizedContentInsideLayout()
|
||||
{
|
||||
// Arrange
|
||||
var routeData = new RouteData(typeof(TestPageRequiringAuthorization), EmptyParametersDictionary);
|
||||
_testAuthorizationService.NextResult = AuthorizationResult.Failed();
|
||||
|
||||
// Act
|
||||
_renderer.RenderRootComponent(_authorizeRouteViewComponentId, ParameterView.FromDictionary(new Dictionary<string, object>
|
||||
{
|
||||
{ nameof(AuthorizeRouteView.RouteData), routeData },
|
||||
{ nameof(AuthorizeRouteView.DefaultLayout), typeof(TestLayout) },
|
||||
}));
|
||||
|
||||
// Assert: renders layout containing "not authorized" message
|
||||
var batch = _renderer.Batches.Single();
|
||||
var layoutDiff = batch.GetComponentDiffs<TestLayout>().Single();
|
||||
Assert.Collection(layoutDiff.Edits,
|
||||
edit => AssertPrependText(batch, edit, "Layout starts here"),
|
||||
edit => AssertPrependText(batch, edit, "Not authorized"),
|
||||
edit => AssertPrependText(batch, edit, "Layout ends here"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void WhenNotAuthorized_RendersCustomNotAuthorizedContentInsideLayout()
|
||||
{
|
||||
// Arrange
|
||||
var routeData = new RouteData(typeof(TestPageRequiringAuthorization), EmptyParametersDictionary);
|
||||
_testAuthorizationService.NextResult = AuthorizationResult.Failed();
|
||||
_authenticationStateProvider.CurrentAuthStateTask = Task.FromResult(new AuthenticationState(
|
||||
new ClaimsPrincipal(new TestIdentity { Name = "Bert" })));
|
||||
|
||||
// Act
|
||||
RenderFragment<AuthenticationState> customNotAuthorized =
|
||||
state => builder => builder.AddContent(0, $"Go away, {state.User.Identity.Name}");
|
||||
_renderer.RenderRootComponent(_authorizeRouteViewComponentId, ParameterView.FromDictionary(new Dictionary<string, object>
|
||||
{
|
||||
{ nameof(AuthorizeRouteView.RouteData), routeData },
|
||||
{ nameof(AuthorizeRouteView.DefaultLayout), typeof(TestLayout) },
|
||||
{ nameof(AuthorizeRouteView.NotAuthorized), customNotAuthorized },
|
||||
}));
|
||||
|
||||
// Assert: renders layout containing "not authorized" message
|
||||
var batch = _renderer.Batches.Single();
|
||||
var layoutDiff = batch.GetComponentDiffs<TestLayout>().Single();
|
||||
Assert.Collection(layoutDiff.Edits,
|
||||
edit => AssertPrependText(batch, edit, "Layout starts here"),
|
||||
edit => AssertPrependText(batch, edit, "Go away, Bert"),
|
||||
edit => AssertPrependText(batch, edit, "Layout ends here"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task WhenAuthorizing_RendersDefaultAuthorizingContentInsideLayout()
|
||||
{
|
||||
// Arrange
|
||||
var routeData = new RouteData(typeof(TestPageRequiringAuthorization), EmptyParametersDictionary);
|
||||
var authStateTcs = new TaskCompletionSource<AuthenticationState>();
|
||||
_authenticationStateProvider.CurrentAuthStateTask = authStateTcs.Task;
|
||||
RenderFragment<AuthenticationState> customNotAuthorized =
|
||||
state => builder => builder.AddContent(0, $"Go away, {state.User.Identity.Name}");
|
||||
|
||||
// Act
|
||||
var firstRenderTask = _renderer.RenderRootComponentAsync(_authorizeRouteViewComponentId, ParameterView.FromDictionary(new Dictionary<string, object>
|
||||
{
|
||||
{ nameof(AuthorizeRouteView.RouteData), routeData },
|
||||
{ nameof(AuthorizeRouteView.DefaultLayout), typeof(TestLayout) },
|
||||
{ nameof(AuthorizeRouteView.NotAuthorized), customNotAuthorized },
|
||||
}));
|
||||
|
||||
// Assert: renders layout containing "authorizing" message
|
||||
Assert.False(firstRenderTask.IsCompleted);
|
||||
var batch = _renderer.Batches.Single();
|
||||
var layoutDiff = batch.GetComponentDiffs<TestLayout>().Single();
|
||||
Assert.Collection(layoutDiff.Edits,
|
||||
edit => AssertPrependText(batch, edit, "Layout starts here"),
|
||||
edit => AssertPrependText(batch, edit, "Authorizing..."),
|
||||
edit => AssertPrependText(batch, edit, "Layout ends here"));
|
||||
|
||||
// Act 2: updates when authorization completes
|
||||
authStateTcs.SetResult(new AuthenticationState(
|
||||
new ClaimsPrincipal(new TestIdentity { Name = "Bert" })));
|
||||
await firstRenderTask;
|
||||
|
||||
// Assert 2: Only the layout is updated
|
||||
batch = _renderer.Batches.Skip(1).Single();
|
||||
var nonEmptyDiff = batch.DiffsInOrder.Where(d => d.Edits.Any()).Single();
|
||||
Assert.Equal(layoutDiff.ComponentId, nonEmptyDiff.ComponentId);
|
||||
Assert.Collection(nonEmptyDiff.Edits, edit =>
|
||||
{
|
||||
Assert.Equal(RenderTreeEditType.UpdateText, edit.Type);
|
||||
Assert.Equal(1, edit.SiblingIndex);
|
||||
AssertFrame.Text(batch.ReferenceFrames[edit.ReferenceFrameIndex], "Go away, Bert");
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void WhenAuthorizing_RendersCustomAuthorizingContentInsideLayout()
|
||||
{
|
||||
// Arrange
|
||||
var routeData = new RouteData(typeof(TestPageRequiringAuthorization), EmptyParametersDictionary);
|
||||
var authStateTcs = new TaskCompletionSource<AuthenticationState>();
|
||||
_authenticationStateProvider.CurrentAuthStateTask = authStateTcs.Task;
|
||||
RenderFragment customAuthorizing =
|
||||
builder => builder.AddContent(0, "Hold on, we're checking your papers.");
|
||||
|
||||
// Act
|
||||
var firstRenderTask = _renderer.RenderRootComponentAsync(_authorizeRouteViewComponentId, ParameterView.FromDictionary(new Dictionary<string, object>
|
||||
{
|
||||
{ nameof(AuthorizeRouteView.RouteData), routeData },
|
||||
{ nameof(AuthorizeRouteView.DefaultLayout), typeof(TestLayout) },
|
||||
{ nameof(AuthorizeRouteView.Authorizing), customAuthorizing },
|
||||
}));
|
||||
|
||||
// Assert: renders layout containing "authorizing" message
|
||||
Assert.False(firstRenderTask.IsCompleted);
|
||||
var batch = _renderer.Batches.Single();
|
||||
var layoutDiff = batch.GetComponentDiffs<TestLayout>().Single();
|
||||
Assert.Collection(layoutDiff.Edits,
|
||||
edit => AssertPrependText(batch, edit, "Layout starts here"),
|
||||
edit => AssertPrependText(batch, edit, "Hold on, we're checking your papers."),
|
||||
edit => AssertPrependText(batch, edit, "Layout ends here"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void WithoutCascadedAuthenticationState_WrapsOutputInCascadingAuthenticationState()
|
||||
{
|
||||
// Arrange/Act
|
||||
var routeData = new RouteData(typeof(TestPageWithNoAuthorization), EmptyParametersDictionary);
|
||||
_renderer.RenderRootComponent(_authorizeRouteViewComponentId, ParameterView.FromDictionary(new Dictionary<string, object>
|
||||
{
|
||||
{ nameof(AuthorizeRouteView.RouteData), routeData }
|
||||
}));
|
||||
|
||||
// Assert
|
||||
var batch = _renderer.Batches.Single();
|
||||
var componentInstances = batch.ReferenceFrames
|
||||
.Where(f => f.FrameType == RenderTreeFrameType.Component)
|
||||
.Select(f => f.Component);
|
||||
|
||||
Assert.Collection(componentInstances,
|
||||
// This is the hierarchy inside the AuthorizeRouteView, which contains its
|
||||
// own CascadingAuthenticationState
|
||||
component => Assert.IsType<CascadingAuthenticationState>(component),
|
||||
component => Assert.IsType<CascadingValue<Task<AuthenticationState>>>(component),
|
||||
component => Assert.IsAssignableFrom<AuthorizeViewCore>(component),
|
||||
component => Assert.IsType<LayoutView>(component),
|
||||
component => Assert.IsType<TestPageWithNoAuthorization>(component));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void WithCascadedAuthenticationState_DoesNotWrapOutputInCascadingAuthenticationState()
|
||||
{
|
||||
// Arrange
|
||||
var routeData = new RouteData(typeof(TestPageWithNoAuthorization), EmptyParametersDictionary);
|
||||
var rootComponent = new AuthorizeRouteViewWithExistingCascadedAuthenticationState(
|
||||
_authenticationStateProvider.CurrentAuthStateTask,
|
||||
routeData);
|
||||
var rootComponentId = _renderer.AssignRootComponentId(rootComponent);
|
||||
|
||||
// Act
|
||||
_renderer.RenderRootComponent(rootComponentId);
|
||||
|
||||
// Assert
|
||||
var batch = _renderer.Batches.Single();
|
||||
var componentInstances = batch.ReferenceFrames
|
||||
.Where(f => f.FrameType == RenderTreeFrameType.Component)
|
||||
.Select(f => f.Component);
|
||||
|
||||
Assert.Collection(componentInstances,
|
||||
// This is the externally-supplied cascading value
|
||||
component => Assert.IsType<CascadingValue<Task<AuthenticationState>>>(component),
|
||||
component => Assert.IsType<AuthorizeRouteView>(component),
|
||||
|
||||
// This is the hierarchy inside the AuthorizeRouteView. It doesn't contain a
|
||||
// further CascadingAuthenticationState
|
||||
component => Assert.IsAssignableFrom<AuthorizeViewCore>(component),
|
||||
component => Assert.IsType<LayoutView>(component),
|
||||
component => Assert.IsType<TestPageWithNoAuthorization>(component));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void UpdatesOutputWhenRouteDataChanges()
|
||||
{
|
||||
// Arrange/Act 1: Start on some route
|
||||
// Not asserting about the initial output, as that is covered by other tests
|
||||
var routeData = new RouteData(typeof(TestPageWithNoAuthorization), EmptyParametersDictionary);
|
||||
_renderer.RenderRootComponent(_authorizeRouteViewComponentId, ParameterView.FromDictionary(new Dictionary<string, object>
|
||||
{
|
||||
{ nameof(AuthorizeRouteView.RouteData), routeData },
|
||||
{ nameof(AuthorizeRouteView.DefaultLayout), typeof(TestLayout) },
|
||||
}));
|
||||
|
||||
// Act 2: Move to another route
|
||||
var routeData2 = new RouteData(typeof(TestPageRequiringAuthorization), EmptyParametersDictionary);
|
||||
var render2Task = _renderer.Dispatcher.InvokeAsync(() => _authorizeRouteViewComponent.SetParametersAsync(ParameterView.FromDictionary(new Dictionary<string, object>
|
||||
{
|
||||
{ nameof(AuthorizeRouteView.RouteData), routeData2 },
|
||||
})));
|
||||
|
||||
// Assert: we retain the layout instance, and mutate its contents
|
||||
Assert.True(render2Task.IsCompletedSuccessfully);
|
||||
Assert.Equal(2, _renderer.Batches.Count);
|
||||
var batch2 = _renderer.Batches[1];
|
||||
var diff = batch2.DiffsInOrder.Where(d => d.Edits.Any()).Single();
|
||||
Assert.Collection(diff.Edits,
|
||||
edit =>
|
||||
{
|
||||
// Inside the layout, we add the new content
|
||||
Assert.Equal(RenderTreeEditType.PrependFrame, edit.Type);
|
||||
Assert.Equal(1, edit.SiblingIndex);
|
||||
AssertFrame.Text(batch2.ReferenceFrames[edit.ReferenceFrameIndex], "Not authorized");
|
||||
},
|
||||
edit =>
|
||||
{
|
||||
// ... and remove the old content
|
||||
Assert.Equal(RenderTreeEditType.RemoveFrame, edit.Type);
|
||||
Assert.Equal(2, edit.SiblingIndex);
|
||||
});
|
||||
}
|
||||
|
||||
private static void AssertPrependText(CapturedBatch batch, RenderTreeEdit edit, string text)
|
||||
{
|
||||
Assert.Equal(RenderTreeEditType.PrependFrame, edit.Type);
|
||||
ref var referenceFrame = ref batch.ReferenceFrames[edit.ReferenceFrameIndex];
|
||||
AssertFrame.Text(referenceFrame, text);
|
||||
}
|
||||
|
||||
class TestPageWithNoAuthorization : ComponentBase { }
|
||||
|
||||
[Authorize]
|
||||
class TestPageRequiringAuthorization : ComponentBase
|
||||
{
|
||||
[Parameter] public string Message { get; set; }
|
||||
|
||||
protected override void BuildRenderTree(RenderTreeBuilder builder)
|
||||
{
|
||||
builder.AddContent(0, $"Hello from the page with message: {Message}");
|
||||
}
|
||||
}
|
||||
|
||||
class TestLayout : LayoutComponentBase
|
||||
{
|
||||
protected override void BuildRenderTree(RenderTreeBuilder builder)
|
||||
{
|
||||
builder.AddContent(0, "Layout starts here");
|
||||
builder.AddContent(1, Body);
|
||||
builder.AddContent(2, "Layout ends here");
|
||||
}
|
||||
}
|
||||
|
||||
class AuthorizeRouteViewWithExistingCascadedAuthenticationState : AutoRenderComponent
|
||||
{
|
||||
private readonly Task<AuthenticationState> _authenticationState;
|
||||
private readonly RouteData _routeData;
|
||||
|
||||
public AuthorizeRouteViewWithExistingCascadedAuthenticationState(
|
||||
Task<AuthenticationState> authenticationState,
|
||||
RouteData routeData)
|
||||
{
|
||||
_authenticationState = authenticationState;
|
||||
_routeData = routeData;
|
||||
}
|
||||
|
||||
protected override void BuildRenderTree(RenderTreeBuilder builder)
|
||||
{
|
||||
builder.OpenComponent<CascadingValue<Task<AuthenticationState>>>(0);
|
||||
builder.AddAttribute(1, nameof(CascadingValue<object>.Value), _authenticationState);
|
||||
builder.AddAttribute(2, nameof(CascadingValue<object>.ChildContent), (RenderFragment)(builder =>
|
||||
{
|
||||
builder.OpenComponent<AuthorizeRouteView>(0);
|
||||
builder.AddAttribute(1, nameof(AuthorizeRouteView.RouteData), _routeData);
|
||||
builder.CloseComponent();
|
||||
}));
|
||||
builder.CloseComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,7 +2,6 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Security.Claims;
|
||||
|
|
@ -332,15 +331,9 @@ namespace Microsoft.AspNetCore.Components
|
|||
Assert.Equal(2, renderer.Batches.Count);
|
||||
var batch2 = renderer.Batches[1];
|
||||
var diff2 = batch2.DiffsByComponentId[authorizeViewComponentId].Single();
|
||||
Assert.Collection(diff2.Edits,
|
||||
edit =>
|
||||
Assert.Collection(diff2.Edits, edit =>
|
||||
{
|
||||
Assert.Equal(RenderTreeEditType.RemoveFrame, edit.Type);
|
||||
Assert.Equal(0, edit.SiblingIndex);
|
||||
},
|
||||
edit =>
|
||||
{
|
||||
Assert.Equal(RenderTreeEditType.PrependFrame, edit.Type);
|
||||
Assert.Equal(RenderTreeEditType.UpdateText, edit.Type);
|
||||
Assert.Equal(0, edit.SiblingIndex);
|
||||
AssertFrame.Text(
|
||||
batch2.ReferenceFrames[edit.ReferenceFrameIndex],
|
||||
|
|
@ -514,15 +507,6 @@ namespace Microsoft.AspNetCore.Components
|
|||
=> Task.FromResult(new AuthenticationState(
|
||||
new ClaimsPrincipal(new TestIdentity { Name = username })));
|
||||
|
||||
class TestIdentity : IIdentity
|
||||
{
|
||||
public string AuthenticationType => "Test";
|
||||
|
||||
public bool IsAuthenticated => true;
|
||||
|
||||
public string Name { get; set; }
|
||||
}
|
||||
|
||||
public TestRenderer CreateTestRenderer(IAuthorizationService authorizationService)
|
||||
{
|
||||
var serviceCollection = new ServiceCollection();
|
||||
|
|
@ -531,52 +515,6 @@ namespace Microsoft.AspNetCore.Components
|
|||
return new TestRenderer(serviceCollection.BuildServiceProvider());
|
||||
}
|
||||
|
||||
private class TestAuthorizationService : IAuthorizationService
|
||||
{
|
||||
public AuthorizationResult NextResult { get; set; }
|
||||
= AuthorizationResult.Failed();
|
||||
|
||||
public List<(ClaimsPrincipal user, object resource, IEnumerable<IAuthorizationRequirement> requirements)> AuthorizeCalls { get; }
|
||||
= new List<(ClaimsPrincipal user, object resource, IEnumerable<IAuthorizationRequirement> requirements)>();
|
||||
|
||||
public Task<AuthorizationResult> AuthorizeAsync(ClaimsPrincipal user, object resource, IEnumerable<IAuthorizationRequirement> requirements)
|
||||
{
|
||||
AuthorizeCalls.Add((user, resource, requirements));
|
||||
|
||||
// The TestAuthorizationService doesn't actually apply any authorization requirements
|
||||
// It just returns the specified NextResult, since we're not trying to test the logic
|
||||
// in DefaultAuthorizationService or similar here. So it's up to tests to set a desired
|
||||
// NextResult and assert that the expected criteria were passed by inspecting AuthorizeCalls.
|
||||
return Task.FromResult(NextResult);
|
||||
}
|
||||
|
||||
public Task<AuthorizationResult> AuthorizeAsync(ClaimsPrincipal user, object resource, string policyName)
|
||||
=> throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private class TestAuthorizationPolicyProvider : IAuthorizationPolicyProvider
|
||||
{
|
||||
private readonly AuthorizationOptions options = new AuthorizationOptions();
|
||||
|
||||
public Task<AuthorizationPolicy> GetDefaultPolicyAsync()
|
||||
=> Task.FromResult(options.DefaultPolicy);
|
||||
|
||||
public Task<AuthorizationPolicy> GetFallbackPolicyAsync()
|
||||
=> Task.FromResult(options.FallbackPolicy);
|
||||
|
||||
public Task<AuthorizationPolicy> GetPolicyAsync(string policyName) => Task.FromResult(
|
||||
new AuthorizationPolicy(new[]
|
||||
{
|
||||
new TestPolicyRequirement { PolicyName = policyName }
|
||||
},
|
||||
new[] { $"TestScheme:{policyName}" }));
|
||||
}
|
||||
|
||||
public class TestPolicyRequirement : IAuthorizationRequirement
|
||||
{
|
||||
public string PolicyName { get; set; }
|
||||
}
|
||||
|
||||
public class AuthorizeViewCoreWithScheme : AuthorizeViewCore
|
||||
{
|
||||
protected override IAuthorizeData[] GetAuthorizeData()
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ namespace Microsoft.AspNetCore.Components
|
|||
{
|
||||
// Arrange: Service
|
||||
var services = new ServiceCollection();
|
||||
var authStateProvider = new TestAuthStateProvider()
|
||||
var authStateProvider = new TestAuthenticationStateProvider()
|
||||
{
|
||||
CurrentAuthStateTask = Task.FromResult(CreateAuthenticationState("Bert"))
|
||||
};
|
||||
|
|
@ -71,7 +71,7 @@ namespace Microsoft.AspNetCore.Components
|
|||
// Arrange: Service
|
||||
var services = new ServiceCollection();
|
||||
var authStateTaskCompletionSource = new TaskCompletionSource<AuthenticationState>();
|
||||
var authStateProvider = new TestAuthStateProvider()
|
||||
var authStateProvider = new TestAuthenticationStateProvider()
|
||||
{
|
||||
CurrentAuthStateTask = authStateTaskCompletionSource.Task
|
||||
};
|
||||
|
|
@ -123,7 +123,7 @@ namespace Microsoft.AspNetCore.Components
|
|||
{
|
||||
// Arrange: Service
|
||||
var services = new ServiceCollection();
|
||||
var authStateProvider = new TestAuthStateProvider()
|
||||
var authStateProvider = new TestAuthenticationStateProvider()
|
||||
{
|
||||
CurrentAuthStateTask = Task.FromResult(CreateAuthenticationState(null))
|
||||
};
|
||||
|
|
@ -190,21 +190,6 @@ namespace Microsoft.AspNetCore.Components
|
|||
}
|
||||
}
|
||||
|
||||
class TestAuthStateProvider : AuthenticationStateProvider
|
||||
{
|
||||
public Task<AuthenticationState> CurrentAuthStateTask { get; set; }
|
||||
|
||||
public override Task<AuthenticationState> GetAuthenticationStateAsync()
|
||||
{
|
||||
return CurrentAuthStateTask;
|
||||
}
|
||||
|
||||
internal void TriggerAuthenticationStateChanged(Task<AuthenticationState> authState)
|
||||
{
|
||||
NotifyAuthenticationStateChanged(authState);
|
||||
}
|
||||
}
|
||||
|
||||
public static AuthenticationState CreateAuthenticationState(string username)
|
||||
=> new AuthenticationState(new ClaimsPrincipal(username == null
|
||||
? new ClaimsIdentity()
|
||||
|
|
|
|||
|
|
@ -0,0 +1,22 @@
|
|||
// 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
|
||||
{
|
||||
public class TestAuthenticationStateProvider : AuthenticationStateProvider
|
||||
{
|
||||
public Task<AuthenticationState> CurrentAuthStateTask { get; set; }
|
||||
|
||||
public override Task<AuthenticationState> GetAuthenticationStateAsync()
|
||||
{
|
||||
return CurrentAuthStateTask;
|
||||
}
|
||||
|
||||
internal void TriggerAuthenticationStateChanged(Task<AuthenticationState> authState)
|
||||
{
|
||||
NotifyAuthenticationStateChanged(authState);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
// 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;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components
|
||||
{
|
||||
public class TestAuthorizationPolicyProvider : IAuthorizationPolicyProvider
|
||||
{
|
||||
private readonly AuthorizationOptions options = new AuthorizationOptions();
|
||||
|
||||
public Task<AuthorizationPolicy> GetDefaultPolicyAsync()
|
||||
=> Task.FromResult(options.DefaultPolicy);
|
||||
|
||||
public Task<AuthorizationPolicy> GetFallbackPolicyAsync()
|
||||
=> Task.FromResult(options.FallbackPolicy);
|
||||
|
||||
public Task<AuthorizationPolicy> GetPolicyAsync(string policyName) => Task.FromResult(
|
||||
new AuthorizationPolicy(new[]
|
||||
{
|
||||
new TestPolicyRequirement { PolicyName = policyName }
|
||||
},
|
||||
new[] { $"TestScheme:{policyName}" }));
|
||||
}
|
||||
|
||||
public class TestPolicyRequirement : IAuthorizationRequirement
|
||||
{
|
||||
public string PolicyName { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Security.Claims;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components
|
||||
{
|
||||
public class TestAuthorizationService : IAuthorizationService
|
||||
{
|
||||
public AuthorizationResult NextResult { get; set; }
|
||||
= AuthorizationResult.Failed();
|
||||
|
||||
public List<(ClaimsPrincipal user, object resource, IEnumerable<IAuthorizationRequirement> requirements)> AuthorizeCalls { get; }
|
||||
= new List<(ClaimsPrincipal user, object resource, IEnumerable<IAuthorizationRequirement> requirements)>();
|
||||
|
||||
public Task<AuthorizationResult> AuthorizeAsync(ClaimsPrincipal user, object resource, IEnumerable<IAuthorizationRequirement> requirements)
|
||||
{
|
||||
AuthorizeCalls.Add((user, resource, requirements));
|
||||
|
||||
// The TestAuthorizationService doesn't actually apply any authorization requirements
|
||||
// It just returns the specified NextResult, since we're not trying to test the logic
|
||||
// in DefaultAuthorizationService or similar here. So it's up to tests to set a desired
|
||||
// NextResult and assert that the expected criteria were passed by inspecting AuthorizeCalls.
|
||||
return Task.FromResult(NextResult);
|
||||
}
|
||||
|
||||
public Task<AuthorizationResult> AuthorizeAsync(ClaimsPrincipal user, object resource, string policyName)
|
||||
=> throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
// 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.Security.Principal;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components
|
||||
{
|
||||
public class TestIdentity : IIdentity
|
||||
{
|
||||
public string AuthenticationType => "Test";
|
||||
|
||||
public bool IsAuthenticated => true;
|
||||
|
||||
public string Name { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,326 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Components.Rendering;
|
||||
using Microsoft.AspNetCore.Components.RenderTree;
|
||||
using Microsoft.AspNetCore.Components.Test.Helpers;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.Test
|
||||
{
|
||||
public class LayoutViewTest
|
||||
{
|
||||
private readonly TestRenderer _renderer;
|
||||
private readonly LayoutView _layoutViewComponent;
|
||||
private readonly int _layoutViewComponentId;
|
||||
|
||||
public LayoutViewTest()
|
||||
{
|
||||
_renderer = new TestRenderer();
|
||||
_layoutViewComponent = new LayoutView();
|
||||
_layoutViewComponentId = _renderer.AssignRootComponentId(_layoutViewComponent);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GivenNoParameters_RendersNothing()
|
||||
{
|
||||
// Arrange/Act
|
||||
var setParametersTask = _renderer.Dispatcher.InvokeAsync(() => _layoutViewComponent.SetParametersAsync(ParameterView.Empty));
|
||||
Assert.True(setParametersTask.IsCompletedSuccessfully);
|
||||
var frames = _renderer.GetCurrentRenderTreeFrames(_layoutViewComponentId).AsEnumerable();
|
||||
|
||||
// Assert
|
||||
Assert.Single(_renderer.Batches);
|
||||
Assert.Empty(frames);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GivenContentButNoLayout_RendersContent()
|
||||
{
|
||||
// Arrange/Act
|
||||
var setParametersTask = _renderer.Dispatcher.InvokeAsync(() => _layoutViewComponent.SetParametersAsync(ParameterView.FromDictionary(new Dictionary<string, object>
|
||||
{
|
||||
{ nameof(LayoutView.ChildContent), (RenderFragment)(builder => {
|
||||
builder.AddContent(123, "Hello");
|
||||
builder.AddContent(456, "Goodbye");
|
||||
})}
|
||||
})));
|
||||
Assert.True(setParametersTask.IsCompletedSuccessfully);
|
||||
var frames = _renderer.GetCurrentRenderTreeFrames(_layoutViewComponentId).AsEnumerable();
|
||||
|
||||
// Assert
|
||||
Assert.Single(_renderer.Batches);
|
||||
Assert.Collection(frames,
|
||||
frame => AssertFrame.Text(frame, "Hello", 123),
|
||||
frame => AssertFrame.Text(frame, "Goodbye", 456));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GivenLayoutButNoContent_RendersLayoutWithEmptyBody()
|
||||
{
|
||||
// Arrange/Act
|
||||
var setParametersTask = _renderer.Dispatcher.InvokeAsync(() => _layoutViewComponent.SetParametersAsync(ParameterView.FromDictionary(new Dictionary<string, object>
|
||||
{
|
||||
{ nameof(LayoutView.Layout), typeof(RootLayout) }
|
||||
})));
|
||||
|
||||
// Assert
|
||||
Assert.True(setParametersTask.IsCompletedSuccessfully);
|
||||
var batch = _renderer.Batches.Single();
|
||||
|
||||
var layoutViewFrames = _renderer.GetCurrentRenderTreeFrames(_layoutViewComponentId).AsEnumerable();
|
||||
Assert.Collection(layoutViewFrames,
|
||||
frame => AssertFrame.Component<RootLayout>(frame, subtreeLength: 2, sequence: 0),
|
||||
frame => AssertFrame.Attribute(frame, nameof(LayoutComponentBase.Body), sequence: 1));
|
||||
|
||||
var rootLayoutComponentId = batch.GetComponentFrames<RootLayout>().Single().ComponentId;
|
||||
var rootLayoutFrames = _renderer.GetCurrentRenderTreeFrames(rootLayoutComponentId).AsEnumerable();
|
||||
Assert.Collection(rootLayoutFrames,
|
||||
frame => AssertFrame.Text(frame, "RootLayout starts here", sequence: 0),
|
||||
frame => AssertFrame.Region(frame, subtreeLength: 1), // i.e., empty region
|
||||
frame => AssertFrame.Text(frame, "RootLayout ends here", sequence: 2));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RendersContentInsideLayout()
|
||||
{
|
||||
// Arrange/Act
|
||||
var setParametersTask = _renderer.Dispatcher.InvokeAsync(() => _layoutViewComponent.SetParametersAsync(ParameterView.FromDictionary(new Dictionary<string, object>
|
||||
{
|
||||
{ nameof(LayoutView.Layout), typeof(RootLayout) },
|
||||
{ nameof(LayoutView.ChildContent), (RenderFragment)(builder => {
|
||||
builder.AddContent(123, "Hello");
|
||||
builder.AddContent(456, "Goodbye");
|
||||
})}
|
||||
})));
|
||||
|
||||
// Assert
|
||||
Assert.True(setParametersTask.IsCompletedSuccessfully);
|
||||
var batch = _renderer.Batches.Single();
|
||||
|
||||
var layoutViewFrames = _renderer.GetCurrentRenderTreeFrames(_layoutViewComponentId).AsEnumerable();
|
||||
Assert.Collection(layoutViewFrames,
|
||||
frame => AssertFrame.Component<RootLayout>(frame, subtreeLength: 2, sequence: 0),
|
||||
frame => AssertFrame.Attribute(frame, nameof(LayoutComponentBase.Body), sequence: 1));
|
||||
|
||||
var rootLayoutComponentId = batch.GetComponentFrames<RootLayout>().Single().ComponentId;
|
||||
var rootLayoutFrames = _renderer.GetCurrentRenderTreeFrames(rootLayoutComponentId).AsEnumerable();
|
||||
Assert.Collection(rootLayoutFrames,
|
||||
frame => AssertFrame.Text(frame, "RootLayout starts here", sequence: 0),
|
||||
frame => AssertFrame.Region(frame, subtreeLength: 3),
|
||||
frame => AssertFrame.Text(frame, "Hello", sequence: 123),
|
||||
frame => AssertFrame.Text(frame, "Goodbye", sequence: 456),
|
||||
frame => AssertFrame.Text(frame, "RootLayout ends here", sequence: 2));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RendersContentInsideNestedLayout()
|
||||
{
|
||||
// Arrange/Act
|
||||
var setParametersTask = _renderer.Dispatcher.InvokeAsync(() => _layoutViewComponent.SetParametersAsync(ParameterView.FromDictionary(new Dictionary<string, object>
|
||||
{
|
||||
{ nameof(LayoutView.Layout), typeof(NestedLayout) },
|
||||
{ nameof(LayoutView.ChildContent), (RenderFragment)(builder => {
|
||||
builder.AddContent(123, "Hello");
|
||||
builder.AddContent(456, "Goodbye");
|
||||
})}
|
||||
})));
|
||||
|
||||
// Assert
|
||||
Assert.True(setParametersTask.IsCompletedSuccessfully);
|
||||
var batch = _renderer.Batches.Single();
|
||||
|
||||
var layoutViewFrames = _renderer.GetCurrentRenderTreeFrames(_layoutViewComponentId).AsEnumerable();
|
||||
Assert.Collection(layoutViewFrames,
|
||||
frame => AssertFrame.Component<RootLayout>(frame, subtreeLength: 2, sequence: 0),
|
||||
frame => AssertFrame.Attribute(frame, nameof(LayoutComponentBase.Body), sequence: 1));
|
||||
|
||||
var rootLayoutComponentId = batch.GetComponentFrames<RootLayout>().Single().ComponentId;
|
||||
var rootLayoutFrames = _renderer.GetCurrentRenderTreeFrames(rootLayoutComponentId).AsEnumerable();
|
||||
Assert.Collection(rootLayoutFrames,
|
||||
frame => AssertFrame.Text(frame, "RootLayout starts here", sequence: 0),
|
||||
frame => AssertFrame.Region(frame, subtreeLength: 3, sequence: 1),
|
||||
frame => AssertFrame.Component<NestedLayout>(frame, subtreeLength: 2, sequence: 0),
|
||||
frame => AssertFrame.Attribute(frame, nameof(LayoutComponentBase.Body), sequence: 1),
|
||||
frame => AssertFrame.Text(frame, "RootLayout ends here", sequence: 2));
|
||||
|
||||
var nestedLayoutComponentId = batch.GetComponentFrames<NestedLayout>().Single().ComponentId;
|
||||
var nestedLayoutFrames = _renderer.GetCurrentRenderTreeFrames(nestedLayoutComponentId).AsEnumerable();
|
||||
Assert.Collection(nestedLayoutFrames,
|
||||
frame => AssertFrame.Text(frame, "NestedLayout starts here", sequence: 0),
|
||||
frame => AssertFrame.Region(frame, subtreeLength: 3, sequence: 1),
|
||||
frame => AssertFrame.Text(frame, "Hello", sequence: 123),
|
||||
frame => AssertFrame.Text(frame, "Goodbye", sequence: 456),
|
||||
frame => AssertFrame.Text(frame, "NestedLayout ends here", sequence: 2));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CanChangeContentWithSameLayout()
|
||||
{
|
||||
// Arrange
|
||||
var setParametersTask = _renderer.Dispatcher.InvokeAsync(() => _layoutViewComponent.SetParametersAsync(ParameterView.FromDictionary(new Dictionary<string, object>
|
||||
{
|
||||
{ nameof(LayoutView.Layout), typeof(NestedLayout) },
|
||||
{ nameof(LayoutView.ChildContent), (RenderFragment)(builder => {
|
||||
builder.AddContent(0, "Initial content");
|
||||
})}
|
||||
})));
|
||||
|
||||
// Act
|
||||
Assert.True(setParametersTask.IsCompletedSuccessfully);
|
||||
_renderer.Dispatcher.InvokeAsync(() => _layoutViewComponent.SetParametersAsync(ParameterView.FromDictionary(new Dictionary<string, object>
|
||||
{
|
||||
{ nameof(LayoutView.Layout), typeof(NestedLayout) },
|
||||
{ nameof(LayoutView.ChildContent), (RenderFragment)(builder => {
|
||||
builder.AddContent(0, "Changed content");
|
||||
})}
|
||||
})));
|
||||
|
||||
// Assert
|
||||
Assert.Equal(2, _renderer.Batches.Count);
|
||||
var batch = _renderer.Batches[1];
|
||||
Assert.Equal(0, batch.DisposedComponentIDs.Count);
|
||||
Assert.Collection(batch.DiffsInOrder,
|
||||
diff => Assert.Empty(diff.Edits), // LayoutView rerendered, but with no changes
|
||||
diff => Assert.Empty(diff.Edits), // RootLayout rerendered, but with no changes
|
||||
diff =>
|
||||
{
|
||||
// NestedLayout rerendered, patching content in place
|
||||
Assert.Collection(diff.Edits, edit =>
|
||||
{
|
||||
Assert.Equal(RenderTreeEditType.UpdateText, edit.Type);
|
||||
Assert.Equal(1, edit.SiblingIndex);
|
||||
AssertFrame.Text(
|
||||
batch.ReferenceFrames[edit.ReferenceFrameIndex],
|
||||
"Changed content",
|
||||
sequence: 0);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CanChangeLayout()
|
||||
{
|
||||
// Arrange
|
||||
var setParametersTask1 = _renderer.Dispatcher.InvokeAsync(() => _layoutViewComponent.SetParametersAsync(ParameterView.FromDictionary(new Dictionary<string, object>
|
||||
{
|
||||
{ nameof(LayoutView.Layout), typeof(NestedLayout) },
|
||||
{ nameof(LayoutView.ChildContent), (RenderFragment)(builder => {
|
||||
builder.AddContent(0, "Some content");
|
||||
})}
|
||||
})));
|
||||
Assert.True(setParametersTask1.IsCompletedSuccessfully);
|
||||
|
||||
// Act
|
||||
var setParametersTask2 = _renderer.Dispatcher.InvokeAsync(() => _layoutViewComponent.SetParametersAsync(ParameterView.FromDictionary(new Dictionary<string, object>
|
||||
{
|
||||
{ nameof(LayoutView.Layout), typeof(OtherNestedLayout) },
|
||||
})));
|
||||
|
||||
// Assert
|
||||
Assert.True(setParametersTask2.IsCompletedSuccessfully);
|
||||
Assert.Equal(2, _renderer.Batches.Count);
|
||||
var batch = _renderer.Batches[1];
|
||||
Assert.Equal(1, batch.DisposedComponentIDs.Count); // Disposes NestedLayout
|
||||
Assert.Collection(batch.DiffsInOrder,
|
||||
diff => Assert.Empty(diff.Edits), // LayoutView rerendered, but with no changes
|
||||
diff =>
|
||||
{
|
||||
// RootLayout rerendered, changing child
|
||||
Assert.Collection(diff.Edits,
|
||||
edit =>
|
||||
{
|
||||
Assert.Equal(RenderTreeEditType.RemoveFrame, edit.Type);
|
||||
Assert.Equal(1, edit.SiblingIndex);
|
||||
},
|
||||
edit =>
|
||||
{
|
||||
Assert.Equal(RenderTreeEditType.PrependFrame, edit.Type);
|
||||
Assert.Equal(1, edit.SiblingIndex);
|
||||
AssertFrame.Component<OtherNestedLayout>(
|
||||
batch.ReferenceFrames[edit.ReferenceFrameIndex],
|
||||
sequence: 0);
|
||||
});
|
||||
},
|
||||
diff =>
|
||||
{
|
||||
// Inserts new OtherNestedLayout
|
||||
Assert.Collection(diff.Edits,
|
||||
edit =>
|
||||
{
|
||||
Assert.Equal(RenderTreeEditType.PrependFrame, edit.Type);
|
||||
Assert.Equal(0, edit.SiblingIndex);
|
||||
AssertFrame.Text(
|
||||
batch.ReferenceFrames[edit.ReferenceFrameIndex],
|
||||
"OtherNestedLayout starts here");
|
||||
},
|
||||
edit =>
|
||||
{
|
||||
Assert.Equal(RenderTreeEditType.PrependFrame, edit.Type);
|
||||
Assert.Equal(1, edit.SiblingIndex);
|
||||
AssertFrame.Text(
|
||||
batch.ReferenceFrames[edit.ReferenceFrameIndex],
|
||||
"Some content");
|
||||
},
|
||||
edit =>
|
||||
{
|
||||
Assert.Equal(RenderTreeEditType.PrependFrame, edit.Type);
|
||||
Assert.Equal(2, edit.SiblingIndex);
|
||||
AssertFrame.Text(
|
||||
batch.ReferenceFrames[edit.ReferenceFrameIndex],
|
||||
"OtherNestedLayout ends here");
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private class RootLayout : AutoRenderComponent
|
||||
{
|
||||
[Parameter]
|
||||
public RenderFragment Body { get; set; }
|
||||
|
||||
protected override void BuildRenderTree(RenderTreeBuilder builder)
|
||||
{
|
||||
if (Body == null)
|
||||
{
|
||||
// Prove that we don't expect layouts to tolerate null values for Body
|
||||
throw new InvalidOperationException("Got a null body when not expecting it");
|
||||
}
|
||||
|
||||
builder.AddContent(0, "RootLayout starts here");
|
||||
builder.AddContent(1, Body);
|
||||
builder.AddContent(2, "RootLayout ends here");
|
||||
}
|
||||
}
|
||||
|
||||
[Layout(typeof(RootLayout))]
|
||||
private class NestedLayout : AutoRenderComponent
|
||||
{
|
||||
[Parameter]
|
||||
public RenderFragment Body { get; set; }
|
||||
|
||||
protected override void BuildRenderTree(RenderTreeBuilder builder)
|
||||
{
|
||||
builder.AddContent(0, "NestedLayout starts here");
|
||||
builder.AddContent(1, Body);
|
||||
builder.AddContent(2, "NestedLayout ends here");
|
||||
}
|
||||
}
|
||||
|
||||
[Layout(typeof(RootLayout))]
|
||||
private class OtherNestedLayout : AutoRenderComponent
|
||||
{
|
||||
[Parameter]
|
||||
public RenderFragment Body { get; set; }
|
||||
|
||||
protected override void BuildRenderTree(RenderTreeBuilder builder)
|
||||
{
|
||||
builder.AddContent(0, "OtherNestedLayout starts here");
|
||||
builder.AddContent(1, Body);
|
||||
builder.AddContent(2, "OtherNestedLayout ends here");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,269 +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 Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.Components.Rendering;
|
||||
using Microsoft.AspNetCore.Components.RenderTree;
|
||||
using Microsoft.AspNetCore.Components.Test.Helpers;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.Test
|
||||
{
|
||||
public class PageDisplayTest
|
||||
{
|
||||
private TestRenderer _renderer = new TestRenderer();
|
||||
private PageDisplay _pageDisplayComponent = new PageDisplay();
|
||||
private int _pageDisplayComponentId;
|
||||
|
||||
public PageDisplayTest()
|
||||
{
|
||||
_renderer = new TestRenderer();
|
||||
_pageDisplayComponent = new PageDisplay();
|
||||
_pageDisplayComponentId = _renderer.AssignRootComponentId(_pageDisplayComponent);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DisplaysComponentInsideLayout()
|
||||
{
|
||||
// Arrange/Act
|
||||
_renderer.Dispatcher.InvokeAsync(() => _pageDisplayComponent.SetParametersAsync(ParameterView.FromDictionary(new Dictionary<string, object>
|
||||
{
|
||||
{ nameof(PageDisplay.Page), typeof(ComponentWithLayout) }
|
||||
})));
|
||||
|
||||
// Assert
|
||||
var batch = _renderer.Batches.Single();
|
||||
Assert.Collection(batch.DiffsInOrder,
|
||||
diff =>
|
||||
{
|
||||
// First is the LayoutDisplay component, which contains a RootLayout
|
||||
var singleEdit = diff.Edits.Single();
|
||||
Assert.Equal(RenderTreeEditType.PrependFrame, singleEdit.Type);
|
||||
AssertFrame.Component<RootLayout>(
|
||||
batch.ReferenceFrames[singleEdit.ReferenceFrameIndex]);
|
||||
},
|
||||
diff =>
|
||||
{
|
||||
// ... then a RootLayout which contains a ComponentWithLayout
|
||||
// First is the LayoutDisplay component, which contains a RootLayout
|
||||
Assert.Collection(diff.Edits,
|
||||
edit =>
|
||||
{
|
||||
Assert.Equal(RenderTreeEditType.PrependFrame, edit.Type);
|
||||
AssertFrame.Text(
|
||||
batch.ReferenceFrames[edit.ReferenceFrameIndex],
|
||||
"RootLayout starts here");
|
||||
},
|
||||
edit =>
|
||||
{
|
||||
Assert.Equal(RenderTreeEditType.PrependFrame, edit.Type);
|
||||
AssertFrame.Component<ComponentWithLayout>(
|
||||
batch.ReferenceFrames[edit.ReferenceFrameIndex]);
|
||||
},
|
||||
edit =>
|
||||
{
|
||||
Assert.Equal(RenderTreeEditType.PrependFrame, edit.Type);
|
||||
AssertFrame.Text(
|
||||
batch.ReferenceFrames[edit.ReferenceFrameIndex],
|
||||
"RootLayout ends here");
|
||||
});
|
||||
},
|
||||
diff =>
|
||||
{
|
||||
// ... then the ComponentWithLayout
|
||||
var singleEdit = diff.Edits.Single();
|
||||
Assert.Equal(RenderTreeEditType.PrependFrame, singleEdit.Type);
|
||||
AssertFrame.Text(
|
||||
batch.ReferenceFrames[singleEdit.ReferenceFrameIndex],
|
||||
$"{nameof(ComponentWithLayout)} is here.");
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DisplaysComponentInsideNestedLayout()
|
||||
{
|
||||
// Arrange/Act
|
||||
_renderer.Dispatcher.InvokeAsync(() => _pageDisplayComponent.SetParametersAsync(ParameterView.FromDictionary(new Dictionary<string, object>
|
||||
{
|
||||
{ nameof(PageDisplay.Page), typeof(ComponentWithNestedLayout) }
|
||||
})));
|
||||
|
||||
// Assert
|
||||
var batch = _renderer.Batches.Single();
|
||||
Assert.Collection(batch.DiffsInOrder,
|
||||
// First, a LayoutDisplay containing a RootLayout
|
||||
diff => AssertFrame.Component<RootLayout>(
|
||||
batch.ReferenceFrames[diff.Edits[0].ReferenceFrameIndex]),
|
||||
// Then a RootLayout containing a NestedLayout
|
||||
diff => AssertFrame.Component<NestedLayout>(
|
||||
batch.ReferenceFrames[diff.Edits[1].ReferenceFrameIndex]),
|
||||
// Then a NestedLayout containing a ComponentWithNestedLayout
|
||||
diff => AssertFrame.Component<ComponentWithNestedLayout>(
|
||||
batch.ReferenceFrames[diff.Edits[1].ReferenceFrameIndex]),
|
||||
// Then the ComponentWithNestedLayout
|
||||
diff => AssertFrame.Text(
|
||||
batch.ReferenceFrames[diff.Edits[0].ReferenceFrameIndex],
|
||||
$"{nameof(ComponentWithNestedLayout)} is here."));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CanChangeDisplayedPageWithSameLayout()
|
||||
{
|
||||
// Arrange
|
||||
_renderer.Dispatcher.InvokeAsync(() => _pageDisplayComponent.SetParametersAsync(ParameterView.FromDictionary(new Dictionary<string, object>
|
||||
{
|
||||
{ nameof(PageDisplay.Page), typeof(ComponentWithLayout) }
|
||||
})));
|
||||
|
||||
// Act
|
||||
_renderer.Dispatcher.InvokeAsync(() => _pageDisplayComponent.SetParametersAsync(ParameterView.FromDictionary(new Dictionary<string, object>
|
||||
{
|
||||
{ nameof(PageDisplay.Page), typeof(DifferentComponentWithLayout) }
|
||||
})));
|
||||
|
||||
// Assert
|
||||
Assert.Equal(2, _renderer.Batches.Count);
|
||||
var batch = _renderer.Batches[1];
|
||||
Assert.Equal(1, batch.DisposedComponentIDs.Count); // Disposed only the inner page component
|
||||
Assert.Collection(batch.DiffsInOrder,
|
||||
diff => Assert.Empty(diff.Edits), // LayoutDisplay rerendered, but with no changes
|
||||
diff =>
|
||||
{
|
||||
// RootLayout rerendered
|
||||
Assert.Collection(diff.Edits,
|
||||
edit =>
|
||||
{
|
||||
// Removed old page
|
||||
Assert.Equal(RenderTreeEditType.RemoveFrame, edit.Type);
|
||||
Assert.Equal(1, edit.SiblingIndex);
|
||||
},
|
||||
edit =>
|
||||
{
|
||||
// Inserted new one
|
||||
Assert.Equal(RenderTreeEditType.PrependFrame, edit.Type);
|
||||
Assert.Equal(1, edit.SiblingIndex);
|
||||
AssertFrame.Component<DifferentComponentWithLayout>(
|
||||
batch.ReferenceFrames[edit.ReferenceFrameIndex]);
|
||||
});
|
||||
},
|
||||
diff =>
|
||||
{
|
||||
// New page rendered
|
||||
var singleEdit = diff.Edits.Single();
|
||||
Assert.Equal(RenderTreeEditType.PrependFrame, singleEdit.Type);
|
||||
AssertFrame.Text(
|
||||
batch.ReferenceFrames[singleEdit.ReferenceFrameIndex],
|
||||
$"{nameof(DifferentComponentWithLayout)} is here.");
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CanChangeDisplayedPageWithDifferentLayout()
|
||||
{
|
||||
// Arrange
|
||||
_renderer.Dispatcher.InvokeAsync(() => _pageDisplayComponent.SetParametersAsync(ParameterView.FromDictionary(new Dictionary<string, object>
|
||||
{
|
||||
{ nameof(PageDisplay.Page), typeof(ComponentWithLayout) }
|
||||
})));
|
||||
|
||||
// Act
|
||||
_renderer.Dispatcher.InvokeAsync(() => _pageDisplayComponent.SetParametersAsync(ParameterView.FromDictionary(new Dictionary<string, object>
|
||||
{
|
||||
{ nameof(PageDisplay.Page), typeof(ComponentWithNestedLayout) }
|
||||
})));
|
||||
|
||||
// Assert
|
||||
Assert.Equal(2, _renderer.Batches.Count);
|
||||
var batch = _renderer.Batches[1];
|
||||
Assert.Equal(1, batch.DisposedComponentIDs.Count); // Disposed only the inner page component
|
||||
Assert.Collection(batch.DiffsInOrder,
|
||||
diff => Assert.Empty(diff.Edits), // LayoutDisplay rerendered, but with no changes
|
||||
diff =>
|
||||
{
|
||||
// RootLayout rerendered
|
||||
Assert.Collection(diff.Edits,
|
||||
edit =>
|
||||
{
|
||||
// Removed old page
|
||||
Assert.Equal(RenderTreeEditType.RemoveFrame, edit.Type);
|
||||
Assert.Equal(1, edit.SiblingIndex);
|
||||
},
|
||||
edit =>
|
||||
{
|
||||
// Inserted new nested layout
|
||||
Assert.Equal(RenderTreeEditType.PrependFrame, edit.Type);
|
||||
Assert.Equal(1, edit.SiblingIndex);
|
||||
AssertFrame.Component<NestedLayout>(
|
||||
batch.ReferenceFrames[edit.ReferenceFrameIndex]);
|
||||
});
|
||||
},
|
||||
diff =>
|
||||
{
|
||||
// New nested layout rendered
|
||||
var edit = diff.Edits[1];
|
||||
Assert.Equal(RenderTreeEditType.PrependFrame, edit.Type);
|
||||
AssertFrame.Component<ComponentWithNestedLayout>(
|
||||
batch.ReferenceFrames[edit.ReferenceFrameIndex]);
|
||||
},
|
||||
diff =>
|
||||
{
|
||||
// New inner page rendered
|
||||
var singleEdit = diff.Edits.Single();
|
||||
Assert.Equal(RenderTreeEditType.PrependFrame, singleEdit.Type);
|
||||
AssertFrame.Text(
|
||||
batch.ReferenceFrames[singleEdit.ReferenceFrameIndex],
|
||||
$"{nameof(ComponentWithNestedLayout)} is here.");
|
||||
});
|
||||
}
|
||||
|
||||
private class RootLayout : AutoRenderComponent
|
||||
{
|
||||
[Parameter]
|
||||
public RenderFragment Body { get; set; }
|
||||
|
||||
protected override void BuildRenderTree(RenderTreeBuilder builder)
|
||||
{
|
||||
builder.AddContent(0, "RootLayout starts here");
|
||||
builder.AddContent(1, Body);
|
||||
builder.AddContent(2, "RootLayout ends here");
|
||||
}
|
||||
}
|
||||
|
||||
[Layout(typeof(RootLayout))]
|
||||
private class NestedLayout : AutoRenderComponent
|
||||
{
|
||||
[Parameter]
|
||||
public RenderFragment Body { get; set; }
|
||||
|
||||
protected override void BuildRenderTree(RenderTreeBuilder builder)
|
||||
{
|
||||
builder.AddContent(0, "NestedLayout starts here");
|
||||
builder.AddContent(1, Body);
|
||||
builder.AddContent(2, "NestedLayout ends here");
|
||||
}
|
||||
}
|
||||
|
||||
[Layout(typeof(RootLayout))]
|
||||
private class ComponentWithLayout : AutoRenderComponent
|
||||
{
|
||||
protected override void BuildRenderTree(RenderTreeBuilder builder)
|
||||
=> builder.AddContent(0, $"{nameof(ComponentWithLayout)} is here.");
|
||||
}
|
||||
|
||||
[Layout(typeof(RootLayout))]
|
||||
private class DifferentComponentWithLayout : AutoRenderComponent
|
||||
{
|
||||
protected override void BuildRenderTree(RenderTreeBuilder builder)
|
||||
=> builder.AddContent(0, $"{nameof(DifferentComponentWithLayout)} is here.");
|
||||
}
|
||||
|
||||
[Layout(typeof(NestedLayout))]
|
||||
private class ComponentWithNestedLayout : AutoRenderComponent
|
||||
{
|
||||
protected override void BuildRenderTree(RenderTreeBuilder builder)
|
||||
=> builder.AddContent(0, $"{nameof(ComponentWithNestedLayout)} is here.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -5,10 +5,8 @@ using System;
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Components.Rendering;
|
||||
using Microsoft.AspNetCore.Components.RenderTree;
|
||||
using Microsoft.AspNetCore.Components.Test.Helpers;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components
|
||||
|
|
@ -97,23 +95,58 @@ namespace Microsoft.AspNetCore.Components
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void IncomingParameterMatchesNoDeclaredParameter_Throws()
|
||||
public void IncomingCascadingValueMatchesCascadingParameter_SetsValue()
|
||||
{
|
||||
// Arrange
|
||||
var target = new HasPropertyWithoutParameterAttribute();
|
||||
var parameters = new ParameterViewBuilder
|
||||
{
|
||||
{ "AnyOtherKey", 123 },
|
||||
}.Build();
|
||||
var builder = new ParameterViewBuilder();
|
||||
builder.Add(nameof(HasCascadingParameter.Cascading), "hi", cascading: true);
|
||||
var parameters = builder.Build();
|
||||
|
||||
var target = new HasCascadingParameter();
|
||||
|
||||
// Act
|
||||
var ex = Assert.Throws<InvalidOperationException>(
|
||||
() => parameters.SetParameterProperties(target));
|
||||
parameters.SetParameterProperties(target);
|
||||
|
||||
// Assert
|
||||
Assert.Equal("hi", target.Cascading);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NoIncomingCascadingValueMatchesDeclaredCascadingParameter_LeavesValueUnchanged()
|
||||
{
|
||||
// Arrange
|
||||
var builder = new ParameterViewBuilder();
|
||||
var parameters = builder.Build();
|
||||
|
||||
var target = new HasCascadingParameter()
|
||||
{
|
||||
Cascading = "bye",
|
||||
};
|
||||
|
||||
// Act
|
||||
parameters.SetParameterProperties(target);
|
||||
|
||||
// Assert
|
||||
Assert.Equal("bye", target.Cascading);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IncomingCascadingValueMatchesNoDeclaredParameter_Throws()
|
||||
{
|
||||
// Arrange
|
||||
var builder = new ParameterViewBuilder();
|
||||
builder.Add("SomethingElse", "hi", cascading: true);
|
||||
var parameters = builder.Build();
|
||||
|
||||
var target = new HasCascadingParameter();
|
||||
|
||||
// Act
|
||||
var ex = Assert.Throws<InvalidOperationException>(() => parameters.SetParameterProperties(target));
|
||||
|
||||
// Assert
|
||||
Assert.Equal(
|
||||
$"Object of type '{typeof(HasPropertyWithoutParameterAttribute).FullName}' does not have a property " +
|
||||
$"matching the name 'AnyOtherKey'.",
|
||||
$"Object of type '{typeof(HasCascadingParameter).FullName}' does not have a property " +
|
||||
$"matching the name 'SomethingElse'.",
|
||||
ex.Message);
|
||||
}
|
||||
|
||||
|
|
@ -139,6 +172,45 @@ namespace Microsoft.AspNetCore.Components
|
|||
ex.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IncomingNonCascadingValueMatchesCascadingParameter_Throws()
|
||||
{
|
||||
// Arrange
|
||||
var target = new HasCascadingParameter();
|
||||
var parameters = new ParameterViewBuilder
|
||||
{
|
||||
{ nameof(HasCascadingParameter.Cascading), 123 },
|
||||
}.Build();
|
||||
|
||||
// Act
|
||||
var ex = Assert.Throws<InvalidOperationException>(() => parameters.SetParameterProperties(target));
|
||||
|
||||
// Assert
|
||||
Assert.Equal(
|
||||
$"Object of type '{typeof(HasCascadingParameter).FullName}' has a property matching the name '{nameof(HasCascadingParameter.Cascading)}', " +
|
||||
$"but it does not have [{nameof(ParameterAttribute)}] applied.",
|
||||
ex.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IncomingCascadingValueMatchesNonCascadingParameter_Throws()
|
||||
{
|
||||
// Arrange
|
||||
var target = new HasInstanceProperties();
|
||||
var builder = new ParameterViewBuilder();
|
||||
builder.Add(nameof(HasInstanceProperties.IntProp), 16, cascading: true);
|
||||
var parameters = builder.Build();
|
||||
|
||||
// Act
|
||||
var ex = Assert.Throws<InvalidOperationException>(() => parameters.SetParameterProperties(target));
|
||||
|
||||
// Assert
|
||||
Assert.Equal(
|
||||
$"The property '{nameof(HasInstanceProperties.IntProp)}' on component type '{typeof(HasInstanceProperties).FullName}' " +
|
||||
$"cannot be set using a cascading value.",
|
||||
ex.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SettingCaptureUnmatchedValuesParameterExplicitlyWorks()
|
||||
{
|
||||
|
|
@ -275,6 +347,51 @@ namespace Microsoft.AspNetCore.Components
|
|||
ex.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IncomingNonCascadingValueMatchesCascadingParameter_WithCaptureUnmatchedValues_DoesNotThrow()
|
||||
{
|
||||
// Arrange
|
||||
var target = new HasCaptureUnmatchedValuesPropertyAndCascadingParameter()
|
||||
{
|
||||
Cascading = "bye",
|
||||
};
|
||||
var parameters = new ParameterViewBuilder
|
||||
{
|
||||
{ nameof(HasCaptureUnmatchedValuesPropertyAndCascadingParameter.Cascading), "hi" },
|
||||
}.Build();
|
||||
|
||||
// Act
|
||||
parameters.SetParameterProperties(target);
|
||||
|
||||
Assert.Collection(
|
||||
target.CaptureUnmatchedValues,
|
||||
kvp =>
|
||||
{
|
||||
Assert.Equal(nameof(HasCaptureUnmatchedValuesPropertyAndCascadingParameter.Cascading), kvp.Key);
|
||||
Assert.Equal("hi", kvp.Value);
|
||||
});
|
||||
Assert.Equal("bye", target.Cascading);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IncomingCascadingValueMatchesNonCascadingParameter_WithCaptureUnmatchedValues_Throws()
|
||||
{
|
||||
// Arrange
|
||||
var target = new HasCaptureUnmatchedValuesProperty();
|
||||
var builder = new ParameterViewBuilder();
|
||||
builder.Add(nameof(HasInstanceProperties.IntProp), 16, cascading: true);
|
||||
var parameters = builder.Build();
|
||||
|
||||
// Act
|
||||
var ex = Assert.Throws<InvalidOperationException>(() => parameters.SetParameterProperties(target));
|
||||
|
||||
// Assert
|
||||
Assert.Equal(
|
||||
$"The property '{nameof(HasCaptureUnmatchedValuesProperty.IntProp)}' on component type '{typeof(HasCaptureUnmatchedValuesProperty).FullName}' " +
|
||||
$"cannot be set using a cascading value.",
|
||||
ex.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IncomingParameterValueMismatchesDeclaredParameterType_Throws()
|
||||
{
|
||||
|
|
@ -397,6 +514,11 @@ namespace Microsoft.AspNetCore.Components
|
|||
}
|
||||
}
|
||||
|
||||
class HasCascadingParameter
|
||||
{
|
||||
[CascadingParameter] public string Cascading { get; set; }
|
||||
}
|
||||
|
||||
class HasPropertyWithoutParameterAttribute
|
||||
{
|
||||
internal int IntProp { get; set; }
|
||||
|
|
@ -436,6 +558,12 @@ namespace Microsoft.AspNetCore.Components
|
|||
[Parameter(CaptureUnmatchedValues = true)] public IReadOnlyDictionary<string, object> CaptureUnmatchedValues { get; set; }
|
||||
}
|
||||
|
||||
class HasCaptureUnmatchedValuesPropertyAndCascadingParameter
|
||||
{
|
||||
[CascadingParameter] public string Cascading { get; set; }
|
||||
[Parameter(CaptureUnmatchedValues = true)] public IReadOnlyDictionary<string, object> CaptureUnmatchedValues { get; set; }
|
||||
}
|
||||
|
||||
class HasDupliateCaptureUnmatchedValuesProperty
|
||||
{
|
||||
[Parameter(CaptureUnmatchedValues = true)] public Dictionary<string, object> CaptureUnmatchedValuesProp1 { get; set; }
|
||||
|
|
@ -449,11 +577,11 @@ namespace Microsoft.AspNetCore.Components
|
|||
|
||||
class ParameterViewBuilder : IEnumerable
|
||||
{
|
||||
private readonly List<(string Name, object Value)> _keyValuePairs
|
||||
= new List<(string, object)>();
|
||||
private readonly List<(string Name, object Value, bool Cascading)> _keyValuePairs
|
||||
= new List<(string, object, bool)>();
|
||||
|
||||
public void Add(string name, object value)
|
||||
=> _keyValuePairs.Add((name, value));
|
||||
public void Add(string name, object value, bool cascading = false)
|
||||
=> _keyValuePairs.Add((name, value, cascading));
|
||||
|
||||
public IEnumerator GetEnumerator()
|
||||
=> throw new NotImplementedException();
|
||||
|
|
@ -461,13 +589,56 @@ namespace Microsoft.AspNetCore.Components
|
|||
public ParameterView Build()
|
||||
{
|
||||
var builder = new RenderTreeBuilder();
|
||||
|
||||
builder.OpenComponent<FakeComponent>(0);
|
||||
foreach (var kvp in _keyValuePairs)
|
||||
{
|
||||
builder.AddAttribute(1, kvp.Name, kvp.Value);
|
||||
if (!kvp.Cascading)
|
||||
{
|
||||
builder.AddAttribute(1, kvp.Name, kvp.Value);
|
||||
}
|
||||
}
|
||||
builder.CloseComponent();
|
||||
return new ParameterView(builder.GetFrames().Array, ownerIndex: 0);
|
||||
|
||||
var view = new ParameterView(builder.GetFrames().Array, ownerIndex: 0);
|
||||
|
||||
var cascadingParameters = new List<CascadingParameterState>();
|
||||
foreach (var kvp in _keyValuePairs)
|
||||
{
|
||||
if (kvp.Cascading)
|
||||
{
|
||||
cascadingParameters.Add(new CascadingParameterState(kvp.Name, new TestCascadingValueProvider(kvp.Value)));
|
||||
}
|
||||
}
|
||||
|
||||
return view.WithCascadingParameters(cascadingParameters);
|
||||
}
|
||||
}
|
||||
|
||||
private class TestCascadingValueProvider : ICascadingValueComponent
|
||||
{
|
||||
public TestCascadingValueProvider(object value)
|
||||
{
|
||||
CurrentValue = value;
|
||||
}
|
||||
|
||||
public object CurrentValue { get; }
|
||||
|
||||
public bool CurrentValueIsFixed => throw new NotImplementedException();
|
||||
|
||||
public bool CanSupplyValue(Type valueType, string valueName)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void Subscribe(ComponentState subscriber)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void Unsubscribe(ComponentState subscriber)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3395,6 +3395,27 @@ namespace Microsoft.AspNetCore.Components.Test
|
|||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CannotStartOverlappingBatches()
|
||||
{
|
||||
// Arrange
|
||||
var renderer = new InvalidRecursiveRenderer();
|
||||
var component = new CallbackOnRenderComponent(() =>
|
||||
{
|
||||
// The renderer disallows one batch to be started inside another, because that
|
||||
// would violate all kinds of state tracking invariants. It's not something that
|
||||
// would ever happen except if you subclass the renderer and do something unsupported
|
||||
// that commences batches from inside each other.
|
||||
renderer.ProcessPendingRender();
|
||||
});
|
||||
var componentId = renderer.AssignRootComponentId(component);
|
||||
|
||||
// Act/Assert
|
||||
var ex = Assert.Throws<InvalidOperationException>(
|
||||
() => renderer.RenderRootComponent(componentId));
|
||||
Assert.Contains("Cannot start a batch when one is already in progress.", ex.Message);
|
||||
}
|
||||
|
||||
private class NoOpRenderer : Renderer
|
||||
{
|
||||
public NoOpRenderer() : base(new TestServiceProvider(), NullLoggerFactory.Instance)
|
||||
|
|
@ -4109,5 +4130,24 @@ namespace Microsoft.AspNetCore.Components.Test
|
|||
private class DerivedEventArgs : EventArgs
|
||||
{
|
||||
}
|
||||
|
||||
class CallbackOnRenderComponent : AutoRenderComponent
|
||||
{
|
||||
private readonly Action _callback;
|
||||
|
||||
public CallbackOnRenderComponent(Action callback)
|
||||
{
|
||||
_callback = callback;
|
||||
}
|
||||
|
||||
protected override void BuildRenderTree(RenderTreeBuilder builder)
|
||||
=> _callback();
|
||||
}
|
||||
|
||||
class InvalidRecursiveRenderer : TestRenderer
|
||||
{
|
||||
public new void ProcessPendingRender()
|
||||
=> base.ProcessPendingRender();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,209 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Components.Rendering;
|
||||
using Microsoft.AspNetCore.Components.RenderTree;
|
||||
using Microsoft.AspNetCore.Components.Test.Helpers;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.Test
|
||||
{
|
||||
public class RouteViewTest
|
||||
{
|
||||
private readonly TestRenderer _renderer;
|
||||
private readonly RouteView _routeViewComponent;
|
||||
private readonly int _routeViewComponentId;
|
||||
|
||||
public RouteViewTest()
|
||||
{
|
||||
_renderer = new TestRenderer();
|
||||
_routeViewComponent = new RouteView();
|
||||
_routeViewComponentId = _renderer.AssignRootComponentId(_routeViewComponent);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ThrowsIfNoRouteDataSupplied()
|
||||
{
|
||||
var ex = Assert.Throws<InvalidOperationException>(() =>
|
||||
{
|
||||
// Throws synchronously, so no need to await
|
||||
_ = _routeViewComponent.SetParametersAsync(ParameterView.Empty);
|
||||
});
|
||||
|
||||
|
||||
Assert.Equal($"The {nameof(RouteView)} component requires a non-null value for the parameter {nameof(RouteView.RouteData)}.", ex.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RendersPageInsideLayoutView()
|
||||
{
|
||||
// Arrange
|
||||
var routeParams = new Dictionary<string, object>
|
||||
{
|
||||
{ nameof(ComponentWithLayout.Message), "Test message" }
|
||||
};
|
||||
var routeData = new RouteData(typeof(ComponentWithLayout), routeParams);
|
||||
|
||||
// Act
|
||||
_renderer.Dispatcher.InvokeAsync(() => _routeViewComponent.SetParametersAsync(ParameterView.FromDictionary(new Dictionary<string, object>
|
||||
{
|
||||
{ nameof(RouteView.RouteData), routeData },
|
||||
})));
|
||||
|
||||
// Assert: RouteView renders LayoutView
|
||||
var batch = _renderer.Batches.Single();
|
||||
var routeViewFrames = _renderer.GetCurrentRenderTreeFrames(_routeViewComponentId).AsEnumerable();
|
||||
Assert.Collection(routeViewFrames,
|
||||
frame => AssertFrame.Component<LayoutView>(frame, subtreeLength: 3, sequence: 0),
|
||||
frame => AssertFrame.Attribute(frame, nameof(LayoutView.Layout), (object)typeof(TestLayout), sequence: 1),
|
||||
frame => AssertFrame.Attribute(frame, nameof(LayoutView.ChildContent), sequence: 2));
|
||||
|
||||
// Assert: LayoutView renders TestLayout
|
||||
var layoutViewComponentId = batch.GetComponentFrames<LayoutView>().Single().ComponentId;
|
||||
var layoutViewFrames = _renderer.GetCurrentRenderTreeFrames(layoutViewComponentId).AsEnumerable();
|
||||
Assert.Collection(layoutViewFrames,
|
||||
frame => AssertFrame.Component<TestLayout>(frame, subtreeLength: 2, sequence: 0),
|
||||
frame => AssertFrame.Attribute(frame, nameof(LayoutComponentBase.Body), sequence: 1));
|
||||
|
||||
// Assert: TestLayout renders page
|
||||
var testLayoutComponentId = batch.GetComponentFrames<TestLayout>().Single().ComponentId;
|
||||
var testLayoutFrames = _renderer.GetCurrentRenderTreeFrames(testLayoutComponentId).AsEnumerable();
|
||||
Assert.Collection(testLayoutFrames,
|
||||
frame => AssertFrame.Text(frame, "Layout starts here", sequence: 0),
|
||||
frame => AssertFrame.Region(frame, subtreeLength: 3),
|
||||
frame => AssertFrame.Component<ComponentWithLayout>(frame, sequence: 0, subtreeLength: 2),
|
||||
frame => AssertFrame.Attribute(frame, nameof(ComponentWithLayout.Message), "Test message", sequence: 1),
|
||||
frame => AssertFrame.Text(frame, "Layout ends here", sequence: 2));
|
||||
|
||||
// Assert: page itself is rendered, having received parameters from the original route data
|
||||
var pageComponentId = batch.GetComponentFrames<ComponentWithLayout>().Single().ComponentId;
|
||||
var pageFrames = _renderer.GetCurrentRenderTreeFrames(pageComponentId).AsEnumerable();
|
||||
Assert.Collection(pageFrames,
|
||||
frame => AssertFrame.Text(frame, "Hello from the page with message 'Test message'", sequence: 0));
|
||||
|
||||
// Assert: nothing else was rendered
|
||||
Assert.Equal(4, batch.DiffsInOrder.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void UsesDefaultLayoutIfNoneSetOnPage()
|
||||
{
|
||||
// Arrange
|
||||
var routeParams = new Dictionary<string, object>();
|
||||
var routeData = new RouteData(typeof(ComponentWithoutLayout), routeParams);
|
||||
|
||||
// Act
|
||||
_renderer.Dispatcher.InvokeAsync(() => _routeViewComponent.SetParametersAsync(ParameterView.FromDictionary(new Dictionary<string, object>
|
||||
{
|
||||
{ nameof(RouteView.RouteData), routeData },
|
||||
{ nameof(RouteView.DefaultLayout), typeof(OtherLayout) },
|
||||
})));
|
||||
|
||||
// Assert: uses default layout
|
||||
// Not asserting about what else gets rendered as that's covered by other tests
|
||||
var batch = _renderer.Batches.Single();
|
||||
var routeViewFrames = _renderer.GetCurrentRenderTreeFrames(_routeViewComponentId).AsEnumerable();
|
||||
Assert.Collection(routeViewFrames,
|
||||
frame => AssertFrame.Component<LayoutView>(frame, subtreeLength: 3, sequence: 0),
|
||||
frame => AssertFrame.Attribute(frame, nameof(LayoutView.Layout), (object)typeof(OtherLayout), sequence: 1),
|
||||
frame => AssertFrame.Attribute(frame, nameof(LayoutView.ChildContent), sequence: 2));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void UsesNoLayoutIfNoneSetOnPageAndNoDefaultSet()
|
||||
{
|
||||
// Arrange
|
||||
var routeParams = new Dictionary<string, object>();
|
||||
var routeData = new RouteData(typeof(ComponentWithoutLayout), routeParams);
|
||||
|
||||
// Act
|
||||
_renderer.Dispatcher.InvokeAsync(() => _routeViewComponent.SetParametersAsync(ParameterView.FromDictionary(new Dictionary<string, object>
|
||||
{
|
||||
{ nameof(RouteView.RouteData), routeData },
|
||||
})));
|
||||
|
||||
// Assert: uses no layout
|
||||
// Not asserting about what else gets rendered as that's covered by other tests
|
||||
var batch = _renderer.Batches.Single();
|
||||
var routeViewFrames = _renderer.GetCurrentRenderTreeFrames(_routeViewComponentId).AsEnumerable();
|
||||
Assert.Collection(routeViewFrames,
|
||||
frame => AssertFrame.Component<LayoutView>(frame, subtreeLength: 3, sequence: 0),
|
||||
frame => AssertFrame.Attribute(frame, nameof(LayoutView.Layout), (object)null, sequence: 1),
|
||||
frame => AssertFrame.Attribute(frame, nameof(LayoutView.ChildContent), sequence: 2));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PageLayoutSupersedesDefaultLayout()
|
||||
{
|
||||
// Arrange
|
||||
var routeParams = new Dictionary<string, object>();
|
||||
var routeData = new RouteData(typeof(ComponentWithLayout), routeParams);
|
||||
|
||||
// Act
|
||||
_renderer.Dispatcher.InvokeAsync(() => _routeViewComponent.SetParametersAsync(ParameterView.FromDictionary(new Dictionary<string, object>
|
||||
{
|
||||
{ nameof(RouteView.RouteData), routeData },
|
||||
{ nameof(RouteView.DefaultLayout), typeof(OtherLayout) },
|
||||
})));
|
||||
|
||||
// Assert: uses layout specified by page
|
||||
// Not asserting about what else gets rendered as that's covered by other tests
|
||||
var batch = _renderer.Batches.Single();
|
||||
var routeViewFrames = _renderer.GetCurrentRenderTreeFrames(_routeViewComponentId).AsEnumerable();
|
||||
Assert.Collection(routeViewFrames,
|
||||
frame => AssertFrame.Component<LayoutView>(frame, subtreeLength: 3, sequence: 0),
|
||||
frame => AssertFrame.Attribute(frame, nameof(LayoutView.Layout), (object)typeof(TestLayout), sequence: 1),
|
||||
frame => AssertFrame.Attribute(frame, nameof(LayoutView.ChildContent), sequence: 2));
|
||||
}
|
||||
|
||||
private class ComponentWithoutLayout : AutoRenderComponent
|
||||
{
|
||||
[Parameter] public string Message { get; set; }
|
||||
|
||||
protected override void BuildRenderTree(RenderTreeBuilder builder)
|
||||
{
|
||||
builder.AddContent(0, $"Hello from the page with message '{Message}'");
|
||||
}
|
||||
}
|
||||
|
||||
[Layout(typeof(TestLayout))]
|
||||
private class ComponentWithLayout : AutoRenderComponent
|
||||
{
|
||||
[Parameter] public string Message { get; set; }
|
||||
|
||||
protected override void BuildRenderTree(RenderTreeBuilder builder)
|
||||
{
|
||||
builder.AddContent(0, $"Hello from the page with message '{Message}'");
|
||||
}
|
||||
}
|
||||
|
||||
private class TestLayout : AutoRenderComponent
|
||||
{
|
||||
[Parameter]
|
||||
public RenderFragment Body { get; set; }
|
||||
|
||||
protected override void BuildRenderTree(RenderTreeBuilder builder)
|
||||
{
|
||||
builder.AddContent(0, "Layout starts here");
|
||||
builder.AddContent(1, Body);
|
||||
builder.AddContent(2, "Layout ends here");
|
||||
}
|
||||
}
|
||||
|
||||
private class OtherLayout : AutoRenderComponent
|
||||
{
|
||||
[Parameter]
|
||||
public RenderFragment Body { get; set; }
|
||||
|
||||
protected override void BuildRenderTree(RenderTreeBuilder builder)
|
||||
{
|
||||
builder.AddContent(0, "OtherLayout starts here");
|
||||
builder.AddContent(1, Body);
|
||||
builder.AddContent(2, "OtherLayout ends here");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -5,6 +5,16 @@
|
|||
|
||||
<ItemGroup>
|
||||
<None Include="$(MSBuildThisFileDirectory)THIRD-PARTY-NOTICES.txt" Pack="true" PackagePath="." />
|
||||
|
||||
<!-- Add a project dependency without reference output assemblies to enforce build order -->
|
||||
<!-- Applying workaround for https://github.com/microsoft/msbuild/issues/2661 and https://github.com/dotnet/sdk/issues/952 -->
|
||||
<ProjectReference
|
||||
Condition="'$(ReferenceBlazorBuildLocally)' == 'true' and '$(BuildNodeJS)' != 'false' and '$(BuildingInsideVisualStudio)' != 'true'"
|
||||
Include="$(RepoRoot)src\Components\Web.JS\Microsoft.AspNetCore.Components.Web.JS.npmproj"
|
||||
ReferenceOutputAssemblies="false"
|
||||
SkipGetTargetFrameworkProperties="true"
|
||||
UndefineProperties="TargetFramework"
|
||||
Private="false" />
|
||||
</ItemGroup>
|
||||
|
||||
<Import Project="Blazor\Build\src\ReferenceFromSource.props" Condition="'$(ReferenceBlazorBuildLocally)' == 'true'" />
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue