Merge branch 'master' into merge/release/5.0-preview7-to-master

This commit is contained in:
Pranav K 2020-07-05 20:54:56 -07:00 committed by GitHub
commit de034feb98
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
373 changed files with 5277 additions and 1913 deletions

View File

@ -433,7 +433,8 @@ stages:
jobName: Linux_musl_x64_build
jobDisplayName: "Build: Linux Musl x64"
agentOs: Linux
buildScript: ./dockerbuild.sh alpine
container: mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.9-WithNode-0fc54a3-20190918214015
buildScript: ./build.sh
buildArgs:
--arch x64
--os-name linux-musl
@ -448,6 +449,7 @@ stages:
$(_InternalRuntimeDownloadArgs)
installNodeJs: false
installJdk: false
skipComponentGovernanceDetection: true
artifacts:
- name: Linux_musl_x64_Logs
path: artifacts/log/
@ -466,7 +468,8 @@ stages:
jobDisplayName: "Build: Linux Musl ARM64"
agentOs: Linux
useHostedUbuntu: false
buildScript: ./dockerbuild.sh ubuntu-alpine37
container: mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-16.04-cross-arm64-alpine-20200413125008-406629a
buildScript: ./build.sh
buildArgs:
--arch arm64
--os-name linux-musl

View File

@ -35,7 +35,8 @@
# Specifies what directory to run build.sh/cmd
# buildScript: string
# Specifies the build script to run. Defaults to build.sh or build.cmd.
# skipComponentGovernanceDetection: boolean
# Determines if component governance detection can be skipped
#
# See https://docs.microsoft.com/en-us/vsts/pipelines/yaml-schema for details
#
@ -60,6 +61,7 @@ parameters:
installJdk: true
timeoutInMinutes: 180
useHostedUbuntu: true
skipComponentGovernanceDetection: false
# We need longer than the default amount of 5 minutes to upload our logs/artifacts. (We currently take around 5 mins in the best case).
# This makes sure we have time to upload everything in the case of a build timeout - really important for investigating a build
@ -114,6 +116,8 @@ jobs:
name: NetCoreInternal-Pool
# Visual Studio Enterprise - contains some stuff, like SQL Server and IIS Express, that we use for testing
queue: BuildPool.Server.Amd64.VS2019
${{ if ne(parameters.container, '') }}:
container: ${{ parameters.container }}
variables:
- AgentOsName: ${{ parameters.agentOs }}
- ASPNETCORE_TEST_LOG_MAXPATH: "200" # Keep test log file name length low enough for artifact zipping
@ -238,7 +242,7 @@ jobs:
continueOnError: true
condition: always()
- ${{ if and(startsWith(parameters.jobDisplayName, 'Build:'), ne(variables['skipComponentGovernanceDetection'], 'true'), notin(variables['Build.Reason'], 'PullRequest')) }}:
- ${{ if and(startsWith(parameters.jobDisplayName, 'Build:'), ne(variables['skipComponentGovernanceDetection'], 'true'), ne(parameters.skipComponentGovernanceDetection, 'true'), notin(variables['Build.Reason'], 'PullRequest')) }}:
- task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0
condition: and(succeeded(), ne(variables['CG_RAN'], 'true'))
displayName: 'Component Detection'

View File

@ -0,0 +1,149 @@
# We want to run quarantined tests on master as well as on PRs
trigger:
batch: true
branches:
include:
- master
schedules:
- cron: "0 */4 * * *"
displayName: Every 4 hours test run
branches:
include:
- master
always: true
variables:
- ${{ if ne(variables['System.TeamProject'], 'internal') }}:
- name: _UseHelixOpenQueues
value: 'true'
- ${{ if eq(variables['System.TeamProject'], 'internal') }}:
- group: DotNet-HelixApi-Access
- name: _UseHelixOpenQueues
value: 'false'
jobs:
- template: jobs/default-build.yml
parameters:
jobName: Helix_quarantined_x64
jobDisplayName: 'Tests: Helix'
agentOs: Windows
timeoutInMinutes: 240
steps:
# Build the shared framework
- script: ./build.cmd -ci -nobl -all -pack -arch x64 /p:ASPNETCORE_TEST_LOG_DIR=artifacts/log
displayName: Build shared fx
- script: ./build.cmd -ci -nobl -noBuildRepoTasks -restore -noBuild -noBuildNative -projects src/Grpc/**/*.csproj
displayName: Restore interop projects
- script: ./build.cmd -ci -nobl -noBuildRepoTasks -noRestore -test -all -noBuildJava -noBuildNative
-projects eng\helix\helix.proj /p:RunQuarantinedTests=true /p:IsRequiredCheck=true /p:IsHelixJob=true
/p:BuildInteropProjects=true /p:RunTemplateTests=true /p:ASPNETCORE_TEST_LOG_DIR=artifacts/log
displayName: Run build.cmd helix target
continueOnError: true
env:
HelixApiAccessToken: $(HelixApiAccessToken) # Needed for internal queues
SYSTEM_ACCESSTOKEN: $(System.AccessToken) # We need to set this env var to publish helix results to Azure Dev Ops
artifacts:
- name: Helix_logs
path: artifacts/log/
publishOnError: true
- template: jobs/default-build.yml
parameters:
jobName: Windows_Quarantined_x64
jobDisplayName: 'Tests: Windows x64'
agentOs: Windows
timeoutInMinutes: 240
isTestingJob: true
steps:
- powershell: "& ./build.ps1 -CI -nobl -all -pack -NoBuildJava"
displayName: Build
# The templates part can be removed when the Blazor Templates run on Helix
- script: ./src/ProjectTemplates/build.cmd -ci -nobl -pack -NoRestore -NoBuilddeps "/p:RunTemplateTests=true"
displayName: Pack Templates
- script: ./build.cmd -ci -nobl -test -NoRestore -NoBuild -NoBuilddeps "/p:RunTemplateTests=true /p:RunQuarantinedTests=true /p:SkipHelixReadyTests=true"
displayName: Run Quarantined Tests
continueOnError: true
- task: PublishTestResults@2
displayName: Publish Quarantined Test Results
inputs:
testResultsFormat: 'xUnit'
testResultsFiles: '*.xml'
searchFolder: '$(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig)/Quarantined'
condition: always()
artifacts:
- name: Windows_Quarantined_Test_Logs
path: artifacts/log/
publishOnError: true
includeForks: true
- name: Windows_Quarantined_Test_Results
path: artifacts/TestResults/
publishOnError: true
includeForks: true
- template: jobs/default-build.yml
parameters:
jobName: MacOS_Quarantined_Test
jobDisplayName: "Tests: macOS 10.14"
agentOs: macOS
timeoutInMinutes: 240
isTestingJob: true
steps:
- bash: ./build.sh --all --pack --ci --nobl --no-build-java
displayName: Build
# The templates part can be removed when the Blazor Templates run on Helix
- bash: ./src/ProjectTemplates/build.sh --ci --nobl --pack --no-restore --no-build-deps
displayName: Pack Templates (for Template tests)
- bash: ./build.sh --no-build --ci --nobl --test -p:RunTemplateTests=true -p:RunQuarantinedTests=true -p:SkipHelixReadyTests=true
displayName: Run Quarantined Tests
continueOnError: true
- task: PublishTestResults@2
displayName: Publish Quarantined Test Results
inputs:
testResultsFormat: 'xUnit'
testResultsFiles: '*.xml'
searchFolder: '$(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig)/Quarantined'
condition: always()
artifacts:
- name: MacOS_Quarantined_Test_Logs
path: artifacts/log/
publishOnError: true
includeForks: true
- name: MacOS_Quarantined_Test_Results
path: artifacts/TestResults/
publishOnError: true
includeForks: true
- template: jobs/default-build.yml
parameters:
jobName: Linux_Quarantined_Test
jobDisplayName: "Tests: Ubuntu 16.04 x64"
agentOs: Linux
timeoutInMinutes: 240
isTestingJob: true
useHostedUbuntu: false
steps:
- bash: ./build.sh --all --pack --ci --nobl --no-build-java
displayName: Build
# The templates part can be removed when the Blazor Templates run on Helix
- bash: ./src/ProjectTemplates/build.sh --ci --nobl --pack --no-restore --no-build-deps
displayName: Pack Templates (for Template tests)
- bash: ./build.sh --no-build --ci --nobl --test -p:RunTemplateTests=true -p:RunQuarantinedTests=true -p:SkipHelixReadyTests=true
displayName: Run Quarantined Tests
continueOnError: true
- task: PublishTestResults@2
displayName: Publish Quarantined Test Results
inputs:
testResultsFormat: 'xUnit'
testResultsFiles: '*.xml'
searchFolder: '$(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig)/Quarantined'
condition: always()
artifacts:
- name: Linux_Quarantined_Test_Logs
path: artifacts/log/
publishOnError: true
includeForks: true
- name: Linux_Quarantined_Test_Results
path: artifacts/TestResults/
publishOnError: true
includeForks: true

View File

@ -1,13 +1,10 @@
# We want to run quarantined tests on master as well as on PRs
trigger:
batch: true
branches:
include:
- master
# We only want to run quarantined tests on master
pr: none
trigger: none
schedules:
- cron: "0 */4 * * *"
displayName: Every 4 hours test run
- cron: "0 18 * * *"
displayName: Run tests once a day at 11 PM
branches:
include:
- master
@ -28,7 +25,7 @@ jobs:
jobName: Helix_quarantined_x64
jobDisplayName: 'Tests: Helix'
agentOs: Windows
timeoutInMinutes: 180
timeoutInMinutes: 480
steps:
# Build the shared framework
- script: ./build.cmd -ci -nobl -all -pack -arch x64 /p:ASPNETCORE_TEST_LOG_DIR=artifacts/log
@ -36,7 +33,7 @@ jobs:
- script: ./build.cmd -ci -nobl -noBuildRepoTasks -restore -noBuild -noBuildNative -projects src/Grpc/**/*.csproj
displayName: Restore interop projects
- script: ./build.cmd -ci -nobl -noBuildRepoTasks -noRestore -test -all -noBuildJava -noBuildNative
-projects eng\helix\helix.proj /p:RunQuarantinedTests=true /p:IsRequiredCheck=true /p:IsHelixJob=true
-projects eng\helix\helix.proj /p:IsHelixDaily=true /p:RunQuarantinedTests=true /p:IsRequiredCheck=true /p:IsHelixJob=true
/p:BuildInteropProjects=true /p:RunTemplateTests=true /p:ASPNETCORE_TEST_LOG_DIR=artifacts/log
displayName: Run build.cmd helix target
continueOnError: true
@ -48,102 +45,27 @@ jobs:
path: artifacts/log/
publishOnError: true
# Helix ARM64
- template: jobs/default-build.yml
parameters:
jobName: Windows_Quarantined_x64
jobDisplayName: 'Tests: Windows x64'
agentOs: Windows
timeoutInMinutes: 180
isTestingJob: true
steps:
- powershell: "& ./build.ps1 -CI -nobl -all -pack -NoBuildJava"
displayName: Build
# The templates part can be removed when the Blazor Templates run on Helix
- script: ./src/ProjectTemplates/build.cmd -ci -nobl -pack -NoRestore -NoBuilddeps "/p:RunTemplateTests=true"
displayName: Pack Templates
- script: ./build.cmd -ci -nobl -test -NoRestore -NoBuild -NoBuilddeps "/p:RunTemplateTests=true /p:RunQuarantinedTests=true /p:SkipHelixReadyTests=true"
displayName: Run Quarantined Tests
continueOnError: true
- task: PublishTestResults@2
displayName: Publish Quarantined Test Results
inputs:
testResultsFormat: 'xUnit'
testResultsFiles: '*.xml'
searchFolder: '$(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig)/Quarantined'
condition: always()
artifacts:
- name: Windows_Quarantined_Test_Logs
path: artifacts/log/
publishOnError: true
includeForks: true
- name: Windows_Quarantined_Test_Results
path: artifacts/TestResults/
publishOnError: true
includeForks: true
- template: jobs/default-build.yml
parameters:
jobName: MacOS_Quarantined_Test
jobDisplayName: "Tests: macOS 10.14"
agentOs: macOS
timeoutInMinutes: 180
isTestingJob: true
steps:
- bash: ./build.sh --all --pack --ci --nobl --no-build-java
displayName: Build
# The templates part can be removed when the Blazor Templates run on Helix
- bash: ./src/ProjectTemplates/build.sh --ci --nobl --pack --no-restore --no-build-deps
displayName: Pack Templates (for Template tests)
- bash: ./build.sh --no-build --ci --nobl --test -p:RunTemplateTests=true -p:RunQuarantinedTests=true -p:SkipHelixReadyTests=true
displayName: Run Quarantined Tests
continueOnError: true
- task: PublishTestResults@2
displayName: Publish Quarantined Test Results
inputs:
testResultsFormat: 'xUnit'
testResultsFiles: '*.xml'
searchFolder: '$(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig)/Quarantined'
condition: always()
artifacts:
- name: MacOS_Quarantined_Test_Logs
path: artifacts/log/
publishOnError: true
includeForks: true
- name: MacOS_Quarantined_Test_Results
path: artifacts/TestResults/
publishOnError: true
includeForks: true
- template: jobs/default-build.yml
parameters:
jobName: Linux_Quarantined_Test
jobDisplayName: "Tests: Ubuntu 16.04 x64"
jobName: Helix_quarantined_arm64
jobDisplayName: "Tests: Helix ARM64"
agentOs: Linux
timeoutInMinutes: 180
isTestingJob: true
useHostedUbuntu: false
timeoutInMinutes: 480
steps:
- bash: ./build.sh --all --pack --ci --nobl --no-build-java
displayName: Build
# The templates part can be removed when the Blazor Templates run on Helix
- bash: ./src/ProjectTemplates/build.sh --ci --nobl --pack --no-restore --no-build-deps
displayName: Pack Templates (for Template tests)
- bash: ./build.sh --no-build --ci --nobl --test -p:RunTemplateTests=true -p:RunQuarantinedTests=true -p:SkipHelixReadyTests=true
displayName: Run Quarantined Tests
- script: ./restore.sh -ci -nobl
displayName: Restore
- script: ./build.sh --ci --nobl --noBuildRepoTasks --arch arm64 -test --no-build-nodejs --all --projects
$(Build.SourcesDirectory)/eng/helix/helix.proj /p:IsHelixJob=true /p:IsHelixDaily=true /p:RunQuarantinedTests=true
/p:ASPNETCORE_TEST_LOG_DIR=artifacts/log
displayName: Run build.sh helix arm64 target
continueOnError: true
- task: PublishTestResults@2
displayName: Publish Quarantined Test Results
inputs:
testResultsFormat: 'xUnit'
testResultsFiles: '*.xml'
searchFolder: '$(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig)/Quarantined'
condition: always()
env:
HelixApiAccessToken: $(HelixApiAccessToken) # Needed for internal queues
SYSTEM_ACCESSTOKEN: $(System.AccessToken) # We need to set this env var to publish helix results to Azure Dev Ops
installNodeJs: false
artifacts:
- name: Linux_Quarantined_Test_Logs
- name: Helix_arm64_logs
path: artifacts/log/
publishOnError: true
includeForks: true
- name: Linux_Quarantined_Test_Results
path: artifacts/TestResults/
publishOnError: true
includeForks: true

6
.github/CODEOWNERS vendored
View File

@ -9,14 +9,16 @@
/eng/common/ @dotnet-maestro-bot
/eng/Versions.props @dotnet-maestro-bot @dougbu
/eng/Version.Details.xml @dotnet-maestro-bot @dougbu
/src/Components/ @SteveSandersonMS
/src/Components/ @SteveSandersonMS @aspnet-blazor-eng
/src/DefaultBuilder/ @tratcher
/src/Hosting/ @tratcher
/src/Http/ @tratcher @jkotalik
/src/Middleware/ @tratcher
/src/Middleware/HttpsPolicy/ @jkotalik
/src/Middleware/Rewrite/ @jkotalik
# /src/ProjectTemplates/ @ryanbrandenburg
# /src/ProjectTemplates/ @ryanbrandenburg
/src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp/ @aspnet-blazor-eng
/src/ProjectTemplates/Web.ProjectTemplates/content/ComponentsWebAssembly-CSharp/ @aspnet-blazor-eng
/src/Security/ @tratcher
/src/Servers/ @tratcher @jkotalik @halter73
/src/Shared/runtime/ @dotnet/http

View File

@ -68,6 +68,8 @@ To update an existing copy, run:
git submodule update --init --recursive
```
**NOTE** some ISPs have been know to use web filtering software that has caused issues with git repository cloning, if you experience issues cloning this repo please review <https://help.github.com/en/github/authenticating-to-github/using-ssh-over-the-https-port>
## Building in Visual Studio
Before opening our .sln files in Visual Studio or VS Code, you need to perform the following actions.
@ -228,6 +230,16 @@ TargetOsName | The base runtime identifier to build for (win, linux,
After building ASP.NET Core from source, you will need to install and use your local version of ASP.NET Core.
See ["Artifacts"](./Artifacts.md) for more explanation of the different folders produced by a build.
Building installers does not run as part of `build.cmd` run without parameters, so you should opt-in for building them:
```ps1
.\build.cmd -all -pack -arch x64
.\build.cmd -all -pack -arch x86 -noBuildJava
.\build.cmd -buildInstallers
```
*Note*: Additional build steps listed above aren't necessary on Linux or macOS.
* Run the installers produced in `artifacts/installers/{Debug, Release}/` for your platform.
* Add a NuGet.Config to your project directory with the following content:

View File

@ -20,12 +20,23 @@ This will restore, and then publish all the test project including some bootstra
- Required queues: Windows10, OSX, Ubuntu1604
- Full queue matrix: Windows[7, 81, 10], Ubuntu[1604, 1804, 2004], Centos7, Debian[8,9], Redhat7, Fedora28, Arm64 (Win10, Debian9)
- The queues are defined in [Helix.Common.props](https://github.com/dotnet/aspnetcore/blob/master/eng/targets/Helix.Common.props)
aspnetcore-ci runs non quarantined tests against the required helix queues as a required PR check and all builds on all branches.
[aspnetcore-ci](https://dev.azure.com/dnceng/public/_build?definitionId=278) runs non quarantined tests against the required helix queues as a required PR check and all builds on all branches.
aspnetcore-quarantined-tests runs only quarantined tests against the required queues only on master every 4 hours.
[aspnetcore-helix-matrix](https://dev.azure.com/dnceng/public/_build?definitionId=837) runs non quarantined tests against all queues twice a day only on public master.
[aspnetcore-quarantined-pr](https://dev.azure.com/dnceng/public/_build?definitionId=869) runs only quarantined tests against the required queues on PRs and on master every 4 hours.
[aspnetcore-quarantined-tests](https://dev.azure.com/dnceng/public/_build?definitionId=331) runs only quarantined tests against all queues only on public master once a day at 11 PM.
You can always manually queue pipeline runs by clicking on the link to the pipeline -> Run Pipeline -> select your branch/tag and commit
## Checkin process expectations
- The normal PR process has aspnetcore-ci will ensure that the required queues are green.
- If your changes are likely to have cross platform impact that would affect more than the required queues, you should kick off a manual aspnetcore-helix-matrix pipeline run against your branch before merging your PR. Even though aspnetcore-helix-matrix is not a required checkin gate, if your changes break this pipeline, you must either immediately revert your changes, or quarantine the test, its never ok to leave this pipeline in a broken state.
aspnetcore-helix-matrix runs non quarantined tests against all queues twice a day only on public master.
## How do I look at the results of a helix run on Azure Pipelines?

View File

@ -3,3 +3,9 @@ Contributor documentation
The primary audience for documentation in this folder is contributors to ASP.NET Core.
If you are looking for documentation on how to *use* ASP.NET Core, go to <https://docs.asp.net>.
# ASP.NET Core developer workflow
- [Building from source](BuildFromSource.md)
- [Troubleshooting build errors](BuildErrors.md)
- [Artifacts structure](Artifacts.md)

View File

@ -67,7 +67,6 @@
<ProjectReferenceProvider Include="Microsoft.JSInterop.WebAssembly" ProjectPath="$(RepoRoot)src\Components\WebAssembly\JSInterop\src\Microsoft.JSInterop.WebAssembly.csproj" />
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Components.WebAssembly.Server" ProjectPath="$(RepoRoot)src\Components\WebAssembly\Server\src\Microsoft.AspNetCore.Components.WebAssembly.Server.csproj" />
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" ProjectPath="$(RepoRoot)src\Components\WebAssembly\WebAssembly.Authentication\src\Microsoft.AspNetCore.Components.WebAssembly.Authentication.csproj" />
<ProjectReferenceProvider Include="System.Net.Http.WebAssemblyHttpHandler" ProjectPath="$(RepoRoot)src\Components\WebAssembly\WebAssemblyHttpHandler\src\Microsoft.AspNetCore.Components.WebAssembly.HttpHandler.csproj" />
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Components.WebAssembly" ProjectPath="$(RepoRoot)src\Components\WebAssembly\WebAssembly\src\Microsoft.AspNetCore.Components.WebAssembly.csproj" />
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Testing" ProjectPath="$(RepoRoot)src\Testing\src\Microsoft.AspNetCore.Testing.csproj" />
<ProjectReferenceProvider Include="Microsoft.AspNetCore" ProjectPath="$(RepoRoot)src\DefaultBuilder\src\Microsoft.AspNetCore.csproj" RefProjectPath="$(RepoRoot)src\DefaultBuilder\ref\Microsoft.AspNetCore.csproj" />

View File

@ -13,288 +13,288 @@
<Uri>https://github.com/dotnet/blazor</Uri>
<Sha>cc449601d638ffaab58ae9487f0fd010bb178a12</Sha>
</Dependency>
<Dependency Name="dotnet-ef" Version="5.0.0-preview.7.20326.1">
<Dependency Name="dotnet-ef" Version="5.0.0-preview.8.20353.5">
<Uri>https://github.com/dotnet/efcore</Uri>
<Sha>0f2b5023539eb0c5a4fc565af7e59b95c252529f</Sha>
<Sha>dff6a1abc282bb642042b4fe3a643f5b586bcf03</Sha>
</Dependency>
<Dependency Name="Microsoft.EntityFrameworkCore.InMemory" Version="5.0.0-preview.7.20326.1">
<Dependency Name="Microsoft.EntityFrameworkCore.InMemory" Version="5.0.0-preview.8.20353.5">
<Uri>https://github.com/dotnet/efcore</Uri>
<Sha>0f2b5023539eb0c5a4fc565af7e59b95c252529f</Sha>
<Sha>dff6a1abc282bb642042b4fe3a643f5b586bcf03</Sha>
</Dependency>
<Dependency Name="Microsoft.EntityFrameworkCore.Relational" Version="5.0.0-preview.7.20326.1">
<Dependency Name="Microsoft.EntityFrameworkCore.Relational" Version="5.0.0-preview.8.20353.5">
<Uri>https://github.com/dotnet/efcore</Uri>
<Sha>0f2b5023539eb0c5a4fc565af7e59b95c252529f</Sha>
<Sha>dff6a1abc282bb642042b4fe3a643f5b586bcf03</Sha>
</Dependency>
<Dependency Name="Microsoft.EntityFrameworkCore.Sqlite" Version="5.0.0-preview.7.20326.1">
<Dependency Name="Microsoft.EntityFrameworkCore.Sqlite" Version="5.0.0-preview.8.20353.5">
<Uri>https://github.com/dotnet/efcore</Uri>
<Sha>0f2b5023539eb0c5a4fc565af7e59b95c252529f</Sha>
<Sha>dff6a1abc282bb642042b4fe3a643f5b586bcf03</Sha>
</Dependency>
<Dependency Name="Microsoft.EntityFrameworkCore.SqlServer" Version="5.0.0-preview.7.20326.1">
<Dependency Name="Microsoft.EntityFrameworkCore.SqlServer" Version="5.0.0-preview.8.20353.5">
<Uri>https://github.com/dotnet/efcore</Uri>
<Sha>0f2b5023539eb0c5a4fc565af7e59b95c252529f</Sha>
<Sha>dff6a1abc282bb642042b4fe3a643f5b586bcf03</Sha>
</Dependency>
<Dependency Name="Microsoft.EntityFrameworkCore.Tools" Version="5.0.0-preview.7.20326.1">
<Dependency Name="Microsoft.EntityFrameworkCore.Tools" Version="5.0.0-preview.8.20353.5">
<Uri>https://github.com/dotnet/efcore</Uri>
<Sha>0f2b5023539eb0c5a4fc565af7e59b95c252529f</Sha>
<Sha>dff6a1abc282bb642042b4fe3a643f5b586bcf03</Sha>
</Dependency>
<Dependency Name="Microsoft.EntityFrameworkCore" Version="5.0.0-preview.7.20326.1">
<Dependency Name="Microsoft.EntityFrameworkCore" Version="5.0.0-preview.8.20353.5">
<Uri>https://github.com/dotnet/efcore</Uri>
<Sha>0f2b5023539eb0c5a4fc565af7e59b95c252529f</Sha>
<Sha>dff6a1abc282bb642042b4fe3a643f5b586bcf03</Sha>
</Dependency>
<Dependency Name="Microsoft.Extensions.Caching.Abstractions" Version="5.0.0-preview.7.20326.1">
<Dependency Name="Microsoft.Extensions.Caching.Abstractions" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha>
<Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency>
<Dependency Name="Microsoft.Extensions.Caching.Memory" Version="5.0.0-preview.7.20326.1">
<Dependency Name="Microsoft.Extensions.Caching.Memory" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha>
<Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency>
<Dependency Name="Microsoft.Extensions.Configuration.Abstractions" Version="5.0.0-preview.7.20326.1">
<Dependency Name="Microsoft.Extensions.Configuration.Abstractions" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha>
<Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency>
<Dependency Name="Microsoft.Extensions.Configuration.Binder" Version="5.0.0-preview.7.20326.1">
<Dependency Name="Microsoft.Extensions.Configuration.Binder" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha>
<Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency>
<Dependency Name="Microsoft.Extensions.Configuration.CommandLine" Version="5.0.0-preview.7.20326.1">
<Dependency Name="Microsoft.Extensions.Configuration.CommandLine" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha>
<Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency>
<Dependency Name="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="5.0.0-preview.7.20326.1">
<Dependency Name="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha>
<Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency>
<Dependency Name="Microsoft.Extensions.Configuration.FileExtensions" Version="5.0.0-preview.7.20326.1">
<Dependency Name="Microsoft.Extensions.Configuration.FileExtensions" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha>
<Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency>
<Dependency Name="Microsoft.Extensions.Configuration.Ini" Version="5.0.0-preview.7.20326.1">
<Dependency Name="Microsoft.Extensions.Configuration.Ini" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha>
<Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency>
<Dependency Name="Microsoft.Extensions.Configuration.Json" Version="5.0.0-preview.7.20326.1">
<Dependency Name="Microsoft.Extensions.Configuration.Json" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha>
<Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency>
<Dependency Name="Microsoft.Extensions.Configuration.UserSecrets" Version="5.0.0-preview.7.20326.1">
<Dependency Name="Microsoft.Extensions.Configuration.UserSecrets" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha>
<Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency>
<Dependency Name="Microsoft.Extensions.Configuration.Xml" Version="5.0.0-preview.7.20326.1">
<Dependency Name="Microsoft.Extensions.Configuration.Xml" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha>
<Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency>
<Dependency Name="Microsoft.Extensions.Configuration" Version="5.0.0-preview.7.20326.1">
<Dependency Name="Microsoft.Extensions.Configuration" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha>
<Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency>
<Dependency Name="Microsoft.Extensions.DependencyInjection.Abstractions" Version="5.0.0-preview.7.20326.1">
<Dependency Name="Microsoft.Extensions.DependencyInjection.Abstractions" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha>
<Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency>
<Dependency Name="Microsoft.Extensions.DependencyInjection" Version="5.0.0-preview.7.20326.1">
<Dependency Name="Microsoft.Extensions.DependencyInjection" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha>
<Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency>
<Dependency Name="Microsoft.Extensions.FileProviders.Abstractions" Version="5.0.0-preview.7.20326.1">
<Dependency Name="Microsoft.Extensions.FileProviders.Abstractions" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha>
<Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency>
<Dependency Name="Microsoft.Extensions.FileProviders.Composite" Version="5.0.0-preview.7.20326.1">
<Dependency Name="Microsoft.Extensions.FileProviders.Composite" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha>
<Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency>
<Dependency Name="Microsoft.Extensions.FileProviders.Physical" Version="5.0.0-preview.7.20326.1">
<Dependency Name="Microsoft.Extensions.FileProviders.Physical" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha>
<Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency>
<Dependency Name="Microsoft.Extensions.FileSystemGlobbing" Version="5.0.0-preview.7.20326.1">
<Dependency Name="Microsoft.Extensions.FileSystemGlobbing" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha>
<Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency>
<Dependency Name="Microsoft.Extensions.HostFactoryResolver.Sources" Version="5.0.0-preview.7.20326.1">
<Dependency Name="Microsoft.Extensions.HostFactoryResolver.Sources" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha>
<Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency>
<Dependency Name="Microsoft.Extensions.Hosting.Abstractions" Version="5.0.0-preview.7.20326.1">
<Dependency Name="Microsoft.Extensions.Hosting.Abstractions" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha>
<Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency>
<Dependency Name="Microsoft.Extensions.Hosting" Version="5.0.0-preview.7.20326.1">
<Dependency Name="Microsoft.Extensions.Hosting" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha>
<Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency>
<Dependency Name="Microsoft.Extensions.Http" Version="5.0.0-preview.7.20326.1">
<Dependency Name="Microsoft.Extensions.Http" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha>
<Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency>
<Dependency Name="Microsoft.Extensions.Logging.Abstractions" Version="5.0.0-preview.7.20326.1">
<Dependency Name="Microsoft.Extensions.Logging.Abstractions" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha>
<Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency>
<Dependency Name="Microsoft.Extensions.Logging.Configuration" Version="5.0.0-preview.7.20326.1">
<Dependency Name="Microsoft.Extensions.Logging.Configuration" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha>
<Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency>
<Dependency Name="Microsoft.Extensions.Logging.Console" Version="5.0.0-preview.7.20326.1">
<Dependency Name="Microsoft.Extensions.Logging.Console" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha>
<Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency>
<Dependency Name="Microsoft.Extensions.Logging.Debug" Version="5.0.0-preview.7.20326.1">
<Dependency Name="Microsoft.Extensions.Logging.Debug" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha>
<Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency>
<Dependency Name="Microsoft.Extensions.Logging.EventSource" Version="5.0.0-preview.7.20326.1">
<Dependency Name="Microsoft.Extensions.Logging.EventSource" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha>
<Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency>
<Dependency Name="Microsoft.Extensions.Logging.EventLog" Version="5.0.0-preview.7.20326.1">
<Dependency Name="Microsoft.Extensions.Logging.EventLog" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha>
<Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency>
<Dependency Name="Microsoft.Extensions.Logging.TraceSource" Version="5.0.0-preview.7.20326.1">
<Dependency Name="Microsoft.Extensions.Logging.TraceSource" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha>
<Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency>
<Dependency Name="Microsoft.Extensions.Logging" Version="5.0.0-preview.7.20326.1">
<Dependency Name="Microsoft.Extensions.Logging" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha>
<Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency>
<Dependency Name="Microsoft.Extensions.Options.ConfigurationExtensions" Version="5.0.0-preview.7.20326.1">
<Dependency Name="Microsoft.Extensions.Options.ConfigurationExtensions" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha>
<Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency>
<Dependency Name="Microsoft.Extensions.Options.DataAnnotations" Version="5.0.0-preview.7.20326.1">
<Dependency Name="Microsoft.Extensions.Options.DataAnnotations" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha>
<Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency>
<Dependency Name="Microsoft.Extensions.Options" Version="5.0.0-preview.7.20326.1">
<Dependency Name="Microsoft.Extensions.Options" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha>
<Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency>
<Dependency Name="Microsoft.Extensions.Primitives" Version="5.0.0-preview.7.20326.1">
<Dependency Name="Microsoft.Extensions.Primitives" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha>
<Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency>
<Dependency Name="Microsoft.Extensions.Internal.Transport" Version="5.0.0-preview.7.20326.1">
<Dependency Name="Microsoft.Extensions.Internal.Transport" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha>
<Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency>
<Dependency Name="Microsoft.Win32.Registry" Version="5.0.0-preview.7.20326.1">
<Dependency Name="Microsoft.Win32.Registry" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha>
<Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency>
<Dependency Name="Microsoft.Win32.SystemEvents" Version="5.0.0-preview.7.20326.1">
<Dependency Name="Microsoft.Win32.SystemEvents" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha>
<Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency>
<Dependency Name="System.ComponentModel.Annotations" Version="5.0.0-preview.7.20326.1">
<Dependency Name="System.ComponentModel.Annotations" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha>
<Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency>
<Dependency Name="System.Diagnostics.DiagnosticSource" Version="5.0.0-preview.7.20326.1">
<Dependency Name="System.Diagnostics.DiagnosticSource" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha>
<Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency>
<Dependency Name="System.Diagnostics.EventLog" Version="5.0.0-preview.7.20326.1">
<Dependency Name="System.Diagnostics.EventLog" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha>
<Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency>
<Dependency Name="System.Drawing.Common" Version="5.0.0-preview.7.20326.1">
<Dependency Name="System.Drawing.Common" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha>
<Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency>
<Dependency Name="System.IO.Pipelines" Version="5.0.0-preview.7.20326.1">
<Dependency Name="System.IO.Pipelines" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha>
<Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency>
<Dependency Name="System.Net.Http.Json" Version="5.0.0-preview.7.20326.1">
<Dependency Name="System.Net.Http.Json" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha>
<Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency>
<Dependency Name="System.Net.Http.WinHttpHandler" Version="5.0.0-preview.7.20326.1">
<Dependency Name="System.Net.Http.WinHttpHandler" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha>
<Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency>
<Dependency Name="System.Net.WebSockets.WebSocketProtocol" Version="5.0.0-preview.7.20326.1">
<Dependency Name="System.Net.WebSockets.WebSocketProtocol" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha>
<Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency>
<Dependency Name="System.Reflection.Metadata" Version="5.0.0-preview.7.20326.1">
<Dependency Name="System.Reflection.Metadata" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha>
<Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency>
<Dependency Name="System.Runtime.CompilerServices.Unsafe" Version="5.0.0-preview.7.20326.1">
<Dependency Name="System.Runtime.CompilerServices.Unsafe" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha>
<Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency>
<Dependency Name="System.Security.Cryptography.Cng" Version="5.0.0-preview.7.20326.1">
<Dependency Name="System.Security.Cryptography.Cng" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha>
<Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency>
<Dependency Name="System.Security.Cryptography.Pkcs" Version="5.0.0-preview.7.20326.1">
<Dependency Name="System.Security.Cryptography.Pkcs" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha>
<Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency>
<Dependency Name="System.Security.Cryptography.Xml" Version="5.0.0-preview.7.20326.1">
<Dependency Name="System.Security.Cryptography.Xml" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha>
<Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency>
<Dependency Name="System.Security.Permissions" Version="5.0.0-preview.7.20326.1">
<Dependency Name="System.Security.Permissions" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha>
<Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency>
<Dependency Name="System.Security.Principal.Windows" Version="5.0.0-preview.7.20326.1">
<Dependency Name="System.Security.Principal.Windows" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha>
<Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency>
<Dependency Name="System.ServiceProcess.ServiceController" Version="5.0.0-preview.7.20326.1">
<Dependency Name="System.ServiceProcess.ServiceController" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha>
<Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency>
<Dependency Name="System.Text.Encodings.Web" Version="5.0.0-preview.7.20326.1">
<Dependency Name="System.Text.Encodings.Web" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha>
<Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency>
<Dependency Name="System.Text.Json" Version="5.0.0-preview.7.20326.1">
<Dependency Name="System.Text.Json" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha>
<Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency>
<Dependency Name="System.Threading.Channels" Version="5.0.0-preview.7.20326.1">
<Dependency Name="System.Threading.Channels" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha>
<Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency>
<Dependency Name="System.Windows.Extensions" Version="5.0.0-preview.7.20326.1">
<Dependency Name="System.Windows.Extensions" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha>
<Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency>
<Dependency Name="Microsoft.Extensions.DependencyModel" Version="5.0.0-preview.7.20326.1">
<Dependency Name="Microsoft.Extensions.DependencyModel" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha>
<Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency>
<Dependency Name="Microsoft.NETCore.App.Ref" Version="5.0.0-preview.7.20326.1">
<Dependency Name="Microsoft.NETCore.App.Ref" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha>
<Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency>
<!--
Win-x64 is used here because we have picked an arbitrary runtime identifier to flow the version of the latest NETCore.App runtime.
All Runtime.$rid packages should have the same version.
-->
<Dependency Name="Microsoft.NETCore.App.Runtime.win-x64" Version="5.0.0-preview.7.20326.1">
<Dependency Name="Microsoft.NETCore.App.Runtime.win-x64" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha>
<Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency>
<Dependency Name="Microsoft.NETCore.App.Internal" Version="5.0.0-preview.7.20326.1">
<Dependency Name="Microsoft.NETCore.App.Internal" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha>
<Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency>
</ProductDependencies>
<ToolsetDependencies>
<!-- Listed explicitly to workaround https://github.com/dotnet/cli/issues/10528 -->
<Dependency Name="Microsoft.NETCore.Platforms" Version="5.0.0-preview.7.20326.1">
<Dependency Name="Microsoft.NETCore.Platforms" Version="5.0.0-preview.8.20352.6">
<Uri>https://github.com/dotnet/runtime</Uri>
<Sha>b0f97149538e3dabde2267efa326c76a628a30ff</Sha>
<Sha>d3e6947f39ee04b0a6a44bfe6ba1310fbc10c7e5</Sha>
</Dependency>
<Dependency Name="Microsoft.DotNet.GenAPI" Version="5.0.0-beta.20316.1">
<Uri>https://github.com/dotnet/arcade</Uri>

View File

@ -9,7 +9,7 @@
<AspNetCoreMajorVersion>5</AspNetCoreMajorVersion>
<AspNetCoreMinorVersion>0</AspNetCoreMinorVersion>
<AspNetCorePatchVersion>0</AspNetCorePatchVersion>
<PreReleaseVersionIteration>7</PreReleaseVersionIteration>
<PreReleaseVersionIteration>8</PreReleaseVersionIteration>
<!--
When StabilizePackageVersion is set to 'true', this branch will produce stable outputs for 'Shipping' packages
-->
@ -66,79 +66,79 @@
<!-- Packages from dotnet/roslyn -->
<MicrosoftNetCompilersToolsetPackageVersion>3.7.0-4.20319.6</MicrosoftNetCompilersToolsetPackageVersion>
<!-- Packages from dotnet/runtime -->
<MicrosoftExtensionsDependencyModelPackageVersion>5.0.0-preview.7.20326.1</MicrosoftExtensionsDependencyModelPackageVersion>
<MicrosoftNETCoreAppInternalPackageVersion>5.0.0-preview.7.20326.1</MicrosoftNETCoreAppInternalPackageVersion>
<MicrosoftNETCoreAppRefPackageVersion>5.0.0-preview.7.20326.1</MicrosoftNETCoreAppRefPackageVersion>
<MicrosoftNETCoreAppRuntimewinx64PackageVersion>5.0.0-preview.7.20326.1</MicrosoftNETCoreAppRuntimewinx64PackageVersion>
<MicrosoftWin32RegistryPackageVersion>5.0.0-preview.7.20326.1</MicrosoftWin32RegistryPackageVersion>
<MicrosoftWin32SystemEventsPackageVersion>5.0.0-preview.7.20326.1</MicrosoftWin32SystemEventsPackageVersion>
<MicrosoftExtensionsCachingAbstractionsPackageVersion>5.0.0-preview.7.20326.1</MicrosoftExtensionsCachingAbstractionsPackageVersion>
<MicrosoftExtensionsCachingMemoryPackageVersion>5.0.0-preview.7.20326.1</MicrosoftExtensionsCachingMemoryPackageVersion>
<MicrosoftExtensionsConfigurationAbstractionsPackageVersion>5.0.0-preview.7.20326.1</MicrosoftExtensionsConfigurationAbstractionsPackageVersion>
<MicrosoftExtensionsConfigurationBinderPackageVersion>5.0.0-preview.7.20326.1</MicrosoftExtensionsConfigurationBinderPackageVersion>
<MicrosoftExtensionsConfigurationCommandLinePackageVersion>5.0.0-preview.7.20326.1</MicrosoftExtensionsConfigurationCommandLinePackageVersion>
<MicrosoftExtensionsConfigurationEnvironmentVariablesPackageVersion>5.0.0-preview.7.20326.1</MicrosoftExtensionsConfigurationEnvironmentVariablesPackageVersion>
<MicrosoftExtensionsConfigurationFileExtensionsPackageVersion>5.0.0-preview.7.20326.1</MicrosoftExtensionsConfigurationFileExtensionsPackageVersion>
<MicrosoftExtensionsConfigurationIniPackageVersion>5.0.0-preview.7.20326.1</MicrosoftExtensionsConfigurationIniPackageVersion>
<MicrosoftExtensionsConfigurationJsonPackageVersion>5.0.0-preview.7.20326.1</MicrosoftExtensionsConfigurationJsonPackageVersion>
<MicrosoftExtensionsConfigurationPackageVersion>5.0.0-preview.7.20326.1</MicrosoftExtensionsConfigurationPackageVersion>
<MicrosoftExtensionsConfigurationUserSecretsPackageVersion>5.0.0-preview.7.20326.1</MicrosoftExtensionsConfigurationUserSecretsPackageVersion>
<MicrosoftExtensionsConfigurationXmlPackageVersion>5.0.0-preview.7.20326.1</MicrosoftExtensionsConfigurationXmlPackageVersion>
<MicrosoftExtensionsDependencyInjectionAbstractionsPackageVersion>5.0.0-preview.7.20326.1</MicrosoftExtensionsDependencyInjectionAbstractionsPackageVersion>
<MicrosoftExtensionsDependencyInjectionPackageVersion>5.0.0-preview.7.20326.1</MicrosoftExtensionsDependencyInjectionPackageVersion>
<MicrosoftExtensionsFileProvidersAbstractionsPackageVersion>5.0.0-preview.7.20326.1</MicrosoftExtensionsFileProvidersAbstractionsPackageVersion>
<MicrosoftExtensionsFileProvidersCompositePackageVersion>5.0.0-preview.7.20326.1</MicrosoftExtensionsFileProvidersCompositePackageVersion>
<MicrosoftExtensionsFileProvidersPhysicalPackageVersion>5.0.0-preview.7.20326.1</MicrosoftExtensionsFileProvidersPhysicalPackageVersion>
<MicrosoftExtensionsFileSystemGlobbingPackageVersion>5.0.0-preview.7.20326.1</MicrosoftExtensionsFileSystemGlobbingPackageVersion>
<MicrosoftExtensionsHostFactoryResolverSourcesPackageVersion>5.0.0-preview.7.20326.1</MicrosoftExtensionsHostFactoryResolverSourcesPackageVersion>
<MicrosoftExtensionsHostingAbstractionsPackageVersion>5.0.0-preview.7.20326.1</MicrosoftExtensionsHostingAbstractionsPackageVersion>
<MicrosoftExtensionsHostingPackageVersion>5.0.0-preview.7.20326.1</MicrosoftExtensionsHostingPackageVersion>
<MicrosoftExtensionsHttpPackageVersion>5.0.0-preview.7.20326.1</MicrosoftExtensionsHttpPackageVersion>
<MicrosoftExtensionsLoggingAbstractionsPackageVersion>5.0.0-preview.7.20326.1</MicrosoftExtensionsLoggingAbstractionsPackageVersion>
<MicrosoftExtensionsLoggingConfigurationPackageVersion>5.0.0-preview.7.20326.1</MicrosoftExtensionsLoggingConfigurationPackageVersion>
<MicrosoftExtensionsLoggingConsolePackageVersion>5.0.0-preview.7.20326.1</MicrosoftExtensionsLoggingConsolePackageVersion>
<MicrosoftExtensionsLoggingDebugPackageVersion>5.0.0-preview.7.20326.1</MicrosoftExtensionsLoggingDebugPackageVersion>
<MicrosoftExtensionsLoggingEventSourcePackageVersion>5.0.0-preview.7.20326.1</MicrosoftExtensionsLoggingEventSourcePackageVersion>
<MicrosoftExtensionsLoggingEventLogPackageVersion>5.0.0-preview.7.20326.1</MicrosoftExtensionsLoggingEventLogPackageVersion>
<MicrosoftExtensionsLoggingPackageVersion>5.0.0-preview.7.20326.1</MicrosoftExtensionsLoggingPackageVersion>
<MicrosoftExtensionsLoggingTraceSourcePackageVersion>5.0.0-preview.7.20326.1</MicrosoftExtensionsLoggingTraceSourcePackageVersion>
<MicrosoftExtensionsOptionsConfigurationExtensionsPackageVersion>5.0.0-preview.7.20326.1</MicrosoftExtensionsOptionsConfigurationExtensionsPackageVersion>
<MicrosoftExtensionsOptionsDataAnnotationsPackageVersion>5.0.0-preview.7.20326.1</MicrosoftExtensionsOptionsDataAnnotationsPackageVersion>
<MicrosoftExtensionsOptionsPackageVersion>5.0.0-preview.7.20326.1</MicrosoftExtensionsOptionsPackageVersion>
<MicrosoftExtensionsPrimitivesPackageVersion>5.0.0-preview.7.20326.1</MicrosoftExtensionsPrimitivesPackageVersion>
<MicrosoftExtensionsInternalTransportPackageVersion>5.0.0-preview.7.20326.1</MicrosoftExtensionsInternalTransportPackageVersion>
<SystemComponentModelAnnotationsPackageVersion>5.0.0-preview.7.20326.1</SystemComponentModelAnnotationsPackageVersion>
<SystemDiagnosticsDiagnosticSourcePackageVersion>5.0.0-preview.7.20326.1</SystemDiagnosticsDiagnosticSourcePackageVersion>
<SystemDiagnosticsEventLogPackageVersion>5.0.0-preview.7.20326.1</SystemDiagnosticsEventLogPackageVersion>
<SystemDrawingCommonPackageVersion>5.0.0-preview.7.20326.1</SystemDrawingCommonPackageVersion>
<SystemIOPipelinesPackageVersion>5.0.0-preview.7.20326.1</SystemIOPipelinesPackageVersion>
<SystemNetHttpJsonPackageVersion>5.0.0-preview.7.20326.1</SystemNetHttpJsonPackageVersion>
<SystemNetHttpWinHttpHandlerPackageVersion>5.0.0-preview.7.20326.1</SystemNetHttpWinHttpHandlerPackageVersion>
<SystemNetWebSocketsWebSocketProtocolPackageVersion>5.0.0-preview.7.20326.1</SystemNetWebSocketsWebSocketProtocolPackageVersion>
<SystemReflectionMetadataPackageVersion>5.0.0-preview.7.20326.1</SystemReflectionMetadataPackageVersion>
<SystemRuntimeCompilerServicesUnsafePackageVersion>5.0.0-preview.7.20326.1</SystemRuntimeCompilerServicesUnsafePackageVersion>
<SystemSecurityCryptographyCngPackageVersion>5.0.0-preview.7.20326.1</SystemSecurityCryptographyCngPackageVersion>
<SystemSecurityCryptographyPkcsPackageVersion>5.0.0-preview.7.20326.1</SystemSecurityCryptographyPkcsPackageVersion>
<SystemSecurityCryptographyXmlPackageVersion>5.0.0-preview.7.20326.1</SystemSecurityCryptographyXmlPackageVersion>
<SystemSecurityPermissionsPackageVersion>5.0.0-preview.7.20326.1</SystemSecurityPermissionsPackageVersion>
<SystemSecurityPrincipalWindowsPackageVersion>5.0.0-preview.7.20326.1</SystemSecurityPrincipalWindowsPackageVersion>
<SystemServiceProcessServiceControllerPackageVersion>5.0.0-preview.7.20326.1</SystemServiceProcessServiceControllerPackageVersion>
<SystemTextEncodingsWebPackageVersion>5.0.0-preview.7.20326.1</SystemTextEncodingsWebPackageVersion>
<SystemTextJsonPackageVersion>5.0.0-preview.7.20326.1</SystemTextJsonPackageVersion>
<SystemThreadingChannelsPackageVersion>5.0.0-preview.7.20326.1</SystemThreadingChannelsPackageVersion>
<SystemWindowsExtensionsPackageVersion>5.0.0-preview.7.20326.1</SystemWindowsExtensionsPackageVersion>
<MicrosoftExtensionsDependencyModelPackageVersion>5.0.0-preview.8.20352.6</MicrosoftExtensionsDependencyModelPackageVersion>
<MicrosoftNETCoreAppInternalPackageVersion>5.0.0-preview.8.20352.6</MicrosoftNETCoreAppInternalPackageVersion>
<MicrosoftNETCoreAppRefPackageVersion>5.0.0-preview.8.20352.6</MicrosoftNETCoreAppRefPackageVersion>
<MicrosoftNETCoreAppRuntimewinx64PackageVersion>5.0.0-preview.8.20352.6</MicrosoftNETCoreAppRuntimewinx64PackageVersion>
<MicrosoftWin32RegistryPackageVersion>5.0.0-preview.8.20352.6</MicrosoftWin32RegistryPackageVersion>
<MicrosoftWin32SystemEventsPackageVersion>5.0.0-preview.8.20352.6</MicrosoftWin32SystemEventsPackageVersion>
<MicrosoftExtensionsCachingAbstractionsPackageVersion>5.0.0-preview.8.20352.6</MicrosoftExtensionsCachingAbstractionsPackageVersion>
<MicrosoftExtensionsCachingMemoryPackageVersion>5.0.0-preview.8.20352.6</MicrosoftExtensionsCachingMemoryPackageVersion>
<MicrosoftExtensionsConfigurationAbstractionsPackageVersion>5.0.0-preview.8.20352.6</MicrosoftExtensionsConfigurationAbstractionsPackageVersion>
<MicrosoftExtensionsConfigurationBinderPackageVersion>5.0.0-preview.8.20352.6</MicrosoftExtensionsConfigurationBinderPackageVersion>
<MicrosoftExtensionsConfigurationCommandLinePackageVersion>5.0.0-preview.8.20352.6</MicrosoftExtensionsConfigurationCommandLinePackageVersion>
<MicrosoftExtensionsConfigurationEnvironmentVariablesPackageVersion>5.0.0-preview.8.20352.6</MicrosoftExtensionsConfigurationEnvironmentVariablesPackageVersion>
<MicrosoftExtensionsConfigurationFileExtensionsPackageVersion>5.0.0-preview.8.20352.6</MicrosoftExtensionsConfigurationFileExtensionsPackageVersion>
<MicrosoftExtensionsConfigurationIniPackageVersion>5.0.0-preview.8.20352.6</MicrosoftExtensionsConfigurationIniPackageVersion>
<MicrosoftExtensionsConfigurationJsonPackageVersion>5.0.0-preview.8.20352.6</MicrosoftExtensionsConfigurationJsonPackageVersion>
<MicrosoftExtensionsConfigurationPackageVersion>5.0.0-preview.8.20352.6</MicrosoftExtensionsConfigurationPackageVersion>
<MicrosoftExtensionsConfigurationUserSecretsPackageVersion>5.0.0-preview.8.20352.6</MicrosoftExtensionsConfigurationUserSecretsPackageVersion>
<MicrosoftExtensionsConfigurationXmlPackageVersion>5.0.0-preview.8.20352.6</MicrosoftExtensionsConfigurationXmlPackageVersion>
<MicrosoftExtensionsDependencyInjectionAbstractionsPackageVersion>5.0.0-preview.8.20352.6</MicrosoftExtensionsDependencyInjectionAbstractionsPackageVersion>
<MicrosoftExtensionsDependencyInjectionPackageVersion>5.0.0-preview.8.20352.6</MicrosoftExtensionsDependencyInjectionPackageVersion>
<MicrosoftExtensionsFileProvidersAbstractionsPackageVersion>5.0.0-preview.8.20352.6</MicrosoftExtensionsFileProvidersAbstractionsPackageVersion>
<MicrosoftExtensionsFileProvidersCompositePackageVersion>5.0.0-preview.8.20352.6</MicrosoftExtensionsFileProvidersCompositePackageVersion>
<MicrosoftExtensionsFileProvidersPhysicalPackageVersion>5.0.0-preview.8.20352.6</MicrosoftExtensionsFileProvidersPhysicalPackageVersion>
<MicrosoftExtensionsFileSystemGlobbingPackageVersion>5.0.0-preview.8.20352.6</MicrosoftExtensionsFileSystemGlobbingPackageVersion>
<MicrosoftExtensionsHostFactoryResolverSourcesPackageVersion>5.0.0-preview.8.20352.6</MicrosoftExtensionsHostFactoryResolverSourcesPackageVersion>
<MicrosoftExtensionsHostingAbstractionsPackageVersion>5.0.0-preview.8.20352.6</MicrosoftExtensionsHostingAbstractionsPackageVersion>
<MicrosoftExtensionsHostingPackageVersion>5.0.0-preview.8.20352.6</MicrosoftExtensionsHostingPackageVersion>
<MicrosoftExtensionsHttpPackageVersion>5.0.0-preview.8.20352.6</MicrosoftExtensionsHttpPackageVersion>
<MicrosoftExtensionsLoggingAbstractionsPackageVersion>5.0.0-preview.8.20352.6</MicrosoftExtensionsLoggingAbstractionsPackageVersion>
<MicrosoftExtensionsLoggingConfigurationPackageVersion>5.0.0-preview.8.20352.6</MicrosoftExtensionsLoggingConfigurationPackageVersion>
<MicrosoftExtensionsLoggingConsolePackageVersion>5.0.0-preview.8.20352.6</MicrosoftExtensionsLoggingConsolePackageVersion>
<MicrosoftExtensionsLoggingDebugPackageVersion>5.0.0-preview.8.20352.6</MicrosoftExtensionsLoggingDebugPackageVersion>
<MicrosoftExtensionsLoggingEventSourcePackageVersion>5.0.0-preview.8.20352.6</MicrosoftExtensionsLoggingEventSourcePackageVersion>
<MicrosoftExtensionsLoggingEventLogPackageVersion>5.0.0-preview.8.20352.6</MicrosoftExtensionsLoggingEventLogPackageVersion>
<MicrosoftExtensionsLoggingPackageVersion>5.0.0-preview.8.20352.6</MicrosoftExtensionsLoggingPackageVersion>
<MicrosoftExtensionsLoggingTraceSourcePackageVersion>5.0.0-preview.8.20352.6</MicrosoftExtensionsLoggingTraceSourcePackageVersion>
<MicrosoftExtensionsOptionsConfigurationExtensionsPackageVersion>5.0.0-preview.8.20352.6</MicrosoftExtensionsOptionsConfigurationExtensionsPackageVersion>
<MicrosoftExtensionsOptionsDataAnnotationsPackageVersion>5.0.0-preview.8.20352.6</MicrosoftExtensionsOptionsDataAnnotationsPackageVersion>
<MicrosoftExtensionsOptionsPackageVersion>5.0.0-preview.8.20352.6</MicrosoftExtensionsOptionsPackageVersion>
<MicrosoftExtensionsPrimitivesPackageVersion>5.0.0-preview.8.20352.6</MicrosoftExtensionsPrimitivesPackageVersion>
<MicrosoftExtensionsInternalTransportPackageVersion>5.0.0-preview.8.20352.6</MicrosoftExtensionsInternalTransportPackageVersion>
<SystemComponentModelAnnotationsPackageVersion>5.0.0-preview.8.20352.6</SystemComponentModelAnnotationsPackageVersion>
<SystemDiagnosticsDiagnosticSourcePackageVersion>5.0.0-preview.8.20352.6</SystemDiagnosticsDiagnosticSourcePackageVersion>
<SystemDiagnosticsEventLogPackageVersion>5.0.0-preview.8.20352.6</SystemDiagnosticsEventLogPackageVersion>
<SystemDrawingCommonPackageVersion>5.0.0-preview.8.20352.6</SystemDrawingCommonPackageVersion>
<SystemIOPipelinesPackageVersion>5.0.0-preview.8.20352.6</SystemIOPipelinesPackageVersion>
<SystemNetHttpJsonPackageVersion>5.0.0-preview.8.20352.6</SystemNetHttpJsonPackageVersion>
<SystemNetHttpWinHttpHandlerPackageVersion>5.0.0-preview.8.20352.6</SystemNetHttpWinHttpHandlerPackageVersion>
<SystemNetWebSocketsWebSocketProtocolPackageVersion>5.0.0-preview.8.20352.6</SystemNetWebSocketsWebSocketProtocolPackageVersion>
<SystemReflectionMetadataPackageVersion>5.0.0-preview.8.20352.6</SystemReflectionMetadataPackageVersion>
<SystemRuntimeCompilerServicesUnsafePackageVersion>5.0.0-preview.8.20352.6</SystemRuntimeCompilerServicesUnsafePackageVersion>
<SystemSecurityCryptographyCngPackageVersion>5.0.0-preview.8.20352.6</SystemSecurityCryptographyCngPackageVersion>
<SystemSecurityCryptographyPkcsPackageVersion>5.0.0-preview.8.20352.6</SystemSecurityCryptographyPkcsPackageVersion>
<SystemSecurityCryptographyXmlPackageVersion>5.0.0-preview.8.20352.6</SystemSecurityCryptographyXmlPackageVersion>
<SystemSecurityPermissionsPackageVersion>5.0.0-preview.8.20352.6</SystemSecurityPermissionsPackageVersion>
<SystemSecurityPrincipalWindowsPackageVersion>5.0.0-preview.8.20352.6</SystemSecurityPrincipalWindowsPackageVersion>
<SystemServiceProcessServiceControllerPackageVersion>5.0.0-preview.8.20352.6</SystemServiceProcessServiceControllerPackageVersion>
<SystemTextEncodingsWebPackageVersion>5.0.0-preview.8.20352.6</SystemTextEncodingsWebPackageVersion>
<SystemTextJsonPackageVersion>5.0.0-preview.8.20352.6</SystemTextJsonPackageVersion>
<SystemThreadingChannelsPackageVersion>5.0.0-preview.8.20352.6</SystemThreadingChannelsPackageVersion>
<SystemWindowsExtensionsPackageVersion>5.0.0-preview.8.20352.6</SystemWindowsExtensionsPackageVersion>
<!-- Only listed explicitly to workaround https://github.com/dotnet/cli/issues/10528 -->
<MicrosoftNETCorePlatformsPackageVersion>5.0.0-preview.7.20326.1</MicrosoftNETCorePlatformsPackageVersion>
<MicrosoftNETCorePlatformsPackageVersion>5.0.0-preview.8.20352.6</MicrosoftNETCorePlatformsPackageVersion>
<!-- Packages from dotnet/blazor -->
<MicrosoftAspNetCoreComponentsWebAssemblyRuntimePackageVersion>3.2.0</MicrosoftAspNetCoreComponentsWebAssemblyRuntimePackageVersion>
<!-- Packages from dotnet/efcore -->
<dotnetefPackageVersion>5.0.0-preview.7.20326.1</dotnetefPackageVersion>
<MicrosoftEntityFrameworkCoreInMemoryPackageVersion>5.0.0-preview.7.20326.1</MicrosoftEntityFrameworkCoreInMemoryPackageVersion>
<MicrosoftEntityFrameworkCoreRelationalPackageVersion>5.0.0-preview.7.20326.1</MicrosoftEntityFrameworkCoreRelationalPackageVersion>
<MicrosoftEntityFrameworkCoreSqlitePackageVersion>5.0.0-preview.7.20326.1</MicrosoftEntityFrameworkCoreSqlitePackageVersion>
<MicrosoftEntityFrameworkCoreSqlServerPackageVersion>5.0.0-preview.7.20326.1</MicrosoftEntityFrameworkCoreSqlServerPackageVersion>
<MicrosoftEntityFrameworkCoreToolsPackageVersion>5.0.0-preview.7.20326.1</MicrosoftEntityFrameworkCoreToolsPackageVersion>
<MicrosoftEntityFrameworkCorePackageVersion>5.0.0-preview.7.20326.1</MicrosoftEntityFrameworkCorePackageVersion>
<dotnetefPackageVersion>5.0.0-preview.8.20353.5</dotnetefPackageVersion>
<MicrosoftEntityFrameworkCoreInMemoryPackageVersion>5.0.0-preview.8.20353.5</MicrosoftEntityFrameworkCoreInMemoryPackageVersion>
<MicrosoftEntityFrameworkCoreRelationalPackageVersion>5.0.0-preview.8.20353.5</MicrosoftEntityFrameworkCoreRelationalPackageVersion>
<MicrosoftEntityFrameworkCoreSqlitePackageVersion>5.0.0-preview.8.20353.5</MicrosoftEntityFrameworkCoreSqlitePackageVersion>
<MicrosoftEntityFrameworkCoreSqlServerPackageVersion>5.0.0-preview.8.20353.5</MicrosoftEntityFrameworkCoreSqlServerPackageVersion>
<MicrosoftEntityFrameworkCoreToolsPackageVersion>5.0.0-preview.8.20353.5</MicrosoftEntityFrameworkCoreToolsPackageVersion>
<MicrosoftEntityFrameworkCorePackageVersion>5.0.0-preview.8.20353.5</MicrosoftEntityFrameworkCorePackageVersion>
</PropertyGroup>
<!--
@ -189,16 +189,16 @@
<MicrosoftCodeAnalysisCSharpPackageVersion>3.4.0</MicrosoftCodeAnalysisCSharpPackageVersion>
<MicrosoftCodeAnalysisCSharpWorkspacesPackageVersion>3.4.0</MicrosoftCodeAnalysisCSharpWorkspacesPackageVersion>
<MicrosoftIdentityModelClientsActiveDirectoryPackageVersion>3.19.8</MicrosoftIdentityModelClientsActiveDirectoryPackageVersion>
<MicrosoftIdentityModelLoggingPackageVersion>6.6.0</MicrosoftIdentityModelLoggingPackageVersion>
<MicrosoftIdentityModelProtocolsOpenIdConnectPackageVersion>6.6.0</MicrosoftIdentityModelProtocolsOpenIdConnectPackageVersion>
<MicrosoftIdentityModelProtocolsWsFederationPackageVersion>6.6.0</MicrosoftIdentityModelProtocolsWsFederationPackageVersion>
<MicrosoftIdentityModelLoggingPackageVersion>5.5.0</MicrosoftIdentityModelLoggingPackageVersion>
<MicrosoftIdentityModelProtocolsOpenIdConnectPackageVersion>5.5.0</MicrosoftIdentityModelProtocolsOpenIdConnectPackageVersion>
<MicrosoftIdentityModelProtocolsWsFederationPackageVersion>5.5.0</MicrosoftIdentityModelProtocolsWsFederationPackageVersion>
<MicrosoftInternalAspNetCoreH2SpecAllPackageVersion>2.2.1</MicrosoftInternalAspNetCoreH2SpecAllPackageVersion>
<MicrosoftNETCoreWindowsApiSetsPackageVersion>1.0.1</MicrosoftNETCoreWindowsApiSetsPackageVersion>
<MicrosoftOwinSecurityCookiesPackageVersion>3.0.1</MicrosoftOwinSecurityCookiesPackageVersion>
<MicrosoftOwinTestingPackageVersion>3.0.1</MicrosoftOwinTestingPackageVersion>
<MicrosoftWebAdministrationPackageVersion>11.1.0</MicrosoftWebAdministrationPackageVersion>
<MicrosoftWebXdtPackageVersion>1.4.0</MicrosoftWebXdtPackageVersion>
<SystemIdentityModelTokensJwtPackageVersion>6.6.0</SystemIdentityModelTokensJwtPackageVersion>
<SystemIdentityModelTokensJwtPackageVersion>5.5.0</SystemIdentityModelTokensJwtPackageVersion>
<!-- Packages from 2.1/2.2 branches used for site extension build -->
<MicrosoftAspNetCoreAzureAppServicesSiteExtension21PackageVersion>2.1.1</MicrosoftAspNetCoreAzureAppServicesSiteExtension21PackageVersion>
<MicrosoftAspNetCoreAzureAppServicesSiteExtension22PackageVersion>2.2.0</MicrosoftAspNetCoreAzureAppServicesSiteExtension22PackageVersion>
@ -221,7 +221,7 @@
<IdentityServer4EntityFrameworkStoragePackageVersion>3.0.0</IdentityServer4EntityFrameworkStoragePackageVersion>
<MessagePackPackageVersion>2.1.90</MessagePackPackageVersion>
<MoqPackageVersion>4.10.0</MoqPackageVersion>
<MonoCecilPackageVersion>0.10.1</MonoCecilPackageVersion>
<MonoCecilPackageVersion>0.11.2</MonoCecilPackageVersion>
<NewtonsoftJsonBsonPackageVersion>1.0.2</NewtonsoftJsonBsonPackageVersion>
<NewtonsoftJsonPackageVersion>12.0.2</NewtonsoftJsonPackageVersion>
<!-- Begin: STOP!!! Razor need to reference the version of JSON that our HOSTS support. -->

View File

@ -1,28 +0,0 @@
FROM microsoft/dotnet:2.1.0-preview1-runtime-deps-alpine
ARG USER
ARG USER_ID
ARG GROUP_ID
ARG WORKDIR
WORKDIR ${WORKDIR}
RUN mkdir -p "/home/$USER" && chown "${USER_ID}:${GROUP_ID}" "/home/$USER"
ENV HOME "/home/$USER"
RUN apk add --no-cache \
bash \
wget \
git \
jq \
curl \
icu-libs \
openssl
USER $USER_ID:$GROUP_ID
# Disable the invariant mode (set in base image)
ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT false
ENV LC_ALL en_US.UTF-8
ENV LANG en_US.UTF-8
# Skip package initilization
ENV DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1

View File

@ -1,19 +0,0 @@
FROM mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-16.04-cross-arm64-alpine10fcdcf-20190208200917
ARG USER
ARG USER_ID
ARG GROUP_ID
ARG WORKDIR
WORKDIR ${WORKDIR}
RUN mkdir -p "/home/$USER" && chown "${USER_ID}:${GROUP_ID}" "/home/$USER"
ENV HOME "/home/$USER"
USER $USER_ID:$GROUP_ID
# Disable the invariant mode (set in base image)
ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT false
ENV LC_ALL en_US.UTF-8
ENV LANG en_US.UTF-8
# Skip package initilization
ENV DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1

View File

@ -39,7 +39,7 @@
</ItemGroup>
<!-- arm64 queues for helix-matrix.yml pipeline -->
<ItemGroup Condition="'$(IsWindowsOnlyTest)' != 'true' AND '$(TargetArchitecture)' == 'arm64' AND '$(IsHelixDaily)' == 'true' AND '$(RunQuarantinedTests)' != 'true'">
<ItemGroup Condition="'$(IsWindowsOnlyTest)' != 'true' AND '$(TargetArchitecture)' == 'arm64' AND '$(IsHelixDaily)' == 'true'">
<HelixAvailableTargetQueue Include="Windows.10.Arm64.Open" Platform="Windows" />
<HelixAvailableTargetQueue Include="(Debian.9.Arm64.Open)Ubuntu.1804.Armarch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-9-helix-arm64v8-a12566d-20190807161036" Platform="Linux" />
</ItemGroup>

View File

@ -257,8 +257,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Compon
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Authentication", "Authentication", "{81250121-9B43-40B1-BF11-CE4458F2676C}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Components.WebAssembly.HttpHandler", "WebAssembly\WebAssemblyHttpHandler\src\Microsoft.AspNetCore.Components.WebAssembly.HttpHandler.csproj", "{031AD67E-DDDE-4A20-874A-8D0A791C6F4C}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Wasm.Authentication.Client", "WebAssembly\testassets\Wasm.Authentication.Client\Wasm.Authentication.Client.csproj", "{5F12F7B9-70BE-48F6-922A-3A1E87EE6BF0}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Wasm.Authentication.Shared", "WebAssembly\testassets\Wasm.Authentication.Shared\Wasm.Authentication.Shared.csproj", "{630D5388-7A2F-42DD-9154-1F62A18CBB69}"
@ -1523,18 +1521,6 @@ Global
{6B0D6C08-FC30-4822-9464-4D24FF4CDC17}.Release|x64.Build.0 = Release|Any CPU
{6B0D6C08-FC30-4822-9464-4D24FF4CDC17}.Release|x86.ActiveCfg = Release|Any CPU
{6B0D6C08-FC30-4822-9464-4D24FF4CDC17}.Release|x86.Build.0 = Release|Any CPU
{031AD67E-DDDE-4A20-874A-8D0A791C6F4C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{031AD67E-DDDE-4A20-874A-8D0A791C6F4C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{031AD67E-DDDE-4A20-874A-8D0A791C6F4C}.Debug|x64.ActiveCfg = Debug|Any CPU
{031AD67E-DDDE-4A20-874A-8D0A791C6F4C}.Debug|x64.Build.0 = Debug|Any CPU
{031AD67E-DDDE-4A20-874A-8D0A791C6F4C}.Debug|x86.ActiveCfg = Debug|Any CPU
{031AD67E-DDDE-4A20-874A-8D0A791C6F4C}.Debug|x86.Build.0 = Debug|Any CPU
{031AD67E-DDDE-4A20-874A-8D0A791C6F4C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{031AD67E-DDDE-4A20-874A-8D0A791C6F4C}.Release|Any CPU.Build.0 = Release|Any CPU
{031AD67E-DDDE-4A20-874A-8D0A791C6F4C}.Release|x64.ActiveCfg = Release|Any CPU
{031AD67E-DDDE-4A20-874A-8D0A791C6F4C}.Release|x64.Build.0 = Release|Any CPU
{031AD67E-DDDE-4A20-874A-8D0A791C6F4C}.Release|x86.ActiveCfg = Release|Any CPU
{031AD67E-DDDE-4A20-874A-8D0A791C6F4C}.Release|x86.Build.0 = Release|Any CPU
{5F12F7B9-70BE-48F6-922A-3A1E87EE6BF0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5F12F7B9-70BE-48F6-922A-3A1E87EE6BF0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5F12F7B9-70BE-48F6-922A-3A1E87EE6BF0}.Debug|x64.ActiveCfg = Debug|Any CPU
@ -1687,7 +1673,6 @@ Global
{5CD61479-5181-4A5B-B90F-9F34316248B3} = {81250121-9B43-40B1-BF11-CE4458F2676C}
{6B0D6C08-FC30-4822-9464-4D24FF4CDC17} = {81250121-9B43-40B1-BF11-CE4458F2676C}
{81250121-9B43-40B1-BF11-CE4458F2676C} = {7260DED9-22A9-4E9D-92F4-5E8A4404DEAF}
{031AD67E-DDDE-4A20-874A-8D0A791C6F4C} = {7260DED9-22A9-4E9D-92F4-5E8A4404DEAF}
{5F12F7B9-70BE-48F6-922A-3A1E87EE6BF0} = {A7ABAC29-F73F-456D-AE54-46842CFC2E10}
{630D5388-7A2F-42DD-9154-1F62A18CBB69} = {A7ABAC29-F73F-456D-AE54-46842CFC2E10}
{A062ACCE-AB0D-4569-9548-4BC0D9A9174B} = {2FC10057-7A0A-4E34-8302-879925BC0102}

View File

@ -125,8 +125,14 @@ namespace Microsoft.AspNetCore.Components
private readonly object _dummy;
private readonly int _dummyPrimitive;
public ElementReference(string id) { throw null; }
public ElementReference(string id, Microsoft.AspNetCore.Components.ElementReferenceContext? context) { throw null; }
public Microsoft.AspNetCore.Components.ElementReferenceContext? Context { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } }
public string Id { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } }
}
public abstract partial class ElementReferenceContext
{
protected ElementReferenceContext() { }
}
[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
public readonly partial struct EventCallback
{
@ -468,6 +474,7 @@ namespace Microsoft.AspNetCore.Components.RenderTree
{
public Renderer(System.IServiceProvider serviceProvider, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory) { }
public abstract Microsoft.AspNetCore.Components.Dispatcher Dispatcher { get; }
protected internal Microsoft.AspNetCore.Components.ElementReferenceContext? ElementReferenceContext { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] protected set { } }
public event System.UnhandledExceptionEventHandler UnhandledSynchronizationException { add { } remove { } }
protected internal int AssignRootComponentId(Microsoft.AspNetCore.Components.IComponent component) { throw null; }
public virtual System.Threading.Tasks.Task DispatchEventAsync(ulong eventHandlerId, Microsoft.AspNetCore.Components.RenderTree.EventFieldInfo fieldInfo, System.EventArgs eventArgs) { throw null; }

View File

@ -125,8 +125,14 @@ namespace Microsoft.AspNetCore.Components
private readonly object _dummy;
private readonly int _dummyPrimitive;
public ElementReference(string id) { throw null; }
public ElementReference(string id, Microsoft.AspNetCore.Components.ElementReferenceContext? context) { throw null; }
public Microsoft.AspNetCore.Components.ElementReferenceContext? Context { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } }
public string Id { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } }
}
public abstract partial class ElementReferenceContext
{
protected ElementReferenceContext() { }
}
[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
public readonly partial struct EventCallback
{
@ -467,6 +473,7 @@ namespace Microsoft.AspNetCore.Components.RenderTree
{
public Renderer(System.IServiceProvider serviceProvider, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory) { }
public abstract Microsoft.AspNetCore.Components.Dispatcher Dispatcher { get; }
protected internal Microsoft.AspNetCore.Components.ElementReferenceContext? ElementReferenceContext { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] protected set { } }
public event System.UnhandledExceptionEventHandler UnhandledSynchronizationException { add { } remove { } }
protected internal int AssignRootComponentId(Microsoft.AspNetCore.Components.IComponent component) { throw null; }
public virtual System.Threading.Tasks.Task DispatchEventAsync(ulong eventHandlerId, Microsoft.AspNetCore.Components.RenderTree.EventFieldInfo fieldInfo, System.EventArgs eventArgs) { throw null; }

View File

@ -23,13 +23,32 @@ namespace Microsoft.AspNetCore.Components
/// </remarks>
public string Id { get; }
public ElementReference(string id)
/// <summary>
/// Gets the <see cref="ElementReferenceContext"/> instance.
/// </summary>
public ElementReferenceContext? Context { get; }
/// <summary>
/// Instantiates a new <see cref="ElementReference" />.
/// </summary>
/// <param name="id">A unique identifier for this <see cref="ElementReference"/>.</param>
/// <param name="context">The nullable <see cref="ElementReferenceContext"/> instance.</param>
public ElementReference(string id, ElementReferenceContext? context)
{
Id = id;
Context = context;
}
internal static ElementReference CreateWithUniqueId()
=> new ElementReference(CreateUniqueId());
/// <summary>
/// Instantiates a new <see cref="ElementReference"/>.
/// </summary>
/// <param name="id">A unique identifier for this <see cref="ElementReference"/>.</param>
public ElementReference(string id) : this(id, null)
{
}
internal static ElementReference CreateWithUniqueId(ElementReferenceContext? context)
=> new ElementReference(CreateUniqueId(), context);
private static string CreateUniqueId()
{

View File

@ -0,0 +1,12 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace Microsoft.AspNetCore.Components
{
/// <summary>
/// Context for an <see cref="ElementReference"/>.
/// </summary>
public abstract class ElementReferenceContext
{
}
}

View File

@ -10,6 +10,7 @@
<ItemGroup>
<Compile Include="$(ComponentsSharedSourceRoot)src\ArrayBuilder.cs" LinkBase="RenderTree" />
<Compile Include="$(ComponentsSharedSourceRoot)src\WebAssemblyJSInteropInternalCalls.cs" />
</ItemGroup>
<ItemGroup>

View File

@ -11,7 +11,7 @@ namespace Microsoft.AspNetCore.Components
static PlatformInfo()
{
IsWebAssembly = RuntimeInformation.IsOSPlatform(OSPlatform.Create("WEBASSEMBLY"));
IsWebAssembly = RuntimeInformation.IsOSPlatform(OSPlatform.Browser);
}
}
}

View File

@ -0,0 +1,23 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace Microsoft.AspNetCore.Components.Profiling
{
internal abstract class ComponentsProfiling
{
// For now, this is only intended for use on Blazor WebAssembly, and will have no effect
// when running on Blazor Server. The reason for having the ComponentsProfiling abstraction
// is so that if we later have two different implementations (one for WebAssembly, one for
// Server), the execution characteristics of calling Start/End will be unchanged and historical
// perf data will still be comparable to newer data.
public static readonly ComponentsProfiling Instance = PlatformInfo.IsWebAssembly
? new WebAssemblyComponentsProfiling()
: (ComponentsProfiling)new NoOpComponentsProfiling();
public abstract void Start([CallerMemberName] string? name = null);
public abstract void End([CallerMemberName] string? name = null);
}
}

View File

@ -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.
namespace Microsoft.AspNetCore.Components.Profiling
{
internal class NoOpComponentsProfiling : ComponentsProfiling
{
public override void Start(string? name)
{
}
public override void End(string? name)
{
}
}
}

View File

@ -0,0 +1,41 @@
// 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 WebAssembly.JSInterop;
namespace Microsoft.AspNetCore.Components.Profiling
{
// Later on, we will likely want to move this into the WebAssembly package. However it needs to
// be inlined into the Components package directly until we're ready to make the underlying
// ComponentsProfile abstraction into a public API. It's possible that this API will never become
// public, or that it will be replaced by something more standard for .NET, if it's possible to
// make that work performantly on WebAssembly.
internal class WebAssemblyComponentsProfiling : ComponentsProfiling
{
static bool IsCapturing = false;
public static void SetCapturing(bool isCapturing)
{
IsCapturing = isCapturing;
}
public override void Start(string? name)
{
if (IsCapturing)
{
InternalCalls.InvokeJSUnmarshalled<string, object, object, object>(
out _, "_blazorProfileStart", name, null, null);
}
}
public override void End(string? name)
{
if (IsCapturing)
{
InternalCalls.InvokeJSUnmarshalled<string, object, object, object>(
out _, "_blazorProfileEnd", name, null, null);
}
}
}
}

View File

@ -5,6 +5,9 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using Microsoft.AspNetCore.Components.Profiling;
using Microsoft.AspNetCore.Components.Rendering;
namespace Microsoft.AspNetCore.Components.RenderTree
@ -25,6 +28,7 @@ namespace Microsoft.AspNetCore.Components.RenderTree
ArrayRange<RenderTreeFrame> oldTree,
ArrayRange<RenderTreeFrame> newTree)
{
ComponentsProfiling.Instance.Start();
var editsBuffer = batchBuilder.EditsBuffer;
var editsBufferStartLength = editsBuffer.Count;
@ -32,7 +36,9 @@ namespace Microsoft.AspNetCore.Components.RenderTree
AppendDiffEntriesForRange(ref diffContext, 0, oldTree.Count, 0, newTree.Count);
var editsSegment = editsBuffer.ToSegment(editsBufferStartLength, editsBuffer.Count);
return new RenderTreeDiff(componentId, editsSegment);
var result = new RenderTreeDiff(componentId, editsSegment);
ComponentsProfiling.Instance.End();
return result;
}
public static void DisposeFrames(RenderBatchBuilder batchBuilder, ArrayRange<RenderTreeFrame> frames)
@ -43,6 +49,7 @@ namespace Microsoft.AspNetCore.Components.RenderTree
int oldStartIndex, int oldEndIndexExcl,
int newStartIndex, int newEndIndexExcl)
{
ProfilingStart();
// This is deliberately a very large method. Parts of it could be factored out
// into other private methods, but doing so comes at a consequential perf cost,
// because it involves so much parameter passing. You can think of the code here
@ -293,10 +300,12 @@ namespace Microsoft.AspNetCore.Components.RenderTree
diffContext.KeyedItemInfoDictionaryPool.Return(keyedItemInfos);
}
}
ProfilingEnd();
}
private static Dictionary<object, KeyedItemInfo> BuildKeyToInfoLookup(DiffContext diffContext, int oldStartIndex, int oldEndIndexExcl, int newStartIndex, int newEndIndexExcl)
{
ProfilingStart();
var result = diffContext.KeyedItemInfoDictionaryPool.Get();
var oldTree = diffContext.OldTree;
var newTree = diffContext.NewTree;
@ -342,6 +351,7 @@ namespace Microsoft.AspNetCore.Components.RenderTree
newStartIndex = NextSiblingIndex(frame, newStartIndex);
}
ProfilingEnd();
return result;
}
@ -374,6 +384,7 @@ namespace Microsoft.AspNetCore.Components.RenderTree
int oldStartIndex, int oldEndIndexExcl,
int newStartIndex, int newEndIndexExcl)
{
ProfilingStart();
// The overhead of the dictionary used by AppendAttributeDiffEntriesForRangeSlow is
// significant, so we want to try and do a merge-join if possible, but fall back to
// a hash-join if not. We'll do a merge join until we hit a case we can't handle and
@ -422,6 +433,7 @@ namespace Microsoft.AspNetCore.Components.RenderTree
ref diffContext,
oldStartIndex, oldEndIndexExcl,
newStartIndex, newEndIndexExcl);
ProfilingEnd();
return;
}
@ -447,9 +459,12 @@ namespace Microsoft.AspNetCore.Components.RenderTree
ref diffContext,
oldStartIndex, oldEndIndexExcl,
newStartIndex, newEndIndexExcl);
ProfilingEnd();
return;
}
}
ProfilingEnd();
}
private static void AppendAttributeDiffEntriesForRangeSlow(
@ -457,6 +472,7 @@ namespace Microsoft.AspNetCore.Components.RenderTree
int oldStartIndex, int oldEndIndexExcl,
int newStartIndex, int newEndIndexExcl)
{
ProfilingStart();
var oldTree = diffContext.OldTree;
var newTree = diffContext.NewTree;
@ -495,6 +511,7 @@ namespace Microsoft.AspNetCore.Components.RenderTree
// We should have processed any additions at this point. Reset for the next batch.
diffContext.AttributeDiffSet.Clear();
ProfilingEnd();
}
private static void UpdateRetainedChildComponent(
@ -502,6 +519,7 @@ namespace Microsoft.AspNetCore.Components.RenderTree
int oldComponentIndex,
int newComponentIndex)
{
ProfilingStart();
var oldTree = diffContext.OldTree;
var newTree = diffContext.NewTree;
ref var oldComponentFrame = ref oldTree[oldComponentIndex];
@ -528,6 +546,8 @@ namespace Microsoft.AspNetCore.Components.RenderTree
{
componentState.SetDirectParameters(newParameters);
}
ProfilingEnd();
}
private static int NextSiblingIndex(in RenderTreeFrame frame, int frameIndex)
@ -550,6 +570,7 @@ namespace Microsoft.AspNetCore.Components.RenderTree
int oldFrameIndex,
int newFrameIndex)
{
ProfilingStart();
var oldTree = diffContext.OldTree;
var newTree = diffContext.NewTree;
ref var oldFrame = ref oldTree[oldFrameIndex];
@ -562,6 +583,7 @@ namespace Microsoft.AspNetCore.Components.RenderTree
{
InsertNewFrame(ref diffContext, newFrameIndex);
RemoveOldFrame(ref diffContext, oldFrameIndex);
ProfilingEnd();
return;
}
@ -687,6 +709,8 @@ namespace Microsoft.AspNetCore.Components.RenderTree
default:
throw new NotImplementedException($"Encountered unsupported frame type during diffing: {newTree[newFrameIndex].FrameType}");
}
ProfilingEnd();
}
// This should only be called for attributes that have the same name. This is an
@ -696,6 +720,7 @@ namespace Microsoft.AspNetCore.Components.RenderTree
int oldFrameIndex,
int newFrameIndex)
{
ProfilingStart();
var oldTree = diffContext.OldTree;
var newTree = diffContext.NewTree;
ref var oldFrame = ref oldTree[oldFrameIndex];
@ -724,10 +749,13 @@ namespace Microsoft.AspNetCore.Components.RenderTree
// since it was unchanged.
newFrame = oldFrame;
}
ProfilingEnd();
}
private static void InsertNewFrame(ref DiffContext diffContext, int newFrameIndex)
{
ProfilingStart();
var newTree = diffContext.NewTree;
ref var newFrame = ref newTree[newFrameIndex];
switch (newFrame.FrameType)
@ -780,10 +808,12 @@ namespace Microsoft.AspNetCore.Components.RenderTree
default:
throw new NotImplementedException($"Unexpected frame type during {nameof(InsertNewFrame)}: {newFrame.FrameType}");
}
ProfilingEnd();
}
private static void RemoveOldFrame(ref DiffContext diffContext, int oldFrameIndex)
{
ProfilingStart();
var oldTree = diffContext.OldTree;
ref var oldFrame = ref oldTree[oldFrameIndex];
switch (oldFrame.FrameType)
@ -825,6 +855,7 @@ namespace Microsoft.AspNetCore.Components.RenderTree
default:
throw new NotImplementedException($"Unexpected frame type during {nameof(RemoveOldFrame)}: {oldFrame.FrameType}");
}
ProfilingEnd();
}
private static int GetAttributesEndIndexExclusive(RenderTreeFrame[] tree, int rootIndex)
@ -858,6 +889,7 @@ namespace Microsoft.AspNetCore.Components.RenderTree
private static void InitializeNewSubtree(ref DiffContext diffContext, int frameIndex)
{
ProfilingStart();
var frames = diffContext.NewTree;
var endIndexExcl = frameIndex + frames[frameIndex].ElementSubtreeLength;
for (var i = frameIndex; i < endIndexExcl; i++)
@ -879,10 +911,12 @@ namespace Microsoft.AspNetCore.Components.RenderTree
break;
}
}
ProfilingEnd();
}
private static void InitializeNewComponentFrame(ref DiffContext diffContext, int frameIndex)
{
ProfilingStart();
var frames = diffContext.NewTree;
ref var frame = ref frames[frameIndex];
@ -899,6 +933,7 @@ namespace Microsoft.AspNetCore.Components.RenderTree
var initialParametersLifetime = new ParameterViewLifetime(diffContext.BatchBuilder);
var initialParameters = new ParameterView(initialParametersLifetime, frames, frameIndex);
childComponentState.SetDirectParameters(initialParameters);
ProfilingEnd();
}
private static void InitializeNewAttributeFrame(ref DiffContext diffContext, ref RenderTreeFrame newFrame)
@ -917,7 +952,7 @@ namespace Microsoft.AspNetCore.Components.RenderTree
private static void InitializeNewElementReferenceCaptureFrame(ref DiffContext diffContext, ref RenderTreeFrame newFrame)
{
var newElementReference = ElementReference.CreateWithUniqueId();
var newElementReference = ElementReference.CreateWithUniqueId(diffContext.Renderer.ElementReferenceContext);
newFrame = newFrame.WithElementReferenceCaptureId(newElementReference.Id);
newFrame.ElementReferenceCaptureAction(newElementReference);
}
@ -943,6 +978,7 @@ namespace Microsoft.AspNetCore.Components.RenderTree
private static void DisposeFramesInRange(RenderBatchBuilder batchBuilder, RenderTreeFrame[] frames, int startIndex, int endIndexExcl)
{
ProfilingStart();
for (var i = startIndex; i < endIndexExcl; i++)
{
ref var frame = ref frames[i];
@ -955,6 +991,7 @@ namespace Microsoft.AspNetCore.Components.RenderTree
batchBuilder.DisposedEventHandlerIds.Append(frame.AttributeEventHandlerId);
}
}
ProfilingEnd();
}
/// <summary>
@ -996,5 +1033,18 @@ namespace Microsoft.AspNetCore.Components.RenderTree
SiblingIndex = 0;
}
}
// Having too many calls to ComponentsProfiling.Instance.Start/End has a measurable perf impact
// even when capturing is disabled. So, to enable detailed profiling for this class, define the
// Profile_RenderTreeDiffBuilder compiler symbol, otherwise the calls are compiled out entirely.
// Enabling detailed profiling adds about 5% to rendering benchmark times.
[Conditional("Profile_RenderTreeDiffBuilder")]
private static void ProfilingStart([CallerMemberName] string? name = null)
=> ComponentsProfiling.Instance.Start(name);
[Conditional("Profile_RenderTreeDiffBuilder")]
private static void ProfilingEnd([CallerMemberName] string? name = null)
=> ComponentsProfiling.Instance.End(name);
}
}

View File

@ -8,6 +8,7 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components.Profiling;
using Microsoft.AspNetCore.Components.Rendering;
using Microsoft.Extensions.Logging;
@ -76,6 +77,12 @@ namespace Microsoft.AspNetCore.Components.RenderTree
/// </summary>
public abstract Dispatcher Dispatcher { get; }
/// <summary>
/// Gets or sets the <see cref="Components.ElementReferenceContext"/> associated with this <see cref="Renderer"/>,
/// if it exists.
/// </summary>
protected internal ElementReferenceContext? ElementReferenceContext { get; protected set; }
/// <summary>
/// Constructs a new component of the specified type.
/// </summary>
@ -214,6 +221,7 @@ namespace Microsoft.AspNetCore.Components.RenderTree
/// </returns>
public virtual Task DispatchEventAsync(ulong eventHandlerId, EventFieldInfo fieldInfo, EventArgs eventArgs)
{
ComponentsProfiling.Instance.Start();
Dispatcher.AssertAccess();
if (!_eventBindings.TryGetValue(eventHandlerId, out var callback))
@ -241,6 +249,7 @@ namespace Microsoft.AspNetCore.Components.RenderTree
catch (Exception e)
{
HandleException(e);
ComponentsProfiling.Instance.End();
return Task.CompletedTask;
}
finally
@ -254,7 +263,9 @@ namespace Microsoft.AspNetCore.Components.RenderTree
// Task completed synchronously or is still running. We already processed all of the rendering
// work that was queued so let our error handler deal with it.
return GetErrorHandledTask(task);
var result = GetErrorHandledTask(task);
ComponentsProfiling.Instance.End();
return result;
}
internal void InstantiateChildComponentOnFrame(ref RenderTreeFrame frame, int parentComponentId)
@ -404,6 +415,7 @@ namespace Microsoft.AspNetCore.Components.RenderTree
private void ProcessRenderQueue()
{
ComponentsProfiling.Instance.Start();
Dispatcher.AssertAccess();
if (_isBatchInProgress)
@ -418,6 +430,7 @@ namespace Microsoft.AspNetCore.Components.RenderTree
{
if (_batchBuilder.ComponentRenderQueue.Count == 0)
{
ComponentsProfiling.Instance.End();
return;
}
@ -429,7 +442,9 @@ namespace Microsoft.AspNetCore.Components.RenderTree
}
var batch = _batchBuilder.ToBatch();
ComponentsProfiling.Instance.Start(nameof(UpdateDisplayAsync));
updateDisplayTask = UpdateDisplayAsync(batch);
ComponentsProfiling.Instance.End(nameof(UpdateDisplayAsync));
// Fire off the execution of OnAfterRenderAsync, but don't wait for it
// if there is async work to be done.
@ -439,6 +454,7 @@ namespace Microsoft.AspNetCore.Components.RenderTree
{
// Ensure we catch errors while running the render functions of the components.
HandleException(e);
ComponentsProfiling.Instance.End();
return;
}
finally
@ -456,6 +472,7 @@ namespace Microsoft.AspNetCore.Components.RenderTree
{
ProcessRenderQueue();
}
ComponentsProfiling.Instance.End();
}
private Task InvokeRenderCompletedCalls(ArrayRange<RenderTreeDiff> updatedComponents, Task updateDisplayTask)

View File

@ -5,6 +5,7 @@ using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components.Profiling;
using Microsoft.AspNetCore.Components.RenderTree;
namespace Microsoft.AspNetCore.Components.Rendering
@ -56,6 +57,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
public void RenderIntoBatch(RenderBatchBuilder batchBuilder, RenderFragment renderFragment)
{
ComponentsProfiling.Instance.Start();
// A component might be in the render queue already before getting disposed by an
// earlier entry in the render queue. In that case, rendering is a no-op.
if (_componentWasDisposed)
@ -67,7 +69,9 @@ namespace Microsoft.AspNetCore.Components.Rendering
(CurrentRenderTree, _renderTreeBuilderPrevious) = (_renderTreeBuilderPrevious, CurrentRenderTree);
CurrentRenderTree.Clear();
ComponentsProfiling.Instance.Start("BuildRenderTree");
renderFragment(CurrentRenderTree);
ComponentsProfiling.Instance.End("BuildRenderTree");
var diff = RenderTreeDiffBuilder.ComputeDiff(
_renderer,
@ -77,6 +81,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
CurrentRenderTree.GetFrames());
batchBuilder.UpdatedComponentDiffs.Append(diff);
batchBuilder.InvalidateParameterViews();
ComponentsProfiling.Instance.End();
}
public bool TryDisposeInBatch(RenderBatchBuilder batchBuilder, [NotNullWhen(false)] out Exception? exception)

View File

@ -4,6 +4,8 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using Microsoft.AspNetCore.Components.Profiling;
using Microsoft.AspNetCore.Components.RenderTree;
namespace Microsoft.AspNetCore.Components.Rendering
@ -43,6 +45,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
/// <param name="elementName">A value representing the type of the element.</param>
public void OpenElement(int sequence, string elementName)
{
ProfilingStart();
// We are entering a new scope, since we track the "duplicate attributes" per
// element/component we might need to clean them up now.
if (_hasSeenAddMultipleAttributes)
@ -53,6 +56,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
_openElementIndices.Push(_entries.Count);
Append(RenderTreeFrame.Element(sequence, elementName));
ProfilingEnd();
}
/// <summary>
@ -61,6 +65,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
/// </summary>
public void CloseElement()
{
ProfilingStart();
var indexOfEntryBeingClosed = _openElementIndices.Pop();
// We might be closing an element with only attributes, run the duplicate cleanup pass
@ -72,6 +77,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
ref var entry = ref _entries.Buffer[indexOfEntryBeingClosed];
entry = entry.WithElementSubtreeLength(_entries.Count - indexOfEntryBeingClosed);
ProfilingEnd();
}
/// <summary>
@ -80,7 +86,11 @@ namespace Microsoft.AspNetCore.Components.Rendering
/// <param name="sequence">An integer that represents the position of the instruction in the source code.</param>
/// <param name="markupContent">Content for the new markup frame.</param>
public void AddMarkupContent(int sequence, string? markupContent)
=> Append(RenderTreeFrame.Markup(sequence, markupContent ?? string.Empty));
{
ProfilingStart();
Append(RenderTreeFrame.Markup(sequence, markupContent ?? string.Empty));
ProfilingEnd();
}
/// <summary>
/// Appends a frame representing text content.
@ -88,7 +98,11 @@ namespace Microsoft.AspNetCore.Components.Rendering
/// <param name="sequence">An integer that represents the position of the instruction in the source code.</param>
/// <param name="textContent">Content for the new text frame.</param>
public void AddContent(int sequence, string? textContent)
=> Append(RenderTreeFrame.Text(sequence, textContent ?? string.Empty));
{
ProfilingStart();
Append(RenderTreeFrame.Text(sequence, textContent ?? string.Empty));
ProfilingEnd();
}
/// <summary>
/// Appends frames representing an arbitrary fragment of content.
@ -97,6 +111,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
/// <param name="fragment">Content to append.</param>
public void AddContent(int sequence, RenderFragment? fragment)
{
ProfilingStart();
if (fragment != null)
{
// We surround the fragment with a region delimiter to indicate that the
@ -107,6 +122,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
fragment(this);
CloseRegion();
}
ProfilingEnd();
}
/// <summary>
@ -117,10 +133,12 @@ namespace Microsoft.AspNetCore.Components.Rendering
/// <param name="value">The value used by <paramref name="fragment"/>.</param>
public void AddContent<TValue>(int sequence, RenderFragment<TValue>? fragment, TValue value)
{
ProfilingStart();
if (fragment != null)
{
AddContent(sequence, fragment(value));
}
ProfilingEnd();
}
/// <summary>
@ -153,6 +171,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
/// <param name="value">The value of the attribute.</param>
public void AddAttribute(int sequence, string name, bool value)
{
ProfilingStart();
AssertCanAddAttribute();
if (_lastNonAttributeFrameType == RenderTreeFrameType.Component)
{
@ -168,6 +187,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
{
TrackAttributeName(name);
}
ProfilingEnd();
}
/// <summary>
@ -184,6 +204,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
/// <param name="value">The value of the attribute.</param>
public void AddAttribute(int sequence, string name, string? value)
{
ProfilingStart();
AssertCanAddAttribute();
if (value != null || _lastNonAttributeFrameType == RenderTreeFrameType.Component)
{
@ -193,6 +214,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
{
TrackAttributeName(name);
}
ProfilingEnd();
}
/// <summary>
@ -209,6 +231,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
/// <param name="value">The value of the attribute.</param>
public void AddAttribute(int sequence, string name, MulticastDelegate? value)
{
ProfilingStart();
AssertCanAddAttribute();
if (value != null || _lastNonAttributeFrameType == RenderTreeFrameType.Component)
{
@ -218,6 +241,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
{
TrackAttributeName(name);
}
ProfilingEnd();
}
/// <summary>
@ -238,6 +262,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
/// </remarks>
public void AddAttribute(int sequence, string name, EventCallback value)
{
ProfilingStart();
AssertCanAddAttribute();
if (_lastNonAttributeFrameType == RenderTreeFrameType.Component)
{
@ -262,6 +287,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
// Track the attribute name if needed since we elided the frame.
TrackAttributeName(name);
}
ProfilingEnd();
}
/// <summary>
@ -282,6 +308,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
/// </remarks>
public void AddAttribute<TArgument>(int sequence, string name, EventCallback<TArgument> value)
{
ProfilingStart();
AssertCanAddAttribute();
if (_lastNonAttributeFrameType == RenderTreeFrameType.Component)
{
@ -306,6 +333,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
// Track the attribute name if needed since we elided the frame.
TrackAttributeName(name);
}
ProfilingEnd();
}
/// <summary>
@ -319,6 +347,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
/// <param name="value">The value of the attribute.</param>
public void AddAttribute(int sequence, string name, object? value)
{
ProfilingStart();
// This looks a bit daunting because we need to handle the boxed/object version of all of the
// types that AddAttribute special cases.
if (_lastNonAttributeFrameType == RenderTreeFrameType.Element)
@ -371,6 +400,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
// This is going to throw. Calling it just to get a consistent exception message.
AssertCanAddAttribute();
}
ProfilingEnd();
}
/// <summary>
@ -385,6 +415,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
/// <param name="frame">A <see cref="RenderTreeFrame"/> holding the name and value of the attribute.</param>
public void AddAttribute(int sequence, in RenderTreeFrame frame)
{
ProfilingStart();
if (frame.FrameType != RenderTreeFrameType.Attribute)
{
throw new ArgumentException($"The {nameof(frame.FrameType)} must be {RenderTreeFrameType.Attribute}.");
@ -392,6 +423,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
AssertCanAddAttribute();
Append(frame.WithAttributeSequence(sequence));
ProfilingEnd();
}
/// <summary>
@ -401,6 +433,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
/// <param name="attributes">A collection of key-value pairs representing attributes.</param>
public void AddMultipleAttributes(int sequence, IEnumerable<KeyValuePair<string, object>>? attributes)
{
ProfilingStart();
// Calling this up-front just to make sure we validate before mutating anything.
AssertCanAddAttribute();
@ -417,6 +450,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
AddAttribute(sequence, attribute.Key, attribute.Value);
}
}
ProfilingEnd();
}
/// <summary>
@ -433,6 +467,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
/// <param name="updatesAttributeName">The name of another attribute whose value can be updated when the event handler is executed.</param>
public void SetUpdatesAttributeName(string updatesAttributeName)
{
ProfilingStart();
if (_entries.Count == 0)
{
throw new InvalidOperationException("No preceding attribute frame exists.");
@ -445,6 +480,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
}
prevFrame = prevFrame.WithAttributeEventUpdatesAttributeName(updatesAttributeName);
ProfilingEnd();
}
/// <summary>
@ -476,10 +512,12 @@ namespace Microsoft.AspNetCore.Components.Rendering
/// <param name="value">The value for the key.</param>
public void SetKey(object? value)
{
ProfilingStart();
if (value == null)
{
// Null is equivalent to not having set a key, which is valuable because Razor syntax doesn't have an
// easy way to have conditional directive attributes
ProfilingEnd();
return;
}
@ -502,10 +540,12 @@ namespace Microsoft.AspNetCore.Components.Rendering
default:
throw new InvalidOperationException($"Cannot set a key on a frame of type {parentFrame.FrameType}.");
}
ProfilingEnd();
}
private void OpenComponentUnchecked(int sequence, Type componentType)
{
ProfilingStart();
// We are entering a new scope, since we track the "duplicate attributes" per
// element/component we might need to clean them up now.
if (_hasSeenAddMultipleAttributes)
@ -516,6 +556,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
_openElementIndices.Push(_entries.Count);
Append(RenderTreeFrame.ChildComponent(sequence, componentType));
ProfilingEnd();
}
/// <summary>
@ -524,6 +565,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
/// </summary>
public void CloseComponent()
{
ProfilingStart();
var indexOfEntryBeingClosed = _openElementIndices.Pop();
// We might be closing a component with only attributes. Run the attribute cleanup pass
@ -535,6 +577,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
ref var entry = ref _entries.Buffer[indexOfEntryBeingClosed];
entry = entry.WithComponentSubtreeLength(_entries.Count - indexOfEntryBeingClosed);
ProfilingEnd();
}
/// <summary>
@ -544,12 +587,14 @@ namespace Microsoft.AspNetCore.Components.Rendering
/// <param name="elementReferenceCaptureAction">An action to be invoked whenever the reference value changes.</param>
public void AddElementReferenceCapture(int sequence, Action<ElementReference> elementReferenceCaptureAction)
{
ProfilingStart();
if (GetCurrentParentFrameType() != RenderTreeFrameType.Element)
{
throw new InvalidOperationException($"Element reference captures may only be added as children of frames of type {RenderTreeFrameType.Element}");
}
Append(RenderTreeFrame.ElementReferenceCapture(sequence, elementReferenceCaptureAction));
ProfilingEnd();
}
/// <summary>
@ -559,6 +604,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
/// <param name="componentReferenceCaptureAction">An action to be invoked whenever the reference value changes.</param>
public void AddComponentReferenceCapture(int sequence, Action<object?> componentReferenceCaptureAction)
{
ProfilingStart();
var parentFrameIndex = GetCurrentParentFrameIndex();
if (!parentFrameIndex.HasValue)
{
@ -572,6 +618,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
}
Append(RenderTreeFrame.ComponentReferenceCapture(sequence, componentReferenceCaptureAction, parentFrameIndexValue));
ProfilingEnd();
}
/// <summary>
@ -580,6 +627,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
/// <param name="sequence">An integer that represents the position of the instruction in the source code.</param>
public void OpenRegion(int sequence)
{
ProfilingStart();
// We are entering a new scope, since we track the "duplicate attributes" per
// element/component we might need to clean them up now.
if (_hasSeenAddMultipleAttributes)
@ -590,6 +638,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
_openElementIndices.Push(_entries.Count);
Append(RenderTreeFrame.Region(sequence));
ProfilingEnd();
}
/// <summary>
@ -598,9 +647,11 @@ namespace Microsoft.AspNetCore.Components.Rendering
/// </summary>
public void CloseRegion()
{
ProfilingStart();
var indexOfEntryBeingClosed = _openElementIndices.Pop();
ref var entry = ref _entries.Buffer[indexOfEntryBeingClosed];
entry = entry.WithRegionSubtreeLength(_entries.Count - indexOfEntryBeingClosed);
ProfilingEnd();
}
private void AssertCanAddAttribute()
@ -628,24 +679,29 @@ namespace Microsoft.AspNetCore.Components.Rendering
/// </summary>
public void Clear()
{
ProfilingStart();
_entries.Clear();
_openElementIndices.Clear();
_lastNonAttributeFrameType = null;
_hasSeenAddMultipleAttributes = false;
_seenAttributeNames?.Clear();
ProfilingEnd();
}
// internal because this should only be used during the post-event tree patching logic
// It's expensive because it involves copying all the subsequent memory in the array
internal void InsertAttributeExpensive(int insertAtIndex, int sequence, string attributeName, object? attributeValue)
{
ProfilingStart();
// Replicate the same attribute omission logic as used elsewhere
if ((attributeValue == null) || (attributeValue is bool boolValue && !boolValue))
{
ProfilingEnd();
return;
}
_entries.InsertExpensive(insertAtIndex, RenderTreeFrame.Attribute(sequence, attributeName, attributeValue));
ProfilingEnd();
}
/// <summary>
@ -669,6 +725,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
// Internal for testing
internal void ProcessDuplicateAttributes(int first)
{
ProfilingStart();
Debug.Assert(_hasSeenAddMultipleAttributes);
// When AddMultipleAttributes method has been called, we need to postprocess attributes while closing
@ -750,6 +807,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
seenAttributeNames.Clear();
_hasSeenAddMultipleAttributes = false;
ProfilingEnd();
}
// Internal for testing
@ -766,7 +824,22 @@ namespace Microsoft.AspNetCore.Components.Rendering
void IDisposable.Dispose()
{
ProfilingStart();
_entries.Dispose();
ProfilingEnd();
}
// Having too many calls to ComponentsProfiling.Instance.Start/End has a measurable perf impact
// even when capturing is disabled. So, to enable detailed profiling for this class, define the
// Profile_RenderTreeBuilder compiler symbol, otherwise the calls are compiled out entirely.
// Enabling detailed profiling adds about 5% to rendering benchmark times.
[Conditional("Profile_RenderTreeBuilder")]
private static void ProfilingStart([CallerMemberName] string? name = null)
=> ComponentsProfiling.Instance.Start(name);
[Conditional("Profile_RenderTreeBuilder")]
private static void ProfilingEnd([CallerMemberName] string? name = null)
=> ComponentsProfiling.Instance.End(name);
}
}

View File

@ -26,7 +26,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
Thread capturedThread = null;
var e = new ManualResetEventSlim();
// Act
context.Post((_) =>
{
@ -766,7 +766,6 @@ namespace Microsoft.AspNetCore.Components.Rendering
}
[Fact]
[QuarantinedTest]
public async Task InvokeAsync_SyncWorkInAsyncTaskIsCompletedFirst()
{
// Simplified version of ServerComponentRenderingTest.CanDispatchAsyncWorkToSyncContext

View File

@ -24,7 +24,6 @@
"WebAssembly\\Server\\test\\Microsoft.AspNetCore.Components.WebAssembly.Server.Tests.csproj",
"WebAssembly\\WebAssembly.Authentication\\src\\Microsoft.AspNetCore.Components.WebAssembly.Authentication.csproj",
"WebAssembly\\WebAssembly.Authentication\\test\\Microsoft.AspNetCore.Components.WebAssembly.Authentication.Tests.csproj",
"WebAssembly\\WebAssemblyHttpHandler\\src\\Microsoft.AspNetCore.Components.WebAssembly.HttpHandler.csproj",
"WebAssembly\\WebAssembly\\src\\Microsoft.AspNetCore.Components.WebAssembly.csproj",
"WebAssembly\\WebAssembly\\test\\Microsoft.AspNetCore.Components.WebAssembly.Tests.csproj",
"WebAssembly\\testassets\\HostedInAspNet.Client\\HostedInAspNet.Client.csproj",

View File

@ -21,26 +21,4 @@
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory)..\, Directory.Build.targets))\Directory.Build.targets" />
<ItemGroup Condition="'$(FixupWebAssemblyHttpHandlerReference)' == 'true'">
<ProjectReference
Include="$(RepoRoot)src\Components\WebAssembly\WebAssemblyHttpHandler\src\Microsoft.AspNetCore.Components.WebAssembly.HttpHandler.csproj"
CopyLocal="false" />
</ItemGroup>
<Target Name="_FixupReferenceToWebAssemblyHttpHandler"
Condition="'$(FixupWebAssemblyHttpHandlerReference)' == 'true'"
AfterTargets="_ResolveBlazorInputs"
BeforeTargets="_ResolveBlazorOutputs">
<!--
ProjectReference doesn't really play well with IncludeAssets behavior you get when referencing
the package with IncludeAssets="compile".
-->
<ItemGroup>
<_HttpHandlerAssembly Include="@(_BlazorUserRuntimeAssembly)"
Condition="%(_BlazorUserRuntimeAssembly.ProjectReferenceOriginalItemSpec) == '$(RepoRoot)src\Components\WebAssembly\WebAssemblyHttpHandler\src\Microsoft.AspNetCore.Components.WebAssembly.HttpHandler.csproj'" />
<_BlazorUserRuntimeAssembly Remove="@(_HttpHandlerAssembly)" />
</ItemGroup>
</Target>
</Project>

View File

@ -64,7 +64,8 @@ namespace Microsoft.AspNetCore.Components.Server.Circuits
_loggerFactory,
_options,
client,
_loggerFactory.CreateLogger<RemoteRenderer>());
_loggerFactory.CreateLogger<RemoteRenderer>(),
jsRuntime.ElementReferenceContext);
var circuitHandlers = scope.ServiceProvider.GetServices<CircuitHandler>()
.OrderBy(h => h.Order)

View File

@ -17,12 +17,15 @@ namespace Microsoft.AspNetCore.Components.Server.Circuits
private readonly ILogger<RemoteJSRuntime> _logger;
private CircuitClientProxy _clientProxy;
public ElementReferenceContext ElementReferenceContext { get; }
public RemoteJSRuntime(IOptions<CircuitOptions> options, ILogger<RemoteJSRuntime> logger)
{
_options = options.Value;
_logger = logger;
DefaultAsyncTimeout = _options.JSInteropDefaultCallTimeout;
JsonSerializerOptions.Converters.Add(new ElementReferenceJsonConverter());
ElementReferenceContext = new WebElementReferenceContext(this);
JsonSerializerOptions.Converters.Add(new ElementReferenceJsonConverter(ElementReferenceContext));
}
internal void Initialize(CircuitClientProxy clientProxy)

View File

@ -37,12 +37,15 @@ namespace Microsoft.AspNetCore.Components.Server.Circuits
ILoggerFactory loggerFactory,
CircuitOptions options,
CircuitClientProxy client,
ILogger logger)
ILogger logger,
ElementReferenceContext? elementReferenceContext)
: base(serviceProvider, loggerFactory)
{
_client = client;
_options = options;
_logger = logger;
ElementReferenceContext = elementReferenceContext;
}
public override Dispatcher Dispatcher { get; } = Dispatcher.CreateDefault();

View File

@ -258,7 +258,13 @@ namespace Microsoft.AspNetCore.Components.Server.Circuits
private class TestRemoteRenderer : RemoteRenderer
{
public TestRemoteRenderer(IServiceProvider serviceProvider, IClientProxy client)
: base(serviceProvider, NullLoggerFactory.Instance, new CircuitOptions(), new CircuitClientProxy(client, "connection"), NullLogger.Instance)
: base(
serviceProvider,
NullLoggerFactory.Instance,
new CircuitOptions(),
new CircuitClientProxy(client, "connection"),
NullLogger.Instance,
null)
{
}

View File

@ -437,7 +437,7 @@ namespace Microsoft.AspNetCore.Components.Web.Rendering
private class TestRemoteRenderer : RemoteRenderer
{
public TestRemoteRenderer(IServiceProvider serviceProvider, ILoggerFactory loggerFactory, CircuitOptions options, CircuitClientProxy client, ILogger logger)
: base(serviceProvider, loggerFactory, options, client, logger)
: base(serviceProvider, loggerFactory, options, client, logger, null)
{
}

View File

@ -38,7 +38,8 @@ namespace Microsoft.AspNetCore.Components.Server.Circuits
NullLoggerFactory.Instance,
new CircuitOptions(),
clientProxy,
NullLogger.Instance);
NullLogger.Instance,
null);
}
handlers = handlers ?? Array.Empty<CircuitHandler>();

View File

@ -1,22 +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.IO;
using System.Text;
using System.Text.Json;
using Moq;
using Xunit;
namespace Microsoft.AspNetCore.Components
{
public class ElementReferenceJsonConverterTest
{
private readonly ElementReferenceJsonConverter Converter = new ElementReferenceJsonConverter();
private readonly ElementReferenceContext ElementReferenceContext;
private readonly ElementReferenceJsonConverter Converter;
public ElementReferenceJsonConverterTest()
{
ElementReferenceContext = Mock.Of<ElementReferenceContext>();
Converter = new ElementReferenceJsonConverter(ElementReferenceContext);
}
[Fact]
public void Serializing_Works()
{
// Arrange
var elementReference = ElementReference.CreateWithUniqueId();
var elementReference = ElementReference.CreateWithUniqueId(ElementReferenceContext);
var expected = $"{{\"__internalId\":\"{elementReference.Id}\"}}";
var memoryStream = new MemoryStream();
var writer = new Utf8JsonWriter(memoryStream);
@ -34,7 +43,7 @@ namespace Microsoft.AspNetCore.Components
public void Deserializing_Works()
{
// Arrange
var id = ElementReference.CreateWithUniqueId().Id;
var id = ElementReference.CreateWithUniqueId(ElementReferenceContext).Id;
var json = $"{{\"__internalId\":\"{id}\"}}";
var bytes = Encoding.UTF8.GetBytes(json);
var reader = new Utf8JsonReader(bytes);
@ -51,7 +60,7 @@ namespace Microsoft.AspNetCore.Components
public void Deserializing_WithFormatting_Works()
{
// Arrange
var id = ElementReference.CreateWithUniqueId().Id;
var id = ElementReference.CreateWithUniqueId(ElementReferenceContext).Id;
var json =
@$"{{
""__internalId"": ""{id}""

View File

@ -11,6 +11,13 @@ namespace Microsoft.AspNetCore.Components
{
private static readonly JsonEncodedText IdProperty = JsonEncodedText.Encode("__internalId");
private readonly ElementReferenceContext _elementReferenceContext;
public ElementReferenceJsonConverter(ElementReferenceContext elementReferenceContext)
{
_elementReferenceContext = elementReferenceContext;
}
public override ElementReference Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
string id = null;
@ -39,7 +46,7 @@ namespace Microsoft.AspNetCore.Components
throw new JsonException("__internalId is required.");
}
return new ElementReference(id);
return new ElementReference(id, _elementReferenceContext);
}
public override void Write(Utf8JsonWriter writer, ElementReference value, JsonSerializerOptions options)

View File

@ -1,6 +1,7 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
namespace WebAssembly.JSInterop
@ -21,6 +22,6 @@ namespace WebAssembly.JSInterop
public static extern string InvokeJSMarshalled(out string exception, ref long asyncHandle, string functionIdentifier, string argsJson);
[MethodImpl(MethodImplOptions.InternalCall)]
public static extern TRes InvokeJSUnmarshalled<T0, T1, T2, TRes>(out string exception, string functionIdentifier, T0 arg0, T1 arg1, T2 arg2);
public static extern TRes InvokeJSUnmarshalled<T0, T1, T2, TRes>(out string exception, string functionIdentifier, [AllowNull] T0 arg0, [AllowNull] T1 arg1, [AllowNull] T2 arg2);
}
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -12,6 +12,7 @@ import { setEventDispatcher } from './Rendering/RendererEventDispatcher';
import { resolveOptions, CircuitStartOptions } from './Platform/Circuits/CircuitStartOptions';
import { DefaultReconnectionHandler } from './Platform/Circuits/DefaultReconnectionHandler';
import { attachRootComponentToLogicalElement } from './Rendering/Renderer';
import { initializeProfiling } from './Platform/Profiling';
let renderingFailed = false;
let started = false;
@ -21,6 +22,7 @@ async function boot(userOptions?: Partial<CircuitStartOptions>): Promise<void> {
throw new Error('Blazor has already started.');
}
started = true;
initializeProfiling(null);
// Establish options to be used
const options = resolveOptions(userOptions);

View File

@ -11,6 +11,7 @@ import { WebAssemblyConfigLoader } from './Platform/WebAssemblyConfigLoader';
import { BootConfigResult } from './Platform/BootConfig';
import { Pointer } from './Platform/Platform';
import { WebAssemblyStartOptions } from './Platform/WebAssemblyStartOptions';
import { profileStart, profileEnd } from './Platform/Profiling';
let started = false;
@ -27,7 +28,9 @@ async function boot(options?: Partial<WebAssemblyStartOptions>): Promise<void> {
const platform = Environment.setPlatform(monoPlatform);
window['Blazor'].platform = platform;
window['Blazor']._internal.renderBatch = (browserRendererId: number, batchAddress: Pointer) => {
profileStart('renderBatch');
renderBatch(browserRendererId, new SharedMemoryRenderBatch(batchAddress));
profileEnd('renderBatch');
};
// Configure navigation via JS Interop

View File

@ -0,0 +1,13 @@
import '@microsoft/dotnet-js-interop';
export const domFunctions = {
focus,
};
function focus(element: HTMLElement): void {
if (element instanceof HTMLElement) {
element.focus();
} else {
throw new Error('Unable to focus an invalid element.');
}
}

View File

@ -1,5 +1,7 @@
import { navigateTo, internalFunctions as navigationManagerInternalFunctions } from './Services/NavigationManager';
import { attachRootComponentToElement } from './Rendering/Renderer';
import { domFunctions } from './DomWrapper';
import { setProfilingEnabled } from './Platform/Profiling';
// Make the following APIs available in global scope for invocation from JS
window['Blazor'] = {
@ -8,5 +10,7 @@ window['Blazor'] = {
_internal: {
attachRootComponentToElement,
navigationManager: navigationManagerInternalFunctions,
domWrapper: domFunctions,
setProfilingEnabled: setProfilingEnabled,
},
};

View File

@ -5,6 +5,7 @@ import { WebAssemblyResourceLoader, LoadingResource } from '../WebAssemblyResour
import { Platform, System_Array, Pointer, System_Object, System_String } from '../Platform';
import { loadTimezoneData } from './TimezoneDataFile';
import { WebAssemblyBootResourceType } from '../WebAssemblyStartOptions';
import { initializeProfiling } from '../Profiling';
let mono_string_get_utf8: (managedString: System_String) => Pointer;
let mono_wasm_add_assembly: (name: string, heapAddress: number, length: number) => void;
@ -34,6 +35,10 @@ export const monoPlatform: Platform = {
start: function start(resourceLoader: WebAssemblyResourceLoader) {
return new Promise<void>((resolve, reject) => {
attachDebuggerHotkey(resourceLoader);
initializeProfiling(isCapturing => {
const setCapturingMethod = bindStaticMethod('Microsoft.AspNetCore.Components', 'Microsoft.AspNetCore.Components.Profiling.WebAssemblyComponentsProfiling', 'SetCapturing');
setCapturingMethod(isCapturing);
});
// dotnet.js assumes the existence of this
window['Browser'] = {

View File

@ -0,0 +1,134 @@
import { System_String } from './Platform';
interface TimingEntry {
// To minimize overhead, don't even decode the strings that arrive from .NET. Assume they are compile-time constants
// and hence the memory address will be fixed, so we can just store the pointer value.
name: string | System_String;
type: 'start' | 'end';
timestamp: number;
}
interface TraceEvent {
// https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/preview
name: string;
cat: string; // Category
ph: 'B' | 'E'; // Phase
ts: number; // Timestamp in microseconds
pid: number; // Process ID
tid: number; // Thread ID
}
let updateCapturingStateInHost: (isCapturing: boolean) => void;
let captureStartTime = 0;
const blazorProfilingEnabledKey = 'blazorProfilingEnabled';
const profilingEnabled = !!localStorage[blazorProfilingEnabledKey];
const entryLog: TimingEntry[] = [];
const openRegionsStack: (string | System_String)[] = [];
export function setProfilingEnabled(enabled: boolean) {
// We only wire up the hotkeys etc. if the following localStorage entry is present during startup
// This is to ensure we're not interfering with any other hotkeys that developers might want to
// use for different purposes, plus it gives us a single point where we can notify .NET code during
// startup about whether profiling should be enabled.
localStorage[blazorProfilingEnabledKey] = (enabled !== false);
location.reload();
}
export function initializeProfiling(setCapturingCallback: ((isCapturing: boolean) => void) | null) {
if (!profilingEnabled) {
return;
}
updateCapturingStateInHost = setCapturingCallback || (() => {});
// Attach hotkey (alt/cmd)+shift+p
const altKeyName = navigator.platform.match(/^Mac/i) ? 'Cmd' : 'Alt';
console.info(`Profiling hotkey: Shift+${altKeyName}+P (when application has focus)`);
document.addEventListener('keydown', evt => {
if (evt.shiftKey && (evt.metaKey || evt.altKey) && evt.code === 'KeyP') {
toggleCaptureEnabled();
}
});
}
export function profileStart(name: System_String | string) {
if (!captureStartTime) {
return;
}
const startTime = performance.now();
openRegionsStack.push(name);
entryLog.push({ name: name, type: 'start', timestamp: startTime });
}
export function profileEnd(name: System_String | string) {
if (!captureStartTime) {
return;
}
const endTime = performance.now();
const poppedRegionName = openRegionsStack.pop();
if (!poppedRegionName) {
throw new Error(`Profiling mismatch: tried to end profiling for '${readJsString(name)}', but the stack was empty.`);
} else if (poppedRegionName !== name) {
throw new Error(`Profiling mismatch: tried to end profiling for '${readJsString(name)}', but the top stack item was '${readJsString(poppedRegionName)}'.`);
}
entryLog.push({ name: name, type: 'end', timestamp: endTime });
}
function profileReset() {
openRegionsStack.length = 0;
entryLog.length = 0;
captureStartTime = 0;
updateCapturingStateInHost(false);
}
function profileExport() {
const traceEvents: TraceEvent[] = entryLog.map(entry => ({
name: readJsString(entry.name)!,
cat: 'PERF',
ph: entry.type === 'start' ? 'B': 'E',
ts: (entry.timestamp - captureStartTime) * 1000,
pid: 0,
tid: 0,
}));
const traceEventsJson = JSON.stringify(traceEvents);
const traceEventsBuffer = new TextEncoder().encode(traceEventsJson);
const anchorElement = document.createElement('a');
anchorElement.href = URL.createObjectURL(new Blob([traceEventsBuffer]));
anchorElement.setAttribute('download', 'trace.json');
anchorElement.click();
URL.revokeObjectURL(anchorElement.href);
}
function toggleCaptureEnabled() {
if (!captureStartTime) {
displayOverlayMessage('Started capturing performance profile...');
updateCapturingStateInHost(true);
captureStartTime = performance.now();
} else {
displayOverlayMessage('Finished capturing performance profile');
profileExport();
profileReset();
}
}
function displayOverlayMessage(message: string) {
const elem = document.createElement('div');
elem.textContent = message;
elem.setAttribute('style', 'position: absolute; z-index: 99999; font-family: \'Sans Serif\'; top: 0; left: 0; padding: 4px; font-size: 12px; background-color: purple; color: white;');
document.body.appendChild(elem);
setTimeout(() => document.body.removeChild(elem), 3000);
}
function readJsString(str: string | System_String) {
// This is expensive, so don't do it while capturing timings. Only do it as part of the export process.
return typeof str === 'string' ? str : BINDING.conv_string(str);
}
// These globals deliberately differ from our normal conventions for attaching functions inside Blazor.*
// because the intention is to minimize overhead in all reasonable ways. Having any dot-separators in the
// name would cause extra string allocations on every invocation.
window['_blazorProfileStart'] = profileStart;
window['_blazorProfileEnd'] = profileEnd;

View File

@ -6,6 +6,7 @@ import { applyCaptureIdToElement } from './ElementReferenceCapture';
import { EventFieldInfo } from './EventFieldInfo';
import { dispatchEvent } from './RendererEventDispatcher';
import { attachToEventDelegator as attachNavigationManagerToEventDelegator } from '../Services/NavigationManager';
import { profileEnd, profileStart } from '../Platform/Profiling';
const selectValuePropname = '_blazorSelectValue';
const sharedTemplateElemForParsing = document.createElement('template');
const sharedSvgElemForParsing = document.createElementNS('http://www.w3.org/2000/svg', 'g');
@ -40,6 +41,8 @@ export class BrowserRenderer {
}
public updateComponent(batch: RenderBatch, componentId: number, edits: ArrayBuilderSegment<RenderTreeEdit>, referenceFrames: ArrayValues<RenderTreeFrame>): void {
profileStart('updateComponent');
const element = this.childComponentLocations[componentId];
if (!element) {
throw new Error(`No element is currently associated with component ${componentId}`);
@ -67,6 +70,8 @@ export class BrowserRenderer {
if ((activeElementBefore instanceof HTMLElement) && ownerDocument && ownerDocument.activeElement !== activeElementBefore) {
activeElementBefore.focus();
}
profileEnd('updateComponent');
}
public disposeComponent(componentId: number) {

View File

@ -14,6 +14,14 @@ namespace Microsoft.AspNetCore.Components
public string? Type { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } }
public string? ValueAttribute { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } }
}
public static partial class ElementReferenceExtensions
{
public static System.Threading.Tasks.ValueTask FocusAsync(this Microsoft.AspNetCore.Components.ElementReference elementReference) { throw null; }
}
public partial class WebElementReferenceContext : Microsoft.AspNetCore.Components.ElementReferenceContext
{
public WebElementReferenceContext(Microsoft.JSInterop.IJSRuntime jsRuntime) { }
}
}
namespace Microsoft.AspNetCore.Components.Forms
{
@ -53,7 +61,7 @@ namespace Microsoft.AspNetCore.Components.Forms
protected TValue CurrentValue { get { throw null; } set { } }
protected string? CurrentValueAsString { get { throw null; } set { } }
protected Microsoft.AspNetCore.Components.Forms.EditContext EditContext { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } }
protected Microsoft.AspNetCore.Components.Forms.FieldIdentifier FieldIdentifier { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } }
protected internal Microsoft.AspNetCore.Components.Forms.FieldIdentifier FieldIdentifier { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } }
[Microsoft.AspNetCore.Components.ParameterAttribute]
[System.Diagnostics.CodeAnalysis.MaybeNullAttribute]
[System.Diagnostics.CodeAnalysis.AllowNullAttribute]
@ -63,7 +71,7 @@ namespace Microsoft.AspNetCore.Components.Forms
[Microsoft.AspNetCore.Components.ParameterAttribute]
public System.Linq.Expressions.Expression<System.Func<TValue>>? ValueExpression { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } }
protected virtual void Dispose(bool disposing) { }
protected virtual string? FormatValueAsString(TValue value) { throw null; }
protected virtual string? FormatValueAsString([System.Diagnostics.CodeAnalysis.AllowNullAttribute] TValue value) { throw null; }
public override System.Threading.Tasks.Task SetParametersAsync(Microsoft.AspNetCore.Components.ParameterView parameters) { throw null; }
void System.IDisposable.Dispose() { }
protected abstract bool TryParseValueFromString(string? value, [System.Diagnostics.CodeAnalysis.MaybeNullAttribute] out TValue result, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(false)] out string? validationErrorMessage);
@ -80,7 +88,7 @@ namespace Microsoft.AspNetCore.Components.Forms
[Microsoft.AspNetCore.Components.ParameterAttribute]
public string ParsingErrorMessage { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } }
protected override void BuildRenderTree(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder builder) { }
protected override string FormatValueAsString(TValue value) { throw null; }
protected override string FormatValueAsString([System.Diagnostics.CodeAnalysis.AllowNullAttribute] TValue value) { throw null; }
protected override bool TryParseValueFromString(string? value, [System.Diagnostics.CodeAnalysis.MaybeNullAttribute] out TValue result, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(false)] out string? validationErrorMessage) { throw null; }
}
public partial class InputNumber<TValue> : Microsoft.AspNetCore.Components.Forms.InputBase<TValue>
@ -89,9 +97,34 @@ namespace Microsoft.AspNetCore.Components.Forms
[Microsoft.AspNetCore.Components.ParameterAttribute]
public string ParsingErrorMessage { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } }
protected override void BuildRenderTree(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder builder) { }
protected override string? FormatValueAsString(TValue value) { throw null; }
protected override string? FormatValueAsString([System.Diagnostics.CodeAnalysis.AllowNullAttribute] TValue value) { throw null; }
protected override bool TryParseValueFromString(string? value, [System.Diagnostics.CodeAnalysis.MaybeNullAttribute] out TValue result, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(false)] out string? validationErrorMessage) { throw null; }
}
public partial class InputRadioGroup<TValue> : Microsoft.AspNetCore.Components.Forms.InputBase<TValue>
{
public InputRadioGroup() { }
[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 string? Name { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } }
protected override void BuildRenderTree(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder builder) { }
protected override void OnParametersSet() { }
protected override bool TryParseValueFromString(string? value, [System.Diagnostics.CodeAnalysis.MaybeNullAttribute] out TValue result, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(false)] out string? validationErrorMessage) { throw null; }
}
public partial class InputRadio<TValue> : Microsoft.AspNetCore.Components.ComponentBase
{
public InputRadio() { }
[Microsoft.AspNetCore.Components.ParameterAttribute(CaptureUnmatchedValues=true)]
public System.Collections.Generic.IReadOnlyDictionary<string, object>? AdditionalAttributes { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } }
[Microsoft.AspNetCore.Components.ParameterAttribute]
public string? Name { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } }
[Microsoft.AspNetCore.Components.ParameterAttribute]
[System.Diagnostics.CodeAnalysis.MaybeNullAttribute]
[System.Diagnostics.CodeAnalysis.AllowNullAttribute]
public TValue Value { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } }
protected override void BuildRenderTree(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder builder) { }
protected override void OnParametersSet() { }
}
public partial class InputSelect<TValue> : Microsoft.AspNetCore.Components.Forms.InputBase<TValue>
{
public InputSelect() { }

View File

@ -14,6 +14,14 @@ namespace Microsoft.AspNetCore.Components
public string? Type { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } }
public string? ValueAttribute { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } }
}
public static partial class ElementReferenceExtensions
{
public static System.Threading.Tasks.ValueTask FocusAsync(this Microsoft.AspNetCore.Components.ElementReference elementReference) { throw null; }
}
public partial class WebElementReferenceContext : Microsoft.AspNetCore.Components.ElementReferenceContext
{
public WebElementReferenceContext(Microsoft.JSInterop.IJSRuntime jsRuntime) { }
}
}
namespace Microsoft.AspNetCore.Components.Forms
{
@ -51,7 +59,7 @@ namespace Microsoft.AspNetCore.Components.Forms
protected TValue CurrentValue { get { throw null; } set { } }
protected string? CurrentValueAsString { get { throw null; } set { } }
protected Microsoft.AspNetCore.Components.Forms.EditContext EditContext { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } }
protected Microsoft.AspNetCore.Components.Forms.FieldIdentifier FieldIdentifier { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } }
protected internal Microsoft.AspNetCore.Components.Forms.FieldIdentifier FieldIdentifier { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } }
[Microsoft.AspNetCore.Components.ParameterAttribute]
public TValue Value { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } }
[Microsoft.AspNetCore.Components.ParameterAttribute]
@ -88,6 +96,29 @@ namespace Microsoft.AspNetCore.Components.Forms
protected override string? FormatValueAsString(TValue value) { throw null; }
protected override bool TryParseValueFromString(string? value, out TValue result, out string? validationErrorMessage) { throw null; }
}
public partial class InputRadioGroup<TValue> : Microsoft.AspNetCore.Components.Forms.InputBase<TValue>
{
public InputRadioGroup() { }
[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 string? Name { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } }
protected override void BuildRenderTree(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder builder) { }
protected override void OnParametersSet() { }
protected override bool TryParseValueFromString(string? value, out TValue result, out string? validationErrorMessage) { throw null; }
}
public partial class InputRadio<TValue> : Microsoft.AspNetCore.Components.ComponentBase
{
public InputRadio() { }
[Microsoft.AspNetCore.Components.ParameterAttribute(CaptureUnmatchedValues=true)]
public System.Collections.Generic.IReadOnlyDictionary<string, object>? AdditionalAttributes { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } }
[Microsoft.AspNetCore.Components.ParameterAttribute]
public string? Name { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } }
[Microsoft.AspNetCore.Components.ParameterAttribute]
public TValue Value { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } }
protected override void BuildRenderTree(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder builder) { }
protected override void OnParametersSet() { }
}
public partial class InputSelect<TValue> : Microsoft.AspNetCore.Components.Forms.InputBase<TValue>
{
public InputSelect() { }

View File

@ -0,0 +1,12 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace Microsoft.AspNetCore.Components
{
internal static class DomWrapperInterop
{
private const string Prefix = "Blazor._internal.domWrapper.";
public const string Focus = Prefix + "focus";
}
}

View File

@ -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;
using System.Threading.Tasks;
using Microsoft.JSInterop;
namespace Microsoft.AspNetCore.Components
{
public static class ElementReferenceExtensions
{
/// <summary>
/// Gives focus to an element given its <see cref="ElementReference"/>.
/// </summary>
/// <param name="elementReference">A reference to the element to focus.</param>
/// <returns>The <see cref="ValueTask"/> representing the asynchronous focus operation.</returns>
public static ValueTask FocusAsync(this ElementReference elementReference)
{
var jsRuntime = elementReference.GetJSRuntime();
if (jsRuntime == null)
{
throw new InvalidOperationException("No JavaScript runtime found.");
}
return jsRuntime.InvokeVoidAsync(DomWrapperInterop.Focus, elementReference);
}
internal static IJSRuntime GetJSRuntime(this ElementReference elementReference)
{
if (!(elementReference.Context is WebElementReferenceContext context))
{
throw new InvalidOperationException("ElementReference has not been configured correctly.");
}
return context.JSRuntime;
}
}
}

View File

@ -58,7 +58,7 @@ namespace Microsoft.AspNetCore.Components.Forms
/// <summary>
/// Gets the <see cref="FieldIdentifier"/> for the bound value.
/// </summary>
protected FieldIdentifier FieldIdentifier { get; set; }
protected internal FieldIdentifier FieldIdentifier { get; set; }
/// <summary>
/// Gets or sets the current value of the input.
@ -142,7 +142,7 @@ namespace Microsoft.AspNetCore.Components.Forms
/// </summary>
/// <param name="value">The value to format.</param>
/// <returns>A string representation of the value.</returns>
protected virtual string? FormatValueAsString(TValue value)
protected virtual string? FormatValueAsString([AllowNull] TValue value)
=> value?.ToString();
/// <summary>

View File

@ -34,7 +34,7 @@ namespace Microsoft.AspNetCore.Components.Forms
}
/// <inheritdoc />
protected override string FormatValueAsString(TValue value)
protected override string FormatValueAsString([AllowNull] TValue value)
{
switch (value)
{

View File

@ -0,0 +1,35 @@
// 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.Diagnostics.CodeAnalysis;
using System.Globalization;
namespace Microsoft.AspNetCore.Components.Forms
{
internal static class InputExtensions
{
public static bool TryParseSelectableValueFromString<TValue>(this InputBase<TValue> input, string? value, [MaybeNull] out TValue result, [NotNullWhen(false)] out string? validationErrorMessage)
{
try
{
if (BindConverter.TryConvertTo<TValue>(value, CultureInfo.CurrentCulture, out var parsedValue))
{
result = parsedValue;
validationErrorMessage = null;
return true;
}
else
{
result = default;
validationErrorMessage = $"The {input.FieldIdentifier.FieldName} field is not valid.";
return false;
}
}
catch (InvalidOperationException ex)
{
throw new InvalidOperationException($"{input.GetType()} does not support the type '{typeof(TValue)}'.", ex);
}
}
}
}

View File

@ -74,7 +74,7 @@ namespace Microsoft.AspNetCore.Components.Forms
/// </summary>
/// <param name="value">The value to format.</param>
/// <returns>A string representation of the value.</returns>
protected override string? FormatValueAsString(TValue value)
protected override string? FormatValueAsString([AllowNull] TValue value)
{
// Avoiding a cast to IFormattable to avoid boxing.
switch (value)

View File

@ -0,0 +1,82 @@
// 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.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using Microsoft.AspNetCore.Components.Rendering;
namespace Microsoft.AspNetCore.Components.Forms
{
/// <summary>
/// An input component used for selecting a value from a group of choices.
/// </summary>
public class InputRadio<TValue> : ComponentBase
{
/// <summary>
/// Gets context for this <see cref="InputRadio{TValue}"/>.
/// </summary>
internal InputRadioContext? Context { get; private set; }
/// <summary>
/// Gets or sets a collection of additional attributes that will be applied to the input element.
/// </summary>
[Parameter(CaptureUnmatchedValues = true)] public IReadOnlyDictionary<string, object>? AdditionalAttributes { get; set; }
/// <summary>
/// Gets or sets the value of this input.
/// </summary>
[AllowNull]
[MaybeNull]
[Parameter]
public TValue Value { get; set; } = default;
/// <summary>
/// Gets or sets the name of the parent input radio group.
/// </summary>
[Parameter] public string? Name { get; set; }
[CascadingParameter] private InputRadioContext? CascadedContext { get; set; }
private string GetCssClass(string fieldClass)
{
if (AdditionalAttributes != null &&
AdditionalAttributes.TryGetValue("class", out var @class) &&
!string.IsNullOrEmpty(Convert.ToString(@class)))
{
return $"{@class} {fieldClass}";
}
return fieldClass;
}
/// <inheritdoc />
protected override void OnParametersSet()
{
Context = string.IsNullOrEmpty(Name) ? CascadedContext : CascadedContext?.FindContextInAncestors(Name);
if (Context == null)
{
throw new InvalidOperationException($"{GetType()} must have an ancestor {typeof(InputRadioGroup<TValue>)} " +
$"with a matching 'Name' property, if specified.");
}
}
/// <inheritdoc />
protected override void BuildRenderTree(RenderTreeBuilder builder)
{
Debug.Assert(Context != null);
builder.OpenElement(0, "input");
builder.AddMultipleAttributes(1, AdditionalAttributes);
builder.AddAttribute(2, "class", GetCssClass(Context.FieldClass));
builder.AddAttribute(3, "type", "radio");
builder.AddAttribute(4, "name", Context.GroupName);
builder.AddAttribute(5, "value", BindConverter.FormatValue(Value?.ToString()));
builder.AddAttribute(6, "checked", Context.CurrentValue?.Equals(Value));
builder.AddAttribute(7, "onchange", Context.ChangeEventCallback);
builder.CloseElement();
}
}
}

View File

@ -0,0 +1,64 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace Microsoft.AspNetCore.Components.Forms
{
/// <summary>
/// Describes context for an <see cref="InputRadio{TValue}"/> component.
/// </summary>
internal class InputRadioContext
{
private readonly InputRadioContext? _parentContext;
/// <summary>
/// Gets the name of the input radio group.
/// </summary>
public string GroupName { get; }
/// <summary>
/// Gets the current selected value in the input radio group.
/// </summary>
public object? CurrentValue { get; }
/// <summary>
/// Gets a css class indicating the validation state of input radio elements.
/// </summary>
public string FieldClass { get; }
/// <summary>
/// Gets the event callback to be invoked when the selected value is changed.
/// </summary>
public EventCallback<ChangeEventArgs> ChangeEventCallback { get; }
/// <summary>
/// Instantiates a new <see cref="InputRadioContext" />.
/// </summary>
/// <param name="parentContext">The parent <see cref="InputRadioContext" />.</param>
/// <param name="groupName">The name of the input radio group.</param>
/// <param name="currentValue">The current selected value in the input radio group.</param>
/// <param name="fieldClass">The css class indicating the validation state of input radio elements.</param>
/// <param name="changeEventCallback">The event callback to be invoked when the selected value is changed.</param>
public InputRadioContext(
InputRadioContext? parentContext,
string groupName,
object? currentValue,
string fieldClass,
EventCallback<ChangeEventArgs> changeEventCallback)
{
_parentContext = parentContext;
GroupName = groupName;
CurrentValue = currentValue;
FieldClass = fieldClass;
ChangeEventCallback = changeEventCallback;
}
/// <summary>
/// Finds an <see cref="InputRadioContext"/> in the context's ancestors with the matching <paramref name="groupName"/>.
/// </summary>
/// <param name="groupName">The group name of the ancestor <see cref="InputRadioContext"/>.</param>
/// <returns>The <see cref="InputRadioContext"/>, or <c>null</c> if none was found.</returns>
public InputRadioContext? FindContextInAncestors(string groupName)
=> string.Equals(GroupName, groupName) ? this : _parentContext?.FindContextInAncestors(groupName);
}
}

View File

@ -0,0 +1,57 @@
// 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.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using Microsoft.AspNetCore.Components.Rendering;
namespace Microsoft.AspNetCore.Components.Forms
{
/// <summary>
/// Groups child <see cref="InputRadio{TValue}"/> components.
/// </summary>
public class InputRadioGroup<TValue> : InputBase<TValue>
{
private readonly string _defaultGroupName = Guid.NewGuid().ToString("N");
private InputRadioContext? _context;
/// <summary>
/// Gets or sets the child content to be rendering inside the <see cref="InputRadioGroup{TValue}"/>.
/// </summary>
[Parameter] public RenderFragment? ChildContent { get; set; }
/// <summary>
/// Gets or sets the name of the group.
/// </summary>
[Parameter] public string? Name { get; set; }
[CascadingParameter] private InputRadioContext? CascadedContext { get; set; }
/// <inheritdoc />
protected override void OnParametersSet()
{
var groupName = !string.IsNullOrEmpty(Name) ? Name : _defaultGroupName;
var fieldClass = EditContext.FieldCssClass(FieldIdentifier);
var changeEventCallback = EventCallback.Factory.CreateBinder<string?>(this, __value => CurrentValueAsString = __value, CurrentValueAsString);
_context = new InputRadioContext(CascadedContext, groupName, CurrentValue, fieldClass, changeEventCallback);
}
/// <inheritdoc />
protected override void BuildRenderTree(RenderTreeBuilder builder)
{
Debug.Assert(_context != null);
builder.OpenComponent<CascadingValue<InputRadioContext>>(2);
builder.AddAttribute(3, "IsFixed", true);
builder.AddAttribute(4, "Value", _context);
builder.AddAttribute(5, "ChildContent", ChildContent);
builder.CloseComponent();
}
/// <inheritdoc />
protected override bool TryParseValueFromString(string? value, [MaybeNull] out TValue result, [NotNullWhen(false)] out string? validationErrorMessage)
=> this.TryParseSelectableValueFromString(value, out result, out validationErrorMessage);
}
}

View File

@ -1,9 +1,7 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using Microsoft.AspNetCore.Components.Rendering;
namespace Microsoft.AspNetCore.Components.Forms
@ -13,8 +11,6 @@ namespace Microsoft.AspNetCore.Components.Forms
/// </summary>
public class InputSelect<TValue> : InputBase<TValue>
{
private static readonly Type? _nullableUnderlyingType = Nullable.GetUnderlyingType(typeof(TValue));
/// <summary>
/// Gets or sets the child content to be rendering inside the select element.
/// </summary>
@ -34,31 +30,6 @@ namespace Microsoft.AspNetCore.Components.Forms
/// <inheritdoc />
protected override bool TryParseValueFromString(string? value, [MaybeNull] out TValue result, [NotNullWhen(false)] out string? validationErrorMessage)
{
if (typeof(TValue) == typeof(string))
{
result = (TValue)(object?)value;
validationErrorMessage = null;
return true;
}
else if (typeof(TValue).IsEnum || (_nullableUnderlyingType != null && _nullableUnderlyingType.IsEnum))
{
var success = BindConverter.TryConvertTo<TValue>(value, CultureInfo.CurrentCulture, out var parsedValue);
if (success)
{
result = parsedValue;
validationErrorMessage = null;
return true;
}
else
{
result = default;
validationErrorMessage = $"The {FieldIdentifier.FieldName} field is not valid.";
return false;
}
}
throw new InvalidOperationException($"{GetType()} does not support the type '{typeof(TValue)}'.");
}
=> this.TryParseSelectableValueFromString(value, out result, out validationErrorMessage);
}
}

View File

@ -1,3 +1,4 @@
using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Components.Server.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Components.Web.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]

View File

@ -0,0 +1,18 @@
// 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.JSInterop;
namespace Microsoft.AspNetCore.Components
{
public class WebElementReferenceContext : ElementReferenceContext
{
internal IJSRuntime JSRuntime { get; }
public WebElementReferenceContext(IJSRuntime jsRuntime)
{
JSRuntime = jsRuntime ?? throw new ArgumentNullException(nameof(jsRuntime));
}
}
}

View File

@ -0,0 +1,138 @@
// 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 System.Linq.Expressions;
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.Forms
{
public class InputRadioTest
{
[Fact]
public async Task ThrowsOnFirstRenderIfInputRadioHasNoGroup()
{
var model = new TestModel();
var rootComponent = new TestInputRadioHostComponent<TestEnum>
{
EditContext = new EditContext(model),
InnerContent = RadioButtonsWithoutGroup(null)
};
var ex = await Assert.ThrowsAsync<InvalidOperationException>(() => RenderAndGetTestInputComponentAsync(rootComponent));
Assert.Contains($"must have an ancestor", ex.Message);
}
[Fact]
public async Task GroupGeneratesNameGuidWhenInvalidNameSupplied()
{
var model = new TestModel();
var rootComponent = new TestInputRadioHostComponent<TestEnum>
{
EditContext = new EditContext(model),
InnerContent = RadioButtonsWithGroup(null, () => model.TestEnum)
};
var inputRadioComponents = await RenderAndGetTestInputComponentAsync(rootComponent);
Assert.All(inputRadioComponents, inputRadio => Assert.True(Guid.TryParseExact(inputRadio.GroupName, "N", out _)));
}
[Fact]
public async Task RadioInputContextExistsWhenValidNameSupplied()
{
var groupName = "group";
var model = new TestModel();
var rootComponent = new TestInputRadioHostComponent<TestEnum>
{
EditContext = new EditContext(model),
InnerContent = RadioButtonsWithGroup(groupName, () => model.TestEnum)
};
var inputRadioComponents = await RenderAndGetTestInputComponentAsync(rootComponent);
Assert.All(inputRadioComponents, inputRadio => Assert.Equal(groupName, inputRadio.GroupName));
}
private static RenderFragment RadioButtonsWithoutGroup(string name) => (builder) =>
{
foreach (var selectedValue in (TestEnum[])Enum.GetValues(typeof(TestEnum)))
{
builder.OpenComponent<TestInputRadio>(0);
builder.AddAttribute(1, "Name", name);
builder.AddAttribute(2, "Value", selectedValue);
builder.CloseComponent();
}
};
private static RenderFragment RadioButtonsWithGroup(string name, Expression<Func<TestEnum>> valueExpression) => (builder) =>
{
builder.OpenComponent<InputRadioGroup<TestEnum>>(0);
builder.AddAttribute(1, "Name", name);
builder.AddAttribute(2, "ValueExpression", valueExpression);
builder.AddAttribute(2, "ChildContent", new RenderFragment((childBuilder) =>
{
foreach (var value in (TestEnum[])Enum.GetValues(typeof(TestEnum)))
{
childBuilder.OpenComponent<TestInputRadio>(0);
childBuilder.AddAttribute(1, "Value", value);
childBuilder.CloseComponent();
}
}));
builder.CloseComponent();
};
private static IEnumerable<TestInputRadio> FindInputRadioComponents(CapturedBatch batch)
=> batch.ReferenceFrames
.Where(f => f.FrameType == RenderTreeFrameType.Component)
.Select(f => f.Component)
.OfType<TestInputRadio>();
private static async Task<IEnumerable<TestInputRadio>> RenderAndGetTestInputComponentAsync(TestInputRadioHostComponent<TestEnum> rootComponent)
{
var testRenderer = new TestRenderer();
var componentId = testRenderer.AssignRootComponentId(rootComponent);
await testRenderer.RenderRootComponentAsync(componentId);
return FindInputRadioComponents(testRenderer.Batches.Single());
}
private enum TestEnum
{
One,
Two,
Three
}
private class TestModel
{
public TestEnum TestEnum { get; set; }
}
private class TestInputRadio : InputRadio<TestEnum>
{
public string GroupName => Context.GroupName;
}
private class TestInputRadioHostComponent<TValue> : AutoRenderComponent
{
public EditContext EditContext { get; set; }
public RenderFragment InnerContent { get; set; }
protected override void BuildRenderTree(RenderTreeBuilder builder)
{
builder.OpenComponent<CascadingValue<EditContext>>(0);
builder.AddAttribute(1, "Value", EditContext);
builder.AddAttribute(2, "ChildContent", InnerContent);
builder.CloseComponent();
}
}
}
}

View File

@ -90,6 +90,88 @@ namespace Microsoft.AspNetCore.Components.Forms
Assert.Null(inputSelectComponent.CurrentValue);
}
// See: https://github.com/dotnet/aspnetcore/issues/9939
[Fact]
public async Task ParsesCurrentValueWhenUsingNotNullableGuid()
{
// Arrange
var model = new TestModel();
var rootComponent = new TestInputSelectHostComponent<Guid>
{
EditContext = new EditContext(model),
ValueExpression = () => model.NotNullableGuid
};
var inputSelectComponent = await RenderAndGetTestInputComponentAsync(rootComponent);
// Act
var guid = Guid.NewGuid();
inputSelectComponent.CurrentValueAsString = guid.ToString();
// Assert
Assert.Equal(guid, inputSelectComponent.CurrentValue);
}
// See: https://github.com/dotnet/aspnetcore/issues/9939
[Fact]
public async Task ParsesCurrentValueWhenUsingNullableGuid()
{
// Arrange
var model = new TestModel();
var rootComponent = new TestInputSelectHostComponent<Guid?>
{
EditContext = new EditContext(model),
ValueExpression = () => model.NullableGuid
};
var inputSelectComponent = await RenderAndGetTestInputComponentAsync(rootComponent);
// Act
var guid = Guid.NewGuid();
inputSelectComponent.CurrentValueAsString = guid.ToString();
// Assert
Assert.Equal(guid, inputSelectComponent.CurrentValue);
}
// See: https://github.com/dotnet/aspnetcore/pull/19562
[Fact]
public async Task ParsesCurrentValueWhenUsingNotNullableInt()
{
// Arrange
var model = new TestModel();
var rootComponent = new TestInputSelectHostComponent<int>
{
EditContext = new EditContext(model),
ValueExpression = () => model.NotNullableInt
};
var inputSelectComponent = await RenderAndGetTestInputComponentAsync(rootComponent);
// Act
inputSelectComponent.CurrentValueAsString = "42";
// Assert
Assert.Equal(42, inputSelectComponent.CurrentValue);
}
// See: https://github.com/dotnet/aspnetcore/pull/19562
[Fact]
public async Task ParsesCurrentValueWhenUsingNullableInt()
{
// Arrange
var model = new TestModel();
var rootComponent = new TestInputSelectHostComponent<int?>
{
EditContext = new EditContext(model),
ValueExpression = () => model.NullableInt
};
var inputSelectComponent = await RenderAndGetTestInputComponentAsync(rootComponent);
// Act
inputSelectComponent.CurrentValueAsString = "42";
// Assert
Assert.Equal(42, inputSelectComponent.CurrentValue);
}
private static TestInputSelect<TValue> FindInputSelectComponent<TValue>(CapturedBatch batch)
=> batch.ReferenceFrames
.Where(f => f.FrameType == RenderTreeFrameType.Component)
@ -117,6 +199,14 @@ namespace Microsoft.AspNetCore.Components.Forms
public TestEnum NotNullableEnum { get; set; }
public TestEnum? NullableEnum { get; set; }
public Guid NotNullableGuid { get; set; }
public Guid? NullableGuid { get; set; }
public int NotNullableInt { get; set; }
public int? NullableInt { get; set; }
}
class TestInputSelect<TValue> : InputSelect<TValue>

View File

@ -9,6 +9,7 @@
</PropertyGroup>
<ItemGroup>
<Compile Include="$(ComponentsSharedSourceRoot)src\WebAssemblyJSInteropInternalCalls.cs" />
<Reference Include="Microsoft.JSInterop" />
</ItemGroup>

View File

@ -188,7 +188,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Authentication
var parameters = ParameterView.FromDictionary(new Dictionary<string, object>
{
[_action] = RemoteAuthenticationActions.LogInCallback,
[_onLogInSucceded] = new EventCallbackFactory().Create< RemoteAuthenticationState>(
[_onLogInSucceded] = new EventCallbackFactory().Create<RemoteAuthenticationState>(
remoteAuthenticator,
(state) => loggingSucceededCalled = true),
});

View File

@ -23,11 +23,6 @@
Private="false"
Condition="'$(BuildNodeJS)' != 'false' and '$(BuildingInsideVisualStudio)' != 'true'" />
<!-- Tracking removing using https://github.com/dotnet/aspnetcore/issues/22283 -->
<ProjectReference
Include="..\..\WebAssemblyHttpHandler\src\Microsoft.AspNetCore.Components.WebAssembly.HttpHandler.csproj"
IncludeAssets="compile" />
<SuppressBaselineReference Include="Microsoft.AspNetCore.Components.WebAssembly.HttpHandler" />
</ItemGroup>

View File

@ -34,6 +34,8 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Rendering
// The WebAssembly renderer registers and unregisters itself with the static registry
_webAssemblyRendererId = RendererRegistry.Add(this);
_logger = loggerFactory.CreateLogger<WebAssemblyRenderer>();
ElementReferenceContext = DefaultWebAssemblyJSRuntime.Instance.ElementReferenceContext;
}
public override Dispatcher Dispatcher => NullDispatcher.Instance;

View File

@ -10,9 +10,12 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Services
{
internal static readonly DefaultWebAssemblyJSRuntime Instance = new DefaultWebAssemblyJSRuntime();
public ElementReferenceContext ElementReferenceContext { get; }
private DefaultWebAssemblyJSRuntime()
{
JsonSerializerOptions.Converters.Add(new ElementReferenceJsonConverter());
ElementReferenceContext = new WebElementReferenceContext(this);
JsonSerializerOptions.Converters.Add(new ElementReferenceJsonConverter(ElementReferenceContext));
}
#pragma warning disable IDE0051 // Remove unused private members. Invoked via Mono's JS interop mechanism (invoke_method)

View File

@ -1,7 +1,10 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using Xunit;
namespace Microsoft.AspNetCore.Blazor.Rendering
namespace Microsoft.AspNetCore.Components.WebAssembly.Rendering
{
public class RenderRegistryTest
{

View File

@ -1,16 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<NuspecFile>$(MSBuildProjectName).nuspec</NuspecFile>
<TargetFramework>netstandard2.1</TargetFramework>
<PackageId>$(MSBuildProjectName)</PackageId>
<AssemblyName>System.Net.Http.WebAssemblyHttpHandler</AssemblyName>
<AssemblyVersion>0.2.2.0</AssemblyVersion>
<ProduceOnlyReferenceAssembly>true</ProduceOnlyReferenceAssembly>
<StrongNameKeyId>Open</StrongNameKeyId>
</PropertyGroup>
<ItemGroup>
<NuspecProperty Include="OutputPath=$(OutputPath)" />
</ItemGroup>
</Project>

View File

@ -1,11 +0,0 @@
using System;
using System.Net.Http;
namespace System.Net.Http
{
public partial class WebAssemblyHttpHandler : System.Net.Http.HttpMessageHandler
{
public WebAssemblyHttpHandler() { }
protected override System.Threading.Tasks.Task<System.Net.Http.HttpResponseMessage> SendAsync(System.Net.Http.HttpRequestMessage request, System.Threading.CancellationToken cancellationToken) { throw null; }
}
}

View File

@ -1,13 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd">
<metadata>
$CommonMetadataElements$
<dependencies>
<group targetFramework=".NETStandard2.1" />
</dependencies>
</metadata>
<files>
$CommonFileElements$
<file src="$OutputPath$System.Net.Http.WebAssemblyHttpHandler.dll" target="lib\netstandard2.1\System.Net.Http.WebAssemblyHttpHandler.dll" />
</files>
</package>

View File

@ -4,8 +4,6 @@
<TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework>
<RuntimeIdentifier>browser-wasm</RuntimeIdentifier>
<UseBlazorWebAssembly>true</UseBlazorWebAssembly>
<FixupWebAssemblyHttpHandlerReference>true</FixupWebAssemblyHttpHandlerReference>
</PropertyGroup>
<ItemGroup>

View File

@ -4,8 +4,6 @@
<TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework>
<RuntimeIdentifier>browser-wasm</RuntimeIdentifier>
<UseBlazorWebAssembly>true</UseBlazorWebAssembly>
<FixupWebAssemblyHttpHandlerReference>true</FixupWebAssemblyHttpHandlerReference>
</PropertyGroup>
<ItemGroup>

View File

@ -40,13 +40,12 @@ namespace Wasm.Performance.Driver
return 1;
}
if (stressRunSeconds < 1)
if (stressRunSeconds < 0)
{
Console.Error.WriteLine("Stress run duration must be a positive integer.");
return 1;
}
if (stressRunSeconds > 0)
else if (stressRunSeconds > 0)
{
isStressRun = true;

View File

@ -15,7 +15,13 @@ namespace Wasm.Performance.Driver
{
const int SeleniumPort = 4444;
static bool RunHeadlessBrowser = true;
static bool PoolForBrowserLogs = false;
static bool PoolForBrowserLogs =
#if DEBUG
true;
#else
false;
#endif
private static async ValueTask<Uri> WaitForServerAsync(int port, CancellationToken cancellationToken)
{

View File

@ -8,6 +8,7 @@
<!-- WebDriver is not strong-named, so this test project cannot be strong named either. -->
<SignAssembly>false</SignAssembly>
<IsTestAssetProject>true</IsTestAssetProject>
<RuntimeIdentifier>linux-x64</RuntimeIdentifier>
</PropertyGroup>
<ItemGroup>

View File

@ -9,7 +9,7 @@ The TestApp is a regular BlazorWASM project and can be run using `dotnet run`. T
Here are the commands you would need to run it locally inside docker:
1. `dotnet publish -c Release -r linux-x64 Driver/Wasm.Performance.Driver.csproj`
1. `dotnet publish -c Release Driver/Wasm.Performance.Driver.csproj`
2. `docker build -t blazor-local -f ./local.dockerfile . `
3. `docker run -it blazor-local`

View File

@ -0,0 +1,122 @@
@page "/gridrendering"
@inject IJSRuntime JSRuntime
@using Wasm.Performance.TestApp.Shared.FastGrid
<h1>20 x 200 Grid</h1>
<fieldset>
<select id="render-mode" @bind="selectedRenderMode">
<option>@RenderMode.FastGrid</option>
<option>@RenderMode.PlainTable</option>
<option>@RenderMode.ComplexTable</option>
</select>
<button id="show" @onclick="Show">Show</button>
<button id="hide" @onclick="Hide">Hide</button>
@if (forecasts != null)
{
<button id="change-page" @onclick="ChangePage">Switch pages</button>
}
</fieldset>
@if (forecasts == null)
{
<p><em>(No data assigned)</em></p>
}
else if (selectedRenderMode == RenderMode.FastGrid)
{
<p>FastGrid represents a minimal, optimized implementation of a grid.</p>
<Grid Data="@forecasts">
<GridColumn TRowData="WeatherForecast" Title="Date">@context.Date.ToShortDateString()</GridColumn>
<GridColumn TRowData="WeatherForecast" Title="TemperatureC">@context.TemperatureC</GridColumn>
<GridColumn TRowData="WeatherForecast" Title="TemperatureF">@context.TemperatureF</GridColumn>
<GridColumn TRowData="WeatherForecast" Title="Summary">@context.Summary</GridColumn>
<GridColumn TRowData="WeatherForecast" Title="Date">@context.Date.ToShortDateString()</GridColumn>
<GridColumn TRowData="WeatherForecast" Title="TemperatureC">@context.TemperatureC</GridColumn>
<GridColumn TRowData="WeatherForecast" Title="TemperatureF">@context.TemperatureF</GridColumn>
<GridColumn TRowData="WeatherForecast" Title="Summary">@context.Summary</GridColumn>
<GridColumn TRowData="WeatherForecast" Title="Date">@context.Date.ToShortDateString()</GridColumn>
<GridColumn TRowData="WeatherForecast" Title="TemperatureC">@context.TemperatureC</GridColumn>
<GridColumn TRowData="WeatherForecast" Title="TemperatureF">@context.TemperatureF</GridColumn>
<GridColumn TRowData="WeatherForecast" Title="Summary">@context.Summary</GridColumn>
<GridColumn TRowData="WeatherForecast" Title="Date">@context.Date.ToShortDateString()</GridColumn>
<GridColumn TRowData="WeatherForecast" Title="TemperatureC">@context.TemperatureC</GridColumn>
<GridColumn TRowData="WeatherForecast" Title="TemperatureF">@context.TemperatureF</GridColumn>
<GridColumn TRowData="WeatherForecast" Title="Summary">@context.Summary</GridColumn>
<GridColumn TRowData="WeatherForecast" Title="Date">@context.Date.ToShortDateString()</GridColumn>
<GridColumn TRowData="WeatherForecast" Title="TemperatureC">@context.TemperatureC</GridColumn>
<GridColumn TRowData="WeatherForecast" Title="TemperatureF">@context.TemperatureF</GridColumn>
<GridColumn TRowData="WeatherForecast" Title="Summary">@context.Summary</GridColumn>
</Grid>
}
else if (selectedRenderMode == RenderMode.PlainTable)
{
<p>PlainTable represents a minimal but not optimized implementation of a grid.</p>
<Wasm.Performance.TestApp.Shared.PlainTable.TableComponent Data="@forecasts" Columns="@Columns" />
}
else if (selectedRenderMode == RenderMode.ComplexTable)
{
<p>ComplexTable represents a maximal, not optimized implementation of a grid, using a wide range of Blazor features at once.</p>
<Wasm.Performance.TestApp.Shared.ComplexTable.TableComponent Data="@forecasts" Columns="@Columns" />
}
@code {
enum RenderMode { PlainTable, ComplexTable, FastGrid }
private RenderMode selectedRenderMode = RenderMode.FastGrid;
private WeatherForecast[] forecasts;
public List<string> Columns { get; set; } = new List<string>
{
"Date", "TemperatureC", "TemperatureF", "Summary",
"Date", "TemperatureC", "TemperatureF", "Summary",
"Date", "TemperatureC", "TemperatureF", "Summary",
"Date", "TemperatureC", "TemperatureF", "Summary",
"Date", "TemperatureC", "TemperatureF", "Summary",
};
private static string[] sampleSummaries = new[] { "Balmy", "Chilly", "Freezing", "Bracing" };
private static WeatherForecast[] staticSampleDataPage1 = Enumerable.Range(0, 200).Select(CreateSampleDataItem).ToArray();
private static WeatherForecast[] staticSampleDataPage2 = Enumerable.Range(200, 200).Select(CreateSampleDataItem).ToArray();
private static WeatherForecast CreateSampleDataItem(int index) => new WeatherForecast
{
Date = DateTime.Now.Date.AddDays(index),
Summary = sampleSummaries[index % sampleSummaries.Length],
TemperatureC = index,
};
void Show()
{
forecasts = staticSampleDataPage1;
}
void Hide()
{
forecasts = null;
}
void ChangePage()
{
forecasts = (forecasts == staticSampleDataPage1) ? staticSampleDataPage2 : staticSampleDataPage1;
}
protected override void OnAfterRender(bool firstRender)
{
BenchmarkEvent.Send(JSRuntime, "Finished rendering table");
}
public class WeatherForecast
{
public DateTime Date { get; set; }
public int TemperatureC { get; set; }
public string Summary { get; set; }
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
}
}

View File

@ -0,0 +1,59 @@
@using WeatherForecast = Pages.GridRendering.WeatherForecast
<td @attributes="@Attributes"
@onclick="@(() => OnClick.Invoke(CellIndex))"
>
@switch (Field)
{
case "Date":
@Item.Date.ToShortDateString()
break;
case "TemperatureC":
@Item.TemperatureC
break;
case "TemperatureF":
@Item.TemperatureF
break;
case "Summary":
@Item.Summary
break;
}
</td>
@code {
[Parameter]
public WeatherForecast Item { get; set; }
[CascadingParameter]
public TableComponent ParentTable { get; set; }
[Parameter]
public string Field { get; set; }
[Parameter]
public int CellIndex { get; set; }
[Parameter]
public int RowIndex { get; set; }
[Parameter]
public bool Selected { get; set; }
[Parameter]
public string FormatString { get; set; }
[Parameter]
public Func<int, Task> OnClick { get; set; }
private protected Dictionary<string, object> Attributes
{
get
{
var attributes = new Dictionary<string, object>();
attributes["tabindex"] = CellIndex;
return attributes;
}
}
}

View File

@ -0,0 +1,39 @@
@using WeatherForecast = Pages.GridRendering.WeatherForecast
<tr class="complex-table-row" style="@rowStyle">
@foreach (var item in Columns)
{
<Cell Item="@Item"
Field="@item"
CellIndex="1"
RowIndex="2"
Selected="@isSelected"
FormatString="foo"
OnClick="@OnCellClick">
</Cell>
}
</tr>
@code {
private bool isSelected = false;
private string rowStyle => isSelected ? "background-color: lightblue;" : "";
[Parameter]
public WeatherForecast Item { get; set; }
[Parameter]
public List<string> Columns { get; set; }
[Parameter]
public Func<int, Task> OnClick { get; set; }
Task OnCellClick(int args)
{
isSelected = !isSelected;
return OnClick.Invoke(args);
}
}

View File

@ -0,0 +1,19 @@
@using WeatherForecast = Pages.GridRendering.WeatherForecast
@foreach (var item in Data)
{
<Row Item="@item" Columns="@Columns"
OnClick="@OnClick"></Row>
}
@code {
[Parameter]
public WeatherForecast[] Data { get; set; }
[Parameter]
public List<string> Columns { get; set; }
[Parameter]
public Func<int, Task> OnClick { get; set; }
}

View File

@ -0,0 +1,46 @@
@using WeatherForecast = Pages.GridRendering.WeatherForecast
<table class="table">
<thead>
<tr>
@foreach (var item in Columns)
{
<th>@item</th>
}
</tr>
</thead>
<tbody>
<CascadingValue Value="@this">
<RowCollection Data="@Data"
Columns="@Columns"
OnClick="@RefreshComponent"></RowCollection>
</CascadingValue>
</tbody>
</table>
@code {
[Parameter]
public WeatherForecast[] Data { get; set; }
[Parameter]
public List<string> Columns { get; set; }
DateTime t1;
DateTime t2;
Task RefreshComponent(int index)
{
t1 = DateTime.Now;
StateHasChanged();
return Task.CompletedTask;
}
protected override Task OnAfterRenderAsync(bool firstRender)
{
if (!firstRender)
{
t2 = DateTime.Now;
Console.WriteLine("Refresh Time " + (t2 - t1).TotalMilliseconds);
}
return base.OnAfterRenderAsync(firstRender);
}
}

View File

@ -0,0 +1,48 @@
@typeparam TRowData
<CascadingValue IsFixed="true" Value="this">@ChildContent</CascadingValue>
<table @attributes="@Attributes">
<thead>
<tr>
@foreach (var col in columns)
{
col.RenderHeader(__builder);
}
</tr>
</thead>
<tbody>
@foreach (var item in Data)
{
<tr @key="item.GetHashCode()" class="@(RowClass?.Invoke(item))">
@foreach (var col in columns)
{
col.RenderCell(__builder, item);
}
</tr>
}
</tbody>
</table>
@code {
[Parameter(CaptureUnmatchedValues = true)] public Dictionary<string, object> Attributes { get; set; }
[Parameter] public ICollection<TRowData> Data { get; set; }
[Parameter] public RenderFragment ChildContent { get; set; }
[Parameter] public Func<TRowData, string> RowClass { get; set; }
private List<GridColumn<TRowData>> columns = new List<GridColumn<TRowData>>();
internal void AddColumn(GridColumn<TRowData> column)
{
columns.Add(column);
}
protected override void OnAfterRender(bool firstRender)
{
if (firstRender)
{
// On the first render, we collect the list of columns, then we have to render them.
StateHasChanged();
}
}
}

View File

@ -0,0 +1,23 @@
@typeparam TRowData
@using Microsoft.AspNetCore.Components.Rendering
@code {
[CascadingParameter] public Grid<TRowData> OwnerGrid { get; set; }
[Parameter] public string Title { get; set; }
[Parameter] public TRowData RowData { get; set; }
[Parameter] public RenderFragment<TRowData> ChildContent { get; set; }
protected override void OnInitialized()
{
OwnerGrid.AddColumn(this);
}
internal void RenderHeader(RenderTreeBuilder __builder)
{
<th>@Title</th>
}
internal void RenderCell(RenderTreeBuilder __builder, TRowData rowData)
{
<td>@ChildContent(rowData)</td>
}
}

View File

@ -6,7 +6,8 @@
<a href="renderlist">RenderList</a> |
<a href="json">JSON</a> |
<a href="orgchart">OrgChart</a> |
<a href="timer">Timer</a>
<a href="timer">Timer</a> |
<a href="gridrendering">Grid</a>
<hr />

View File

@ -0,0 +1,30 @@
@using WeatherForecast = Pages.GridRendering.WeatherForecast
<td @onclick="@(() => OnClick.Invoke(1))">
@switch (Field)
{
case "Date":
@Item.Date.ToShortDateString()
break;
case "TemperatureC":
@Item.TemperatureC
break;
case "TemperatureF":
@Item.TemperatureF
break;
case "Summary":
@Item.Summary
break;
}
</td>
@code {
[Parameter]
public WeatherForecast Item { get; set; }
[Parameter]
public string Field { get; set; }
[Parameter]
public Func<int, Task> OnClick { get; set; }
}

View File

@ -0,0 +1,35 @@
@using WeatherForecast = Pages.GridRendering.WeatherForecast
<tr style="@rowStyle">
@foreach (var item in Columns)
{
<Cell Item="@Item"
Field="@item"
OnClick="@OnCellClick">
</Cell>
}
</tr>
@code {
private bool isSelected = false;
private string rowStyle => isSelected ? "background-color: lightblue;" : "";
[Parameter]
public WeatherForecast Item { get; set; }
[Parameter]
public List<string> Columns { get; set; }
[Parameter]
public Func<int, Task> OnClick { get; set; }
Task OnCellClick(int args)
{
isSelected = !isSelected;
return OnClick.Invoke(args);
}
}

View File

@ -0,0 +1,19 @@
@using WeatherForecast = Pages.GridRendering.WeatherForecast
@foreach (var item in Data)
{
<Row Item="@item" Columns="@Columns"
OnClick="@OnClick"></Row>
}
@code {
[Parameter]
public WeatherForecast[] Data { get; set; }
[Parameter]
public List<string> Columns { get; set; }
[Parameter]
public Func<int, Task> OnClick { get; set; }
}

View File

@ -0,0 +1,44 @@
@using WeatherForecast = Pages.GridRendering.WeatherForecast
<table class="table">
<thead>
<tr>
@foreach (var item in Columns)
{
<th>@item</th>
}
</tr>
</thead>
<tbody>
<RowCollection Data="@Data"
Columns="@Columns"
OnClick="@RefreshComponent"></RowCollection>
</tbody>
</table>
@code {
[Parameter]
public WeatherForecast[] Data { get; set; }
[Parameter]
public List<string> Columns { get; set; }
DateTime t1;
DateTime t2;
Task RefreshComponent(int index)
{
t1 = DateTime.Now;
StateHasChanged();
return Task.CompletedTask;
}
protected override Task OnAfterRenderAsync(bool firstRender)
{
if (!firstRender)
{
t2 = DateTime.Now;
Console.WriteLine("Refresh Time " + (t2 - t1).TotalMilliseconds);
}
return base.OnAfterRenderAsync(firstRender);
}
}

View File

@ -0,0 +1,105 @@
import { group, benchmark, setup, teardown } from './lib/minibench/minibench.js';
import { receiveEvent } from './util/BenchmarkEvents.js';
import { BlazorApp } from './util/BlazorApp.js';
import { setInputValue } from './util/DOM.js';
group('Grid', () => {
let app;
setup(async () => {
app = new BlazorApp();
await app.start();
app.navigateTo('gridrendering');
});
teardown(() => {
app.dispose();
});
benchmark('PlainTable: From blank', () => measureRenderGridFromBlank(app), {
setup: () => prepare(app, 'PlainTable', false),
descriptor: {
name: 'blazorwasm/render-plaintable-from-blank',
description: 'Time to render plain table from blank (ms)'
}
});
benchmark('PlainTable: Switch pages', () => measureRenderGridSwitchPages(app), {
setup: () => prepare(app, 'PlainTable', true),
descriptor: {
name: 'blazorwasm/render-plaintable-switch-pages',
description: 'Time to render plain table change of page (ms)'
}
});
benchmark('ComplexTable: From blank', () => measureRenderGridFromBlank(app), {
setup: () => prepare(app, 'ComplexTable', false),
descriptor: {
name: 'blazorwasm/render-complextable-from-blank',
description: 'Time to render complex table from blank (ms)'
}
});
benchmark('ComplexTable: Switch pages', () => measureRenderGridSwitchPages(app), {
setup: () => prepare(app, 'ComplexTable', true),
descriptor: {
name: 'blazorwasm/render-complextable-switch-pages',
description: 'Time to render complex table change of page (ms)'
}
});
benchmark('FastGrid: From blank', () => measureRenderGridFromBlank(app), {
setup: () => prepare(app, 'FastGrid', false),
descriptor: {
name: 'blazorwasm/render-fastgrid-from-blank',
description: 'Time to render fast grid from blank (ms)'
}
});
benchmark('FastGrid: Switch pages', () => measureRenderGridSwitchPages(app), {
setup: () => prepare(app, 'FastGrid', true),
descriptor: {
name: 'blazorwasm/render-fastgrid-switch-pages',
description: 'Time to render fast grid change of page (ms)'
}
});
});
async function prepare(app, renderMode, populateTable) {
const renderModeSelect = app.window.document.querySelector('#render-mode');
setInputValue(renderModeSelect, renderMode);
if (populateTable) {
let nextRenderCompletion = receiveEvent('Finished rendering table');
app.window.document.querySelector(populateTable ? '#show' : '#hide').click();
await nextRenderCompletion;
}
}
async function measureRenderGridFromBlank(app) {
const appDocument = app.window.document;
let nextRenderCompletion = receiveEvent('Finished rendering table');
appDocument.querySelector('#hide').click();
await nextRenderCompletion;
if (appDocument.querySelectorAll('tbody tr').length !== 0) {
throw new Error('Wrong number of rows rendered');
}
nextRenderCompletion = receiveEvent('Finished rendering table');
appDocument.querySelector('#show').click();
await nextRenderCompletion;
if (appDocument.querySelectorAll('tbody tr').length !== 200) {
throw new Error('Wrong number of rows rendered');
}
}
async function measureRenderGridSwitchPages(app) {
const appDocument = app.window.document;
let nextRenderCompletion = receiveEvent('Finished rendering table');
appDocument.querySelector('#change-page').click();
await nextRenderCompletion;
}

View File

@ -4,6 +4,7 @@ import './appStartup.js';
import './renderList.js';
import './jsonHandling.js';
import './orgChart.js';
import './grid.js';
import { getBlazorDownloadSize } from './blazorDownloadSize.js';
new HtmlUI('E2E Performance', '#display');

View File

@ -20,10 +20,11 @@ ADD https://api.github.com/repos/dotnet/aspnetcore/git/ref/heads/${gitBranch} /a
RUN git init \
&& git fetch https://github.com/aspnet/aspnetcore ${gitBranch} \
&& git reset --hard FETCH_HEAD \
&& git submodule update --init
&& git submodule update --init \
&& git remote add origin https://github.com/aspnet/aspnetcore
RUN ./restore.sh
RUN .dotnet/dotnet publish -c Release -r linux-x64 -o /app ./src/Components/benchmarkapps/Wasm.Performance/Driver/Wasm.Performance.Driver.csproj
RUN .dotnet/dotnet publish -c Release --no-restore -o /app ./src/Components/benchmarkapps/Wasm.Performance/Driver/Wasm.Performance.Driver.csproj
RUN chmod +x /app/Wasm.Performance.Driver
WORKDIR /app

View File

@ -3,7 +3,7 @@ FROM selenium/standalone-chrome:3.141.59-mercury as final
ENV StressRunDuration=0
WORKDIR /app
COPY ./Driver/bin/Release/netcoreapp3.1/linux-x64/publish ./
COPY ./Driver/bin/Release/net5.0/linux-x64/publish ./
COPY ./exec.sh ./
ENTRYPOINT [ "bash", "./exec.sh" ]

View File

@ -6,6 +6,7 @@ using BasicTestApp;
using BasicTestApp.HttpClientTest;
using Microsoft.AspNetCore.Components.E2ETest.Infrastructure.ServerFixtures;
using Microsoft.AspNetCore.E2ETesting;
using Microsoft.AspNetCore.Testing;
using OpenQA.Selenium;
using OpenQA.Selenium.Support.UI;
using TestServer;
@ -44,6 +45,7 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Tests
}
[Fact]
[QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/23366")]
public void CanSendAndReceiveBytes()
{
IssueRequest("/subdir/api/data");

View File

@ -7,6 +7,7 @@ using BasicTestApp;
using Microsoft.AspNetCore.Components.E2ETest.Infrastructure;
using Microsoft.AspNetCore.Components.E2ETest.Infrastructure.ServerFixtures;
using Microsoft.AspNetCore.E2ETesting;
using Microsoft.AspNetCore.Testing;
using Moq;
using OpenQA.Selenium;
using OpenQA.Selenium.Support.UI;
@ -506,6 +507,7 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Tests
}
[Fact]
[QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/23596")]
public void CanBindTextboxNullableDouble()
{
var target = Browser.FindElement(By.Id("textbox-nullable-double"));

View File

@ -42,7 +42,7 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Tests
}
[Fact]
[QuarantinedTest]
[QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/23366")]
public void CanRenderTextOnlyComponent()
{
var appElement = Browser.MountTestComponent<TextOnlyComponent>();
@ -400,6 +400,26 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Tests
Browser.Equal("Clicks: 2", () => inputElement.GetAttribute("value"));
}
[Fact]
public void CanUseFocusExtensionToFocusElement()
{
var appElement = Browser.MountTestComponent<ElementFocusComponent>();
var buttonElement = appElement.FindElement(By.Id("focus-button"));
// Make sure the input element isn't focused when the test begins; we don't want
// the test to pass just because the input started as the focused element
Browser.NotEqual("focus-input", getFocusedElementId);
// Click the button whose callback focuses the input element
buttonElement.Click();
// Verify that the input element is focused
Browser.Equal("focus-input", getFocusedElementId);
// A local helper that gets the ID of the focused element.
string getFocusedElementId() => Browser.SwitchTo().ActiveElement().GetAttribute("id");
}
[Fact]
public void CanCaptureReferencesToDynamicallyAddedElements()
{
@ -464,6 +484,7 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Tests
}
[Fact]
[QuarantinedTest]
public void CanRenderMarkupBlocks()
{
var appElement = Browser.MountTestComponent<MarkupBlockComponent>();

View File

@ -6,6 +6,7 @@ using BasicTestApp;
using Microsoft.AspNetCore.Components.E2ETest.Infrastructure;
using Microsoft.AspNetCore.Components.E2ETest.Infrastructure.ServerFixtures;
using Microsoft.AspNetCore.E2ETesting;
using Microsoft.AspNetCore.Testing;
using OpenQA.Selenium;
using Xunit;
using Xunit.Abstractions;
@ -50,6 +51,7 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Tests
}
[Fact]
[QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/23596")]
public void ShowsErrorNotification_OnError_Reload()
{
var causeErrorButton = Browser.Exists(By.Id("throw-simple-exception"));

Some files were not shown because too many files have changed in this diff Show More