Merge branch 'master' into merge/release/5.0-preview8-to-master
This commit is contained in:
commit
84b30133a7
|
|
@ -4,6 +4,11 @@
|
|||
# Daily Tests for ASP.NET Core SignalR
|
||||
# These use Sauce Labs resources, hence they run daily rather than per-commit.
|
||||
|
||||
variables:
|
||||
- ${{ if ne(variables['System.TeamProject'], 'public') }}:
|
||||
- group: DotNet-MSRC-Storage
|
||||
- group: AzureDevOps-Artifact-Feeds-Pats
|
||||
|
||||
# The only Daily Tests we have run in Sauce Labs and only need to run on one machine (because they just trigger SauceLabs)
|
||||
# Hence we use the 'default-build.yml' template because it represents a single phase
|
||||
jobs:
|
||||
|
|
|
|||
|
|
@ -0,0 +1,66 @@
|
|||
---
|
||||
name: 🐞 Razor Tooling Bug report
|
||||
about: Report an issue about something that is not working in the new Razor tooling
|
||||
labels: area-razor.tooling, feature-razor.vs
|
||||
---
|
||||
|
||||
<!--
|
||||
|
||||
More information on our issue management policies can be found here: https://aka.ms/aspnet/issue-policies
|
||||
|
||||
Please keep in mind that the GitHub issue tracker is not intended as a general support forum, but for reporting **non-security** bugs and feature requests.
|
||||
|
||||
If you believe you have an issue that affects the SECURITY of the platform, please do NOT create an issue and instead email your issue details to secure@microsoft.com. Your report may be eligible for our [bug bounty](https://www.microsoft.com/en-us/msrc/bounty-dot-net-core) but ONLY if it is reported through email.
|
||||
For other types of questions, consider using [StackOverflow](https://stackoverflow.com).
|
||||
|
||||
-->
|
||||
|
||||
<!-- NOTE: This issue template is meant specifically to be used for issues with the new experimental Razor tooling experience provided in Visual Studio's Preview Feature pane -->
|
||||
|
||||
### Describe the bug
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
### To Reproduce
|
||||
<!--
|
||||
We ❤ code! Point us to a minimalistic repro project hosted in a GitHub repo.
|
||||
For a repro project, create a new ASP.NET Core project using the template of your your choice, apply the minimum required code to result in the issue you're observing.
|
||||
|
||||
We will close this issue if:
|
||||
- the repro project you share with us is complex. We can't investigate custom projects, so don't point us to such, please.
|
||||
- if we will not be able to repro the behavior you're reporting
|
||||
-->
|
||||
|
||||
### Logs & Exceptions
|
||||
|
||||
Please collect the data below before reporting your issue to aid us in diagnosing the root cause.
|
||||
|
||||
#### Activity log
|
||||
[Here](https://docs.microsoft.com/en-us/visualstudio/extensibility/how-to-use-the-activity-log?view=vs-2019#to-examine-the-activity-log) are the instructions on how to generate/acquire one.
|
||||
|
||||
#### Razor Language Server Client log
|
||||
<!-- In Visual Studio's `Output` window, the drop-down contains a `Razor Language Server Client` item. Include that below. -->
|
||||
<details>
|
||||
<summary>Razor Language Server Client Log Output</summary>
|
||||
|
||||
Paste log output here
|
||||
|
||||
</details>
|
||||
|
||||
#### HTML Language Server Client log
|
||||
<!-- In Visual Studio's `Output` window, the drop-down contains a `HtmlyLanguageClient` item. Include that below. -->
|
||||
<details>
|
||||
<summary>HTML Language Server Client Log Output</summary>
|
||||
|
||||
Paste log output here
|
||||
|
||||
</details>
|
||||
|
||||
### Further technical details
|
||||
- VS version (Help => About Microsoft Visual Studio, i.e. 16.8.0 Preview 1 30313.27...). If in Codespaces there will be two versions (server and client), please provide both.
|
||||
- Scenario (Local, LiveShare, Codespaces)
|
||||
|
||||
### Pre-requisite checklist
|
||||
- [ ] Steps to reproduce the issue
|
||||
- [ ] Visual Studio Activity Log attached.
|
||||
- [ ] Razor Language Server client logs included.
|
||||
- [ ] HTML Language Server client logs included
|
||||
930
AspNetCore.sln
930
AspNetCore.sln
File diff suppressed because it is too large
Load Diff
|
|
@ -151,9 +151,7 @@
|
|||
Include="$(RepoRoot)src\Analyzers\Internal.AspNetCore.Analyzers\src\Internal.AspNetCore.Analyzers.csproj"
|
||||
ReferenceOutputAssembly="false"
|
||||
OutputItemType="Analyzer"
|
||||
PrivateAssets="All"
|
||||
Version="$(InternalAspNetCoreAnalyzersPackageVersion)"
|
||||
IsImplicitlyDefined="true" />
|
||||
PrivateAssets="All" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Compilation options which apply to all languages. Language-specific options should be set in eng/targets/$(lang).Common.props -->
|
||||
|
|
|
|||
|
|
@ -2,9 +2,6 @@
|
|||
<configuration>
|
||||
<packageSources>
|
||||
<clear />
|
||||
<!--Begin: Package sources managed by Dependency Flow automation. Do not edit the sources below.-->
|
||||
<add key="darc-pub-dotnet-blazor-cc44960" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/darc-pub-dotnet-blazor-cc449601/nuget/v3/index.json" />
|
||||
<!--End: Package sources managed by Dependency Flow automation. Do not edit the sources above.-->
|
||||
<add key="dotnet-eng" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json" />
|
||||
<add key="dotnet-tools" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json" />
|
||||
<add key="dotnet5" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet5/nuget/v3/index.json" />
|
||||
|
|
|
|||
|
|
@ -4,6 +4,22 @@ Building ASP.NET Core from source allows you to tweak and customize ASP.NET Core
|
|||
|
||||
See <https://github.com/dotnet/aspnetcore/labels/area-infrastructure> for known issues and to track ongoing work.
|
||||
|
||||
## Clone the source code
|
||||
|
||||
ASP.NET Core uses git submodules to include the source from a few other projects.
|
||||
|
||||
For a new copy of the project, run:
|
||||
|
||||
```ps1
|
||||
git clone --recursive https://github.com/dotnet/aspnetcore
|
||||
```
|
||||
|
||||
To update an existing copy, run:
|
||||
|
||||
```ps1
|
||||
git submodule update --init --recursive
|
||||
```
|
||||
|
||||
## Install pre-requisites
|
||||
|
||||
### Windows
|
||||
|
|
@ -22,7 +38,8 @@ Building ASP.NET Core on Windows requires:
|
|||
However, any Visual Studio 2019 instance that meets the requirements should be fine. See [global.json](/global.json)
|
||||
and [eng/scripts/vs.json](/eng/scripts/vs.json) for those requirements. By default, the script will install Visual Studio Enterprise Edition, however you can use a different edition by passing the `-Edition` flag.
|
||||
* Git. <https://git-scm.org>
|
||||
* NodeJS. LTS version of 10.14.2 or newer <https://nodejs.org>
|
||||
* NodeJS. LTS version of 10.14.2 or newer <https://nodejs.org>.
|
||||
* Install yarn globally (`npm install -g yarn`)
|
||||
* Java Development Kit 11 or newer. Either:
|
||||
* OpenJDK <https://jdk.java.net/>
|
||||
* Oracle's JDK <https://www.oracle.com/technetwork/java/javase/downloads/index.html>
|
||||
|
|
@ -52,22 +69,6 @@ Building ASP.NET Core on macOS or Linux requires:
|
|||
* OpenJDK <https://jdk.java.net/>
|
||||
* Oracle's JDK <https://www.oracle.com/technetwork/java/javase/downloads/index.html>
|
||||
|
||||
## Clone the source code
|
||||
|
||||
ASP.NET Core uses git submodules to include the source from a few other projects.
|
||||
|
||||
For a new copy of the project, run:
|
||||
|
||||
```ps1
|
||||
git clone --recursive https://github.com/dotnet/aspnetcore
|
||||
```
|
||||
|
||||
To update an existing copy, run:
|
||||
|
||||
```ps1
|
||||
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
|
||||
|
|
@ -86,6 +87,9 @@ Before opening our .sln/.slnf files in Visual Studio or VS Code, you need to per
|
|||
> :bulb: Pro tip: you will also want to run this command after pulling large sets of changes. On the master
|
||||
> branch, we regularly update the versions of .NET Core SDK required to build the repo.
|
||||
> You will need to restart Visual Studio every time we update the .NET Core SDK.
|
||||
> To allow executing the setup script, you may need to update the execution policy on your machine.
|
||||
You can do so by running the `Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser` command
|
||||
in PowerShell. For more information on execution policies, you can read the [execution policy docs](https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.security/set-executionpolicy).
|
||||
|
||||
2. Use the `startvs.cmd` script to open Visual Studio .sln/.slnf files. This script first sets the required
|
||||
environment variables.
|
||||
|
|
@ -128,6 +132,18 @@ Executing `.\restore.cmd` or `.\build.cmd` may produce these errors:
|
|||
|
||||
In most cases, this is because the option _Use previews of the .NET Core SDK_ in VS2019 is not checked. Start Visual Studio, go to _Tools > Options_ and check _Use previews of the .NET Core SDK_ under _Environment > Preview Features_.
|
||||
|
||||
### Common error: HTTP Error 500.33 - ANCM Request Handler Load Failure
|
||||
|
||||
The [ASP.NET Core Module](https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/aspnet-core-module) (ANCM) for IIS is not supported when running projects in this repository.
|
||||
|
||||
After using `startvs.cmd` to open a solution in Visual Studio, the Kestrel web host option must be used (name of the project) and not IIS Express.
|
||||
|
||||
Example of running the `MvcSandbox` project:
|
||||
|
||||
`.\startvs.cmd .\src\Mvc\Mvc.sln`
|
||||
|
||||

|
||||
|
||||
## Building with Visual Studio Code
|
||||
|
||||
Using Visual Studio Code with this repo requires setting environment variables on command line first.
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ This will restore, and then publish all the test project including some bootstra
|
|||
## Overview of the helix usage in our pipelines
|
||||
|
||||
- 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)
|
||||
- Full queue matrix: Windows[7, 81, 10], Ubuntu[1604, 1804, 2004], Centos7, Debian9, 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](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.
|
||||
|
|
|
|||
|
|
@ -100,16 +100,64 @@ is changing to `Microsoft.AspNetCore.BetterThanOrange`, you would need to make t
|
|||
</ItemGroup>
|
||||
```
|
||||
|
||||
## Updating dependencies manually
|
||||
## A darc cheatsheet
|
||||
|
||||
If the `dotnet-maestro` bot has not correctly updated the dependencies, it may be worthwhile running `darc` manually:
|
||||
`darc` is a command-line tool that is used for dependency management in the dotnet ecosystem of repos. `darc` can be installed using the `darc-init` scripts located inside the `eng/common` directory. Once `darc` is installed, you'll need to set up the appropriate access tokens as outlined [in the official Darc docs](https://github.com/dotnet/arcade/blob/master/Documentation/Darc.md#setting-up-your-darc-client).
|
||||
|
||||
Once `darc` is installed and set-up, it can be used to modify the subscriptions and dependencies in a project.
|
||||
|
||||
**Getting the list of subscriptions in a repo**
|
||||
|
||||
Subscriptions are objects that define the ecosystem repos we are listening for updates to, the frequency we are looking for updates, and more.
|
||||
|
||||
```bash
|
||||
darc get-subscriptions --target-branch master --target-repo aspnetcore$ --regex
|
||||
```
|
||||
|
||||
**Disable/enable a subscription**
|
||||
|
||||
```bash
|
||||
darc subscription-status --id {subscriptionIdHere} --enable
|
||||
darc subscription-status --id {subscriptionIdHere} --disable
|
||||
```
|
||||
|
||||
**Trigger a subscription**
|
||||
|
||||
Triggering a subscription will search for updates in its dependencies and open a PR in the target repo via the dotnet-maestro bot with these changes.
|
||||
|
||||
```bash
|
||||
darc trigger-subscriptions --id {subscriptionIdHere}
|
||||
```
|
||||
|
||||
**Manually update dependencies**
|
||||
|
||||
If the `dotnet-maestro` bot has not correctly updated the dependencies, `darc update-dependencies` may be used to update the dependencies manually. Note, you'll need to run the commands below in a separate branch and submit a PR with the changes. These are the things that the bot should do for you if you use `trigger-subscriptions` or automatically (when the subscription fires e.g. about 15 minutes after a dependency's build completes if `Update Frequency: EveryBuild`).
|
||||
|
||||
```bash
|
||||
darc update-dependencies --channel '.NET Core 3.1 Release'
|
||||
darc update-dependencies --channel '.NET 5 Dev' --source-repo efcore
|
||||
```
|
||||
|
||||
Generally, using `trigger-subscriptions` is preferred for creating dependency updates instead of manually updating dependencies in your own PR.
|
||||
|
||||
**Toggling batchability of subscription**
|
||||
|
||||
Subscriptions can be batched. When a dependency update is detected, `darc` will bundle the commits for that update with existing dependency PRs. To toggle whether a subscription is batched or not, you will need to use the `update-subscription` command.
|
||||
|
||||
```bash
|
||||
darc update-subscription --id {subscriptionIdHere}
|
||||
```
|
||||
|
||||
Your shell's default editor will open and allow you to edit the metadata of the subscription.
|
||||
|
||||
To disable batching, set `Batchable` to `False` and update the `Merge Policies` section with the following YAML.
|
||||
|
||||
```
|
||||
- Name: Standard
|
||||
Properties: {}
|
||||
```
|
||||
|
||||
To enable batching, set `Batchable` to `True` and remove any `Merge Policies` set on the subscription.
|
||||
|
||||
Note: Merge policies can only be set on unbatched subscriptions. Be sure to set/unset the `Merge Policies` field properly as you toggle batchability.
|
||||
|
||||
1. Install `darc` as described in <https://github.com/dotnet/arcade/blob/master/Documentation/Darc.md#setting-up-your-darc-client>
|
||||
2. Run `darc update-dependencies --channel '.NET Core 3.1 Release'`
|
||||
* Use `'trigger-subscriptions'` to prod the bot to create a PR if you do not want to make local changes
|
||||
* Use `'.NET 3 Eng''` to update dependencies from dotnet/arcade
|
||||
* Use `'.NET Eng - Latest'` to update dependencies from dotnet/arcade in the `master` branch
|
||||
* Use `'VS Master'` to update dependencies from dotnet/roslyn in the `master` branch
|
||||
* Use `'.NET 5 Dev'` to update dependencies from dotnet/efcore or dotnet/runtime in the `master` branch
|
||||
3. `git diff` to confirm the tool's changes
|
||||
4. Proceed with usual commit and PR
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 31 KiB |
|
|
@ -44,10 +44,6 @@
|
|||
<!-- Project selection can be overridden on the command line by passing in -projects. -->
|
||||
<When Condition="'$(ProjectToBuild)' != ''">
|
||||
<ItemGroup>
|
||||
<!-- Include RTMVersions.csproj unless this invocation is building RepoTasks.csproj or won't compile C#. -->
|
||||
<ProjectToBuild Include="$(RepoRoot)eng\RTMVersions\RTMVersions.csproj"
|
||||
Exclude="@(ProjectToExclude)"
|
||||
Condition=" $(ProjectToBuild.EndsWith('.csproj')) AND !$(ProjectToBuild.EndsWith('RepoTasks.csproj')) " />
|
||||
<ProjectToBuild Include="$(ProjectToBuild)" Exclude="@(ProjectToExclude);$(RepoRoot)**\bin\**\*;$(RepoRoot)**\obj\**\*">
|
||||
<RestoreInParallel Condition="'%(Extension)' == '.npmproj'">false</RestoreInParallel>
|
||||
</ProjectToBuild>
|
||||
|
|
@ -125,11 +121,8 @@
|
|||
<!--
|
||||
Use caution to avoid deep recursion. If the globbing pattern picks up something which exceeds MAX_PATH,
|
||||
the entire pattern will silently fail to evaluate correctly.
|
||||
|
||||
Include RTMVersions.csproj when building any managed projects.
|
||||
-->
|
||||
<DotNetProjects Include="
|
||||
$(RepoRoot)eng\RTMVersions\RTMVersions.csproj;
|
||||
$(RepoRoot)src\Framework\App.Ref\src\Microsoft.AspNetCore.App.Ref.csproj;
|
||||
$(RepoRoot)src\Framework\App.Runtime\src\Microsoft.AspNetCore.App.Runtime.csproj;
|
||||
$(RepoRoot)src\Framework\App.Ref.Internal\src\Microsoft.AspNetCore.App.Ref.Internal.csproj;
|
||||
|
|
@ -178,7 +171,6 @@
|
|||
$(RepoRoot)**\obj\**\*;"
|
||||
Condition=" '$(BuildMainlyReferenceProviders)' != 'true' " />
|
||||
<DotNetProjects Include="
|
||||
$(RepoRoot)eng\RTMVersions\RTMVersions.csproj;
|
||||
$(RepoRoot)src\DefaultBuilder\**\src\*.csproj;
|
||||
$(RepoRoot)src\Features\JsonPatch\**\src\*.csproj;
|
||||
$(RepoRoot)src\DataProtection\**\src\*.csproj;
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@
|
|||
-->
|
||||
<Project>
|
||||
<ItemGroup>
|
||||
@(_ProjectReferenceProvider->'<ProjectReferenceProvider Include="%(Identity)" ProjectPath="%24(RepoRoot)%(ProjectFileRelativePath)" />', '%0A ')
|
||||
@(_ProjectReferenceProvider->'<ProjectReferenceProvider Include="%(Identity)" ProjectPath="%24(RepoRoot)%(ProjectFileRelativePath)" />', '%0A ')
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
]]></ProjectListContent>
|
||||
|
|
|
|||
|
|
@ -71,6 +71,8 @@ and are generated based on the last package release.
|
|||
<LatestPackageReference Include="System.Reflection.Metadata" />
|
||||
<LatestPackageReference Include="System.Runtime.CompilerServices.Unsafe" />
|
||||
<LatestPackageReference Include="System.Runtime.InteropServices.RuntimeInformation" />
|
||||
<!-- System.Security.AccessControl should only be referenced in Dependencies.props and RTMVersions.csproj. -->
|
||||
<LatestPackageReference Include="System.Security.AccessControl" />
|
||||
<LatestPackageReference Include="System.Security.Cryptography.Cng" />
|
||||
<LatestPackageReference Include="System.Security.Cryptography.Pkcs" />
|
||||
<LatestPackageReference Include="System.Security.Cryptography.Xml" />
|
||||
|
|
@ -104,6 +106,7 @@ and are generated based on the last package release.
|
|||
<LatestPackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Runtime" />
|
||||
<LatestPackageReference Include="Microsoft.Bcl.AsyncInterfaces" />
|
||||
<LatestPackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" />
|
||||
<LatestPackageReference Include="Microsoft.CodeAnalysis.PublicApiAnalyzers" />
|
||||
<LatestPackageReference Include="Microsoft.EntityFrameworkCore.InMemory" />
|
||||
<LatestPackageReference Include="Microsoft.EntityFrameworkCore.Relational" />
|
||||
<LatestPackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" />
|
||||
|
|
@ -159,6 +162,7 @@ and are generated based on the last package release.
|
|||
<LatestPackageReference Include="Libuv" />
|
||||
<LatestPackageReference Include="MessagePack" />
|
||||
<LatestPackageReference Include="MessagePackAnalyzer" />
|
||||
<LatestPackageReference Include="Microsoft.Data.SqlClient" />
|
||||
<LatestPackageReference Include="Microsoft.Identity.Web.UI" />
|
||||
<LatestPackageReference Include="Microsoft.Graph" />
|
||||
<LatestPackageReference Include="Mono.Cecil" />
|
||||
|
|
@ -178,7 +182,6 @@ and are generated based on the last package release.
|
|||
<LatestPackageReference Include="xunit.assert" />
|
||||
<LatestPackageReference Include="xunit.extensibility.core" />
|
||||
<LatestPackageReference Include="xunit.extensibility.execution" />
|
||||
<LatestPackageReference Include="Microsoft.Data.SqlClient" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Label="Dependencies with versions.">
|
||||
|
|
|
|||
|
|
@ -5,160 +5,160 @@
|
|||
-->
|
||||
<Project>
|
||||
<ItemGroup>
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore" ProjectPath="$(RepoRoot)src\DefaultBuilder\src\Microsoft.AspNetCore.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.JsonPatch" ProjectPath="$(RepoRoot)src\Features\JsonPatch\src\Microsoft.AspNetCore.JsonPatch.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.DataProtection.Abstractions" ProjectPath="$(RepoRoot)src\DataProtection\Abstractions\src\Microsoft.AspNetCore.DataProtection.Abstractions.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Cryptography.Internal" ProjectPath="$(RepoRoot)src\DataProtection\Cryptography.Internal\src\Microsoft.AspNetCore.Cryptography.Internal.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" ProjectPath="$(RepoRoot)src\DataProtection\Cryptography.KeyDerivation\src\Microsoft.AspNetCore.Cryptography.KeyDerivation.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.DataProtection" ProjectPath="$(RepoRoot)src\DataProtection\DataProtection\src\Microsoft.AspNetCore.DataProtection.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.DataProtection.EntityFrameworkCore" ProjectPath="$(RepoRoot)src\DataProtection\EntityFrameworkCore\src\Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.DataProtection.Extensions" ProjectPath="$(RepoRoot)src\DataProtection\Extensions\src\Microsoft.AspNetCore.DataProtection.Extensions.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" ProjectPath="$(RepoRoot)src\DataProtection\StackExchangeRedis\src\Microsoft.AspNetCore.DataProtection.StackExchangeRedis.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Antiforgery" ProjectPath="$(RepoRoot)src\Antiforgery\src\Microsoft.AspNetCore.Antiforgery.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Hosting.Abstractions" ProjectPath="$(RepoRoot)src\Hosting\Abstractions\src\Microsoft.AspNetCore.Hosting.Abstractions.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Hosting" ProjectPath="$(RepoRoot)src\Hosting\Hosting\src\Microsoft.AspNetCore.Hosting.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Hosting.Server.Abstractions" ProjectPath="$(RepoRoot)src\Hosting\Server.Abstractions\src\Microsoft.AspNetCore.Hosting.Server.Abstractions.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.TestHost" ProjectPath="$(RepoRoot)src\Hosting\TestHost\src\Microsoft.AspNetCore.TestHost.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Hosting.WindowsServices" ProjectPath="$(RepoRoot)src\Hosting\WindowsServices\src\Microsoft.AspNetCore.Hosting.WindowsServices.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Authentication.Abstractions" ProjectPath="$(RepoRoot)src\Http\Authentication.Abstractions\src\Microsoft.AspNetCore.Authentication.Abstractions.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Authentication.Core" ProjectPath="$(RepoRoot)src\Http\Authentication.Core\src\Microsoft.AspNetCore.Authentication.Core.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.Net.Http.Headers" ProjectPath="$(RepoRoot)src\Http\Headers\src\Microsoft.Net.Http.Headers.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Http.Abstractions" ProjectPath="$(RepoRoot)src\Http\Http.Abstractions\src\Microsoft.AspNetCore.Http.Abstractions.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Http.Extensions" ProjectPath="$(RepoRoot)src\Http\Http.Extensions\src\Microsoft.AspNetCore.Http.Extensions.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Http.Features" ProjectPath="$(RepoRoot)src\Http\Http.Features\src\Microsoft.AspNetCore.Http.Features.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Http" ProjectPath="$(RepoRoot)src\Http\Http\src\Microsoft.AspNetCore.Http.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Metadata" ProjectPath="$(RepoRoot)src\Http\Metadata\src\Microsoft.AspNetCore.Metadata.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Owin" ProjectPath="$(RepoRoot)src\Http\Owin\src\Microsoft.AspNetCore.Owin.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Routing.Abstractions" ProjectPath="$(RepoRoot)src\Http\Routing.Abstractions\src\Microsoft.AspNetCore.Routing.Abstractions.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Routing" ProjectPath="$(RepoRoot)src\Http\Routing\src\Microsoft.AspNetCore.Routing.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.WebUtilities" ProjectPath="$(RepoRoot)src\Http\WebUtilities\src\Microsoft.AspNetCore.WebUtilities.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Html.Abstractions" ProjectPath="$(RepoRoot)src\Html\Abstractions\src\Microsoft.AspNetCore.Html.Abstractions.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.ApiAuthorization.IdentityServer" ProjectPath="$(RepoRoot)src\Identity\ApiAuthorization.IdentityServer\src\Microsoft.AspNetCore.ApiAuthorization.IdentityServer.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Identity" ProjectPath="$(RepoRoot)src\Identity\Core\src\Microsoft.AspNetCore.Identity.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" ProjectPath="$(RepoRoot)src\Identity\EntityFrameworkCore\src\Microsoft.AspNetCore.Identity.EntityFrameworkCore.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.Extensions.Identity.Core" ProjectPath="$(RepoRoot)src\Identity\Extensions.Core\src\Microsoft.Extensions.Identity.Core.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.Extensions.Identity.Stores" ProjectPath="$(RepoRoot)src\Identity\Extensions.Stores\src\Microsoft.Extensions.Identity.Stores.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Identity.Specification.Tests" ProjectPath="$(RepoRoot)src\Identity\Specification.Tests\src\Microsoft.AspNetCore.Identity.Specification.Tests.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Identity.UI" ProjectPath="$(RepoRoot)src\Identity\UI\src\Microsoft.AspNetCore.Identity.UI.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Connections.Abstractions" ProjectPath="$(RepoRoot)src\Servers\Connections.Abstractions\src\Microsoft.AspNetCore.Connections.Abstractions.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Server.HttpSys" ProjectPath="$(RepoRoot)src\Servers\HttpSys\src\Microsoft.AspNetCore.Server.HttpSys.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Server.IISIntegration" ProjectPath="$(RepoRoot)src\Servers\IIS\IISIntegration\src\Microsoft.AspNetCore.Server.IISIntegration.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Server.IIS" ProjectPath="$(RepoRoot)src\Servers\IIS\IIS\src\Microsoft.AspNetCore.Server.IIS.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Server.Kestrel.Core" ProjectPath="$(RepoRoot)src\Servers\Kestrel\Core\src\Microsoft.AspNetCore.Server.Kestrel.Core.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Server.Kestrel" ProjectPath="$(RepoRoot)src\Servers\Kestrel\Kestrel\src\Microsoft.AspNetCore.Server.Kestrel.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv" ProjectPath="$(RepoRoot)src\Servers\Kestrel\Transport.Libuv\src\Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Server.Kestrel.Transport.Experimental.Quic" ProjectPath="$(RepoRoot)src\Servers\Kestrel\Transport.Quic\src\Microsoft.AspNetCore.Server.Kestrel.Transport.Experimental.Quic.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets" ProjectPath="$(RepoRoot)src\Servers\Kestrel\Transport.Sockets\src\Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Authentication.Certificate" ProjectPath="$(RepoRoot)src\Security\Authentication\Certificate\src\Microsoft.AspNetCore.Authentication.Certificate.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Authentication.Cookies" ProjectPath="$(RepoRoot)src\Security\Authentication\Cookies\src\Microsoft.AspNetCore.Authentication.Cookies.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Authentication" ProjectPath="$(RepoRoot)src\Security\Authentication\Core\src\Microsoft.AspNetCore.Authentication.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Authentication.Facebook" ProjectPath="$(RepoRoot)src\Security\Authentication\Facebook\src\Microsoft.AspNetCore.Authentication.Facebook.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Authentication.Google" ProjectPath="$(RepoRoot)src\Security\Authentication\Google\src\Microsoft.AspNetCore.Authentication.Google.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Authentication.JwtBearer" ProjectPath="$(RepoRoot)src\Security\Authentication\JwtBearer\src\Microsoft.AspNetCore.Authentication.JwtBearer.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Authentication.MicrosoftAccount" ProjectPath="$(RepoRoot)src\Security\Authentication\MicrosoftAccount\src\Microsoft.AspNetCore.Authentication.MicrosoftAccount.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Authentication.Negotiate" ProjectPath="$(RepoRoot)src\Security\Authentication\Negotiate\src\Microsoft.AspNetCore.Authentication.Negotiate.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Authentication.OAuth" ProjectPath="$(RepoRoot)src\Security\Authentication\OAuth\src\Microsoft.AspNetCore.Authentication.OAuth.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" ProjectPath="$(RepoRoot)src\Security\Authentication\OpenIdConnect\src\Microsoft.AspNetCore.Authentication.OpenIdConnect.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Authentication.Twitter" ProjectPath="$(RepoRoot)src\Security\Authentication\Twitter\src\Microsoft.AspNetCore.Authentication.Twitter.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Authentication.WsFederation" ProjectPath="$(RepoRoot)src\Security\Authentication\WsFederation\src\Microsoft.AspNetCore.Authentication.WsFederation.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Authorization" ProjectPath="$(RepoRoot)src\Security\Authorization\Core\src\Microsoft.AspNetCore.Authorization.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Authorization.Policy" ProjectPath="$(RepoRoot)src\Security\Authorization\Policy\src\Microsoft.AspNetCore.Authorization.Policy.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.CookiePolicy" ProjectPath="$(RepoRoot)src\Security\CookiePolicy\src\Microsoft.AspNetCore.CookiePolicy.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.Web.Xdt.Extensions" ProjectPath="$(RepoRoot)src\SiteExtensions\Microsoft.Web.Xdt.Extensions\src\Microsoft.Web.Xdt.Extensions.csproj" />
|
||||
<ProjectReferenceProvider Include="dotnet-getdocument" ProjectPath="$(RepoRoot)src\Tools\dotnet-getdocument\src\dotnet-getdocument.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.Extensions.ApiDescription.Client" ProjectPath="$(RepoRoot)src\Tools\Extensions.ApiDescription.Client\src\Microsoft.Extensions.ApiDescription.Client.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.Extensions.ApiDescription.Server" ProjectPath="$(RepoRoot)src\Tools\Extensions.ApiDescription.Server\src\Microsoft.Extensions.ApiDescription.Server.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.DeveloperCertificates.XPlat" ProjectPath="$(RepoRoot)src\Tools\FirstRunCertGenerator\src\Microsoft.AspNetCore.DeveloperCertificates.XPlat.csproj" />
|
||||
<ProjectReferenceProvider Include="GetDocument.Insider" ProjectPath="$(RepoRoot)src\Tools\GetDocumentInsider\src\GetDocumentInsider.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.Extensions.Logging.AzureAppServices" ProjectPath="$(RepoRoot)src\Logging.AzureAppServices\src\Microsoft.Extensions.Logging.AzureAppServices.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.ConcurrencyLimiter" ProjectPath="$(RepoRoot)src\Middleware\ConcurrencyLimiter\src\Microsoft.AspNetCore.ConcurrencyLimiter.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Cors" ProjectPath="$(RepoRoot)src\Middleware\CORS\src\Microsoft.AspNetCore.Cors.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Diagnostics.Abstractions" ProjectPath="$(RepoRoot)src\Middleware\Diagnostics.Abstractions\src\Microsoft.AspNetCore.Diagnostics.Abstractions.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" ProjectPath="$(RepoRoot)src\Middleware\Diagnostics.EntityFrameworkCore\src\Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Diagnostics" ProjectPath="$(RepoRoot)src\Middleware\Diagnostics\src\Microsoft.AspNetCore.Diagnostics.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.HeaderPropagation" ProjectPath="$(RepoRoot)src\Middleware\HeaderPropagation\src\Microsoft.AspNetCore.HeaderPropagation.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore" ProjectPath="$(RepoRoot)src\Middleware\HealthChecks.EntityFrameworkCore\src\Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Diagnostics.HealthChecks" ProjectPath="$(RepoRoot)src\Middleware\HealthChecks\src\Microsoft.AspNetCore.Diagnostics.HealthChecks.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.HostFiltering" ProjectPath="$(RepoRoot)src\Middleware\HostFiltering\src\Microsoft.AspNetCore.HostFiltering.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.HttpOverrides" ProjectPath="$(RepoRoot)src\Middleware\HttpOverrides\src\Microsoft.AspNetCore.HttpOverrides.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.HttpsPolicy" ProjectPath="$(RepoRoot)src\Middleware\HttpsPolicy\src\Microsoft.AspNetCore.HttpsPolicy.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Localization.Routing" ProjectPath="$(RepoRoot)src\Middleware\Localization.Routing\src\Microsoft.AspNetCore.Localization.Routing.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Localization" ProjectPath="$(RepoRoot)src\Middleware\Localization\src\Microsoft.AspNetCore.Localization.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.MiddlewareAnalysis" ProjectPath="$(RepoRoot)src\Middleware\MiddlewareAnalysis\src\Microsoft.AspNetCore.MiddlewareAnalysis.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.NodeServices" ProjectPath="$(RepoRoot)src\Middleware\NodeServices\src\Microsoft.AspNetCore.NodeServices.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.ResponseCaching.Abstractions" ProjectPath="$(RepoRoot)src\Middleware\ResponseCaching.Abstractions\src\Microsoft.AspNetCore.ResponseCaching.Abstractions.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.ResponseCaching" ProjectPath="$(RepoRoot)src\Middleware\ResponseCaching\src\Microsoft.AspNetCore.ResponseCaching.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.ResponseCompression" ProjectPath="$(RepoRoot)src\Middleware\ResponseCompression\src\Microsoft.AspNetCore.ResponseCompression.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Rewrite" ProjectPath="$(RepoRoot)src\Middleware\Rewrite\src\Microsoft.AspNetCore.Rewrite.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Session" ProjectPath="$(RepoRoot)src\Middleware\Session\src\Microsoft.AspNetCore.Session.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.SpaServices.Extensions" ProjectPath="$(RepoRoot)src\Middleware\SpaServices.Extensions\src\Microsoft.AspNetCore.SpaServices.Extensions.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.SpaServices" ProjectPath="$(RepoRoot)src\Middleware\SpaServices\src\Microsoft.AspNetCore.SpaServices.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.StaticFiles" ProjectPath="$(RepoRoot)src\Middleware\StaticFiles\src\Microsoft.AspNetCore.StaticFiles.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.WebSockets" ProjectPath="$(RepoRoot)src\Middleware\WebSockets\src\Microsoft.AspNetCore.WebSockets.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X" ProjectPath="$(RepoRoot)src\Razor\Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X\src\Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Mvc.Razor.Extensions.Version2_X" ProjectPath="$(RepoRoot)src\Razor\Microsoft.AspNetCore.Mvc.Razor.Extensions.Version2_X\src\Microsoft.AspNetCore.Mvc.Razor.Extensions.Version2_X.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Mvc.Razor.Extensions" ProjectPath="$(RepoRoot)src\Razor\Microsoft.AspNetCore.Mvc.Razor.Extensions\src\Microsoft.AspNetCore.Mvc.Razor.Extensions.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Razor.Language" ProjectPath="$(RepoRoot)src\Razor\Microsoft.AspNetCore.Razor.Language\src\Microsoft.AspNetCore.Razor.Language.csproj" />
|
||||
<ProjectReferenceProvider Include="rzc" ProjectPath="$(RepoRoot)src\Razor\Microsoft.AspNetCore.Razor.Tools\src\Microsoft.AspNetCore.Razor.Tools.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.CodeAnalysis.Razor" ProjectPath="$(RepoRoot)src\Razor\Microsoft.CodeAnalysis.Razor\src\Microsoft.CodeAnalysis.Razor.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.NET.Sdk.Razor" ProjectPath="$(RepoRoot)src\Razor\Microsoft.NET.Sdk.Razor\src\Microsoft.NET.Sdk.Razor.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Razor.Runtime" ProjectPath="$(RepoRoot)src\Razor\Razor.Runtime\src\Microsoft.AspNetCore.Razor.Runtime.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Razor" ProjectPath="$(RepoRoot)src\Razor\Razor\src\Microsoft.AspNetCore.Razor.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Mvc.Abstractions" ProjectPath="$(RepoRoot)src\Mvc\Mvc.Abstractions\src\Microsoft.AspNetCore.Mvc.Abstractions.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Mvc.ApiExplorer" ProjectPath="$(RepoRoot)src\Mvc\Mvc.ApiExplorer\src\Microsoft.AspNetCore.Mvc.ApiExplorer.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Mvc.Core" ProjectPath="$(RepoRoot)src\Mvc\Mvc.Core\src\Microsoft.AspNetCore.Mvc.Core.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Mvc.Cors" ProjectPath="$(RepoRoot)src\Mvc\Mvc.Cors\src\Microsoft.AspNetCore.Mvc.Cors.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Mvc.DataAnnotations" ProjectPath="$(RepoRoot)src\Mvc\Mvc.DataAnnotations\src\Microsoft.AspNetCore.Mvc.DataAnnotations.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Mvc.Formatters.Json" ProjectPath="$(RepoRoot)src\Mvc\Mvc.Formatters.Json\src\Microsoft.AspNetCore.Mvc.Formatters.Json.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Mvc.Formatters.Xml" ProjectPath="$(RepoRoot)src\Mvc\Mvc.Formatters.Xml\src\Microsoft.AspNetCore.Mvc.Formatters.Xml.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Mvc.Localization" ProjectPath="$(RepoRoot)src\Mvc\Mvc.Localization\src\Microsoft.AspNetCore.Mvc.Localization.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" ProjectPath="$(RepoRoot)src\Mvc\Mvc.NewtonsoftJson\src\Microsoft.AspNetCore.Mvc.NewtonsoftJson.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" ProjectPath="$(RepoRoot)src\Mvc\Mvc.Razor.RuntimeCompilation\src\Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Mvc.RazorPages" ProjectPath="$(RepoRoot)src\Mvc\Mvc.RazorPages\src\Microsoft.AspNetCore.Mvc.RazorPages.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Mvc.Razor" ProjectPath="$(RepoRoot)src\Mvc\Mvc.Razor\src\Microsoft.AspNetCore.Mvc.Razor.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Mvc.TagHelpers" ProjectPath="$(RepoRoot)src\Mvc\Mvc.TagHelpers\src\Microsoft.AspNetCore.Mvc.TagHelpers.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Mvc.Testing" ProjectPath="$(RepoRoot)src\Mvc\Mvc.Testing\src\Microsoft.AspNetCore.Mvc.Testing.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Mvc.ViewFeatures" ProjectPath="$(RepoRoot)src\Mvc\Mvc.ViewFeatures\src\Microsoft.AspNetCore.Mvc.ViewFeatures.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Mvc" ProjectPath="$(RepoRoot)src\Mvc\Mvc\src\Microsoft.AspNetCore.Mvc.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Authentication.AzureAD.UI" ProjectPath="$(RepoRoot)src\Azure\AzureAD\Authentication.AzureAD.UI\src\Microsoft.AspNetCore.Authentication.AzureAD.UI.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Authentication.AzureADB2C.UI" ProjectPath="$(RepoRoot)src\Azure\AzureAD\Authentication.AzureADB2C.UI\src\Microsoft.AspNetCore.Authentication.AzureADB2C.UI.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.AzureAppServices.HostingStartup" ProjectPath="$(RepoRoot)src\Azure\AzureAppServices.HostingStartup\src\Microsoft.AspNetCore.AzureAppServices.HostingStartup.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.AzureAppServicesIntegration" ProjectPath="$(RepoRoot)src\Azure\AzureAppServicesIntegration\src\Microsoft.AspNetCore.AzureAppServicesIntegration.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.SignalR.Client.Core" ProjectPath="$(RepoRoot)src\SignalR\clients\csharp\Client.Core\src\Microsoft.AspNetCore.SignalR.Client.Core.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.SignalR.Client" ProjectPath="$(RepoRoot)src\SignalR\clients\csharp\Client\src\Microsoft.AspNetCore.SignalR.Client.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Http.Connections.Client" ProjectPath="$(RepoRoot)src\SignalR\clients\csharp\Http.Connections.Client\src\Microsoft.AspNetCore.Http.Connections.Client.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Http.Connections.Common" ProjectPath="$(RepoRoot)src\SignalR\common\Http.Connections.Common\src\Microsoft.AspNetCore.Http.Connections.Common.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Http.Connections" ProjectPath="$(RepoRoot)src\SignalR\common\Http.Connections\src\Microsoft.AspNetCore.Http.Connections.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.SignalR.Protocols.Json" ProjectPath="$(RepoRoot)src\SignalR\common\Protocols.Json\src\Microsoft.AspNetCore.SignalR.Protocols.Json.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.SignalR.Protocols.MessagePack" ProjectPath="$(RepoRoot)src\SignalR\common\Protocols.MessagePack\src\Microsoft.AspNetCore.SignalR.Protocols.MessagePack.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.SignalR.Protocols.NewtonsoftJson" ProjectPath="$(RepoRoot)src\SignalR\common\Protocols.NewtonsoftJson\src\Microsoft.AspNetCore.SignalR.Protocols.NewtonsoftJson.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.SignalR.Common" ProjectPath="$(RepoRoot)src\SignalR\common\SignalR.Common\src\Microsoft.AspNetCore.SignalR.Common.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.SignalR.Core" ProjectPath="$(RepoRoot)src\SignalR\server\Core\src\Microsoft.AspNetCore.SignalR.Core.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.SignalR" ProjectPath="$(RepoRoot)src\SignalR\server\SignalR\src\Microsoft.AspNetCore.SignalR.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.SignalR.Specification.Tests" ProjectPath="$(RepoRoot)src\SignalR\server\Specification.Tests\src\Microsoft.AspNetCore.SignalR.Specification.Tests.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.SignalR.StackExchangeRedis" ProjectPath="$(RepoRoot)src\SignalR\server\StackExchangeRedis\src\Microsoft.AspNetCore.SignalR.StackExchangeRedis.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Components.Authorization" ProjectPath="$(RepoRoot)src\Components\Authorization\src\Microsoft.AspNetCore.Components.Authorization.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Components" ProjectPath="$(RepoRoot)src\Components\Components\src\Microsoft.AspNetCore.Components.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Components.Forms" ProjectPath="$(RepoRoot)src\Components\Forms\src\Microsoft.AspNetCore.Components.Forms.csproj" />
|
||||
<ProjectReferenceProvider Include="Ignitor" ProjectPath="$(RepoRoot)src\Components\Ignitor\src\Ignitor.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Components.Server" ProjectPath="$(RepoRoot)src\Components\Server\src\Microsoft.AspNetCore.Components.Server.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Components.Web.Extensions" ProjectPath="$(RepoRoot)src\Components\Web.Extensions\src\Microsoft.AspNetCore.Components.Web.Extensions.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.Authentication.WebAssembly.Msal" ProjectPath="$(RepoRoot)src\Components\WebAssembly\Authentication.Msal\src\Microsoft.Authentication.WebAssembly.Msal.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.JSInterop.WebAssembly" ProjectPath="$(RepoRoot)src\Components\WebAssembly\JSInterop\src\Microsoft.JSInterop.WebAssembly.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.NET.Sdk.BlazorWebAssembly" ProjectPath="$(RepoRoot)src\Components\WebAssembly\Sdk\src\Microsoft.NET.Sdk.BlazorWebAssembly.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="Microsoft.AspNetCore.Components.WebAssembly" ProjectPath="$(RepoRoot)src\Components\WebAssembly\WebAssembly\src\Microsoft.AspNetCore.Components.WebAssembly.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Components.Web" ProjectPath="$(RepoRoot)src\Components\Web\src\Microsoft.AspNetCore.Components.Web.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.Extensions.FileProviders.Embedded" ProjectPath="$(RepoRoot)src\FileProviders\Embedded\src\Microsoft.Extensions.FileProviders.Embedded.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.Extensions.Configuration.KeyPerFile" ProjectPath="$(RepoRoot)src\Configuration.KeyPerFile\src\Microsoft.Extensions.Configuration.KeyPerFile.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.Extensions.Localization.Abstractions" ProjectPath="$(RepoRoot)src\Localization\Abstractions\src\Microsoft.Extensions.Localization.Abstractions.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.Extensions.Localization" ProjectPath="$(RepoRoot)src\Localization\Localization\src\Microsoft.Extensions.Localization.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.Extensions.ObjectPool" ProjectPath="$(RepoRoot)src\ObjectPool\src\Microsoft.Extensions.ObjectPool.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.JSInterop" ProjectPath="$(RepoRoot)src\JSInterop\Microsoft.JSInterop\src\Microsoft.JSInterop.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.Extensions.WebEncoders" ProjectPath="$(RepoRoot)src\WebEncoders\src\Microsoft.Extensions.WebEncoders.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions" ProjectPath="$(RepoRoot)src\HealthChecks\Abstractions\src\Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.Extensions.Diagnostics.HealthChecks" ProjectPath="$(RepoRoot)src\HealthChecks\HealthChecks\src\Microsoft.Extensions.Diagnostics.HealthChecks.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" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.JsonPatch" ProjectPath="$(RepoRoot)src\Features\JsonPatch\src\Microsoft.AspNetCore.JsonPatch.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.DataProtection.Abstractions" ProjectPath="$(RepoRoot)src\DataProtection\Abstractions\src\Microsoft.AspNetCore.DataProtection.Abstractions.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Cryptography.Internal" ProjectPath="$(RepoRoot)src\DataProtection\Cryptography.Internal\src\Microsoft.AspNetCore.Cryptography.Internal.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" ProjectPath="$(RepoRoot)src\DataProtection\Cryptography.KeyDerivation\src\Microsoft.AspNetCore.Cryptography.KeyDerivation.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.DataProtection" ProjectPath="$(RepoRoot)src\DataProtection\DataProtection\src\Microsoft.AspNetCore.DataProtection.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.DataProtection.EntityFrameworkCore" ProjectPath="$(RepoRoot)src\DataProtection\EntityFrameworkCore\src\Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.DataProtection.Extensions" ProjectPath="$(RepoRoot)src\DataProtection\Extensions\src\Microsoft.AspNetCore.DataProtection.Extensions.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" ProjectPath="$(RepoRoot)src\DataProtection\StackExchangeRedis\src\Microsoft.AspNetCore.DataProtection.StackExchangeRedis.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Antiforgery" ProjectPath="$(RepoRoot)src\Antiforgery\src\Microsoft.AspNetCore.Antiforgery.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Hosting.Abstractions" ProjectPath="$(RepoRoot)src\Hosting\Abstractions\src\Microsoft.AspNetCore.Hosting.Abstractions.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Hosting" ProjectPath="$(RepoRoot)src\Hosting\Hosting\src\Microsoft.AspNetCore.Hosting.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Hosting.Server.Abstractions" ProjectPath="$(RepoRoot)src\Hosting\Server.Abstractions\src\Microsoft.AspNetCore.Hosting.Server.Abstractions.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.TestHost" ProjectPath="$(RepoRoot)src\Hosting\TestHost\src\Microsoft.AspNetCore.TestHost.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Hosting.WindowsServices" ProjectPath="$(RepoRoot)src\Hosting\WindowsServices\src\Microsoft.AspNetCore.Hosting.WindowsServices.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Authentication.Abstractions" ProjectPath="$(RepoRoot)src\Http\Authentication.Abstractions\src\Microsoft.AspNetCore.Authentication.Abstractions.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Authentication.Core" ProjectPath="$(RepoRoot)src\Http\Authentication.Core\src\Microsoft.AspNetCore.Authentication.Core.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.Net.Http.Headers" ProjectPath="$(RepoRoot)src\Http\Headers\src\Microsoft.Net.Http.Headers.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Http.Abstractions" ProjectPath="$(RepoRoot)src\Http\Http.Abstractions\src\Microsoft.AspNetCore.Http.Abstractions.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Http.Extensions" ProjectPath="$(RepoRoot)src\Http\Http.Extensions\src\Microsoft.AspNetCore.Http.Extensions.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Http.Features" ProjectPath="$(RepoRoot)src\Http\Http.Features\src\Microsoft.AspNetCore.Http.Features.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Http" ProjectPath="$(RepoRoot)src\Http\Http\src\Microsoft.AspNetCore.Http.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Metadata" ProjectPath="$(RepoRoot)src\Http\Metadata\src\Microsoft.AspNetCore.Metadata.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Owin" ProjectPath="$(RepoRoot)src\Http\Owin\src\Microsoft.AspNetCore.Owin.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Routing.Abstractions" ProjectPath="$(RepoRoot)src\Http\Routing.Abstractions\src\Microsoft.AspNetCore.Routing.Abstractions.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Routing" ProjectPath="$(RepoRoot)src\Http\Routing\src\Microsoft.AspNetCore.Routing.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.WebUtilities" ProjectPath="$(RepoRoot)src\Http\WebUtilities\src\Microsoft.AspNetCore.WebUtilities.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Html.Abstractions" ProjectPath="$(RepoRoot)src\Html\Abstractions\src\Microsoft.AspNetCore.Html.Abstractions.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.ApiAuthorization.IdentityServer" ProjectPath="$(RepoRoot)src\Identity\ApiAuthorization.IdentityServer\src\Microsoft.AspNetCore.ApiAuthorization.IdentityServer.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Identity" ProjectPath="$(RepoRoot)src\Identity\Core\src\Microsoft.AspNetCore.Identity.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" ProjectPath="$(RepoRoot)src\Identity\EntityFrameworkCore\src\Microsoft.AspNetCore.Identity.EntityFrameworkCore.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.Extensions.Identity.Core" ProjectPath="$(RepoRoot)src\Identity\Extensions.Core\src\Microsoft.Extensions.Identity.Core.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.Extensions.Identity.Stores" ProjectPath="$(RepoRoot)src\Identity\Extensions.Stores\src\Microsoft.Extensions.Identity.Stores.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Identity.Specification.Tests" ProjectPath="$(RepoRoot)src\Identity\Specification.Tests\src\Microsoft.AspNetCore.Identity.Specification.Tests.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Identity.UI" ProjectPath="$(RepoRoot)src\Identity\UI\src\Microsoft.AspNetCore.Identity.UI.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Connections.Abstractions" ProjectPath="$(RepoRoot)src\Servers\Connections.Abstractions\src\Microsoft.AspNetCore.Connections.Abstractions.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Server.HttpSys" ProjectPath="$(RepoRoot)src\Servers\HttpSys\src\Microsoft.AspNetCore.Server.HttpSys.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Server.IISIntegration" ProjectPath="$(RepoRoot)src\Servers\IIS\IISIntegration\src\Microsoft.AspNetCore.Server.IISIntegration.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Server.IIS" ProjectPath="$(RepoRoot)src\Servers\IIS\IIS\src\Microsoft.AspNetCore.Server.IIS.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Server.Kestrel.Core" ProjectPath="$(RepoRoot)src\Servers\Kestrel\Core\src\Microsoft.AspNetCore.Server.Kestrel.Core.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Server.Kestrel" ProjectPath="$(RepoRoot)src\Servers\Kestrel\Kestrel\src\Microsoft.AspNetCore.Server.Kestrel.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv" ProjectPath="$(RepoRoot)src\Servers\Kestrel\Transport.Libuv\src\Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Server.Kestrel.Transport.Experimental.Quic" ProjectPath="$(RepoRoot)src\Servers\Kestrel\Transport.Quic\src\Microsoft.AspNetCore.Server.Kestrel.Transport.Experimental.Quic.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets" ProjectPath="$(RepoRoot)src\Servers\Kestrel\Transport.Sockets\src\Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Authentication.Certificate" ProjectPath="$(RepoRoot)src\Security\Authentication\Certificate\src\Microsoft.AspNetCore.Authentication.Certificate.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Authentication.Cookies" ProjectPath="$(RepoRoot)src\Security\Authentication\Cookies\src\Microsoft.AspNetCore.Authentication.Cookies.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Authentication" ProjectPath="$(RepoRoot)src\Security\Authentication\Core\src\Microsoft.AspNetCore.Authentication.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Authentication.Facebook" ProjectPath="$(RepoRoot)src\Security\Authentication\Facebook\src\Microsoft.AspNetCore.Authentication.Facebook.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Authentication.Google" ProjectPath="$(RepoRoot)src\Security\Authentication\Google\src\Microsoft.AspNetCore.Authentication.Google.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Authentication.JwtBearer" ProjectPath="$(RepoRoot)src\Security\Authentication\JwtBearer\src\Microsoft.AspNetCore.Authentication.JwtBearer.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Authentication.MicrosoftAccount" ProjectPath="$(RepoRoot)src\Security\Authentication\MicrosoftAccount\src\Microsoft.AspNetCore.Authentication.MicrosoftAccount.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Authentication.Negotiate" ProjectPath="$(RepoRoot)src\Security\Authentication\Negotiate\src\Microsoft.AspNetCore.Authentication.Negotiate.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Authentication.OAuth" ProjectPath="$(RepoRoot)src\Security\Authentication\OAuth\src\Microsoft.AspNetCore.Authentication.OAuth.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" ProjectPath="$(RepoRoot)src\Security\Authentication\OpenIdConnect\src\Microsoft.AspNetCore.Authentication.OpenIdConnect.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Authentication.Twitter" ProjectPath="$(RepoRoot)src\Security\Authentication\Twitter\src\Microsoft.AspNetCore.Authentication.Twitter.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Authentication.WsFederation" ProjectPath="$(RepoRoot)src\Security\Authentication\WsFederation\src\Microsoft.AspNetCore.Authentication.WsFederation.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Authorization" ProjectPath="$(RepoRoot)src\Security\Authorization\Core\src\Microsoft.AspNetCore.Authorization.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Authorization.Policy" ProjectPath="$(RepoRoot)src\Security\Authorization\Policy\src\Microsoft.AspNetCore.Authorization.Policy.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.CookiePolicy" ProjectPath="$(RepoRoot)src\Security\CookiePolicy\src\Microsoft.AspNetCore.CookiePolicy.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.Web.Xdt.Extensions" ProjectPath="$(RepoRoot)src\SiteExtensions\Microsoft.Web.Xdt.Extensions\src\Microsoft.Web.Xdt.Extensions.csproj" />
|
||||
<ProjectReferenceProvider Include="dotnet-getdocument" ProjectPath="$(RepoRoot)src\Tools\dotnet-getdocument\src\dotnet-getdocument.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.Extensions.ApiDescription.Client" ProjectPath="$(RepoRoot)src\Tools\Extensions.ApiDescription.Client\src\Microsoft.Extensions.ApiDescription.Client.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.Extensions.ApiDescription.Server" ProjectPath="$(RepoRoot)src\Tools\Extensions.ApiDescription.Server\src\Microsoft.Extensions.ApiDescription.Server.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.DeveloperCertificates.XPlat" ProjectPath="$(RepoRoot)src\Tools\FirstRunCertGenerator\src\Microsoft.AspNetCore.DeveloperCertificates.XPlat.csproj" />
|
||||
<ProjectReferenceProvider Include="GetDocument.Insider" ProjectPath="$(RepoRoot)src\Tools\GetDocumentInsider\src\GetDocument.Insider.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.Extensions.Logging.AzureAppServices" ProjectPath="$(RepoRoot)src\Logging.AzureAppServices\src\Microsoft.Extensions.Logging.AzureAppServices.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.ConcurrencyLimiter" ProjectPath="$(RepoRoot)src\Middleware\ConcurrencyLimiter\src\Microsoft.AspNetCore.ConcurrencyLimiter.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Cors" ProjectPath="$(RepoRoot)src\Middleware\CORS\src\Microsoft.AspNetCore.Cors.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Diagnostics.Abstractions" ProjectPath="$(RepoRoot)src\Middleware\Diagnostics.Abstractions\src\Microsoft.AspNetCore.Diagnostics.Abstractions.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" ProjectPath="$(RepoRoot)src\Middleware\Diagnostics.EntityFrameworkCore\src\Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Diagnostics" ProjectPath="$(RepoRoot)src\Middleware\Diagnostics\src\Microsoft.AspNetCore.Diagnostics.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.HeaderPropagation" ProjectPath="$(RepoRoot)src\Middleware\HeaderPropagation\src\Microsoft.AspNetCore.HeaderPropagation.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore" ProjectPath="$(RepoRoot)src\Middleware\HealthChecks.EntityFrameworkCore\src\Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Diagnostics.HealthChecks" ProjectPath="$(RepoRoot)src\Middleware\HealthChecks\src\Microsoft.AspNetCore.Diagnostics.HealthChecks.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.HostFiltering" ProjectPath="$(RepoRoot)src\Middleware\HostFiltering\src\Microsoft.AspNetCore.HostFiltering.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.HttpOverrides" ProjectPath="$(RepoRoot)src\Middleware\HttpOverrides\src\Microsoft.AspNetCore.HttpOverrides.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.HttpsPolicy" ProjectPath="$(RepoRoot)src\Middleware\HttpsPolicy\src\Microsoft.AspNetCore.HttpsPolicy.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Localization.Routing" ProjectPath="$(RepoRoot)src\Middleware\Localization.Routing\src\Microsoft.AspNetCore.Localization.Routing.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Localization" ProjectPath="$(RepoRoot)src\Middleware\Localization\src\Microsoft.AspNetCore.Localization.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.MiddlewareAnalysis" ProjectPath="$(RepoRoot)src\Middleware\MiddlewareAnalysis\src\Microsoft.AspNetCore.MiddlewareAnalysis.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.NodeServices" ProjectPath="$(RepoRoot)src\Middleware\NodeServices\src\Microsoft.AspNetCore.NodeServices.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.ResponseCaching.Abstractions" ProjectPath="$(RepoRoot)src\Middleware\ResponseCaching.Abstractions\src\Microsoft.AspNetCore.ResponseCaching.Abstractions.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.ResponseCaching" ProjectPath="$(RepoRoot)src\Middleware\ResponseCaching\src\Microsoft.AspNetCore.ResponseCaching.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.ResponseCompression" ProjectPath="$(RepoRoot)src\Middleware\ResponseCompression\src\Microsoft.AspNetCore.ResponseCompression.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Rewrite" ProjectPath="$(RepoRoot)src\Middleware\Rewrite\src\Microsoft.AspNetCore.Rewrite.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Session" ProjectPath="$(RepoRoot)src\Middleware\Session\src\Microsoft.AspNetCore.Session.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.SpaServices.Extensions" ProjectPath="$(RepoRoot)src\Middleware\SpaServices.Extensions\src\Microsoft.AspNetCore.SpaServices.Extensions.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.SpaServices" ProjectPath="$(RepoRoot)src\Middleware\SpaServices\src\Microsoft.AspNetCore.SpaServices.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.StaticFiles" ProjectPath="$(RepoRoot)src\Middleware\StaticFiles\src\Microsoft.AspNetCore.StaticFiles.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.WebSockets" ProjectPath="$(RepoRoot)src\Middleware\WebSockets\src\Microsoft.AspNetCore.WebSockets.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X" ProjectPath="$(RepoRoot)src\Razor\Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X\src\Microsoft.AspNetCore.Mvc.Razor.Extensions.Version1_X.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Mvc.Razor.Extensions.Version2_X" ProjectPath="$(RepoRoot)src\Razor\Microsoft.AspNetCore.Mvc.Razor.Extensions.Version2_X\src\Microsoft.AspNetCore.Mvc.Razor.Extensions.Version2_X.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Mvc.Razor.Extensions" ProjectPath="$(RepoRoot)src\Razor\Microsoft.AspNetCore.Mvc.Razor.Extensions\src\Microsoft.AspNetCore.Mvc.Razor.Extensions.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Razor.Language" ProjectPath="$(RepoRoot)src\Razor\Microsoft.AspNetCore.Razor.Language\src\Microsoft.AspNetCore.Razor.Language.csproj" />
|
||||
<ProjectReferenceProvider Include="rzc" ProjectPath="$(RepoRoot)src\Razor\Microsoft.AspNetCore.Razor.Tools\src\rzc.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.CodeAnalysis.Razor" ProjectPath="$(RepoRoot)src\Razor\Microsoft.CodeAnalysis.Razor\src\Microsoft.CodeAnalysis.Razor.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.NET.Sdk.Razor" ProjectPath="$(RepoRoot)src\Razor\Microsoft.NET.Sdk.Razor\src\Microsoft.NET.Sdk.Razor.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Razor.Runtime" ProjectPath="$(RepoRoot)src\Razor\Razor.Runtime\src\Microsoft.AspNetCore.Razor.Runtime.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Razor" ProjectPath="$(RepoRoot)src\Razor\Razor\src\Microsoft.AspNetCore.Razor.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Mvc.Abstractions" ProjectPath="$(RepoRoot)src\Mvc\Mvc.Abstractions\src\Microsoft.AspNetCore.Mvc.Abstractions.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Mvc.ApiExplorer" ProjectPath="$(RepoRoot)src\Mvc\Mvc.ApiExplorer\src\Microsoft.AspNetCore.Mvc.ApiExplorer.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Mvc.Core" ProjectPath="$(RepoRoot)src\Mvc\Mvc.Core\src\Microsoft.AspNetCore.Mvc.Core.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Mvc.Cors" ProjectPath="$(RepoRoot)src\Mvc\Mvc.Cors\src\Microsoft.AspNetCore.Mvc.Cors.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Mvc.DataAnnotations" ProjectPath="$(RepoRoot)src\Mvc\Mvc.DataAnnotations\src\Microsoft.AspNetCore.Mvc.DataAnnotations.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Mvc.Formatters.Json" ProjectPath="$(RepoRoot)src\Mvc\Mvc.Formatters.Json\src\Microsoft.AspNetCore.Mvc.Formatters.Json.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Mvc.Formatters.Xml" ProjectPath="$(RepoRoot)src\Mvc\Mvc.Formatters.Xml\src\Microsoft.AspNetCore.Mvc.Formatters.Xml.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Mvc.Localization" ProjectPath="$(RepoRoot)src\Mvc\Mvc.Localization\src\Microsoft.AspNetCore.Mvc.Localization.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" ProjectPath="$(RepoRoot)src\Mvc\Mvc.NewtonsoftJson\src\Microsoft.AspNetCore.Mvc.NewtonsoftJson.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" ProjectPath="$(RepoRoot)src\Mvc\Mvc.Razor.RuntimeCompilation\src\Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Mvc.RazorPages" ProjectPath="$(RepoRoot)src\Mvc\Mvc.RazorPages\src\Microsoft.AspNetCore.Mvc.RazorPages.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Mvc.Razor" ProjectPath="$(RepoRoot)src\Mvc\Mvc.Razor\src\Microsoft.AspNetCore.Mvc.Razor.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Mvc.TagHelpers" ProjectPath="$(RepoRoot)src\Mvc\Mvc.TagHelpers\src\Microsoft.AspNetCore.Mvc.TagHelpers.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Mvc.Testing" ProjectPath="$(RepoRoot)src\Mvc\Mvc.Testing\src\Microsoft.AspNetCore.Mvc.Testing.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Mvc.ViewFeatures" ProjectPath="$(RepoRoot)src\Mvc\Mvc.ViewFeatures\src\Microsoft.AspNetCore.Mvc.ViewFeatures.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Mvc" ProjectPath="$(RepoRoot)src\Mvc\Mvc\src\Microsoft.AspNetCore.Mvc.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Authentication.AzureAD.UI" ProjectPath="$(RepoRoot)src\Azure\AzureAD\Authentication.AzureAD.UI\src\Microsoft.AspNetCore.Authentication.AzureAD.UI.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Authentication.AzureADB2C.UI" ProjectPath="$(RepoRoot)src\Azure\AzureAD\Authentication.AzureADB2C.UI\src\Microsoft.AspNetCore.Authentication.AzureADB2C.UI.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.AzureAppServices.HostingStartup" ProjectPath="$(RepoRoot)src\Azure\AzureAppServices.HostingStartup\src\Microsoft.AspNetCore.AzureAppServices.HostingStartup.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.AzureAppServicesIntegration" ProjectPath="$(RepoRoot)src\Azure\AzureAppServicesIntegration\src\Microsoft.AspNetCore.AzureAppServicesIntegration.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.SignalR.Client.Core" ProjectPath="$(RepoRoot)src\SignalR\clients\csharp\Client.Core\src\Microsoft.AspNetCore.SignalR.Client.Core.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.SignalR.Client" ProjectPath="$(RepoRoot)src\SignalR\clients\csharp\Client\src\Microsoft.AspNetCore.SignalR.Client.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Http.Connections.Client" ProjectPath="$(RepoRoot)src\SignalR\clients\csharp\Http.Connections.Client\src\Microsoft.AspNetCore.Http.Connections.Client.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Http.Connections.Common" ProjectPath="$(RepoRoot)src\SignalR\common\Http.Connections.Common\src\Microsoft.AspNetCore.Http.Connections.Common.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Http.Connections" ProjectPath="$(RepoRoot)src\SignalR\common\Http.Connections\src\Microsoft.AspNetCore.Http.Connections.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.SignalR.Protocols.Json" ProjectPath="$(RepoRoot)src\SignalR\common\Protocols.Json\src\Microsoft.AspNetCore.SignalR.Protocols.Json.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.SignalR.Protocols.MessagePack" ProjectPath="$(RepoRoot)src\SignalR\common\Protocols.MessagePack\src\Microsoft.AspNetCore.SignalR.Protocols.MessagePack.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.SignalR.Protocols.NewtonsoftJson" ProjectPath="$(RepoRoot)src\SignalR\common\Protocols.NewtonsoftJson\src\Microsoft.AspNetCore.SignalR.Protocols.NewtonsoftJson.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.SignalR.Common" ProjectPath="$(RepoRoot)src\SignalR\common\SignalR.Common\src\Microsoft.AspNetCore.SignalR.Common.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.SignalR.Core" ProjectPath="$(RepoRoot)src\SignalR\server\Core\src\Microsoft.AspNetCore.SignalR.Core.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.SignalR" ProjectPath="$(RepoRoot)src\SignalR\server\SignalR\src\Microsoft.AspNetCore.SignalR.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.SignalR.Specification.Tests" ProjectPath="$(RepoRoot)src\SignalR\server\Specification.Tests\src\Microsoft.AspNetCore.SignalR.Specification.Tests.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.SignalR.StackExchangeRedis" ProjectPath="$(RepoRoot)src\SignalR\server\StackExchangeRedis\src\Microsoft.AspNetCore.SignalR.StackExchangeRedis.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Components.Authorization" ProjectPath="$(RepoRoot)src\Components\Authorization\src\Microsoft.AspNetCore.Components.Authorization.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Components" ProjectPath="$(RepoRoot)src\Components\Components\src\Microsoft.AspNetCore.Components.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Components.Forms" ProjectPath="$(RepoRoot)src\Components\Forms\src\Microsoft.AspNetCore.Components.Forms.csproj" />
|
||||
<ProjectReferenceProvider Include="Ignitor" ProjectPath="$(RepoRoot)src\Components\Ignitor\src\Ignitor.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Components.Server" ProjectPath="$(RepoRoot)src\Components\Server\src\Microsoft.AspNetCore.Components.Server.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Components.Web.Extensions" ProjectPath="$(RepoRoot)src\Components\Web.Extensions\src\Microsoft.AspNetCore.Components.Web.Extensions.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.Authentication.WebAssembly.Msal" ProjectPath="$(RepoRoot)src\Components\WebAssembly\Authentication.Msal\src\Microsoft.Authentication.WebAssembly.Msal.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.JSInterop.WebAssembly" ProjectPath="$(RepoRoot)src\Components\WebAssembly\JSInterop\src\Microsoft.JSInterop.WebAssembly.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.NET.Sdk.BlazorWebAssembly" ProjectPath="$(RepoRoot)src\Components\WebAssembly\Sdk\src\Microsoft.NET.Sdk.BlazorWebAssembly.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="Microsoft.AspNetCore.Components.WebAssembly" ProjectPath="$(RepoRoot)src\Components\WebAssembly\WebAssembly\src\Microsoft.AspNetCore.Components.WebAssembly.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Components.Web" ProjectPath="$(RepoRoot)src\Components\Web\src\Microsoft.AspNetCore.Components.Web.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.Extensions.FileProviders.Embedded" ProjectPath="$(RepoRoot)src\FileProviders\Embedded\src\Microsoft.Extensions.FileProviders.Embedded.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.Extensions.Configuration.KeyPerFile" ProjectPath="$(RepoRoot)src\Configuration.KeyPerFile\src\Microsoft.Extensions.Configuration.KeyPerFile.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.Extensions.Localization.Abstractions" ProjectPath="$(RepoRoot)src\Localization\Abstractions\src\Microsoft.Extensions.Localization.Abstractions.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.Extensions.Localization" ProjectPath="$(RepoRoot)src\Localization\Localization\src\Microsoft.Extensions.Localization.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.Extensions.ObjectPool" ProjectPath="$(RepoRoot)src\ObjectPool\src\Microsoft.Extensions.ObjectPool.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.JSInterop" ProjectPath="$(RepoRoot)src\JSInterop\Microsoft.JSInterop\src\Microsoft.JSInterop.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.Extensions.WebEncoders" ProjectPath="$(RepoRoot)src\WebEncoders\src\Microsoft.Extensions.WebEncoders.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions" ProjectPath="$(RepoRoot)src\HealthChecks\Abstractions\src\Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.Extensions.Diagnostics.HealthChecks" ProjectPath="$(RepoRoot)src\HealthChecks\HealthChecks\src\Microsoft.Extensions.Diagnostics.HealthChecks.csproj" />
|
||||
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Testing" ProjectPath="$(RepoRoot)src\Testing\src\Microsoft.AspNetCore.Testing.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -1,6 +0,0 @@
|
|||
<Project>
|
||||
<!-- Minimize what gets set to avoid useless references in this simple project. -->
|
||||
<Import Project="..\Common.props" />
|
||||
<Import Project="..\Versions.props" />
|
||||
<Import Project="..\Dependencies.props" />
|
||||
</Project>
|
||||
|
|
@ -1 +0,0 @@
|
|||
<Project />
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<!--
|
||||
Gather project references for compilation against RTM packages. %(RTMVersion) is set for about a dozen packages
|
||||
in all servicing builds. Cannot reference two versions of a package, mandating this separate package.
|
||||
-->
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<IsPackable>false</IsPackable>
|
||||
|
||||
<!-- Don't bother building anything here. We only need to ensure the RTM packages are on disk. -->
|
||||
<DebugType>none</DebugType>
|
||||
<IncludeBuildOutput>false</IncludeBuildOutput>
|
||||
<CopyBuildOutputToPublishDirectory>false</CopyBuildOutputToPublishDirectory>
|
||||
<CopyBuildOutputToOutputDirectory>false</CopyBuildOutputToOutputDirectory>
|
||||
<CopyOutputSymbolsToOutputDirectory>false</CopyOutputSymbolsToOutputDirectory>
|
||||
<GenerateDependencyFile>false</GenerateDependencyFile>
|
||||
|
||||
<!-- This project should not be referenced via the `<Reference>` implementation. -->
|
||||
<IsProjectReferenceProvider>false</IsProjectReferenceProvider>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="@(LatestPackageReference->HasMetadata('RTMVersion'))" Version="%(RTMVersion)" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Arcade SDK calls Test target on every project in the repo but provides an empty fallback. Do same here. -->
|
||||
<Target Name="Test" />
|
||||
</Project>
|
||||
|
|
@ -13,304 +13,309 @@
|
|||
<Uri>https://github.com/dotnet/blazor</Uri>
|
||||
<Sha>cc449601d638ffaab58ae9487f0fd010bb178a12</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="dotnet-ef" Version="5.0.0-preview.8.20360.8">
|
||||
<Dependency Name="dotnet-ef" Version="5.0.0-rc.1.20372.13">
|
||||
<Uri>https://github.com/dotnet/efcore</Uri>
|
||||
<Sha>58abc390e0e3eb849b5773da3f5ed2982ade521d</Sha>
|
||||
<Sha>59734ea22f29d22f8d0c1673c59a99c54ec4e78d</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.EntityFrameworkCore.InMemory" Version="5.0.0-preview.8.20360.8">
|
||||
<Dependency Name="Microsoft.EntityFrameworkCore.InMemory" Version="5.0.0-rc.1.20372.13">
|
||||
<Uri>https://github.com/dotnet/efcore</Uri>
|
||||
<Sha>58abc390e0e3eb849b5773da3f5ed2982ade521d</Sha>
|
||||
<Sha>59734ea22f29d22f8d0c1673c59a99c54ec4e78d</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.EntityFrameworkCore.Relational" Version="5.0.0-preview.8.20360.8">
|
||||
<Dependency Name="Microsoft.EntityFrameworkCore.Relational" Version="5.0.0-rc.1.20372.13">
|
||||
<Uri>https://github.com/dotnet/efcore</Uri>
|
||||
<Sha>58abc390e0e3eb849b5773da3f5ed2982ade521d</Sha>
|
||||
<Sha>59734ea22f29d22f8d0c1673c59a99c54ec4e78d</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.EntityFrameworkCore.Sqlite" Version="5.0.0-preview.8.20360.8">
|
||||
<Dependency Name="Microsoft.EntityFrameworkCore.Sqlite" Version="5.0.0-rc.1.20372.13">
|
||||
<Uri>https://github.com/dotnet/efcore</Uri>
|
||||
<Sha>58abc390e0e3eb849b5773da3f5ed2982ade521d</Sha>
|
||||
<Sha>59734ea22f29d22f8d0c1673c59a99c54ec4e78d</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.EntityFrameworkCore.SqlServer" Version="5.0.0-preview.8.20360.8">
|
||||
<Dependency Name="Microsoft.EntityFrameworkCore.SqlServer" Version="5.0.0-rc.1.20372.13">
|
||||
<Uri>https://github.com/dotnet/efcore</Uri>
|
||||
<Sha>58abc390e0e3eb849b5773da3f5ed2982ade521d</Sha>
|
||||
<Sha>59734ea22f29d22f8d0c1673c59a99c54ec4e78d</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.EntityFrameworkCore.Tools" Version="5.0.0-preview.8.20360.8">
|
||||
<Dependency Name="Microsoft.EntityFrameworkCore.Tools" Version="5.0.0-rc.1.20372.13">
|
||||
<Uri>https://github.com/dotnet/efcore</Uri>
|
||||
<Sha>58abc390e0e3eb849b5773da3f5ed2982ade521d</Sha>
|
||||
<Sha>59734ea22f29d22f8d0c1673c59a99c54ec4e78d</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.EntityFrameworkCore" Version="5.0.0-preview.8.20360.8">
|
||||
<Dependency Name="Microsoft.EntityFrameworkCore" Version="5.0.0-rc.1.20372.13">
|
||||
<Uri>https://github.com/dotnet/efcore</Uri>
|
||||
<Sha>58abc390e0e3eb849b5773da3f5ed2982ade521d</Sha>
|
||||
<Sha>59734ea22f29d22f8d0c1673c59a99c54ec4e78d</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Caching.Abstractions" Version="5.0.0-preview.8.20361.2">
|
||||
<Dependency Name="Microsoft.Extensions.Caching.Abstractions" Version="5.0.0-rc.1.20370.4">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha>
|
||||
<Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Caching.Memory" Version="5.0.0-preview.8.20361.2">
|
||||
<Dependency Name="Microsoft.Extensions.Caching.Memory" Version="5.0.0-rc.1.20370.4">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha>
|
||||
<Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Configuration.Abstractions" Version="5.0.0-preview.8.20361.2">
|
||||
<Dependency Name="Microsoft.Extensions.Configuration.Abstractions" Version="5.0.0-rc.1.20370.4">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha>
|
||||
<Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Configuration.Binder" Version="5.0.0-preview.8.20361.2">
|
||||
<Dependency Name="Microsoft.Extensions.Configuration.Binder" Version="5.0.0-rc.1.20370.4">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha>
|
||||
<Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Configuration.CommandLine" Version="5.0.0-preview.8.20361.2">
|
||||
<Dependency Name="Microsoft.Extensions.Configuration.CommandLine" Version="5.0.0-rc.1.20370.4">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha>
|
||||
<Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="5.0.0-preview.8.20361.2">
|
||||
<Dependency Name="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="5.0.0-rc.1.20370.4">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha>
|
||||
<Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Configuration.FileExtensions" Version="5.0.0-preview.8.20361.2">
|
||||
<Dependency Name="Microsoft.Extensions.Configuration.FileExtensions" Version="5.0.0-rc.1.20370.4">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha>
|
||||
<Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Configuration.Ini" Version="5.0.0-preview.8.20361.2">
|
||||
<Dependency Name="Microsoft.Extensions.Configuration.Ini" Version="5.0.0-rc.1.20370.4">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha>
|
||||
<Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Configuration.Json" Version="5.0.0-preview.8.20361.2">
|
||||
<Dependency Name="Microsoft.Extensions.Configuration.Json" Version="5.0.0-rc.1.20370.4">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha>
|
||||
<Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Configuration.UserSecrets" Version="5.0.0-preview.8.20361.2">
|
||||
<Dependency Name="Microsoft.Extensions.Configuration.UserSecrets" Version="5.0.0-rc.1.20370.4">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha>
|
||||
<Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Configuration.Xml" Version="5.0.0-preview.8.20361.2">
|
||||
<Dependency Name="Microsoft.Extensions.Configuration.Xml" Version="5.0.0-rc.1.20370.4">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha>
|
||||
<Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Configuration" Version="5.0.0-preview.8.20361.2">
|
||||
<Dependency Name="Microsoft.Extensions.Configuration" Version="5.0.0-rc.1.20370.4">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha>
|
||||
<Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.DependencyInjection.Abstractions" Version="5.0.0-preview.8.20361.2">
|
||||
<Dependency Name="Microsoft.Extensions.DependencyInjection.Abstractions" Version="5.0.0-rc.1.20370.4">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha>
|
||||
<Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.DependencyInjection" Version="5.0.0-preview.8.20361.2">
|
||||
<Dependency Name="Microsoft.Extensions.DependencyInjection" Version="5.0.0-rc.1.20370.4">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha>
|
||||
<Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.FileProviders.Abstractions" Version="5.0.0-preview.8.20361.2">
|
||||
<Dependency Name="Microsoft.Extensions.FileProviders.Abstractions" Version="5.0.0-rc.1.20370.4">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha>
|
||||
<Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.FileProviders.Composite" Version="5.0.0-preview.8.20361.2">
|
||||
<Dependency Name="Microsoft.Extensions.FileProviders.Composite" Version="5.0.0-rc.1.20370.4">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha>
|
||||
<Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.FileProviders.Physical" Version="5.0.0-preview.8.20361.2">
|
||||
<Dependency Name="Microsoft.Extensions.FileProviders.Physical" Version="5.0.0-rc.1.20370.4">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha>
|
||||
<Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.FileSystemGlobbing" Version="5.0.0-preview.8.20361.2">
|
||||
<Dependency Name="Microsoft.Extensions.FileSystemGlobbing" Version="5.0.0-rc.1.20370.4">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha>
|
||||
<Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.HostFactoryResolver.Sources" Version="5.0.0-preview.8.20361.2">
|
||||
<Dependency Name="Microsoft.Extensions.HostFactoryResolver.Sources" Version="5.0.0-rc.1.20370.4">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha>
|
||||
<Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Hosting.Abstractions" Version="5.0.0-preview.8.20361.2">
|
||||
<Dependency Name="Microsoft.Extensions.Hosting.Abstractions" Version="5.0.0-rc.1.20370.4">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha>
|
||||
<Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Hosting" Version="5.0.0-preview.8.20361.2">
|
||||
<Dependency Name="Microsoft.Extensions.Hosting" Version="5.0.0-rc.1.20370.4">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha>
|
||||
<Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Http" Version="5.0.0-preview.8.20361.2">
|
||||
<Dependency Name="Microsoft.Extensions.Http" Version="5.0.0-rc.1.20370.4">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha>
|
||||
<Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Logging.Abstractions" Version="5.0.0-preview.8.20361.2">
|
||||
<Dependency Name="Microsoft.Extensions.Logging.Abstractions" Version="5.0.0-rc.1.20370.4">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha>
|
||||
<Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Logging.Configuration" Version="5.0.0-preview.8.20361.2">
|
||||
<Dependency Name="Microsoft.Extensions.Logging.Configuration" Version="5.0.0-rc.1.20370.4">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha>
|
||||
<Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Logging.Console" Version="5.0.0-preview.8.20361.2">
|
||||
<Dependency Name="Microsoft.Extensions.Logging.Console" Version="5.0.0-rc.1.20370.4">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha>
|
||||
<Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Logging.Debug" Version="5.0.0-preview.8.20361.2">
|
||||
<Dependency Name="Microsoft.Extensions.Logging.Debug" Version="5.0.0-rc.1.20370.4">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha>
|
||||
<Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Logging.EventSource" Version="5.0.0-preview.8.20361.2">
|
||||
<Dependency Name="Microsoft.Extensions.Logging.EventSource" Version="5.0.0-rc.1.20370.4">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha>
|
||||
<Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Logging.EventLog" Version="5.0.0-preview.8.20361.2">
|
||||
<Dependency Name="Microsoft.Extensions.Logging.EventLog" Version="5.0.0-rc.1.20370.4">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha>
|
||||
<Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Logging.TraceSource" Version="5.0.0-preview.8.20361.2">
|
||||
<Dependency Name="Microsoft.Extensions.Logging.TraceSource" Version="5.0.0-rc.1.20370.4">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha>
|
||||
<Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Logging" Version="5.0.0-preview.8.20361.2">
|
||||
<Dependency Name="Microsoft.Extensions.Logging" Version="5.0.0-rc.1.20370.4">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha>
|
||||
<Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Options.ConfigurationExtensions" Version="5.0.0-preview.8.20361.2">
|
||||
<Dependency Name="Microsoft.Extensions.Options.ConfigurationExtensions" Version="5.0.0-rc.1.20370.4">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha>
|
||||
<Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Options.DataAnnotations" Version="5.0.0-preview.8.20361.2">
|
||||
<Dependency Name="Microsoft.Extensions.Options.DataAnnotations" Version="5.0.0-rc.1.20370.4">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha>
|
||||
<Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Options" Version="5.0.0-preview.8.20361.2">
|
||||
<Dependency Name="Microsoft.Extensions.Options" Version="5.0.0-rc.1.20370.4">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha>
|
||||
<Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Primitives" Version="5.0.0-preview.8.20361.2">
|
||||
<Dependency Name="Microsoft.Extensions.Primitives" Version="5.0.0-rc.1.20370.4">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha>
|
||||
<Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Internal.Transport" Version="5.0.0-preview.8.20361.2">
|
||||
<Dependency Name="Microsoft.Extensions.Internal.Transport" Version="5.0.0-rc.1.20370.4">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha>
|
||||
<Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Win32.Registry" Version="5.0.0-preview.8.20361.2">
|
||||
<Dependency Name="Microsoft.Win32.Registry" Version="5.0.0-rc.1.20370.4">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha>
|
||||
<Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Win32.SystemEvents" Version="5.0.0-preview.8.20361.2">
|
||||
<Dependency Name="Microsoft.Win32.SystemEvents" Version="5.0.0-rc.1.20370.4">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha>
|
||||
<Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="System.ComponentModel.Annotations" Version="5.0.0-preview.8.20361.2">
|
||||
<Dependency Name="System.ComponentModel.Annotations" Version="5.0.0-rc.1.20370.4">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha>
|
||||
<Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="System.Diagnostics.DiagnosticSource" Version="5.0.0-preview.8.20361.2">
|
||||
<Dependency Name="System.Diagnostics.DiagnosticSource" Version="5.0.0-rc.1.20370.4">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha>
|
||||
<Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="System.Diagnostics.EventLog" Version="5.0.0-preview.8.20361.2">
|
||||
<Dependency Name="System.Diagnostics.EventLog" Version="5.0.0-rc.1.20370.4">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha>
|
||||
<Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="System.Drawing.Common" Version="5.0.0-preview.8.20361.2">
|
||||
<Dependency Name="System.Drawing.Common" Version="5.0.0-rc.1.20370.4">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha>
|
||||
<Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="System.IO.Pipelines" Version="5.0.0-preview.8.20361.2">
|
||||
<Dependency Name="System.IO.Pipelines" Version="5.0.0-rc.1.20370.4">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha>
|
||||
<Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="System.Net.Http.Json" Version="5.0.0-preview.8.20361.2">
|
||||
<Dependency Name="System.Net.Http.Json" Version="5.0.0-rc.1.20370.4">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha>
|
||||
<Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="System.Net.Http.WinHttpHandler" Version="5.0.0-preview.8.20361.2">
|
||||
<Dependency Name="System.Net.Http.WinHttpHandler" Version="5.0.0-rc.1.20370.4">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha>
|
||||
<Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="System.Net.WebSockets.WebSocketProtocol" Version="5.0.0-preview.8.20361.2">
|
||||
<Dependency Name="System.Net.WebSockets.WebSocketProtocol" Version="5.0.0-rc.1.20370.4">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha>
|
||||
<Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="System.Reflection.Metadata" Version="5.0.0-preview.8.20361.2">
|
||||
<Dependency Name="System.Reflection.Metadata" Version="5.0.0-rc.1.20370.4">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha>
|
||||
<Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="System.Resources.Extensions" Version="5.0.0-preview.8.20361.2">
|
||||
<Dependency Name="System.Resources.Extensions" Version="5.0.0-rc.1.20370.4">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha>
|
||||
<Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="System.Runtime.CompilerServices.Unsafe" Version="5.0.0-preview.8.20361.2">
|
||||
<Dependency Name="System.Runtime.CompilerServices.Unsafe" Version="5.0.0-rc.1.20370.4">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha>
|
||||
<Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="System.Security.Cryptography.Cng" Version="5.0.0-preview.8.20361.2">
|
||||
<!-- System.Security.AccessControl should only be referenced in Dependencies.props and RTMVersions.csproj. -->
|
||||
<Dependency Name="System.Security.AccessControl" Version="5.0.0-rc.1.20370.4">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha>
|
||||
<Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="System.Security.Cryptography.Pkcs" Version="5.0.0-preview.8.20361.2">
|
||||
<Dependency Name="System.Security.Cryptography.Cng" Version="5.0.0-rc.1.20370.4">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha>
|
||||
<Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="System.Security.Cryptography.Xml" Version="5.0.0-preview.8.20361.2">
|
||||
<Dependency Name="System.Security.Cryptography.Pkcs" Version="5.0.0-rc.1.20370.4">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha>
|
||||
<Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="System.Security.Permissions" Version="5.0.0-preview.8.20361.2">
|
||||
<Dependency Name="System.Security.Cryptography.Xml" Version="5.0.0-rc.1.20370.4">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha>
|
||||
<Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="System.Security.Principal.Windows" Version="5.0.0-preview.8.20361.2">
|
||||
<Dependency Name="System.Security.Permissions" Version="5.0.0-rc.1.20370.4">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha>
|
||||
<Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="System.ServiceProcess.ServiceController" Version="5.0.0-preview.8.20361.2">
|
||||
<Dependency Name="System.Security.Principal.Windows" Version="5.0.0-rc.1.20370.4">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha>
|
||||
<Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="System.Text.Encodings.Web" Version="5.0.0-preview.8.20361.2">
|
||||
<Dependency Name="System.ServiceProcess.ServiceController" Version="5.0.0-rc.1.20370.4">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha>
|
||||
<Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="System.Text.Json" Version="5.0.0-preview.8.20361.2">
|
||||
<Dependency Name="System.Text.Encodings.Web" Version="5.0.0-rc.1.20370.4">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha>
|
||||
<Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="System.Threading.Channels" Version="5.0.0-preview.8.20361.2">
|
||||
<Dependency Name="System.Text.Json" Version="5.0.0-rc.1.20370.4">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha>
|
||||
<Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="System.Windows.Extensions" Version="5.0.0-preview.8.20361.2">
|
||||
<Dependency Name="System.Threading.Channels" Version="5.0.0-rc.1.20370.4">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha>
|
||||
<Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.DependencyModel" Version="5.0.0-preview.8.20361.2">
|
||||
<Dependency Name="System.Windows.Extensions" Version="5.0.0-rc.1.20370.4">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha>
|
||||
<Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.NETCore.App.Ref" Version="5.0.0-preview.8.20361.2">
|
||||
<Dependency Name="Microsoft.Extensions.DependencyModel" Version="5.0.0-rc.1.20370.4">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha>
|
||||
<Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.NETCore.App.Ref" Version="5.0.0-rc.1.20370.4">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</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.8.20361.2">
|
||||
<Dependency Name="Microsoft.NETCore.App.Runtime.win-x64" Version="5.0.0-rc.1.20370.4">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha>
|
||||
<Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.NETCore.App.Internal" Version="5.0.0-preview.8.20361.2">
|
||||
<Dependency Name="Microsoft.NETCore.App.Internal" Version="5.0.0-rc.1.20370.4">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha>
|
||||
<Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</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.8.20361.2">
|
||||
<Dependency Name="Microsoft.NETCore.Platforms" Version="5.0.0-rc.1.20370.4">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha>
|
||||
<Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.DotNet.Arcade.Sdk" Version="5.0.0-beta.20377.2">
|
||||
<Dependency Name="Microsoft.DotNet.Arcade.Sdk" Version="5.0.0-beta.20374.1">
|
||||
<Uri>https://github.com/dotnet/arcade</Uri>
|
||||
<Sha>22d6355c4f3c9ac00b0e3abf9d85f2fb07e4787b</Sha>
|
||||
<Sha>f6192d1e284a08ac05041d05fa6e60dec74b24f5</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.DotNet.Helix.Sdk" Version="5.0.0-beta.20364.3">
|
||||
<Dependency Name="Microsoft.DotNet.Helix.Sdk" Version="5.0.0-beta.20374.1">
|
||||
<Uri>https://github.com/dotnet/arcade</Uri>
|
||||
<Sha>ff5d4b6c8dbdaeacb6e6159d3f8185118dffd915</Sha>
|
||||
<Sha>f6192d1e284a08ac05041d05fa6e60dec74b24f5</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Net.Compilers.Toolset" Version="3.8.0-1.20361.1">
|
||||
<Dependency Name="Microsoft.Net.Compilers.Toolset" Version="3.8.0-2.20379.3">
|
||||
<Uri>https://github.com/dotnet/roslyn</Uri>
|
||||
<Sha>f24d2c5c98211908ab90d6f1f42e7592411d6058</Sha>
|
||||
<Sha>7238563e5c051535770a9266c45d925012ad2b76</Sha>
|
||||
</Dependency>
|
||||
</ToolsetDependencies>
|
||||
</Dependencies>
|
||||
|
|
|
|||
|
|
@ -9,14 +9,14 @@
|
|||
<AspNetCoreMajorVersion>5</AspNetCoreMajorVersion>
|
||||
<AspNetCoreMinorVersion>0</AspNetCoreMinorVersion>
|
||||
<AspNetCorePatchVersion>0</AspNetCorePatchVersion>
|
||||
<PreReleaseVersionIteration>8</PreReleaseVersionIteration>
|
||||
<PreReleaseVersionIteration>1</PreReleaseVersionIteration>
|
||||
<!--
|
||||
When StabilizePackageVersion is set to 'true', this branch will produce stable outputs for 'Shipping' packages
|
||||
-->
|
||||
<StabilizePackageVersion Condition="'$(StabilizePackageVersion)' == ''">false</StabilizePackageVersion>
|
||||
<DotNetFinalVersionKind Condition="'$(StabilizePackageVersion)' == 'true'">release</DotNetFinalVersionKind>
|
||||
<PreReleaseVersionLabel>preview</PreReleaseVersionLabel>
|
||||
<PreReleaseBrandingLabel>Preview $(PreReleaseVersionIteration)</PreReleaseBrandingLabel>
|
||||
<PreReleaseVersionLabel>rc</PreReleaseVersionLabel>
|
||||
<PreReleaseBrandingLabel>RC $(PreReleaseVersionIteration)</PreReleaseBrandingLabel>
|
||||
<IncludePreReleaseLabelInPackageVersion>true</IncludePreReleaseLabelInPackageVersion>
|
||||
<IncludePreReleaseLabelInPackageVersion Condition=" '$(DotNetFinalVersionKind)' == 'release' ">false</IncludePreReleaseLabelInPackageVersion>
|
||||
<AspNetCoreMajorMinorVersion>$(AspNetCoreMajorVersion).$(AspNetCoreMinorVersion)</AspNetCoreMajorMinorVersion>
|
||||
|
|
@ -62,82 +62,84 @@
|
|||
-->
|
||||
<PropertyGroup Label="Automated">
|
||||
<!-- Packages from dotnet/roslyn -->
|
||||
<MicrosoftNetCompilersToolsetPackageVersion>3.8.0-1.20361.1</MicrosoftNetCompilersToolsetPackageVersion>
|
||||
<MicrosoftNetCompilersToolsetPackageVersion>3.8.0-2.20379.3</MicrosoftNetCompilersToolsetPackageVersion>
|
||||
<!-- Packages from dotnet/runtime -->
|
||||
<MicrosoftExtensionsDependencyModelPackageVersion>5.0.0-preview.8.20361.2</MicrosoftExtensionsDependencyModelPackageVersion>
|
||||
<MicrosoftNETCoreAppInternalPackageVersion>5.0.0-preview.8.20361.2</MicrosoftNETCoreAppInternalPackageVersion>
|
||||
<MicrosoftNETCoreAppRefPackageVersion>5.0.0-preview.8.20361.2</MicrosoftNETCoreAppRefPackageVersion>
|
||||
<MicrosoftNETCoreAppRuntimewinx64PackageVersion>5.0.0-preview.8.20361.2</MicrosoftNETCoreAppRuntimewinx64PackageVersion>
|
||||
<MicrosoftWin32RegistryPackageVersion>5.0.0-preview.8.20361.2</MicrosoftWin32RegistryPackageVersion>
|
||||
<MicrosoftWin32SystemEventsPackageVersion>5.0.0-preview.8.20361.2</MicrosoftWin32SystemEventsPackageVersion>
|
||||
<MicrosoftExtensionsCachingAbstractionsPackageVersion>5.0.0-preview.8.20361.2</MicrosoftExtensionsCachingAbstractionsPackageVersion>
|
||||
<MicrosoftExtensionsCachingMemoryPackageVersion>5.0.0-preview.8.20361.2</MicrosoftExtensionsCachingMemoryPackageVersion>
|
||||
<MicrosoftExtensionsConfigurationAbstractionsPackageVersion>5.0.0-preview.8.20361.2</MicrosoftExtensionsConfigurationAbstractionsPackageVersion>
|
||||
<MicrosoftExtensionsConfigurationBinderPackageVersion>5.0.0-preview.8.20361.2</MicrosoftExtensionsConfigurationBinderPackageVersion>
|
||||
<MicrosoftExtensionsConfigurationCommandLinePackageVersion>5.0.0-preview.8.20361.2</MicrosoftExtensionsConfigurationCommandLinePackageVersion>
|
||||
<MicrosoftExtensionsConfigurationEnvironmentVariablesPackageVersion>5.0.0-preview.8.20361.2</MicrosoftExtensionsConfigurationEnvironmentVariablesPackageVersion>
|
||||
<MicrosoftExtensionsConfigurationFileExtensionsPackageVersion>5.0.0-preview.8.20361.2</MicrosoftExtensionsConfigurationFileExtensionsPackageVersion>
|
||||
<MicrosoftExtensionsConfigurationIniPackageVersion>5.0.0-preview.8.20361.2</MicrosoftExtensionsConfigurationIniPackageVersion>
|
||||
<MicrosoftExtensionsConfigurationJsonPackageVersion>5.0.0-preview.8.20361.2</MicrosoftExtensionsConfigurationJsonPackageVersion>
|
||||
<MicrosoftExtensionsConfigurationPackageVersion>5.0.0-preview.8.20361.2</MicrosoftExtensionsConfigurationPackageVersion>
|
||||
<MicrosoftExtensionsConfigurationUserSecretsPackageVersion>5.0.0-preview.8.20361.2</MicrosoftExtensionsConfigurationUserSecretsPackageVersion>
|
||||
<MicrosoftExtensionsConfigurationXmlPackageVersion>5.0.0-preview.8.20361.2</MicrosoftExtensionsConfigurationXmlPackageVersion>
|
||||
<MicrosoftExtensionsDependencyInjectionAbstractionsPackageVersion>5.0.0-preview.8.20361.2</MicrosoftExtensionsDependencyInjectionAbstractionsPackageVersion>
|
||||
<MicrosoftExtensionsDependencyInjectionPackageVersion>5.0.0-preview.8.20361.2</MicrosoftExtensionsDependencyInjectionPackageVersion>
|
||||
<MicrosoftExtensionsFileProvidersAbstractionsPackageVersion>5.0.0-preview.8.20361.2</MicrosoftExtensionsFileProvidersAbstractionsPackageVersion>
|
||||
<MicrosoftExtensionsFileProvidersCompositePackageVersion>5.0.0-preview.8.20361.2</MicrosoftExtensionsFileProvidersCompositePackageVersion>
|
||||
<MicrosoftExtensionsFileProvidersPhysicalPackageVersion>5.0.0-preview.8.20361.2</MicrosoftExtensionsFileProvidersPhysicalPackageVersion>
|
||||
<MicrosoftExtensionsFileSystemGlobbingPackageVersion>5.0.0-preview.8.20361.2</MicrosoftExtensionsFileSystemGlobbingPackageVersion>
|
||||
<MicrosoftExtensionsHostFactoryResolverSourcesPackageVersion>5.0.0-preview.8.20361.2</MicrosoftExtensionsHostFactoryResolverSourcesPackageVersion>
|
||||
<MicrosoftExtensionsHostingAbstractionsPackageVersion>5.0.0-preview.8.20361.2</MicrosoftExtensionsHostingAbstractionsPackageVersion>
|
||||
<MicrosoftExtensionsHostingPackageVersion>5.0.0-preview.8.20361.2</MicrosoftExtensionsHostingPackageVersion>
|
||||
<MicrosoftExtensionsHttpPackageVersion>5.0.0-preview.8.20361.2</MicrosoftExtensionsHttpPackageVersion>
|
||||
<MicrosoftExtensionsLoggingAbstractionsPackageVersion>5.0.0-preview.8.20361.2</MicrosoftExtensionsLoggingAbstractionsPackageVersion>
|
||||
<MicrosoftExtensionsLoggingConfigurationPackageVersion>5.0.0-preview.8.20361.2</MicrosoftExtensionsLoggingConfigurationPackageVersion>
|
||||
<MicrosoftExtensionsLoggingConsolePackageVersion>5.0.0-preview.8.20361.2</MicrosoftExtensionsLoggingConsolePackageVersion>
|
||||
<MicrosoftExtensionsLoggingDebugPackageVersion>5.0.0-preview.8.20361.2</MicrosoftExtensionsLoggingDebugPackageVersion>
|
||||
<MicrosoftExtensionsLoggingEventSourcePackageVersion>5.0.0-preview.8.20361.2</MicrosoftExtensionsLoggingEventSourcePackageVersion>
|
||||
<MicrosoftExtensionsLoggingEventLogPackageVersion>5.0.0-preview.8.20361.2</MicrosoftExtensionsLoggingEventLogPackageVersion>
|
||||
<MicrosoftExtensionsLoggingPackageVersion>5.0.0-preview.8.20361.2</MicrosoftExtensionsLoggingPackageVersion>
|
||||
<MicrosoftExtensionsLoggingTraceSourcePackageVersion>5.0.0-preview.8.20361.2</MicrosoftExtensionsLoggingTraceSourcePackageVersion>
|
||||
<MicrosoftExtensionsOptionsConfigurationExtensionsPackageVersion>5.0.0-preview.8.20361.2</MicrosoftExtensionsOptionsConfigurationExtensionsPackageVersion>
|
||||
<MicrosoftExtensionsOptionsDataAnnotationsPackageVersion>5.0.0-preview.8.20361.2</MicrosoftExtensionsOptionsDataAnnotationsPackageVersion>
|
||||
<MicrosoftExtensionsOptionsPackageVersion>5.0.0-preview.8.20361.2</MicrosoftExtensionsOptionsPackageVersion>
|
||||
<MicrosoftExtensionsPrimitivesPackageVersion>5.0.0-preview.8.20361.2</MicrosoftExtensionsPrimitivesPackageVersion>
|
||||
<MicrosoftExtensionsInternalTransportPackageVersion>5.0.0-preview.8.20361.2</MicrosoftExtensionsInternalTransportPackageVersion>
|
||||
<SystemComponentModelAnnotationsPackageVersion>5.0.0-preview.8.20361.2</SystemComponentModelAnnotationsPackageVersion>
|
||||
<SystemDiagnosticsDiagnosticSourcePackageVersion>5.0.0-preview.8.20361.2</SystemDiagnosticsDiagnosticSourcePackageVersion>
|
||||
<SystemDiagnosticsEventLogPackageVersion>5.0.0-preview.8.20361.2</SystemDiagnosticsEventLogPackageVersion>
|
||||
<SystemDrawingCommonPackageVersion>5.0.0-preview.8.20361.2</SystemDrawingCommonPackageVersion>
|
||||
<SystemIOPipelinesPackageVersion>5.0.0-preview.8.20361.2</SystemIOPipelinesPackageVersion>
|
||||
<SystemNetHttpJsonPackageVersion>5.0.0-preview.8.20361.2</SystemNetHttpJsonPackageVersion>
|
||||
<SystemNetHttpWinHttpHandlerPackageVersion>5.0.0-preview.8.20361.2</SystemNetHttpWinHttpHandlerPackageVersion>
|
||||
<SystemNetWebSocketsWebSocketProtocolPackageVersion>5.0.0-preview.8.20361.2</SystemNetWebSocketsWebSocketProtocolPackageVersion>
|
||||
<SystemReflectionMetadataPackageVersion>5.0.0-preview.8.20361.2</SystemReflectionMetadataPackageVersion>
|
||||
<SystemResourcesExtensionsPackageVersion>5.0.0-preview.8.20361.2</SystemResourcesExtensionsPackageVersion>
|
||||
<SystemRuntimeCompilerServicesUnsafePackageVersion>5.0.0-preview.8.20361.2</SystemRuntimeCompilerServicesUnsafePackageVersion>
|
||||
<SystemSecurityCryptographyCngPackageVersion>5.0.0-preview.8.20361.2</SystemSecurityCryptographyCngPackageVersion>
|
||||
<SystemSecurityCryptographyPkcsPackageVersion>5.0.0-preview.8.20361.2</SystemSecurityCryptographyPkcsPackageVersion>
|
||||
<SystemSecurityCryptographyXmlPackageVersion>5.0.0-preview.8.20361.2</SystemSecurityCryptographyXmlPackageVersion>
|
||||
<SystemSecurityPermissionsPackageVersion>5.0.0-preview.8.20361.2</SystemSecurityPermissionsPackageVersion>
|
||||
<SystemSecurityPrincipalWindowsPackageVersion>5.0.0-preview.8.20361.2</SystemSecurityPrincipalWindowsPackageVersion>
|
||||
<SystemServiceProcessServiceControllerPackageVersion>5.0.0-preview.8.20361.2</SystemServiceProcessServiceControllerPackageVersion>
|
||||
<SystemTextEncodingsWebPackageVersion>5.0.0-preview.8.20361.2</SystemTextEncodingsWebPackageVersion>
|
||||
<SystemTextJsonPackageVersion>5.0.0-preview.8.20361.2</SystemTextJsonPackageVersion>
|
||||
<SystemThreadingChannelsPackageVersion>5.0.0-preview.8.20361.2</SystemThreadingChannelsPackageVersion>
|
||||
<SystemWindowsExtensionsPackageVersion>5.0.0-preview.8.20361.2</SystemWindowsExtensionsPackageVersion>
|
||||
<MicrosoftExtensionsDependencyModelPackageVersion>5.0.0-rc.1.20370.4</MicrosoftExtensionsDependencyModelPackageVersion>
|
||||
<MicrosoftNETCoreAppInternalPackageVersion>5.0.0-rc.1.20370.4</MicrosoftNETCoreAppInternalPackageVersion>
|
||||
<MicrosoftNETCoreAppRefPackageVersion>5.0.0-rc.1.20370.4</MicrosoftNETCoreAppRefPackageVersion>
|
||||
<MicrosoftNETCoreAppRuntimewinx64PackageVersion>5.0.0-rc.1.20370.4</MicrosoftNETCoreAppRuntimewinx64PackageVersion>
|
||||
<MicrosoftWin32RegistryPackageVersion>5.0.0-rc.1.20370.4</MicrosoftWin32RegistryPackageVersion>
|
||||
<MicrosoftWin32SystemEventsPackageVersion>5.0.0-rc.1.20370.4</MicrosoftWin32SystemEventsPackageVersion>
|
||||
<MicrosoftExtensionsCachingAbstractionsPackageVersion>5.0.0-rc.1.20370.4</MicrosoftExtensionsCachingAbstractionsPackageVersion>
|
||||
<MicrosoftExtensionsCachingMemoryPackageVersion>5.0.0-rc.1.20370.4</MicrosoftExtensionsCachingMemoryPackageVersion>
|
||||
<MicrosoftExtensionsConfigurationAbstractionsPackageVersion>5.0.0-rc.1.20370.4</MicrosoftExtensionsConfigurationAbstractionsPackageVersion>
|
||||
<MicrosoftExtensionsConfigurationBinderPackageVersion>5.0.0-rc.1.20370.4</MicrosoftExtensionsConfigurationBinderPackageVersion>
|
||||
<MicrosoftExtensionsConfigurationCommandLinePackageVersion>5.0.0-rc.1.20370.4</MicrosoftExtensionsConfigurationCommandLinePackageVersion>
|
||||
<MicrosoftExtensionsConfigurationEnvironmentVariablesPackageVersion>5.0.0-rc.1.20370.4</MicrosoftExtensionsConfigurationEnvironmentVariablesPackageVersion>
|
||||
<MicrosoftExtensionsConfigurationFileExtensionsPackageVersion>5.0.0-rc.1.20370.4</MicrosoftExtensionsConfigurationFileExtensionsPackageVersion>
|
||||
<MicrosoftExtensionsConfigurationIniPackageVersion>5.0.0-rc.1.20370.4</MicrosoftExtensionsConfigurationIniPackageVersion>
|
||||
<MicrosoftExtensionsConfigurationJsonPackageVersion>5.0.0-rc.1.20370.4</MicrosoftExtensionsConfigurationJsonPackageVersion>
|
||||
<MicrosoftExtensionsConfigurationPackageVersion>5.0.0-rc.1.20370.4</MicrosoftExtensionsConfigurationPackageVersion>
|
||||
<MicrosoftExtensionsConfigurationUserSecretsPackageVersion>5.0.0-rc.1.20370.4</MicrosoftExtensionsConfigurationUserSecretsPackageVersion>
|
||||
<MicrosoftExtensionsConfigurationXmlPackageVersion>5.0.0-rc.1.20370.4</MicrosoftExtensionsConfigurationXmlPackageVersion>
|
||||
<MicrosoftExtensionsDependencyInjectionAbstractionsPackageVersion>5.0.0-rc.1.20370.4</MicrosoftExtensionsDependencyInjectionAbstractionsPackageVersion>
|
||||
<MicrosoftExtensionsDependencyInjectionPackageVersion>5.0.0-rc.1.20370.4</MicrosoftExtensionsDependencyInjectionPackageVersion>
|
||||
<MicrosoftExtensionsFileProvidersAbstractionsPackageVersion>5.0.0-rc.1.20370.4</MicrosoftExtensionsFileProvidersAbstractionsPackageVersion>
|
||||
<MicrosoftExtensionsFileProvidersCompositePackageVersion>5.0.0-rc.1.20370.4</MicrosoftExtensionsFileProvidersCompositePackageVersion>
|
||||
<MicrosoftExtensionsFileProvidersPhysicalPackageVersion>5.0.0-rc.1.20370.4</MicrosoftExtensionsFileProvidersPhysicalPackageVersion>
|
||||
<MicrosoftExtensionsFileSystemGlobbingPackageVersion>5.0.0-rc.1.20370.4</MicrosoftExtensionsFileSystemGlobbingPackageVersion>
|
||||
<MicrosoftExtensionsHostFactoryResolverSourcesPackageVersion>5.0.0-rc.1.20370.4</MicrosoftExtensionsHostFactoryResolverSourcesPackageVersion>
|
||||
<MicrosoftExtensionsHostingAbstractionsPackageVersion>5.0.0-rc.1.20370.4</MicrosoftExtensionsHostingAbstractionsPackageVersion>
|
||||
<MicrosoftExtensionsHostingPackageVersion>5.0.0-rc.1.20370.4</MicrosoftExtensionsHostingPackageVersion>
|
||||
<MicrosoftExtensionsHttpPackageVersion>5.0.0-rc.1.20370.4</MicrosoftExtensionsHttpPackageVersion>
|
||||
<MicrosoftExtensionsLoggingAbstractionsPackageVersion>5.0.0-rc.1.20370.4</MicrosoftExtensionsLoggingAbstractionsPackageVersion>
|
||||
<MicrosoftExtensionsLoggingConfigurationPackageVersion>5.0.0-rc.1.20370.4</MicrosoftExtensionsLoggingConfigurationPackageVersion>
|
||||
<MicrosoftExtensionsLoggingConsolePackageVersion>5.0.0-rc.1.20370.4</MicrosoftExtensionsLoggingConsolePackageVersion>
|
||||
<MicrosoftExtensionsLoggingDebugPackageVersion>5.0.0-rc.1.20370.4</MicrosoftExtensionsLoggingDebugPackageVersion>
|
||||
<MicrosoftExtensionsLoggingEventSourcePackageVersion>5.0.0-rc.1.20370.4</MicrosoftExtensionsLoggingEventSourcePackageVersion>
|
||||
<MicrosoftExtensionsLoggingEventLogPackageVersion>5.0.0-rc.1.20370.4</MicrosoftExtensionsLoggingEventLogPackageVersion>
|
||||
<MicrosoftExtensionsLoggingPackageVersion>5.0.0-rc.1.20370.4</MicrosoftExtensionsLoggingPackageVersion>
|
||||
<MicrosoftExtensionsLoggingTraceSourcePackageVersion>5.0.0-rc.1.20370.4</MicrosoftExtensionsLoggingTraceSourcePackageVersion>
|
||||
<MicrosoftExtensionsOptionsConfigurationExtensionsPackageVersion>5.0.0-rc.1.20370.4</MicrosoftExtensionsOptionsConfigurationExtensionsPackageVersion>
|
||||
<MicrosoftExtensionsOptionsDataAnnotationsPackageVersion>5.0.0-rc.1.20370.4</MicrosoftExtensionsOptionsDataAnnotationsPackageVersion>
|
||||
<MicrosoftExtensionsOptionsPackageVersion>5.0.0-rc.1.20370.4</MicrosoftExtensionsOptionsPackageVersion>
|
||||
<MicrosoftExtensionsPrimitivesPackageVersion>5.0.0-rc.1.20370.4</MicrosoftExtensionsPrimitivesPackageVersion>
|
||||
<MicrosoftExtensionsInternalTransportPackageVersion>5.0.0-rc.1.20370.4</MicrosoftExtensionsInternalTransportPackageVersion>
|
||||
<SystemComponentModelAnnotationsPackageVersion>5.0.0-rc.1.20370.4</SystemComponentModelAnnotationsPackageVersion>
|
||||
<SystemDiagnosticsDiagnosticSourcePackageVersion>5.0.0-rc.1.20370.4</SystemDiagnosticsDiagnosticSourcePackageVersion>
|
||||
<SystemDiagnosticsEventLogPackageVersion>5.0.0-rc.1.20370.4</SystemDiagnosticsEventLogPackageVersion>
|
||||
<SystemDrawingCommonPackageVersion>5.0.0-rc.1.20370.4</SystemDrawingCommonPackageVersion>
|
||||
<SystemIOPipelinesPackageVersion>5.0.0-rc.1.20370.4</SystemIOPipelinesPackageVersion>
|
||||
<SystemNetHttpJsonPackageVersion>5.0.0-rc.1.20370.4</SystemNetHttpJsonPackageVersion>
|
||||
<SystemNetHttpWinHttpHandlerPackageVersion>5.0.0-rc.1.20370.4</SystemNetHttpWinHttpHandlerPackageVersion>
|
||||
<SystemNetWebSocketsWebSocketProtocolPackageVersion>5.0.0-rc.1.20370.4</SystemNetWebSocketsWebSocketProtocolPackageVersion>
|
||||
<SystemReflectionMetadataPackageVersion>5.0.0-rc.1.20370.4</SystemReflectionMetadataPackageVersion>
|
||||
<SystemResourcesExtensionsPackageVersion>5.0.0-rc.1.20370.4</SystemResourcesExtensionsPackageVersion>
|
||||
<SystemRuntimeCompilerServicesUnsafePackageVersion>5.0.0-rc.1.20370.4</SystemRuntimeCompilerServicesUnsafePackageVersion>
|
||||
<!-- System.Security.AccessControl should only be referenced in Dependencies.props and RTMVersions.csproj. -->
|
||||
<SystemSecurityAccessControlPackageVersion>5.0.0-rc.1.20370.4</SystemSecurityAccessControlPackageVersion>
|
||||
<SystemSecurityCryptographyCngPackageVersion>5.0.0-rc.1.20370.4</SystemSecurityCryptographyCngPackageVersion>
|
||||
<SystemSecurityCryptographyPkcsPackageVersion>5.0.0-rc.1.20370.4</SystemSecurityCryptographyPkcsPackageVersion>
|
||||
<SystemSecurityCryptographyXmlPackageVersion>5.0.0-rc.1.20370.4</SystemSecurityCryptographyXmlPackageVersion>
|
||||
<SystemSecurityPermissionsPackageVersion>5.0.0-rc.1.20370.4</SystemSecurityPermissionsPackageVersion>
|
||||
<SystemSecurityPrincipalWindowsPackageVersion>5.0.0-rc.1.20370.4</SystemSecurityPrincipalWindowsPackageVersion>
|
||||
<SystemServiceProcessServiceControllerPackageVersion>5.0.0-rc.1.20370.4</SystemServiceProcessServiceControllerPackageVersion>
|
||||
<SystemTextEncodingsWebPackageVersion>5.0.0-rc.1.20370.4</SystemTextEncodingsWebPackageVersion>
|
||||
<SystemTextJsonPackageVersion>5.0.0-rc.1.20370.4</SystemTextJsonPackageVersion>
|
||||
<SystemThreadingChannelsPackageVersion>5.0.0-rc.1.20370.4</SystemThreadingChannelsPackageVersion>
|
||||
<SystemWindowsExtensionsPackageVersion>5.0.0-rc.1.20370.4</SystemWindowsExtensionsPackageVersion>
|
||||
<!-- Only listed explicitly to workaround https://github.com/dotnet/cli/issues/10528 -->
|
||||
<MicrosoftNETCorePlatformsPackageVersion>5.0.0-preview.8.20361.2</MicrosoftNETCorePlatformsPackageVersion>
|
||||
<MicrosoftNETCorePlatformsPackageVersion>5.0.0-rc.1.20370.4</MicrosoftNETCorePlatformsPackageVersion>
|
||||
<!-- Packages from dotnet/blazor -->
|
||||
<MicrosoftAspNetCoreComponentsWebAssemblyRuntimePackageVersion>3.2.0</MicrosoftAspNetCoreComponentsWebAssemblyRuntimePackageVersion>
|
||||
<!-- Packages from dotnet/efcore -->
|
||||
<dotnetefPackageVersion>5.0.0-preview.8.20360.8</dotnetefPackageVersion>
|
||||
<MicrosoftEntityFrameworkCoreInMemoryPackageVersion>5.0.0-preview.8.20360.8</MicrosoftEntityFrameworkCoreInMemoryPackageVersion>
|
||||
<MicrosoftEntityFrameworkCoreRelationalPackageVersion>5.0.0-preview.8.20360.8</MicrosoftEntityFrameworkCoreRelationalPackageVersion>
|
||||
<MicrosoftEntityFrameworkCoreSqlitePackageVersion>5.0.0-preview.8.20360.8</MicrosoftEntityFrameworkCoreSqlitePackageVersion>
|
||||
<MicrosoftEntityFrameworkCoreSqlServerPackageVersion>5.0.0-preview.8.20360.8</MicrosoftEntityFrameworkCoreSqlServerPackageVersion>
|
||||
<MicrosoftEntityFrameworkCoreToolsPackageVersion>5.0.0-preview.8.20360.8</MicrosoftEntityFrameworkCoreToolsPackageVersion>
|
||||
<MicrosoftEntityFrameworkCorePackageVersion>5.0.0-preview.8.20360.8</MicrosoftEntityFrameworkCorePackageVersion>
|
||||
<dotnetefPackageVersion>5.0.0-rc.1.20372.13</dotnetefPackageVersion>
|
||||
<MicrosoftEntityFrameworkCoreInMemoryPackageVersion>5.0.0-rc.1.20372.13</MicrosoftEntityFrameworkCoreInMemoryPackageVersion>
|
||||
<MicrosoftEntityFrameworkCoreRelationalPackageVersion>5.0.0-rc.1.20372.13</MicrosoftEntityFrameworkCoreRelationalPackageVersion>
|
||||
<MicrosoftEntityFrameworkCoreSqlitePackageVersion>5.0.0-rc.1.20372.13</MicrosoftEntityFrameworkCoreSqlitePackageVersion>
|
||||
<MicrosoftEntityFrameworkCoreSqlServerPackageVersion>5.0.0-rc.1.20372.13</MicrosoftEntityFrameworkCoreSqlServerPackageVersion>
|
||||
<MicrosoftEntityFrameworkCoreToolsPackageVersion>5.0.0-rc.1.20372.13</MicrosoftEntityFrameworkCoreToolsPackageVersion>
|
||||
<MicrosoftEntityFrameworkCorePackageVersion>5.0.0-rc.1.20372.13</MicrosoftEntityFrameworkCorePackageVersion>
|
||||
</PropertyGroup>
|
||||
<!--
|
||||
|
||||
|
|
@ -155,7 +157,6 @@
|
|||
-->
|
||||
<MicrosoftNETCoreAppRuntimeVersion>$(MicrosoftNETCoreAppRuntimewinx64PackageVersion)</MicrosoftNETCoreAppRuntimeVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<!--
|
||||
We ship ref/ assemblies for runtime packages in our targeting targeting pack. When servicing that targeting pack,
|
||||
these assemblies must not change. Must also compile our assemblies against the initial ref/ assemblies for runtime
|
||||
|
|
@ -163,6 +164,14 @@
|
|||
Upshot is we need Major.Minor.0 runtime packages for compilation and the targeting pack and Major.Minor.Latest
|
||||
runtime packages for everything else. This is not an issue for assemblies available in Microsoft.NETCore.App.Ref or
|
||||
Microsoft.Extensions.Internal.Transport because it is next to impossible we would service those packages.
|
||||
|
||||
System.Security.AccessControl should only be referenced in Dependencies.props and RTMVersions.csproj. Because
|
||||
it's a transitive reference, we reship the ref/ assembly in Microsoft.AspNetCore.App.Ref. dotnet/runtime ships
|
||||
the implementation assemblies in Microsoft.NETCore.App.Runtime.* packages.
|
||||
|
||||
If testing this configuration prior to servicing, update the versions of dependencies too. E.g. change
|
||||
`$(SystemSecurityPrincipalWindowsV0PackageVersion)` if you change `$(SystemSecurityAccessControlV0PackageVersion)`
|
||||
because System.Security.AccessControl will otherwise be loadable. This should not be necessary in servicing.
|
||||
-->
|
||||
<PropertyGroup Condition=" '$(IsServicingBuild)' == 'true' ">
|
||||
<MicrosoftWin32RegistryV0PackageVersion>$(MicrosoftWin32RegistryPackageVersion.Split('.')[0]).$(MicrosoftWin32RegistryPackageVersion.Split('.')[1]).0</MicrosoftWin32RegistryV0PackageVersion>
|
||||
|
|
@ -178,7 +187,6 @@
|
|||
<SystemSecurityPrincipalWindowsV0PackageVersion>$(SystemSecurityPrincipalWindowsPackageVersion.Split('.')[0]).$(SystemSecurityPrincipalWindowsPackageVersion.Split('.')[1]).0</SystemSecurityPrincipalWindowsV0PackageVersion>
|
||||
<SystemWindowsExtensionsV0PackageVersion>$(SystemWindowsExtensionsPackageVersion.Split('.')[0]).$(SystemWindowsExtensionsPackageVersion.Split('.')[1]).0</SystemWindowsExtensionsV0PackageVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Label="Manual">
|
||||
<!-- DiagnosticAdapter package pinned temporarily until migrated/deprecated -->
|
||||
<MicrosoftExtensionsDiagnosticAdapterPackageVersion>5.0.0-preview.4.20180.4</MicrosoftExtensionsDiagnosticAdapterPackageVersion>
|
||||
|
|
@ -211,6 +219,7 @@
|
|||
<MicrosoftCodeAnalysisCommonPackageVersion>3.7.0-4.20351.7</MicrosoftCodeAnalysisCommonPackageVersion>
|
||||
<MicrosoftCodeAnalysisCSharpPackageVersion>3.7.0-4.20351.7</MicrosoftCodeAnalysisCSharpPackageVersion>
|
||||
<MicrosoftCodeAnalysisCSharpWorkspacesPackageVersion>3.7.0-4.20351.7</MicrosoftCodeAnalysisCSharpWorkspacesPackageVersion>
|
||||
<MicrosoftCodeAnalysisPublicApiAnalyzersPackageVersion>3.3.0-beta2.final</MicrosoftCodeAnalysisPublicApiAnalyzersPackageVersion>
|
||||
<MicrosoftCodeAnalysisFxCopAnalyzersPackageVersion>3.0.0</MicrosoftCodeAnalysisFxCopAnalyzersPackageVersion>
|
||||
<MicrosoftCssParserPackageVersion>1.0.0-20200708.1</MicrosoftCssParserPackageVersion>
|
||||
<MicrosoftIdentityModelClientsActiveDirectoryPackageVersion>3.19.8</MicrosoftIdentityModelClientsActiveDirectoryPackageVersion>
|
||||
|
|
@ -255,9 +264,6 @@
|
|||
<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. -->
|
||||
<Razor_NewtonsoftJsonPackageVersion>9.0.1</Razor_NewtonsoftJsonPackageVersion>
|
||||
<!-- End: STOP!!! Razor need to reference the version of JSON that our HOSTS support. -->
|
||||
<NSwagApiDescriptionClientPackageVersion>13.0.4</NSwagApiDescriptionClientPackageVersion>
|
||||
<SeleniumSupportPackageVersion>3.12.1</SeleniumSupportPackageVersion>
|
||||
<SeleniumWebDriverMicrosoftDriverPackageVersion>17.17134.0</SeleniumWebDriverMicrosoftDriverPackageVersion>
|
||||
|
|
|
|||
|
|
@ -127,29 +127,40 @@ endif()
|
|||
|
||||
# Specify link flags
|
||||
|
||||
function(add_toolchain_linker_flag Flag)
|
||||
set(Config "${ARGV1}")
|
||||
set(CONFIG_SUFFIX "")
|
||||
if (NOT Config STREQUAL "")
|
||||
set(CONFIG_SUFFIX "_${Config}")
|
||||
endif()
|
||||
set("CMAKE_EXE_LINKER_FLAGS${CONFIG_SUFFIX}" "${CMAKE_EXE_LINKER_FLAGS${CONFIG_SUFFIX}} ${Flag}" PARENT_SCOPE)
|
||||
set("CMAKE_SHARED_LINKER_FLAGS${CONFIG_SUFFIX}" "${CMAKE_SHARED_LINKER_FLAGS${CONFIG_SUFFIX}} ${Flag}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
|
||||
if(TARGET_ARCH_NAME STREQUAL "armel")
|
||||
if(DEFINED TIZEN_TOOLCHAIN) # For Tizen only
|
||||
add_link_options("-B${CROSS_ROOTFS}/usr/lib/gcc/${TIZEN_TOOLCHAIN}")
|
||||
add_link_options("-L${CROSS_ROOTFS}/lib")
|
||||
add_link_options("-L${CROSS_ROOTFS}/usr/lib")
|
||||
add_link_options("-L${CROSS_ROOTFS}/usr/lib/gcc/${TIZEN_TOOLCHAIN}")
|
||||
add_toolchain_linker_flag("-B${CROSS_ROOTFS}/usr/lib/gcc/${TIZEN_TOOLCHAIN}")
|
||||
add_toolchain_linker_flag("-L${CROSS_ROOTFS}/lib")
|
||||
add_toolchain_linker_flag("-L${CROSS_ROOTFS}/usr/lib")
|
||||
add_toolchain_linker_flag("-L${CROSS_ROOTFS}/usr/lib/gcc/${TIZEN_TOOLCHAIN}")
|
||||
endif()
|
||||
elseif(TARGET_ARCH_NAME STREQUAL "arm64")
|
||||
if(DEFINED TIZEN_TOOLCHAIN) # For Tizen only
|
||||
add_link_options("-B${CROSS_ROOTFS}/usr/lib64/gcc/${TIZEN_TOOLCHAIN}")
|
||||
add_link_options("-L${CROSS_ROOTFS}/lib64")
|
||||
add_link_options("-L${CROSS_ROOTFS}/usr/lib64")
|
||||
add_link_options("-L${CROSS_ROOTFS}/usr/lib64/gcc/${TIZEN_TOOLCHAIN}")
|
||||
add_toolchain_linker_flag("-B${CROSS_ROOTFS}/usr/lib64/gcc/${TIZEN_TOOLCHAIN}")
|
||||
add_toolchain_linker_flag("-L${CROSS_ROOTFS}/lib64")
|
||||
add_toolchain_linker_flag("-L${CROSS_ROOTFS}/usr/lib64")
|
||||
add_toolchain_linker_flag("-L${CROSS_ROOTFS}/usr/lib64/gcc/${TIZEN_TOOLCHAIN}")
|
||||
|
||||
add_link_options("-Wl,--rpath-link=${CROSS_ROOTFS}/lib64")
|
||||
add_link_options("-Wl,--rpath-link=${CROSS_ROOTFS}/usr/lib64")
|
||||
add_link_options("-Wl,--rpath-link=${CROSS_ROOTFS}/usr/lib64/gcc/${TIZEN_TOOLCHAIN}")
|
||||
add_toolchain_linker_flag("-Wl,--rpath-link=${CROSS_ROOTFS}/lib64")
|
||||
add_toolchain_linker_flag("-Wl,--rpath-link=${CROSS_ROOTFS}/usr/lib64")
|
||||
add_toolchain_linker_flag("-Wl,--rpath-link=${CROSS_ROOTFS}/usr/lib64/gcc/${TIZEN_TOOLCHAIN}")
|
||||
endif()
|
||||
elseif(TARGET_ARCH_NAME STREQUAL "x86")
|
||||
add_link_options(-m32)
|
||||
add_toolchain_linker_flag(-m32)
|
||||
elseif(ILLUMOS)
|
||||
add_link_options("-L${CROSS_ROOTFS}/lib/amd64")
|
||||
add_link_options("-L${CROSS_ROOTFS}/usr/amd64/lib")
|
||||
add_toolchain_linker_flag("-L${CROSS_ROOTFS}/lib/amd64")
|
||||
add_toolchain_linker_flag("-L${CROSS_ROOTFS}/usr/amd64/lib")
|
||||
endif()
|
||||
|
||||
# Specify compile options
|
||||
|
|
|
|||
|
|
@ -247,7 +247,7 @@ namespace RunTests
|
|||
{
|
||||
// Timeout test run 5 minutes before the Helix job would timeout
|
||||
var cts = new CancellationTokenSource(Options.Timeout.Subtract(TimeSpan.FromMinutes(5)));
|
||||
var commonTestArgs = $"vstest {Options.Target} --logger:xunit --logger:\"console;verbosity=normal\" --blame";
|
||||
var commonTestArgs = $"test {Options.Target} --logger:xunit --logger:\"console;verbosity=normal\" --blame \"CollectHangDump;TestTimeout=5m\"";
|
||||
if (Options.Quarantined)
|
||||
{
|
||||
Console.WriteLine("Running quarantined tests.");
|
||||
|
|
@ -331,6 +331,22 @@ namespace RunTests
|
|||
{
|
||||
Console.WriteLine("No logs found in artifacts/log");
|
||||
}
|
||||
Console.WriteLine($"Copying TestResults/**/*.dmp to {HELIX_WORKITEM_UPLOAD_ROOT}/");
|
||||
if (Directory.Exists("TestResults"))
|
||||
{
|
||||
foreach (var file in Directory.EnumerateFiles("TestResults", "*.dmp", SearchOption.AllDirectories))
|
||||
{
|
||||
var fileName = Path.GetFileName(file);
|
||||
Console.WriteLine($"Copying: {file} to {Path.Combine(HELIX_WORKITEM_UPLOAD_ROOT, fileName)}");
|
||||
// Need to copy to HELIX_WORKITEM_UPLOAD_ROOT and HELIX_WORKITEM_UPLOAD_ROOT/../ in order for Azure Devops attachments to link properly and for Helix to store the logs
|
||||
File.Copy(file, Path.Combine(HELIX_WORKITEM_UPLOAD_ROOT, fileName));
|
||||
File.Copy(file, Path.Combine(HELIX_WORKITEM_UPLOAD_ROOT, "..", fileName));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("No dmps found in TestResults");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@
|
|||
Windows.7.Amd64.Open
|
||||
OSX.1014.Amd64.Open
|
||||
Centos.7.Amd64.Open
|
||||
Debian.8.Amd64.Open
|
||||
Debian.9.Amd64.Open
|
||||
Redhat.7.Amd64.Open
|
||||
.PARAMETER RunQuarantinedTests
|
||||
|
|
@ -39,4 +38,4 @@ $env:BUILD_REPOSITORY_NAME="aspnetcore"
|
|||
$env:SYSTEM_TEAMPROJECT="aspnetcore"
|
||||
|
||||
$HelixQueues = $HelixQueues -replace ";", "%3B"
|
||||
dotnet msbuild $Project /t:Helix /p:TargetArchitecture="$TargetArchitecture" /p:IsRequiredCheck=true /p:IsHelixDaily=true /p:HelixTargetQueues=$HelixQueues /p:RunQuarantinedTests=$RunQuarantinedTests /p:_UseHelixOpenQueues=true /p:ASPNETCORE_TEST_LOG_DIR=artifacts/log
|
||||
dotnet msbuild $Project /t:Helix /p:TargetArchitecture="$TargetArchitecture" /p:IsRequiredCheck=true /p:IsHelixDaily=true /p:HelixTargetQueues=$HelixQueues /p:RunQuarantinedTests=$RunQuarantinedTests /p:_UseHelixOpenQueues=true /p:ASPNETCORE_TEST_LOG_DIR=artifacts/log
|
||||
|
|
|
|||
|
|
@ -18,9 +18,8 @@
|
|||
several versions older than latest. We reference the project to ensure it's built before the other projects that use it. Since this
|
||||
is a project reference, we must explicitly import the props file and also specify the output location of the SDK directory.
|
||||
-->
|
||||
<ProjectReference Include="$(RepoRoot)src\Razor\Microsoft.NET.Sdk.Razor\src\Microsoft.NET.Sdk.Razor.csproj"
|
||||
<Reference Include="Microsoft.NET.Sdk.Razor"
|
||||
PrivateAssets="All"
|
||||
IsImplicitlyDefined="true"
|
||||
ReferenceOutputAssembly="false"
|
||||
SkipGetTargetFrameworkProperties="true"
|
||||
UndefineProperties="TargetFramework;TargetFrameworks" />
|
||||
|
|
|
|||
|
|
@ -6,6 +6,30 @@
|
|||
<TargetFrameworkIdentifier>.NETFramework</TargetFrameworkIdentifier>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- Ensure API changes show up clearly in PRs. -->
|
||||
<PropertyGroup>
|
||||
<_TFMDirectory>$(TargetFramework)</_TFMDirectory>
|
||||
<_TFMDirectory Condition=" '$(TargetFramework)' == '$(DefaultNetCoreTargetFramework)' ">netcoreapp</_TFMDirectory>
|
||||
|
||||
<!-- Public members should not use oblivious types. Not done with all nullable annotations. -->
|
||||
<NoWarn>$(NoWarn);RS0041</NoWarn>
|
||||
</PropertyGroup>
|
||||
<ItemGroup Condition=" '$(IsImplementationProject)' == 'true' AND
|
||||
'$(DotNetBuildFromSource)' != 'true' AND
|
||||
! $(RepoRelativeProjectDir.Contains('Tools')) ">
|
||||
<!-- Package does nothing in projects lacking PublicAPI.Shipped.txt or PublicAPI.Unshipped.txt files. -->
|
||||
<Reference Include="Microsoft.CodeAnalysis.PublicApiAnalyzers" ExcludeAssets="Compile" PrivateAssets="All" />
|
||||
|
||||
<AdditionalFiles Include="PublicAPI.Shipped.txt"
|
||||
Condition=" Exists('$(MSBuildProjectDirectory)\PublicAPI.Shipped.txt') " />
|
||||
<AdditionalFiles Include="PublicAPI.Unshipped.txt"
|
||||
Condition=" Exists('$(MSBuildProjectDirectory)\PublicAPI.Unshipped.txt') " />
|
||||
<AdditionalFiles Include="PublicAPI.Shipped.txt"
|
||||
Condition=" Exists('$(MSBuildProjectDirectory)\$(_TFMDirectory)\PublicAPI.Shipped.txt') " />
|
||||
<AdditionalFiles Include="PublicAPI.Unshipped.txt"
|
||||
Condition=" Exists('$(MSBuildProjectDirectory)\$(_TFMDirectory)\PublicAPI.Unshipped.txt') " />
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="GetCustomAssemblyAttributes"
|
||||
BeforeTargets="GetAssemblyAttributes"
|
||||
DependsOnTargets="InitializeSourceControlInformation">
|
||||
|
|
|
|||
|
|
@ -32,7 +32,6 @@
|
|||
<HelixAvailableTargetQueue Include="Ubuntu.1804.Amd64.Open" Platform="Linux" />
|
||||
<HelixAvailableTargetQueue Include="Ubuntu.2004.Amd64.Open" Platform="Linux" />
|
||||
<HelixAvailableTargetQueue Include="Centos.7.Amd64.Open" Platform="Linux" />
|
||||
<HelixAvailableTargetQueue Include="Debian.8.Amd64.Open" Platform="Linux" />
|
||||
<HelixAvailableTargetQueue Include="Debian.9.Amd64.Open" Platform="Linux" />
|
||||
<HelixAvailableTargetQueue Include="Redhat.7.Amd64.Open" Platform="Linux" />
|
||||
<HelixAvailableTargetQueue Include="(Fedora.28.Amd64.Open)Ubuntu.1604.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:fedora-28-helix-09ca40b-20190508143249" Platform="Linux" />
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
<!--
|
||||
|
||||
The targets in this file are used to implement custom <Reference> resolution.
|
||||
For more details, see /docs/ReferenceResolution.md.
|
||||
|
||||
|
|
@ -76,8 +75,6 @@
|
|||
<_AllowedExplicitPackageReference Include="FSharp.Core" Condition="'$(MSBuildProjectExtension)' == '.fsproj'" />
|
||||
<_ExplicitPackageReference Include="@(PackageReference)" Exclude="@(_ImplicitPackageReference);@(_AllowedExplicitPackageReference)" />
|
||||
|
||||
<_UnusedProjectReferenceProvider Include="@(ProjectReferenceProvider)" Exclude="@(Reference)" />
|
||||
|
||||
<_CompilationOnlyReference Condition="'$(TargetFramework)' == 'netstandard2.0'"
|
||||
Include="@(Reference->WithMetadataValue('NuGetPackageId','NETStandard.Library'))" />
|
||||
|
||||
|
|
@ -91,24 +88,55 @@
|
|||
@(Reference->WithMetadataValue('IsSharedSource', 'true'));
|
||||
@(Reference->WithMetadataValue('PrivateAssets', 'All'))" />
|
||||
<_OriginalReferences Include="@(Reference)" />
|
||||
|
||||
<!--
|
||||
Turn Reference items into a ProjectReference when UseProjectReferences is true.
|
||||
Order matters. This comes before package resolution because projects should be used when possible instead of packages.
|
||||
-->
|
||||
<_ProjectReferenceByAssemblyName Condition="'$(UseProjectReferences)' == 'true'"
|
||||
Include="@(ProjectReferenceProvider)"
|
||||
Exclude="@(_UnusedProjectReferenceProvider)" />
|
||||
|
||||
<ProjectReference Include="@(_ProjectReferenceByAssemblyName->'%(ProjectPath)')" />
|
||||
<Reference Remove="@(_ProjectReferenceByAssemblyName)" />
|
||||
</ItemGroup>
|
||||
|
||||
<!--
|
||||
This target resolves remaining Referene items to Packages, if possible. If not, they are left as Reference items fo the SDK to resolve.
|
||||
This target helps ensure projects within the shared framework do no unintentionally add new references,
|
||||
and that assemblies outside the shared framework reference the framework as a whole instead of using
|
||||
individual assemblies.
|
||||
Turn Reference items into a ProjectReference when UseProjectReferences is true. Order matters; this
|
||||
comes before package resolution because projects should be used when possible instead of packages.
|
||||
-->
|
||||
<ItemGroup Condition=" '$(EnableCustomReferenceResolution)' == 'true' AND '$(UseProjectReferences)' == 'true' ">
|
||||
<!-- Copy then Update / Copy to intersect the ProjectReferenceProvider and Reference item groups. -->
|
||||
<_AllProjectReference Include="@(ProjectReferenceProvider)" />
|
||||
|
||||
<!-- Use only Reference items when project is a reference provider. Simplifies project moves and shortens files. -->
|
||||
<_AllProjectReference Update="@(ProjectReference->'%(Filename)')" DirectUse="1" />
|
||||
|
||||
<_AllProjectReference Update="@(Reference)" Use="1">
|
||||
<!--
|
||||
Metadata list is long because (a) Update defaults to copying no metadata and (b) ProjectReference metadata
|
||||
may include (real) Reference metadata and MSBuild task parameters. Even so, the list below is not exhaustive.
|
||||
-->
|
||||
<Aliases>%(Reference.Aliases)</Aliases>
|
||||
<BuildInParallel>%(Reference.BuildInParallel)</BuildInParallel>
|
||||
<DoNotHarvest>%(Reference.DoNotHarvest)</DoNotHarvest>
|
||||
<ExcludeAssets>%(Reference.ExcludeAssets)</ExcludeAssets>
|
||||
<IncludeAssets>%(Reference.IncludeAssets)</IncludeAssets>
|
||||
<IsNativeImage>%(Reference.IsNativeImage)</IsNativeImage>
|
||||
<LinkBase>%(Reference.LinkBase)</LinkBase>
|
||||
<Name>%(Reference.Name)</Name>
|
||||
<OutputItemType>%(Reference.OutputItemType)</OutputItemType>
|
||||
<Package>%(Reference.Package)</Package>
|
||||
<Private>%(Reference.Private)</Private>
|
||||
<PrivateAssets>%(Reference.PrivateAssets)</PrivateAssets>
|
||||
<Project>%(Reference.Project)</Project>
|
||||
<Properties>%(Reference.Properties)</Properties>
|
||||
<Publish>%(Reference.Publish)</Publish>
|
||||
<ReferenceOutputAssembly>%(Reference.ReferenceOutputAssembly)</ReferenceOutputAssembly>
|
||||
<SetPlatform>%(Reference.SetPlatform)</SetPlatform>
|
||||
<SkipGetTargetFrameworkProperties>%(Reference.SkipGetTargetFrameworkProperties)</SkipGetTargetFrameworkProperties>
|
||||
<Targets>%(Reference.Targets)</Targets>
|
||||
<UndefineProperties>%(Reference.UndefineProperties)</UndefineProperties>
|
||||
<Watch>%(Reference.Watch)</Watch>
|
||||
</_AllProjectReference>
|
||||
|
||||
<ProjectReference Include="@(_AllProjectReference->WithMetadataValue('Use', '1')->'%(ProjectPath)')" Use="" />
|
||||
<Reference Remove="@(_AllProjectReference->WithMetadataValue('Use', '1'))" />
|
||||
</ItemGroup>
|
||||
|
||||
<!--
|
||||
This target helps ensure projects within the shared framework do no unintentionally add new references, and that
|
||||
assemblies outside the shared framework reference the framework as a whole instead of using individual assemblies.
|
||||
In addition, enforce use of Reference items for projects reference providers.
|
||||
-->
|
||||
<Target Name="_CheckForReferenceBoundaries" BeforeTargets="CollectPackageReferences;ResolveReferences">
|
||||
<Error
|
||||
|
|
@ -118,6 +146,10 @@
|
|||
<Error
|
||||
Condition="@(_InvalidReferenceToNonSharedFxAssembly->Count()) != 0 AND '$(TargetFramework)' == '$(DefaultNetCoreTargetFramework)'"
|
||||
Text="Cannot reference "%(_InvalidReferenceToNonSharedFxAssembly.Identity)". This dependency is not in the shared framework. See docs/SharedFramework.md for instructions on how to modify what is in the shared framework." />
|
||||
|
||||
<Error
|
||||
Condition=" '$(EnableCustomReferenceResolution)' == 'true' AND @(_AllProjectReference->WithMetadataValue('DirectUse', '1')->Count()) != 0 "
|
||||
Text="Cannot reference "%(_AllProjectReference.Identity)" with a ProjectReference item; use a Reference item." />
|
||||
</Target>
|
||||
|
||||
<Target Name="_WarnAboutRedundantRef" AfterTargets="ResolveFrameworkReferences;ProcessFrameworkReferences">
|
||||
|
|
@ -127,14 +159,15 @@
|
|||
</Target>
|
||||
|
||||
<!--
|
||||
This target resolves remaining Referene items to Packages, if possible. If not, they are left as Reference items fo the SDK to resolve.
|
||||
This executes on NuGet restore and during DesignTimeBuild. It should not run in the outer, cross-targeting build.
|
||||
This target resolves remaining Reference items to Packages, if possible. If not, they are left as Reference
|
||||
items for the SDK to resolve. This executes on NuGet restore and during DesignTimeBuild. It should not run in
|
||||
outer, cross-targeting build.
|
||||
-->
|
||||
<Target Name="ResolveCustomReferences"
|
||||
BeforeTargets="CheckForImplicitPackageReferenceOverrides;CollectPackageReferences;ResolvePackageAssets"
|
||||
Condition=" '$(TargetFramework)' != '' AND '$(EnableCustomReferenceResolution)' == 'true' ">
|
||||
<ItemGroup>
|
||||
<!-- Ensure only content asset are consumed from .Sources packages -->
|
||||
<!-- Ensure only content assets are consumed from .Sources packages. -->
|
||||
<Reference>
|
||||
<IncludeAssets Condition="'%(IsSharedSource)' == 'true'">ContentFiles;Build</IncludeAssets>
|
||||
<PrivateAssets Condition="'%(IsSharedSource)' == 'true'">All</PrivateAssets>
|
||||
|
|
@ -205,21 +238,23 @@
|
|||
</Target>
|
||||
|
||||
<!--
|
||||
Muck with @(ResolvedCompileFileDefinitions) items between generation and use in order to compile against RTM lib/
|
||||
Change @(ResolvedCompileFileDefinitions) items between generation and use in order to compile against RTM lib/
|
||||
or ref/ assemblies. The approach works for all TFMs because it happens after a specific assembly is chosen for
|
||||
compilation; no need to restrict this to (say) the default TFM.
|
||||
|
||||
Condition checks for RTMVersions.csproj.nuget.g.props file only to ensure restore operation is complete.
|
||||
|
||||
This target could get confused if the layout changes for one of the dozen special-cased packages during servicing.
|
||||
E.g. ResolvePackageAssets picks a compatible assembly from the 5.0.1 package and _UseRTMReferenceAssemblies
|
||||
changes the path to one not present in the 5.0.0 package. Fortunately, this will break the build with complaints
|
||||
about the "invalid strong name".
|
||||
-->
|
||||
<Target Name="_UseRTMReferenceAssemblies"
|
||||
Condition=" '$(EnableCustomReferenceResolution)' == 'true' AND EXISTS('$(RepoRoot)eng\RTMVersions\obj\RTMVersions.csproj.nuget.g.props') "
|
||||
Condition=" '$(MSBuildProjectName)' != 'RepoTasks' "
|
||||
AfterTargets="ResolvePackageAssets"
|
||||
BeforeTargets="GenerateBuildDependencyFile;GeneratePublishDependencyFile;ILLink;ResolveLockFileReferences"
|
||||
DependsOnTargets="ResolvePackageAssets">
|
||||
<Error Condition=" !EXISTS('$(RepoRoot)artifacts\obj\RepoTasks\RepoTasks.csproj.nuget.g.props') "
|
||||
Text="The eng/tools/RepoTasks project must be restored before building other projects." />
|
||||
|
||||
<JoinItems Left="@(ResolvedCompileFileDefinitions)"
|
||||
Right="@(LatestPackageReference->HasMetadata('RTMVersion'))"
|
||||
LeftKey="Filename"
|
||||
|
|
@ -283,6 +318,8 @@
|
|||
Text="Only implementation projects should set IsAspNetCoreApp=true." />
|
||||
<Error Condition=" '$(IsAspNetCoreApp)' != 'true' AND $(HasReferenceAssembly) "
|
||||
Text="Only projects in the shared framework i.e. IsAspNetCoreApp==true should produce a reference assembly." />
|
||||
<Warning Condition=" '$(IsProjectReferenceProvider)' == 'true' AND '$(AssemblyName)' != '$(MSBuildProjectName)' "
|
||||
Text="Project name "$(MSBuildProjectName)" is confusing; assembly is named "$(AssemblyName)"." />
|
||||
|
||||
<ItemGroup Condition=" '$(IsProjectReferenceProvider)' == 'true' ">
|
||||
<ProvidesReference Include="$(AssemblyName)">
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ namespace RepoTasks
|
|||
|
||||
Log.LogMessage(MessageImportance.High, $"Attempting download '{source}' to '{target}'");
|
||||
|
||||
using (var httpClient = new HttpClient())
|
||||
using (var httpClient = new HttpClient { Timeout = TimeSpan.FromMinutes(5) })
|
||||
{
|
||||
for (int retryNumber = 0; retryNumber < MaxRetries; retryNumber++)
|
||||
{
|
||||
|
|
@ -146,4 +146,4 @@ namespace RepoTasks
|
|||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,5 +36,15 @@
|
|||
<Reference Include="Microsoft.Deployment.WindowsInstaller.Package">
|
||||
<HintPath>$(WiXSdkPath)\Microsoft.Deployment.WindowsInstaller.Package.dll</HintPath>
|
||||
</Reference>
|
||||
|
||||
<!--
|
||||
Gather project references for compilation against RTM packages. %(RTMVersion) is set for about a dozen packages
|
||||
in all servicing builds. Cannot reference two versions of a package, mandating this separation from projects
|
||||
using the relevant packages.
|
||||
-->
|
||||
<PackageReference Include="@(LatestPackageReference->HasMetadata('RTMVersion'))"
|
||||
IncludeAssets="None"
|
||||
PrivateAssets="All"
|
||||
Version="%(RTMVersion)" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@
|
|||
},
|
||||
"msbuild-sdks": {
|
||||
"Yarn.MSBuild": "1.15.2",
|
||||
"Microsoft.DotNet.Arcade.Sdk": "5.0.0-beta.20377.2",
|
||||
"Microsoft.DotNet.Helix.Sdk": "5.0.0-beta.20364.3"
|
||||
"Microsoft.DotNet.Arcade.Sdk": "5.0.0-beta.20374.1",
|
||||
"Microsoft.DotNet.Helix.Sdk": "5.0.0-beta.20374.1"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ namespace A.Internal.Namespace
|
|||
|
||||
[Theory]
|
||||
[MemberData(nameof(PublicMemberDefinitions))]
|
||||
[QuarantinedTest]
|
||||
[QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/22440")]
|
||||
public async Task PublicExposureOfPubternalTypeProducesPUB0001(string member)
|
||||
{
|
||||
var code = GetSourceFromNamespaceDeclaration($@"
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace IISSample
|
||||
|
|
@ -58,18 +60,22 @@ namespace IISSample
|
|||
});
|
||||
}
|
||||
|
||||
public static void Main(string[] args)
|
||||
public static Task Main(string[] args)
|
||||
{
|
||||
var host = new WebHostBuilder()
|
||||
var host = new HostBuilder()
|
||||
.ConfigureWebHost(webHostBuilder =>
|
||||
{
|
||||
webHostBuilder
|
||||
.UseKestrel()
|
||||
.UseStartup<Startup>();
|
||||
})
|
||||
.ConfigureLogging(factory =>
|
||||
{
|
||||
factory.AddConsole();
|
||||
})
|
||||
.UseKestrel()
|
||||
.UseStartup<Startup>()
|
||||
.Build();
|
||||
|
||||
host.Run();
|
||||
return host.RunAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace IISSample
|
||||
|
|
@ -70,20 +72,23 @@ namespace IISSample
|
|||
});
|
||||
}
|
||||
|
||||
public static void Main(string[] args)
|
||||
public static Task Main(string[] args)
|
||||
{
|
||||
var host = new WebHostBuilder()
|
||||
var host = new HostBuilder()
|
||||
.ConfigureWebHost(webHostBuilder =>
|
||||
{
|
||||
webHostBuilder
|
||||
.UseKestrel()
|
||||
.UseAzureAppServices()
|
||||
.UseStartup<Startup>();
|
||||
})
|
||||
.ConfigureLogging(factory =>
|
||||
{
|
||||
factory.AddConsole();
|
||||
})
|
||||
.UseKestrel()
|
||||
.UseAzureAppServices()
|
||||
.UseStartup<Startup>()
|
||||
.Build();
|
||||
|
||||
host.Run();
|
||||
return host.RunAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -54,6 +54,12 @@ namespace Microsoft.AspNetCore.Components.Authorization
|
|||
[Parameter]
|
||||
public RenderFragment Authorizing { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The resource to which access is being controlled.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public object Resource { get; set; }
|
||||
|
||||
[CascadingParameter]
|
||||
private Task<AuthenticationState> ExistingCascadedAuthenticationState { get; set; }
|
||||
|
||||
|
|
@ -82,6 +88,7 @@ namespace Microsoft.AspNetCore.Components.Authorization
|
|||
builder.AddAttribute(2, nameof(AuthorizeRouteViewCore.Authorized), _renderAuthorizedDelegate);
|
||||
builder.AddAttribute(3, nameof(AuthorizeRouteViewCore.Authorizing), _renderAuthorizingDelegate);
|
||||
builder.AddAttribute(4, nameof(AuthorizeRouteViewCore.NotAuthorized), _renderNotAuthorizedDelegate);
|
||||
builder.AddAttribute(5, nameof(AuthorizeRouteViewCore.Resource), Resource);
|
||||
builder.CloseComponent();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -76,6 +76,78 @@ namespace Microsoft.AspNetCore.Components.Authorization
|
|||
edit => AssertPrependText(batch, edit, "Hello from the page with message: Hello, world!"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AuthorizesWhenResourceIsSet()
|
||||
{
|
||||
// Arrange
|
||||
var routeData = new RouteData(typeof(TestPageRequiringAuthorization), new Dictionary<string, object>
|
||||
{
|
||||
{ nameof(TestPageRequiringAuthorization.Message), "Hello, world!" }
|
||||
});
|
||||
var resource = "foo";
|
||||
_testAuthorizationService.NextResult = AuthorizationResult.Success();
|
||||
|
||||
// Act
|
||||
_renderer.RenderRootComponent(_authorizeRouteViewComponentId, ParameterView.FromDictionary(new Dictionary<string, object>
|
||||
{
|
||||
{ nameof(AuthorizeRouteView.RouteData), routeData },
|
||||
{ nameof(AuthorizeRouteView.DefaultLayout), typeof(TestLayout) },
|
||||
{ nameof(AuthorizeRouteView.Resource), resource }
|
||||
}));
|
||||
|
||||
// Assert: renders layout
|
||||
var batch = _renderer.Batches.Single();
|
||||
var layoutDiff = batch.GetComponentDiffs<TestLayout>().Single();
|
||||
Assert.Collection(layoutDiff.Edits,
|
||||
edit => AssertPrependText(batch, edit, "Layout starts here"),
|
||||
edit =>
|
||||
{
|
||||
Assert.Equal(RenderTreeEditType.PrependFrame, edit.Type);
|
||||
AssertFrame.Component<TestPageRequiringAuthorization>(batch.ReferenceFrames[edit.ReferenceFrameIndex]);
|
||||
},
|
||||
edit => AssertPrependText(batch, edit, "Layout ends here"));
|
||||
|
||||
// Assert: renders page
|
||||
var pageDiff = batch.GetComponentDiffs<TestPageRequiringAuthorization>().Single();
|
||||
Assert.Collection(pageDiff.Edits,
|
||||
edit => AssertPrependText(batch, edit, "Hello from the page with message: Hello, world!"));
|
||||
|
||||
// Assert: Asserts that the Resource is present and set to "foo"
|
||||
Assert.Collection(_testAuthorizationService.AuthorizeCalls, call=>
|
||||
{
|
||||
Assert.Equal(resource, call.resource.ToString());
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NotAuthorizedWhenResourceMissing()
|
||||
{
|
||||
// Arrange
|
||||
var routeData = new RouteData(typeof(TestPageRequiringAuthorization), EmptyParametersDictionary);
|
||||
_testAuthorizationService.NextResult = AuthorizationResult.Failed();
|
||||
|
||||
// Act
|
||||
_renderer.RenderRootComponent(_authorizeRouteViewComponentId, ParameterView.FromDictionary(new Dictionary<string, object>
|
||||
{
|
||||
{ nameof(AuthorizeRouteView.RouteData), routeData },
|
||||
{ nameof(AuthorizeRouteView.DefaultLayout), typeof(TestLayout) },
|
||||
}));
|
||||
|
||||
// Assert: renders layout containing "not authorized" message
|
||||
var batch = _renderer.Batches.Single();
|
||||
var layoutDiff = batch.GetComponentDiffs<TestLayout>().Single();
|
||||
Assert.Collection(layoutDiff.Edits,
|
||||
edit => AssertPrependText(batch, edit, "Layout starts here"),
|
||||
edit => AssertPrependText(batch, edit, "Not authorized"),
|
||||
edit => AssertPrependText(batch, edit, "Layout ends here"));
|
||||
|
||||
// Assert: Asserts that the Resource is Null
|
||||
Assert.Collection(_testAuthorizationService.AuthorizeCalls, call=>
|
||||
{
|
||||
Assert.Null(call.resource);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void WhenNotAuthorized_RendersDefaultNotAuthorizedContentInsideLayout()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -61,6 +61,13 @@ namespace Microsoft.AspNetCore.Components
|
|||
return Receiver.HandleEventAsync(new EventCallbackWorkItem(Delegate), arg);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invokes the delegate associated with this binding and dispatches an event notification to the
|
||||
/// appropriate component.
|
||||
/// </summary>
|
||||
/// <returns>A <see cref="Task"/> which completes asynchronously once event processing has completed.</returns>
|
||||
public Task InvokeAsync() => InvokeAsync(null!);
|
||||
|
||||
object? IEventCallback.UnpackForRenderTree()
|
||||
{
|
||||
return RequiresExplicitReceiver ? (object)this : Delegate;
|
||||
|
|
|
|||
|
|
@ -56,6 +56,13 @@ namespace Microsoft.AspNetCore.Components
|
|||
return Receiver.HandleEventAsync(new EventCallbackWorkItem(Delegate), arg);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invokes the delegate associated with this binding and dispatches an event notification to the
|
||||
/// appropriate component.
|
||||
/// </summary>
|
||||
/// <returns>A <see cref="Task"/> which completes asynchronously once event processing has completed.</returns>
|
||||
public Task InvokeAsync() => InvokeAsync(default!);
|
||||
|
||||
internal EventCallback AsUntyped()
|
||||
{
|
||||
return new EventCallback(Receiver ?? Delegate?.Target as IHandleEvent, Delegate);
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@
|
|||
|
||||
<ItemGroup>
|
||||
<Compile Include="$(ComponentsSharedSourceRoot)src\ArrayBuilder.cs" LinkBase="RenderTree" />
|
||||
<Compile Include="$(ComponentsSharedSourceRoot)src\WebAssemblyJSInteropInternalCalls.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -142,8 +142,8 @@ namespace Microsoft.AspNetCore.Components
|
|||
|
||||
var oldIndex = oldParameters._ownerIndex;
|
||||
var newIndex = _ownerIndex;
|
||||
var oldEndIndexExcl = oldIndex + oldParameters._frames[oldIndex].ComponentSubtreeLength;
|
||||
var newEndIndexExcl = newIndex + _frames[newIndex].ComponentSubtreeLength;
|
||||
var oldEndIndexExcl = oldIndex + oldParameters._frames[oldIndex].ComponentSubtreeLengthField;
|
||||
var newEndIndexExcl = newIndex + _frames[newIndex].ComponentSubtreeLengthField;
|
||||
while (true)
|
||||
{
|
||||
// First, stop if we've reached the end of either subtree
|
||||
|
|
@ -162,21 +162,21 @@ namespace Microsoft.AspNetCore.Components
|
|||
ref var newFrame = ref _frames[newIndex];
|
||||
|
||||
// Stop if we've reached the end of either subtree's sequence of attributes
|
||||
oldFinished = oldFrame.FrameType != RenderTreeFrameType.Attribute;
|
||||
newFinished = newFrame.FrameType != RenderTreeFrameType.Attribute;
|
||||
oldFinished = oldFrame.FrameTypeField != RenderTreeFrameType.Attribute;
|
||||
newFinished = newFrame.FrameTypeField != RenderTreeFrameType.Attribute;
|
||||
if (oldFinished || newFinished)
|
||||
{
|
||||
return oldFinished == newFinished; // Same only if we have same number of parameters
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!string.Equals(oldFrame.AttributeName, newFrame.AttributeName, StringComparison.Ordinal))
|
||||
if (!string.Equals(oldFrame.AttributeNameField, newFrame.AttributeNameField, StringComparison.Ordinal))
|
||||
{
|
||||
return false; // Different names
|
||||
}
|
||||
|
||||
var oldValue = oldFrame.AttributeValue;
|
||||
var newValue = newFrame.AttributeValue;
|
||||
var oldValue = oldFrame.AttributeValueField;
|
||||
var newValue = newFrame.AttributeValueField;
|
||||
if (ChangeDetection.MayHaveChanged(oldValue, newValue))
|
||||
{
|
||||
return false;
|
||||
|
|
@ -216,8 +216,8 @@ namespace Microsoft.AspNetCore.Components
|
|||
public static ParameterView FromDictionary(IDictionary<string, object> parameters)
|
||||
{
|
||||
var frames = new RenderTreeFrame[parameters.Count + 1];
|
||||
frames[0] = RenderTreeFrame.Element(0, GeneratedParameterViewElementName)
|
||||
.WithElementSubtreeLength(frames.Length);
|
||||
frames[0] = RenderTreeFrame.Element(0, GeneratedParameterViewElementName);
|
||||
frames[0].ElementSubtreeLengthField = frames.Length;
|
||||
|
||||
var i = 0;
|
||||
foreach (var kvp in parameters)
|
||||
|
|
@ -303,7 +303,7 @@ namespace Microsoft.AspNetCore.Components
|
|||
{
|
||||
_frames = frames;
|
||||
_ownerIndex = ownerIndex;
|
||||
_ownerDescendantsEndIndexExcl = ownerIndex + _frames[ownerIndex].ElementSubtreeLength;
|
||||
_ownerDescendantsEndIndexExcl = ownerIndex + _frames[ownerIndex].ElementSubtreeLengthField;
|
||||
_currentIndex = ownerIndex;
|
||||
_current = default;
|
||||
}
|
||||
|
|
@ -321,7 +321,7 @@ namespace Microsoft.AspNetCore.Components
|
|||
|
||||
// ... or if you get to its first non-attribute descendant (because attributes
|
||||
// are always before any other type of descendant)
|
||||
if (_frames[nextIndex].FrameType != RenderTreeFrameType.Attribute)
|
||||
if (_frames[nextIndex].FrameTypeField != RenderTreeFrameType.Attribute)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
@ -329,7 +329,7 @@ namespace Microsoft.AspNetCore.Components
|
|||
_currentIndex = nextIndex;
|
||||
|
||||
ref var frame = ref _frames[_currentIndex];
|
||||
_current = new ParameterValue(frame.AttributeName, frame.AttributeValue, false);
|
||||
_current = new ParameterValue(frame.AttributeNameField, frame.AttributeValueField, false);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,23 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.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);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.Profiling
|
||||
{
|
||||
internal class NoOpComponentsProfiling : ComponentsProfiling
|
||||
{
|
||||
public override void Start(string? name)
|
||||
{
|
||||
}
|
||||
|
||||
public override void End(string? name)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -41,7 +41,7 @@ namespace Microsoft.AspNetCore.Components.Reflection
|
|||
foreach (var parameter in parameters)
|
||||
{
|
||||
var parameterName = parameter.Name;
|
||||
if (!writers.WritersByName.TryGetValue(parameterName, out var writer))
|
||||
if (!writers.TryGetValue(parameterName, out var writer))
|
||||
{
|
||||
// Case 1: There is nowhere to put this value.
|
||||
ThrowForUnknownIncomingParameterName(targetType, parameterName);
|
||||
|
|
@ -82,7 +82,7 @@ namespace Microsoft.AspNetCore.Components.Reflection
|
|||
isCaptureUnmatchedValuesParameterSetExplicitly = true;
|
||||
}
|
||||
|
||||
if (writers.WritersByName.TryGetValue(parameterName, out var writer))
|
||||
if (writers.TryGetValue(parameterName, out var writer))
|
||||
{
|
||||
if (!writer.Cascading && parameter.Cascading)
|
||||
{
|
||||
|
|
@ -245,9 +245,15 @@ namespace Microsoft.AspNetCore.Components.Reflection
|
|||
|
||||
private class WritersForType
|
||||
{
|
||||
private const int MaxCachedWriterLookups = 100;
|
||||
private readonly Dictionary<string, IPropertySetter> _underlyingWriters;
|
||||
private readonly ConcurrentDictionary<string, IPropertySetter?> _referenceEqualityWritersCache;
|
||||
|
||||
public WritersForType(Type targetType)
|
||||
{
|
||||
WritersByName = new Dictionary<string, IPropertySetter>(StringComparer.OrdinalIgnoreCase);
|
||||
_underlyingWriters = new Dictionary<string, IPropertySetter>(StringComparer.OrdinalIgnoreCase);
|
||||
_referenceEqualityWritersCache = new ConcurrentDictionary<string, IPropertySetter?>(ReferenceEqualityComparer.Instance);
|
||||
|
||||
foreach (var propertyInfo in GetCandidateBindableProperties(targetType))
|
||||
{
|
||||
var parameterAttribute = propertyInfo.GetCustomAttribute<ParameterAttribute>();
|
||||
|
|
@ -267,14 +273,14 @@ namespace Microsoft.AspNetCore.Components.Reflection
|
|||
|
||||
var propertySetter = MemberAssignment.CreatePropertySetter(targetType, propertyInfo, cascading: cascadingParameterAttribute != null);
|
||||
|
||||
if (WritersByName.ContainsKey(propertyName))
|
||||
if (_underlyingWriters.ContainsKey(propertyName))
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
$"The type '{targetType.FullName}' declares more than one parameter matching the " +
|
||||
$"name '{propertyName.ToLowerInvariant()}'. Parameter names are case-insensitive and must be unique.");
|
||||
}
|
||||
|
||||
WritersByName.Add(propertyName, propertySetter);
|
||||
_underlyingWriters.Add(propertyName, propertySetter);
|
||||
|
||||
if (parameterAttribute != null && parameterAttribute.CaptureUnmatchedValues)
|
||||
{
|
||||
|
|
@ -298,11 +304,38 @@ namespace Microsoft.AspNetCore.Components.Reflection
|
|||
}
|
||||
}
|
||||
|
||||
public Dictionary<string, IPropertySetter> WritersByName { get; }
|
||||
|
||||
public IPropertySetter? CaptureUnmatchedValuesWriter { get; }
|
||||
|
||||
public string? CaptureUnmatchedValuesPropertyName { get; }
|
||||
|
||||
public bool TryGetValue(string parameterName, [MaybeNullWhen(false)] out IPropertySetter writer)
|
||||
{
|
||||
// In intensive parameter-passing scenarios, one of the most expensive things we do is the
|
||||
// lookup from parameterName to writer. Pre-5.0 that was because of the string hashing.
|
||||
// To optimize this, we now have a cache in front of the lookup which is keyed by parameterName's
|
||||
// object identity (not its string hash). So in most cases we can resolve the lookup without
|
||||
// having to hash the string. We only fall back on hashing the string if the cache gets full,
|
||||
// which would only be in very unusual situations because components don't typically have many
|
||||
// parameters, and the parameterName strings usually come from compile-time constants.
|
||||
if (!_referenceEqualityWritersCache.TryGetValue(parameterName, out writer))
|
||||
{
|
||||
_underlyingWriters.TryGetValue(parameterName, out writer);
|
||||
|
||||
// Note that because we're not locking around this, it's possible we might
|
||||
// actually write more than MaxCachedWriterLookups entries due to concurrent
|
||||
// writes. However this won't cause any problems.
|
||||
// Also note that the value we're caching might be 'null'. It's valid to cache
|
||||
// lookup misses just as much as hits, since then we can more quickly identify
|
||||
// incoming values that don't have a corresponding writer and thus will end up
|
||||
// being passed as catch-all parameter values.
|
||||
if (_referenceEqualityWritersCache.Count < MaxCachedWriterLookups)
|
||||
{
|
||||
_referenceEqualityWritersCache.TryAdd(parameterName, writer);
|
||||
}
|
||||
}
|
||||
|
||||
return writer != null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ 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
|
||||
|
|
@ -28,7 +27,6 @@ namespace Microsoft.AspNetCore.Components.RenderTree
|
|||
ArrayRange<RenderTreeFrame> oldTree,
|
||||
ArrayRange<RenderTreeFrame> newTree)
|
||||
{
|
||||
ComponentsProfiling.Instance.Start();
|
||||
var editsBuffer = batchBuilder.EditsBuffer;
|
||||
var editsBufferStartLength = editsBuffer.Count;
|
||||
|
||||
|
|
@ -37,7 +35,6 @@ namespace Microsoft.AspNetCore.Components.RenderTree
|
|||
|
||||
var editsSegment = editsBuffer.ToSegment(editsBufferStartLength, editsBuffer.Count);
|
||||
var result = new RenderTreeDiff(componentId, editsSegment);
|
||||
ComponentsProfiling.Instance.End();
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -49,7 +46,6 @@ 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
|
||||
|
|
@ -82,7 +78,7 @@ namespace Microsoft.AspNetCore.Components.RenderTree
|
|||
if (hasMoreOld)
|
||||
{
|
||||
ref var oldFrame = ref oldTree[oldStartIndex];
|
||||
oldSeq = oldFrame.Sequence;
|
||||
oldSeq = oldFrame.SequenceField;
|
||||
oldKey = KeyValue(ref oldFrame);
|
||||
}
|
||||
else
|
||||
|
|
@ -94,7 +90,7 @@ namespace Microsoft.AspNetCore.Components.RenderTree
|
|||
if (hasMoreNew)
|
||||
{
|
||||
ref var newFrame = ref newTree[newStartIndex];
|
||||
newSeq = newFrame.Sequence;
|
||||
newSeq = newFrame.SequenceField;
|
||||
newKey = KeyValue(ref newFrame);
|
||||
}
|
||||
else
|
||||
|
|
@ -199,7 +195,7 @@ namespace Microsoft.AspNetCore.Components.RenderTree
|
|||
var newLoopsBackLater = false;
|
||||
for (var testIndex = newStartIndex + 1; testIndex < newEndIndexExcl; testIndex++)
|
||||
{
|
||||
if (newTree[testIndex].Sequence < newSeq)
|
||||
if (newTree[testIndex].SequenceField < newSeq)
|
||||
{
|
||||
newLoopsBackLater = true;
|
||||
break;
|
||||
|
|
@ -222,7 +218,7 @@ namespace Microsoft.AspNetCore.Components.RenderTree
|
|||
var oldLoopsBackLater = false;
|
||||
for (var testIndex = oldStartIndex + 1; testIndex < oldEndIndexExcl; testIndex++)
|
||||
{
|
||||
if (oldTree[testIndex].Sequence < oldSeq)
|
||||
if (oldTree[testIndex].SequenceField < oldSeq)
|
||||
{
|
||||
oldLoopsBackLater = true;
|
||||
break;
|
||||
|
|
@ -300,12 +296,10 @@ 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;
|
||||
|
|
@ -318,7 +312,7 @@ namespace Microsoft.AspNetCore.Components.RenderTree
|
|||
{
|
||||
if (result.ContainsKey(key))
|
||||
{
|
||||
ThrowExceptionForDuplicateKey(key);
|
||||
ThrowExceptionForDuplicateKey(key, frame);
|
||||
}
|
||||
|
||||
result[key] = new KeyedItemInfo(oldStartIndex, -1);
|
||||
|
|
@ -341,7 +335,7 @@ namespace Microsoft.AspNetCore.Components.RenderTree
|
|||
{
|
||||
if (existingEntry.NewIndex >= 0)
|
||||
{
|
||||
ThrowExceptionForDuplicateKey(key);
|
||||
ThrowExceptionForDuplicateKey(key, frame);
|
||||
}
|
||||
|
||||
result[key] = new KeyedItemInfo(existingEntry.OldIndex, newStartIndex);
|
||||
|
|
@ -351,23 +345,32 @@ namespace Microsoft.AspNetCore.Components.RenderTree
|
|||
newStartIndex = NextSiblingIndex(frame, newStartIndex);
|
||||
}
|
||||
|
||||
ProfilingEnd();
|
||||
return result;
|
||||
}
|
||||
|
||||
private static void ThrowExceptionForDuplicateKey(object key)
|
||||
private static void ThrowExceptionForDuplicateKey(object key, in RenderTreeFrame frame)
|
||||
{
|
||||
throw new InvalidOperationException($"More than one sibling has the same key value, '{key}'. Key values must be unique.");
|
||||
switch (frame.FrameTypeField)
|
||||
{
|
||||
case RenderTreeFrameType.Component:
|
||||
throw new InvalidOperationException($"More than one sibling of component '{frame.ComponentTypeField}' has the same key value, '{key}'. Key values must be unique.");
|
||||
|
||||
case RenderTreeFrameType.Element:
|
||||
throw new InvalidOperationException($"More than one sibling of element '{frame.ElementNameField}' has the same key value, '{key}'. Key values must be unique.");
|
||||
|
||||
default:
|
||||
throw new InvalidOperationException($"More than one sibling has the same key value, '{key}'. Key values must be unique.");
|
||||
}
|
||||
}
|
||||
|
||||
private static object KeyValue(ref RenderTreeFrame frame)
|
||||
{
|
||||
switch (frame.FrameType)
|
||||
switch (frame.FrameTypeField)
|
||||
{
|
||||
case RenderTreeFrameType.Element:
|
||||
return frame.ElementKey;
|
||||
return frame.ElementKeyField;
|
||||
case RenderTreeFrameType.Component:
|
||||
return frame.ComponentKey;
|
||||
return frame.ComponentKeyField;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
|
@ -384,7 +387,6 @@ 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
|
||||
|
|
@ -403,10 +405,10 @@ namespace Microsoft.AspNetCore.Components.RenderTree
|
|||
|
||||
while (hasMoreOld || hasMoreNew)
|
||||
{
|
||||
var oldSeq = hasMoreOld ? oldTree[oldStartIndex].Sequence : int.MaxValue;
|
||||
var newSeq = hasMoreNew ? newTree[newStartIndex].Sequence : int.MaxValue;
|
||||
var oldAttributeName = oldTree[oldStartIndex].AttributeName;
|
||||
var newAttributeName = newTree[newStartIndex].AttributeName;
|
||||
var oldSeq = hasMoreOld ? oldTree[oldStartIndex].SequenceField : int.MaxValue;
|
||||
var newSeq = hasMoreNew ? newTree[newStartIndex].SequenceField : int.MaxValue;
|
||||
var oldAttributeName = oldTree[oldStartIndex].AttributeNameField;
|
||||
var newAttributeName = newTree[newStartIndex].AttributeNameField;
|
||||
|
||||
if (oldSeq == newSeq &&
|
||||
string.Equals(oldAttributeName, newAttributeName, StringComparison.Ordinal))
|
||||
|
|
@ -433,7 +435,6 @@ namespace Microsoft.AspNetCore.Components.RenderTree
|
|||
ref diffContext,
|
||||
oldStartIndex, oldEndIndexExcl,
|
||||
newStartIndex, newEndIndexExcl);
|
||||
ProfilingEnd();
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -459,12 +460,9 @@ namespace Microsoft.AspNetCore.Components.RenderTree
|
|||
ref diffContext,
|
||||
oldStartIndex, oldEndIndexExcl,
|
||||
newStartIndex, newEndIndexExcl);
|
||||
ProfilingEnd();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ProfilingEnd();
|
||||
}
|
||||
|
||||
private static void AppendAttributeDiffEntriesForRangeSlow(
|
||||
|
|
@ -472,7 +470,6 @@ namespace Microsoft.AspNetCore.Components.RenderTree
|
|||
int oldStartIndex, int oldEndIndexExcl,
|
||||
int newStartIndex, int newEndIndexExcl)
|
||||
{
|
||||
ProfilingStart();
|
||||
var oldTree = diffContext.OldTree;
|
||||
var newTree = diffContext.NewTree;
|
||||
|
||||
|
|
@ -484,12 +481,12 @@ namespace Microsoft.AspNetCore.Components.RenderTree
|
|||
// 3. iterate through the remaining attributes in the set and add them
|
||||
for (var i = newStartIndex; i < newEndIndexExcl; i++)
|
||||
{
|
||||
diffContext.AttributeDiffSet[newTree[i].AttributeName] = i;
|
||||
diffContext.AttributeDiffSet[newTree[i].AttributeNameField] = i;
|
||||
}
|
||||
|
||||
for (var i = oldStartIndex; i < oldEndIndexExcl; i++)
|
||||
{
|
||||
var oldName = oldTree[i].AttributeName;
|
||||
var oldName = oldTree[i].AttributeNameField;
|
||||
if (diffContext.AttributeDiffSet.TryGetValue(oldName, out var matchIndex))
|
||||
{
|
||||
// Has a match in the new tree, look for a diff
|
||||
|
|
@ -511,7 +508,6 @@ 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(
|
||||
|
|
@ -519,15 +515,15 @@ namespace Microsoft.AspNetCore.Components.RenderTree
|
|||
int oldComponentIndex,
|
||||
int newComponentIndex)
|
||||
{
|
||||
ProfilingStart();
|
||||
var oldTree = diffContext.OldTree;
|
||||
var newTree = diffContext.NewTree;
|
||||
ref var oldComponentFrame = ref oldTree[oldComponentIndex];
|
||||
ref var newComponentFrame = ref newTree[newComponentIndex];
|
||||
var componentState = oldComponentFrame.ComponentState;
|
||||
var componentState = oldComponentFrame.ComponentStateField;
|
||||
|
||||
// Preserve the actual componentInstance
|
||||
newComponentFrame = newComponentFrame.WithComponent(componentState);
|
||||
newComponentFrame.ComponentStateField = componentState;
|
||||
newComponentFrame.ComponentIdField = componentState.ComponentId;
|
||||
|
||||
// As an important rendering optimization, we want to skip parameter update
|
||||
// notifications if we know for sure they haven't changed/mutated. The
|
||||
|
|
@ -546,20 +542,18 @@ namespace Microsoft.AspNetCore.Components.RenderTree
|
|||
{
|
||||
componentState.SetDirectParameters(newParameters);
|
||||
}
|
||||
|
||||
ProfilingEnd();
|
||||
}
|
||||
|
||||
private static int NextSiblingIndex(in RenderTreeFrame frame, int frameIndex)
|
||||
{
|
||||
switch (frame.FrameType)
|
||||
switch (frame.FrameTypeField)
|
||||
{
|
||||
case RenderTreeFrameType.Component:
|
||||
return frameIndex + frame.ComponentSubtreeLength;
|
||||
return frameIndex + frame.ComponentSubtreeLengthField;
|
||||
case RenderTreeFrameType.Element:
|
||||
return frameIndex + frame.ElementSubtreeLength;
|
||||
return frameIndex + frame.ElementSubtreeLengthField;
|
||||
case RenderTreeFrameType.Region:
|
||||
return frameIndex + frame.RegionSubtreeLength;
|
||||
return frameIndex + frame.RegionSubtreeLengthField;
|
||||
default:
|
||||
return frameIndex + 1;
|
||||
}
|
||||
|
|
@ -570,7 +564,6 @@ namespace Microsoft.AspNetCore.Components.RenderTree
|
|||
int oldFrameIndex,
|
||||
int newFrameIndex)
|
||||
{
|
||||
ProfilingStart();
|
||||
var oldTree = diffContext.OldTree;
|
||||
var newTree = diffContext.NewTree;
|
||||
ref var oldFrame = ref oldTree[oldFrameIndex];
|
||||
|
|
@ -578,12 +571,11 @@ namespace Microsoft.AspNetCore.Components.RenderTree
|
|||
|
||||
// This can't happen for sequence-matched frames from .razor components, but it can happen if you write your
|
||||
// builder logic manually or if two dissimilar frames matched by key. Treat as completely unrelated.
|
||||
var newFrameType = newFrame.FrameType;
|
||||
if (oldFrame.FrameType != newFrameType)
|
||||
var newFrameType = newFrame.FrameTypeField;
|
||||
if (oldFrame.FrameTypeField != newFrameType)
|
||||
{
|
||||
InsertNewFrame(ref diffContext, newFrameIndex);
|
||||
RemoveOldFrame(ref diffContext, oldFrameIndex);
|
||||
ProfilingEnd();
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -595,8 +587,8 @@ namespace Microsoft.AspNetCore.Components.RenderTree
|
|||
{
|
||||
case RenderTreeFrameType.Text:
|
||||
{
|
||||
var oldText = oldFrame.TextContent;
|
||||
var newText = newFrame.TextContent;
|
||||
var oldText = oldFrame.TextContentField;
|
||||
var newText = newFrame.TextContentField;
|
||||
if (!string.Equals(oldText, newText, StringComparison.Ordinal))
|
||||
{
|
||||
var referenceFrameIndex = diffContext.ReferenceFrames.Append(newFrame);
|
||||
|
|
@ -608,8 +600,8 @@ namespace Microsoft.AspNetCore.Components.RenderTree
|
|||
|
||||
case RenderTreeFrameType.Markup:
|
||||
{
|
||||
var oldMarkup = oldFrame.MarkupContent;
|
||||
var newMarkup = newFrame.MarkupContent;
|
||||
var oldMarkup = oldFrame.MarkupContentField;
|
||||
var newMarkup = newFrame.MarkupContentField;
|
||||
if (!string.Equals(oldMarkup, newMarkup, StringComparison.Ordinal))
|
||||
{
|
||||
var referenceFrameIndex = diffContext.ReferenceFrames.Append(newFrame);
|
||||
|
|
@ -621,8 +613,8 @@ namespace Microsoft.AspNetCore.Components.RenderTree
|
|||
|
||||
case RenderTreeFrameType.Element:
|
||||
{
|
||||
var oldElementName = oldFrame.ElementName;
|
||||
var newElementName = newFrame.ElementName;
|
||||
var oldElementName = oldFrame.ElementNameField;
|
||||
var newElementName = newFrame.ElementNameField;
|
||||
if (string.Equals(oldElementName, newElementName, StringComparison.Ordinal))
|
||||
{
|
||||
var oldFrameAttributesEndIndexExcl = GetAttributesEndIndexExclusive(oldTree, oldFrameIndex);
|
||||
|
|
@ -635,8 +627,8 @@ namespace Microsoft.AspNetCore.Components.RenderTree
|
|||
newFrameIndex + 1, newFrameAttributesEndIndexExcl);
|
||||
|
||||
// Diff the children
|
||||
var oldFrameChildrenEndIndexExcl = oldFrameIndex + oldFrame.ElementSubtreeLength;
|
||||
var newFrameChildrenEndIndexExcl = newFrameIndex + newFrame.ElementSubtreeLength;
|
||||
var oldFrameChildrenEndIndexExcl = oldFrameIndex + oldFrame.ElementSubtreeLengthField;
|
||||
var newFrameChildrenEndIndexExcl = newFrameIndex + newFrame.ElementSubtreeLengthField;
|
||||
var hasChildrenToProcess =
|
||||
oldFrameChildrenEndIndexExcl > oldFrameAttributesEndIndexExcl ||
|
||||
newFrameChildrenEndIndexExcl > newFrameAttributesEndIndexExcl;
|
||||
|
|
@ -670,14 +662,14 @@ namespace Microsoft.AspNetCore.Components.RenderTree
|
|||
{
|
||||
AppendDiffEntriesForRange(
|
||||
ref diffContext,
|
||||
oldFrameIndex + 1, oldFrameIndex + oldFrame.RegionSubtreeLength,
|
||||
newFrameIndex + 1, newFrameIndex + newFrame.RegionSubtreeLength);
|
||||
oldFrameIndex + 1, oldFrameIndex + oldFrame.RegionSubtreeLengthField,
|
||||
newFrameIndex + 1, newFrameIndex + newFrame.RegionSubtreeLengthField);
|
||||
break;
|
||||
}
|
||||
|
||||
case RenderTreeFrameType.Component:
|
||||
{
|
||||
if (oldFrame.ComponentType == newFrame.ComponentType)
|
||||
if (oldFrame.ComponentTypeField == newFrame.ComponentTypeField)
|
||||
{
|
||||
UpdateRetainedChildComponent(
|
||||
ref diffContext,
|
||||
|
|
@ -707,10 +699,8 @@ namespace Microsoft.AspNetCore.Components.RenderTree
|
|||
// We don't handle attributes here, they have their own diff logic.
|
||||
// See AppendDiffEntriesForAttributeFrame
|
||||
default:
|
||||
throw new NotImplementedException($"Encountered unsupported frame type during diffing: {newTree[newFrameIndex].FrameType}");
|
||||
throw new NotImplementedException($"Encountered unsupported frame type during diffing: {newTree[newFrameIndex].FrameTypeField}");
|
||||
}
|
||||
|
||||
ProfilingEnd();
|
||||
}
|
||||
|
||||
// This should only be called for attributes that have the same name. This is an
|
||||
|
|
@ -720,14 +710,13 @@ namespace Microsoft.AspNetCore.Components.RenderTree
|
|||
int oldFrameIndex,
|
||||
int newFrameIndex)
|
||||
{
|
||||
ProfilingStart();
|
||||
var oldTree = diffContext.OldTree;
|
||||
var newTree = diffContext.NewTree;
|
||||
ref var oldFrame = ref oldTree[oldFrameIndex];
|
||||
ref var newFrame = ref newTree[newFrameIndex];
|
||||
|
||||
// Using Equals to account for string comparisons, nulls, etc.
|
||||
var valueChanged = !Equals(oldFrame.AttributeValue, newFrame.AttributeValue);
|
||||
var valueChanged = !Equals(oldFrame.AttributeValueField, newFrame.AttributeValueField);
|
||||
if (valueChanged)
|
||||
{
|
||||
InitializeNewAttributeFrame(ref diffContext, ref newFrame);
|
||||
|
|
@ -736,29 +725,26 @@ namespace Microsoft.AspNetCore.Components.RenderTree
|
|||
|
||||
// If we're replacing an old event handler ID with a new one, register the old one for disposal,
|
||||
// plus keep track of the old->new chain until the old one is fully disposed
|
||||
if (oldFrame.AttributeEventHandlerId > 0)
|
||||
if (oldFrame.AttributeEventHandlerIdField > 0)
|
||||
{
|
||||
diffContext.Renderer.TrackReplacedEventHandlerId(oldFrame.AttributeEventHandlerId, newFrame.AttributeEventHandlerId);
|
||||
diffContext.BatchBuilder.DisposedEventHandlerIds.Append(oldFrame.AttributeEventHandlerId);
|
||||
diffContext.Renderer.TrackReplacedEventHandlerId(oldFrame.AttributeEventHandlerIdField, newFrame.AttributeEventHandlerIdField);
|
||||
diffContext.BatchBuilder.DisposedEventHandlerIds.Append(oldFrame.AttributeEventHandlerIdField);
|
||||
}
|
||||
}
|
||||
else if (oldFrame.AttributeEventHandlerId > 0)
|
||||
else if (oldFrame.AttributeEventHandlerIdField > 0)
|
||||
{
|
||||
// Retain the event handler ID by copying the old frame over the new frame.
|
||||
// this will prevent us from needing to dispose the old event handler
|
||||
// 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)
|
||||
switch (newFrame.FrameTypeField)
|
||||
{
|
||||
case RenderTreeFrameType.Attribute:
|
||||
{
|
||||
|
|
@ -771,7 +757,7 @@ namespace Microsoft.AspNetCore.Components.RenderTree
|
|||
case RenderTreeFrameType.Element:
|
||||
{
|
||||
InitializeNewSubtree(ref diffContext, newFrameIndex);
|
||||
var referenceFrameIndex = diffContext.ReferenceFrames.Append(newTree, newFrameIndex, newFrame.ElementSubtreeLength);
|
||||
var referenceFrameIndex = diffContext.ReferenceFrames.Append(newTree, newFrameIndex, newFrame.ElementSubtreeLengthField);
|
||||
diffContext.Edits.Append(RenderTreeEdit.PrependFrame(diffContext.SiblingIndex, referenceFrameIndex));
|
||||
diffContext.SiblingIndex++;
|
||||
break;
|
||||
|
|
@ -779,7 +765,7 @@ namespace Microsoft.AspNetCore.Components.RenderTree
|
|||
case RenderTreeFrameType.Region:
|
||||
{
|
||||
var regionChildFrameIndex = newFrameIndex + 1;
|
||||
var regionChildFrameEndIndexExcl = newFrameIndex + newFrame.RegionSubtreeLength;
|
||||
var regionChildFrameEndIndexExcl = newFrameIndex + newFrame.RegionSubtreeLengthField;
|
||||
while (regionChildFrameIndex < regionChildFrameEndIndexExcl)
|
||||
{
|
||||
InsertNewFrame(ref diffContext, regionChildFrameIndex);
|
||||
|
|
@ -806,31 +792,29 @@ namespace Microsoft.AspNetCore.Components.RenderTree
|
|||
break;
|
||||
}
|
||||
default:
|
||||
throw new NotImplementedException($"Unexpected frame type during {nameof(InsertNewFrame)}: {newFrame.FrameType}");
|
||||
throw new NotImplementedException($"Unexpected frame type during {nameof(InsertNewFrame)}: {newFrame.FrameTypeField}");
|
||||
}
|
||||
ProfilingEnd();
|
||||
}
|
||||
|
||||
private static void RemoveOldFrame(ref DiffContext diffContext, int oldFrameIndex)
|
||||
{
|
||||
ProfilingStart();
|
||||
var oldTree = diffContext.OldTree;
|
||||
ref var oldFrame = ref oldTree[oldFrameIndex];
|
||||
switch (oldFrame.FrameType)
|
||||
switch (oldFrame.FrameTypeField)
|
||||
{
|
||||
case RenderTreeFrameType.Attribute:
|
||||
{
|
||||
diffContext.Edits.Append(RenderTreeEdit.RemoveAttribute(diffContext.SiblingIndex, oldFrame.AttributeName));
|
||||
if (oldFrame.AttributeEventHandlerId > 0)
|
||||
diffContext.Edits.Append(RenderTreeEdit.RemoveAttribute(diffContext.SiblingIndex, oldFrame.AttributeNameField));
|
||||
if (oldFrame.AttributeEventHandlerIdField > 0)
|
||||
{
|
||||
diffContext.BatchBuilder.DisposedEventHandlerIds.Append(oldFrame.AttributeEventHandlerId);
|
||||
diffContext.BatchBuilder.DisposedEventHandlerIds.Append(oldFrame.AttributeEventHandlerIdField);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case RenderTreeFrameType.Component:
|
||||
case RenderTreeFrameType.Element:
|
||||
{
|
||||
var endIndexExcl = oldFrameIndex + oldFrame.ElementSubtreeLength;
|
||||
var endIndexExcl = oldFrameIndex + oldFrame.ElementSubtreeLengthField;
|
||||
DisposeFramesInRange(diffContext.BatchBuilder, oldTree, oldFrameIndex, endIndexExcl);
|
||||
diffContext.Edits.Append(RenderTreeEdit.RemoveFrame(diffContext.SiblingIndex));
|
||||
break;
|
||||
|
|
@ -838,7 +822,7 @@ namespace Microsoft.AspNetCore.Components.RenderTree
|
|||
case RenderTreeFrameType.Region:
|
||||
{
|
||||
var regionChildFrameIndex = oldFrameIndex + 1;
|
||||
var regionChildFrameEndIndexExcl = oldFrameIndex + oldFrame.RegionSubtreeLength;
|
||||
var regionChildFrameEndIndexExcl = oldFrameIndex + oldFrame.RegionSubtreeLengthField;
|
||||
while (regionChildFrameIndex < regionChildFrameEndIndexExcl)
|
||||
{
|
||||
RemoveOldFrame(ref diffContext, regionChildFrameIndex);
|
||||
|
|
@ -853,18 +837,17 @@ namespace Microsoft.AspNetCore.Components.RenderTree
|
|||
break;
|
||||
}
|
||||
default:
|
||||
throw new NotImplementedException($"Unexpected frame type during {nameof(RemoveOldFrame)}: {oldFrame.FrameType}");
|
||||
throw new NotImplementedException($"Unexpected frame type during {nameof(RemoveOldFrame)}: {oldFrame.FrameTypeField}");
|
||||
}
|
||||
ProfilingEnd();
|
||||
}
|
||||
|
||||
private static int GetAttributesEndIndexExclusive(RenderTreeFrame[] tree, int rootIndex)
|
||||
{
|
||||
var descendantsEndIndexExcl = rootIndex + tree[rootIndex].ElementSubtreeLength;
|
||||
var descendantsEndIndexExcl = rootIndex + tree[rootIndex].ElementSubtreeLengthField;
|
||||
var index = rootIndex + 1;
|
||||
for (; index < descendantsEndIndexExcl; index++)
|
||||
{
|
||||
if (tree[index].FrameType != RenderTreeFrameType.Attribute)
|
||||
if (tree[index].FrameTypeField != RenderTreeFrameType.Attribute)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
|
@ -889,13 +872,12 @@ 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;
|
||||
var endIndexExcl = frameIndex + frames[frameIndex].ElementSubtreeLengthField;
|
||||
for (var i = frameIndex; i < endIndexExcl; i++)
|
||||
{
|
||||
ref var frame = ref frames[i];
|
||||
switch (frame.FrameType)
|
||||
switch (frame.FrameTypeField)
|
||||
{
|
||||
case RenderTreeFrameType.Component:
|
||||
InitializeNewComponentFrame(ref diffContext, i);
|
||||
|
|
@ -911,29 +893,26 @@ 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];
|
||||
|
||||
if (frame.ComponentState != null)
|
||||
if (frame.ComponentStateField != null)
|
||||
{
|
||||
throw new InvalidOperationException($"Child component already exists during {nameof(InitializeNewComponentFrame)}");
|
||||
}
|
||||
|
||||
var parentComponentId = diffContext.ComponentId;
|
||||
diffContext.Renderer.InstantiateChildComponentOnFrame(ref frame, parentComponentId);
|
||||
var childComponentState = frame.ComponentState;
|
||||
var childComponentState = frame.ComponentStateField;
|
||||
|
||||
// Set initial parameters
|
||||
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)
|
||||
|
|
@ -942,9 +921,9 @@ namespace Microsoft.AspNetCore.Components.RenderTree
|
|||
//
|
||||
// We're following a simple heuristic here that's reflected in the ts runtime
|
||||
// based on the common usage of attributes for DOM events.
|
||||
if ((newFrame.AttributeValue is MulticastDelegate || newFrame.AttributeValue is EventCallback) &&
|
||||
newFrame.AttributeName.Length >= 3 &&
|
||||
newFrame.AttributeName.StartsWith("on"))
|
||||
if ((newFrame.AttributeValueField is MulticastDelegate || newFrame.AttributeValueField is EventCallback) &&
|
||||
newFrame.AttributeNameField.Length >= 3 &&
|
||||
newFrame.AttributeNameField.StartsWith("on", StringComparison.Ordinal))
|
||||
{
|
||||
diffContext.Renderer.AssignEventHandlerId(ref newFrame);
|
||||
}
|
||||
|
|
@ -953,14 +932,14 @@ namespace Microsoft.AspNetCore.Components.RenderTree
|
|||
private static void InitializeNewElementReferenceCaptureFrame(ref DiffContext diffContext, ref RenderTreeFrame newFrame)
|
||||
{
|
||||
var newElementReference = ElementReference.CreateWithUniqueId(diffContext.Renderer.ElementReferenceContext);
|
||||
newFrame = newFrame.WithElementReferenceCaptureId(newElementReference.Id);
|
||||
newFrame.ElementReferenceCaptureAction(newElementReference);
|
||||
newFrame.ElementReferenceCaptureIdField = newElementReference.Id;
|
||||
newFrame.ElementReferenceCaptureActionField(newElementReference);
|
||||
}
|
||||
|
||||
private static void InitializeNewComponentReferenceCaptureFrame(ref DiffContext diffContext, ref RenderTreeFrame newFrame)
|
||||
{
|
||||
ref var parentFrame = ref diffContext.NewTree[newFrame.ComponentReferenceCaptureParentFrameIndex];
|
||||
if (parentFrame.FrameType != RenderTreeFrameType.Component)
|
||||
ref var parentFrame = ref diffContext.NewTree[newFrame.ComponentReferenceCaptureParentFrameIndexField];
|
||||
if (parentFrame.FrameTypeField != RenderTreeFrameType.Component)
|
||||
{
|
||||
// Should never happen, but will help with diagnosis if it does
|
||||
throw new InvalidOperationException($"{nameof(RenderTreeFrameType.ComponentReferenceCapture)} frame references invalid parent index.");
|
||||
|
|
@ -973,25 +952,23 @@ namespace Microsoft.AspNetCore.Components.RenderTree
|
|||
throw new InvalidOperationException($"Trying to initialize {nameof(RenderTreeFrameType.ComponentReferenceCapture)} frame before parent component was assigned.");
|
||||
}
|
||||
|
||||
newFrame.ComponentReferenceCaptureAction(componentInstance);
|
||||
newFrame.ComponentReferenceCaptureActionField(componentInstance);
|
||||
}
|
||||
|
||||
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];
|
||||
if (frame.FrameType == RenderTreeFrameType.Component && frame.ComponentState != null)
|
||||
if (frame.FrameTypeField == RenderTreeFrameType.Component && frame.ComponentStateField != null)
|
||||
{
|
||||
batchBuilder.ComponentDisposalQueue.Enqueue(frame.ComponentId);
|
||||
batchBuilder.ComponentDisposalQueue.Enqueue(frame.ComponentIdField);
|
||||
}
|
||||
else if (frame.FrameType == RenderTreeFrameType.Attribute && frame.AttributeEventHandlerId > 0)
|
||||
else if (frame.FrameTypeField == RenderTreeFrameType.Attribute && frame.AttributeEventHandlerIdField > 0)
|
||||
{
|
||||
batchBuilder.DisposedEventHandlerIds.Append(frame.AttributeEventHandlerId);
|
||||
batchBuilder.DisposedEventHandlerIds.Append(frame.AttributeEventHandlerIdField);
|
||||
}
|
||||
}
|
||||
ProfilingEnd();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -1033,18 +1010,5 @@ 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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ namespace Microsoft.AspNetCore.Components.RenderTree
|
|||
//
|
||||
// Represents an entry in a tree of user interface (UI) items.
|
||||
[StructLayout(LayoutKind.Explicit, Pack = 4)]
|
||||
public readonly struct RenderTreeFrame
|
||||
public struct RenderTreeFrame
|
||||
{
|
||||
// Note that the struct layout has to be valid in both 32-bit and 64-bit runtime platforms,
|
||||
// which means that all reference-type fields need to take up 8 bytes (except for the last
|
||||
|
|
@ -48,72 +48,86 @@ namespace Microsoft.AspNetCore.Components.RenderTree
|
|||
// Common
|
||||
// --------------------------------------------------------------------------------
|
||||
|
||||
[FieldOffset(0)] internal int SequenceField;
|
||||
[FieldOffset(4)] internal RenderTreeFrameType FrameTypeField;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the sequence number of the frame. Sequence numbers indicate the relative source
|
||||
/// positions of the instructions that inserted the frames. Sequence numbers are only
|
||||
/// comparable within the same sequence (typically, the same source method).
|
||||
/// </summary>
|
||||
[FieldOffset(0)] public readonly int Sequence;
|
||||
public int Sequence => SequenceField;
|
||||
|
||||
/// <summary>
|
||||
/// Describes the type of this frame.
|
||||
/// </summary>
|
||||
[FieldOffset(4)] public readonly RenderTreeFrameType FrameType;
|
||||
public RenderTreeFrameType FrameType => FrameTypeField;
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
// RenderTreeFrameType.Element
|
||||
// --------------------------------------------------------------------------------
|
||||
|
||||
[FieldOffset(8)] internal int ElementSubtreeLengthField;
|
||||
[FieldOffset(16)] internal string ElementNameField;
|
||||
[FieldOffset(24)] internal object ElementKeyField;
|
||||
|
||||
/// <summary>
|
||||
/// If the <see cref="FrameType"/> property equals <see cref="RenderTreeFrameType.Element"/>
|
||||
/// gets the number of frames in the subtree for which this frame is the root.
|
||||
/// The value is zero if the frame has not yet been closed.
|
||||
/// </summary>
|
||||
[FieldOffset(8)] public readonly int ElementSubtreeLength;
|
||||
public int ElementSubtreeLength => ElementSubtreeLengthField;
|
||||
|
||||
/// <summary>
|
||||
/// If the <see cref="FrameType"/> property equals <see cref="RenderTreeFrameType.Element"/>,
|
||||
/// gets a name representing the type of the element. Otherwise, the value is undefined.
|
||||
/// </summary>
|
||||
[FieldOffset(16)] public readonly string ElementName;
|
||||
public string ElementName => ElementNameField;
|
||||
|
||||
/// <summary>
|
||||
/// If the <see cref="FrameType"/> property equals <see cref="RenderTreeFrameType.Element"/>,
|
||||
/// gets the element's diffing key, or null if none was specified.
|
||||
/// </summary>
|
||||
[FieldOffset(24)] public readonly object ElementKey;
|
||||
public object ElementKey => ElementKeyField;
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
// RenderTreeFrameType.Text
|
||||
// --------------------------------------------------------------------------------
|
||||
|
||||
[FieldOffset(16)] internal string TextContentField;
|
||||
|
||||
/// <summary>
|
||||
/// If the <see cref="FrameType"/> property equals <see cref="RenderTreeFrameType.Text"/>,
|
||||
/// gets the content of the text frame. Otherwise, the value is undefined.
|
||||
/// </summary>
|
||||
[FieldOffset(16)] public readonly string TextContent;
|
||||
public string TextContent => TextContentField;
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
// RenderTreeFrameType.Attribute
|
||||
// --------------------------------------------------------------------------------
|
||||
|
||||
[FieldOffset(8)] internal ulong AttributeEventHandlerIdField;
|
||||
[FieldOffset(16)] internal string AttributeNameField;
|
||||
[FieldOffset(24)] internal object AttributeValueField;
|
||||
[FieldOffset(32)] internal string AttributeEventUpdatesAttributeNameField;
|
||||
|
||||
/// <summary>
|
||||
/// If the <see cref="FrameType"/> property equals <see cref="RenderTreeFrameType.Attribute"/>
|
||||
/// gets the ID of the corresponding event handler, if any.
|
||||
/// </summary>
|
||||
[FieldOffset(8)] public readonly ulong AttributeEventHandlerId;
|
||||
public ulong AttributeEventHandlerId => AttributeEventHandlerIdField;
|
||||
|
||||
/// <summary>
|
||||
/// If the <see cref="FrameType"/> property equals <see cref="RenderTreeFrameType.Attribute"/>,
|
||||
/// gets the attribute name. Otherwise, the value is undefined.
|
||||
/// </summary>
|
||||
[FieldOffset(16)] public readonly string AttributeName;
|
||||
public string AttributeName => AttributeNameField;
|
||||
|
||||
/// <summary>
|
||||
/// If the <see cref="FrameType"/> property equals <see cref="RenderTreeFrameType.Attribute"/>,
|
||||
/// gets the attribute value. Otherwise, the value is undefined.
|
||||
/// </summary>
|
||||
[FieldOffset(24)] public readonly object AttributeValue;
|
||||
public object AttributeValue => AttributeValueField;
|
||||
|
||||
/// <summary>
|
||||
/// If the <see cref="FrameType"/> property equals <see cref="RenderTreeFrameType.Attribute"/>,
|
||||
|
|
@ -121,80 +135,94 @@ namespace Microsoft.AspNetCore.Components.RenderTree
|
|||
/// can be updated to represent the UI state prior to executing the event handler. This is
|
||||
/// primarily used in two-way bindings.
|
||||
/// </summary>
|
||||
[FieldOffset(32)] public readonly string AttributeEventUpdatesAttributeName;
|
||||
public string AttributeEventUpdatesAttributeName => AttributeEventUpdatesAttributeNameField;
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
// RenderTreeFrameType.Component
|
||||
// --------------------------------------------------------------------------------
|
||||
|
||||
[FieldOffset(8)] internal int ComponentSubtreeLengthField;
|
||||
[FieldOffset(12)] internal int ComponentIdField;
|
||||
[FieldOffset(16)] internal Type ComponentTypeField;
|
||||
[FieldOffset(24)] internal ComponentState ComponentStateField;
|
||||
[FieldOffset(32)] internal object ComponentKeyField;
|
||||
|
||||
/// <summary>
|
||||
/// If the <see cref="FrameType"/> property equals <see cref="RenderTreeFrameType.Component"/>
|
||||
/// gets the number of frames in the subtree for which this frame is the root.
|
||||
/// The value is zero if the frame has not yet been closed.
|
||||
/// </summary>
|
||||
[FieldOffset(8)] public readonly int ComponentSubtreeLength;
|
||||
public int ComponentSubtreeLength => ComponentSubtreeLengthField;
|
||||
|
||||
/// <summary>
|
||||
/// If the <see cref="FrameType"/> property equals <see cref="RenderTreeFrameType.Component"/>,
|
||||
/// gets the child component instance identifier.
|
||||
/// </summary>
|
||||
[FieldOffset(12)] public readonly int ComponentId;
|
||||
public int ComponentId => ComponentIdField;
|
||||
|
||||
/// <summary>
|
||||
/// If the <see cref="FrameType"/> property equals <see cref="RenderTreeFrameType.Component"/>,
|
||||
/// gets the type of the child component.
|
||||
/// </summary>
|
||||
[FieldOffset(16)] public readonly Type ComponentType;
|
||||
public Type ComponentType => ComponentTypeField;
|
||||
|
||||
/// <summary>
|
||||
/// If the <see cref="FrameType"/> property equals <see cref="RenderTreeFrameType.Component"/>,
|
||||
/// gets the child component state object. Otherwise, the value is undefined.
|
||||
/// </summary>
|
||||
[FieldOffset(24)] internal readonly ComponentState ComponentState;
|
||||
internal ComponentState ComponentState => ComponentStateField;
|
||||
|
||||
/// <summary>
|
||||
/// If the <see cref="FrameType"/> property equals <see cref="RenderTreeFrameType.Component"/>,
|
||||
/// gets the component's diffing key, or null if none was specified.
|
||||
/// </summary>
|
||||
[FieldOffset(32)] public readonly object ComponentKey;
|
||||
public object ComponentKey => ComponentKeyField;
|
||||
|
||||
/// <summary>
|
||||
/// If the <see cref="FrameType"/> property equals <see cref="RenderTreeFrameType.Component"/>,
|
||||
/// gets the child component instance. Otherwise, the value is undefined.
|
||||
/// </summary>
|
||||
public IComponent Component => ComponentState?.Component;
|
||||
public IComponent Component => ComponentStateField?.Component;
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
// RenderTreeFrameType.Region
|
||||
// --------------------------------------------------------------------------------
|
||||
|
||||
[FieldOffset(8)] internal int RegionSubtreeLengthField;
|
||||
|
||||
/// <summary>
|
||||
/// If the <see cref="FrameType"/> property equals <see cref="RenderTreeFrameType.Region"/>
|
||||
/// gets the number of frames in the subtree for which this frame is the root.
|
||||
/// The value is zero if the frame has not yet been closed.
|
||||
/// </summary>
|
||||
[FieldOffset(8)] public readonly int RegionSubtreeLength;
|
||||
public int RegionSubtreeLength => RegionSubtreeLengthField;
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
// RenderTreeFrameType.ElementReferenceCapture
|
||||
// --------------------------------------------------------------------------------
|
||||
|
||||
[FieldOffset(16)] internal string ElementReferenceCaptureIdField;
|
||||
[FieldOffset(24)] internal Action<ElementReference> ElementReferenceCaptureActionField;
|
||||
|
||||
/// <summary>
|
||||
/// If the <see cref="FrameType"/> property equals <see cref="RenderTreeFrameType.ElementReferenceCapture"/>,
|
||||
/// gets the ID of the reference capture. Otherwise, the value is undefined.
|
||||
/// </summary>
|
||||
[FieldOffset(16)] public readonly string ElementReferenceCaptureId;
|
||||
public string ElementReferenceCaptureId => ElementReferenceCaptureIdField;
|
||||
|
||||
/// <summary>
|
||||
/// If the <see cref="FrameType"/> property equals <see cref="RenderTreeFrameType.ElementReferenceCapture"/>,
|
||||
/// gets the action that writes the reference to its target. Otherwise, the value is undefined.
|
||||
/// </summary>
|
||||
[FieldOffset(24)] public readonly Action<ElementReference> ElementReferenceCaptureAction;
|
||||
public Action<ElementReference> ElementReferenceCaptureAction => ElementReferenceCaptureActionField;
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
// RenderTreeFrameType.ComponentReferenceCapture
|
||||
// --------------------------------------------------------------------------------
|
||||
|
||||
[FieldOffset(8)] internal int ComponentReferenceCaptureParentFrameIndexField;
|
||||
[FieldOffset(16)] internal Action<object> ComponentReferenceCaptureActionField;
|
||||
|
||||
/// <summary>
|
||||
/// If the <see cref="FrameType"/> property equals <see cref="RenderTreeFrameType.ComponentReferenceCapture"/>,
|
||||
/// gets the index of the parent frame representing the component being captured. Otherwise, the value is undefined.
|
||||
|
|
@ -205,49 +233,51 @@ namespace Microsoft.AspNetCore.Components.RenderTree
|
|||
/// initialization logic in RenderTreeDiffBuilder to walk the frames hierarchically, then it would know
|
||||
/// the parent index at the point where it wants to initialize the ComponentReferenceCapture frame.
|
||||
/// </summary>
|
||||
[FieldOffset(8)] public readonly int ComponentReferenceCaptureParentFrameIndex;
|
||||
public int ComponentReferenceCaptureParentFrameIndex => ComponentReferenceCaptureParentFrameIndexField;
|
||||
|
||||
/// <summary>
|
||||
/// If the <see cref="FrameType"/> property equals <see cref="RenderTreeFrameType.ComponentReferenceCapture"/>,
|
||||
/// gets the action that writes the reference to its target. Otherwise, the value is undefined.
|
||||
/// </summary>
|
||||
[FieldOffset(16)] public readonly Action<object> ComponentReferenceCaptureAction;
|
||||
public Action<object> ComponentReferenceCaptureAction => ComponentReferenceCaptureActionField;
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
// RenderTreeFrameType.Markup
|
||||
// --------------------------------------------------------------------------------
|
||||
|
||||
[FieldOffset(16)] internal string MarkupContentField;
|
||||
|
||||
/// <summary>
|
||||
/// If the <see cref="FrameType"/> property equals <see cref="RenderTreeFrameType.Markup"/>,
|
||||
/// gets the content of the markup frame. Otherwise, the value is undefined.
|
||||
/// </summary>
|
||||
[FieldOffset(16)] public readonly string MarkupContent;
|
||||
public string MarkupContent => MarkupContentField;
|
||||
|
||||
// Element constructor
|
||||
private RenderTreeFrame(int sequence, int elementSubtreeLength, string elementName, object elementKey)
|
||||
: this()
|
||||
{
|
||||
Sequence = sequence;
|
||||
FrameType = RenderTreeFrameType.Element;
|
||||
ElementSubtreeLength = elementSubtreeLength;
|
||||
ElementName = elementName;
|
||||
ElementKey = elementKey;
|
||||
SequenceField = sequence;
|
||||
FrameTypeField = RenderTreeFrameType.Element;
|
||||
ElementSubtreeLengthField = elementSubtreeLength;
|
||||
ElementNameField = elementName;
|
||||
ElementKeyField = elementKey;
|
||||
}
|
||||
|
||||
// Component constructor
|
||||
private RenderTreeFrame(int sequence, int componentSubtreeLength, Type componentType, ComponentState componentState, object componentKey)
|
||||
: this()
|
||||
{
|
||||
Sequence = sequence;
|
||||
FrameType = RenderTreeFrameType.Component;
|
||||
ComponentSubtreeLength = componentSubtreeLength;
|
||||
ComponentType = componentType;
|
||||
ComponentKey = componentKey;
|
||||
SequenceField = sequence;
|
||||
FrameTypeField = RenderTreeFrameType.Component;
|
||||
ComponentSubtreeLengthField = componentSubtreeLength;
|
||||
ComponentTypeField = componentType;
|
||||
ComponentKeyField = componentKey;
|
||||
|
||||
if (componentState != null)
|
||||
{
|
||||
ComponentState = componentState;
|
||||
ComponentId = componentState.ComponentId;
|
||||
ComponentStateField = componentState;
|
||||
ComponentIdField = componentState.ComponentId;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -255,25 +285,25 @@ namespace Microsoft.AspNetCore.Components.RenderTree
|
|||
private RenderTreeFrame(int sequence, int regionSubtreeLength)
|
||||
: this()
|
||||
{
|
||||
Sequence = sequence;
|
||||
FrameType = RenderTreeFrameType.Region;
|
||||
RegionSubtreeLength = regionSubtreeLength;
|
||||
SequenceField = sequence;
|
||||
FrameTypeField = RenderTreeFrameType.Region;
|
||||
RegionSubtreeLengthField = regionSubtreeLength;
|
||||
}
|
||||
|
||||
// Text/markup constructor
|
||||
private RenderTreeFrame(int sequence, bool isMarkup, string textOrMarkup)
|
||||
: this()
|
||||
{
|
||||
Sequence = sequence;
|
||||
SequenceField = sequence;
|
||||
if (isMarkup)
|
||||
{
|
||||
FrameType = RenderTreeFrameType.Markup;
|
||||
MarkupContent = textOrMarkup;
|
||||
FrameTypeField = RenderTreeFrameType.Markup;
|
||||
MarkupContentField = textOrMarkup;
|
||||
}
|
||||
else
|
||||
{
|
||||
FrameType = RenderTreeFrameType.Text;
|
||||
TextContent = textOrMarkup;
|
||||
FrameTypeField = RenderTreeFrameType.Text;
|
||||
TextContentField = textOrMarkup;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -281,32 +311,32 @@ namespace Microsoft.AspNetCore.Components.RenderTree
|
|||
private RenderTreeFrame(int sequence, string attributeName, object attributeValue, ulong attributeEventHandlerId, string attributeEventUpdatesAttributeName)
|
||||
: this()
|
||||
{
|
||||
FrameType = RenderTreeFrameType.Attribute;
|
||||
Sequence = sequence;
|
||||
AttributeName = attributeName;
|
||||
AttributeValue = attributeValue;
|
||||
AttributeEventHandlerId = attributeEventHandlerId;
|
||||
AttributeEventUpdatesAttributeName = attributeEventUpdatesAttributeName;
|
||||
FrameTypeField = RenderTreeFrameType.Attribute;
|
||||
SequenceField = sequence;
|
||||
AttributeNameField = attributeName;
|
||||
AttributeValueField = attributeValue;
|
||||
AttributeEventHandlerIdField = attributeEventHandlerId;
|
||||
AttributeEventUpdatesAttributeNameField = attributeEventUpdatesAttributeName;
|
||||
}
|
||||
|
||||
// Element reference capture constructor
|
||||
private RenderTreeFrame(int sequence, Action<ElementReference> elementReferenceCaptureAction, string elementReferenceCaptureId)
|
||||
: this()
|
||||
{
|
||||
FrameType = RenderTreeFrameType.ElementReferenceCapture;
|
||||
Sequence = sequence;
|
||||
ElementReferenceCaptureAction = elementReferenceCaptureAction;
|
||||
ElementReferenceCaptureId = elementReferenceCaptureId;
|
||||
FrameTypeField = RenderTreeFrameType.ElementReferenceCapture;
|
||||
SequenceField = sequence;
|
||||
ElementReferenceCaptureActionField = elementReferenceCaptureAction;
|
||||
ElementReferenceCaptureIdField = elementReferenceCaptureId;
|
||||
}
|
||||
|
||||
// Component reference capture constructor
|
||||
private RenderTreeFrame(int sequence, Action<object> componentReferenceCaptureAction, int parentFrameIndex)
|
||||
: this()
|
||||
{
|
||||
FrameType = RenderTreeFrameType.ComponentReferenceCapture;
|
||||
Sequence = sequence;
|
||||
ComponentReferenceCaptureAction = componentReferenceCaptureAction;
|
||||
ComponentReferenceCaptureParentFrameIndex = parentFrameIndex;
|
||||
FrameTypeField = RenderTreeFrameType.ComponentReferenceCapture;
|
||||
SequenceField = sequence;
|
||||
ComponentReferenceCaptureActionField = componentReferenceCaptureAction;
|
||||
ComponentReferenceCaptureParentFrameIndexField = parentFrameIndex;
|
||||
}
|
||||
|
||||
internal static RenderTreeFrame Element(int sequence, string elementName)
|
||||
|
|
@ -337,61 +367,61 @@ namespace Microsoft.AspNetCore.Components.RenderTree
|
|||
=> new RenderTreeFrame(sequence, componentReferenceCaptureAction: componentReferenceCaptureAction, parentFrameIndex: parentFrameIndex);
|
||||
|
||||
internal RenderTreeFrame WithElementSubtreeLength(int elementSubtreeLength)
|
||||
=> new RenderTreeFrame(Sequence, elementSubtreeLength: elementSubtreeLength, ElementName, ElementKey);
|
||||
=> new RenderTreeFrame(SequenceField, elementSubtreeLength: elementSubtreeLength, ElementNameField, ElementKeyField);
|
||||
|
||||
internal RenderTreeFrame WithComponentSubtreeLength(int componentSubtreeLength)
|
||||
=> new RenderTreeFrame(Sequence, componentSubtreeLength: componentSubtreeLength, ComponentType, ComponentState, ComponentKey);
|
||||
=> new RenderTreeFrame(SequenceField, componentSubtreeLength: componentSubtreeLength, ComponentTypeField, ComponentStateField, ComponentKeyField);
|
||||
|
||||
internal RenderTreeFrame WithAttributeSequence(int sequence)
|
||||
=> new RenderTreeFrame(sequence, attributeName: AttributeName, AttributeValue, AttributeEventHandlerId, AttributeEventUpdatesAttributeName);
|
||||
=> new RenderTreeFrame(sequence, attributeName: AttributeNameField, AttributeValueField, AttributeEventHandlerIdField, AttributeEventUpdatesAttributeNameField);
|
||||
|
||||
internal RenderTreeFrame WithComponent(ComponentState componentState)
|
||||
=> new RenderTreeFrame(Sequence, componentSubtreeLength: ComponentSubtreeLength, ComponentType, componentState, ComponentKey);
|
||||
=> new RenderTreeFrame(SequenceField, componentSubtreeLength: ComponentSubtreeLengthField, ComponentTypeField, componentState, ComponentKeyField);
|
||||
|
||||
internal RenderTreeFrame WithAttributeEventHandlerId(ulong eventHandlerId)
|
||||
=> new RenderTreeFrame(Sequence, attributeName: AttributeName, AttributeValue, eventHandlerId, AttributeEventUpdatesAttributeName);
|
||||
=> new RenderTreeFrame(SequenceField, attributeName: AttributeNameField, AttributeValueField, eventHandlerId, AttributeEventUpdatesAttributeNameField);
|
||||
|
||||
internal RenderTreeFrame WithAttributeValue(object attributeValue)
|
||||
=> new RenderTreeFrame(Sequence, attributeName: AttributeName, attributeValue, AttributeEventHandlerId, AttributeEventUpdatesAttributeName);
|
||||
=> new RenderTreeFrame(SequenceField, attributeName: AttributeNameField, attributeValue, AttributeEventHandlerIdField, AttributeEventUpdatesAttributeNameField);
|
||||
|
||||
internal RenderTreeFrame WithAttributeEventUpdatesAttributeName(string attributeUpdatesAttributeName)
|
||||
=> new RenderTreeFrame(Sequence, attributeName: AttributeName, AttributeValue, AttributeEventHandlerId, attributeUpdatesAttributeName);
|
||||
=> new RenderTreeFrame(SequenceField, attributeName: AttributeNameField, AttributeValueField, AttributeEventHandlerIdField, attributeUpdatesAttributeName);
|
||||
|
||||
internal RenderTreeFrame WithRegionSubtreeLength(int regionSubtreeLength)
|
||||
=> new RenderTreeFrame(Sequence, regionSubtreeLength: regionSubtreeLength);
|
||||
=> new RenderTreeFrame(SequenceField, regionSubtreeLength: regionSubtreeLength);
|
||||
|
||||
internal RenderTreeFrame WithElementReferenceCaptureId(string elementReferenceCaptureId)
|
||||
=> new RenderTreeFrame(Sequence, elementReferenceCaptureAction: ElementReferenceCaptureAction, elementReferenceCaptureId);
|
||||
=> new RenderTreeFrame(SequenceField, elementReferenceCaptureAction: ElementReferenceCaptureActionField, elementReferenceCaptureId);
|
||||
|
||||
internal RenderTreeFrame WithElementKey(object elementKey)
|
||||
=> new RenderTreeFrame(Sequence, elementSubtreeLength: ElementSubtreeLength, ElementName, elementKey);
|
||||
=> new RenderTreeFrame(SequenceField, elementSubtreeLength: ElementSubtreeLengthField, ElementNameField, elementKey);
|
||||
|
||||
internal RenderTreeFrame WithComponentKey(object componentKey)
|
||||
=> new RenderTreeFrame(Sequence, componentSubtreeLength: ComponentSubtreeLength, ComponentType, ComponentState, componentKey);
|
||||
=> new RenderTreeFrame(SequenceField, componentSubtreeLength: ComponentSubtreeLengthField, ComponentTypeField, ComponentStateField, componentKey);
|
||||
|
||||
/// <inheritdoc />
|
||||
// Just to be nice for debugging and unit tests.
|
||||
public override string ToString()
|
||||
{
|
||||
switch (FrameType)
|
||||
switch (FrameTypeField)
|
||||
{
|
||||
case RenderTreeFrameType.Attribute:
|
||||
return $"Attribute: (seq={Sequence}, id={AttributeEventHandlerId}) '{AttributeName}'='{AttributeValue}'";
|
||||
|
||||
case RenderTreeFrameType.Component:
|
||||
return $"Component: (seq={Sequence}, key={ComponentKey ?? "(none)"}, len={ComponentSubtreeLength}) {ComponentType}";
|
||||
return $"Component: (seq={Sequence}, key={ComponentKeyField ?? "(none)"}, len={ComponentSubtreeLength}) {ComponentType}";
|
||||
|
||||
case RenderTreeFrameType.Element:
|
||||
return $"Element: (seq={Sequence}, key={ElementKey ?? "(none)"}, len={ElementSubtreeLength}) {ElementName}";
|
||||
return $"Element: (seq={Sequence}, key={ElementKeyField ?? "(none)"}, len={ElementSubtreeLength}) {ElementName}";
|
||||
|
||||
case RenderTreeFrameType.Region:
|
||||
return $"Region: (seq={Sequence}, len={RegionSubtreeLength})";
|
||||
|
||||
case RenderTreeFrameType.Text:
|
||||
return $"Text: (seq={Sequence}, len=n/a) {EscapeNewlines(TextContent)}";
|
||||
return $"Text: (seq={Sequence}, len=n/a) {EscapeNewlines(TextContentField)}";
|
||||
|
||||
case RenderTreeFrameType.Markup:
|
||||
return $"Markup: (seq={Sequence}, len=n/a) {EscapeNewlines(TextContent)}";
|
||||
return $"Markup: (seq={Sequence}, len=n/a) {EscapeNewlines(TextContentField)}";
|
||||
|
||||
case RenderTreeFrameType.ElementReferenceCapture:
|
||||
return $"ElementReferenceCapture: (seq={Sequence}, len=n/a) {ElementReferenceCaptureAction}";
|
||||
|
|
|
|||
|
|
@ -0,0 +1,137 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.RenderTree
|
||||
{
|
||||
/// <summary>
|
||||
/// A special subclass of <see cref="ArrayBuilder{T}"/> that contains methods optimized for appending <see cref="RenderTreeFrame"/> entries.
|
||||
/// </summary>
|
||||
internal class RenderTreeFrameArrayBuilder : ArrayBuilder<RenderTreeFrame>
|
||||
{
|
||||
// You may notice a repeated block at the top of each of these methods. This is intentionally inlined into each
|
||||
// method because doing so improves intensive rendering scenarios by around 1% (based on the FastGrid benchmark).
|
||||
|
||||
public void AppendElement(int sequence, string elementName)
|
||||
{
|
||||
if (_itemsInUse == _items.Length)
|
||||
{
|
||||
GrowBuffer(_items.Length * 2);
|
||||
}
|
||||
|
||||
_items[_itemsInUse++] = new RenderTreeFrame
|
||||
{
|
||||
SequenceField = sequence,
|
||||
FrameTypeField = RenderTreeFrameType.Element,
|
||||
ElementNameField = elementName,
|
||||
};
|
||||
}
|
||||
|
||||
public void AppendText(int sequence, string textContent)
|
||||
{
|
||||
if (_itemsInUse == _items.Length)
|
||||
{
|
||||
GrowBuffer(_items.Length * 2);
|
||||
}
|
||||
|
||||
_items[_itemsInUse++] = new RenderTreeFrame
|
||||
{
|
||||
SequenceField = sequence,
|
||||
FrameTypeField = RenderTreeFrameType.Text,
|
||||
TextContentField = textContent,
|
||||
};
|
||||
}
|
||||
|
||||
public void AppendMarkup(int sequence, string markupContent)
|
||||
{
|
||||
if (_itemsInUse == _items.Length)
|
||||
{
|
||||
GrowBuffer(_items.Length * 2);
|
||||
}
|
||||
|
||||
_items[_itemsInUse++] = new RenderTreeFrame
|
||||
{
|
||||
SequenceField = sequence,
|
||||
FrameTypeField = RenderTreeFrameType.Markup,
|
||||
MarkupContentField = markupContent,
|
||||
};
|
||||
}
|
||||
|
||||
public void AppendAttribute(int sequence, string attributeName, object? attributeValue)
|
||||
{
|
||||
if (_itemsInUse == _items.Length)
|
||||
{
|
||||
GrowBuffer(_items.Length * 2);
|
||||
}
|
||||
|
||||
_items[_itemsInUse++] = new RenderTreeFrame
|
||||
{
|
||||
SequenceField = sequence,
|
||||
FrameTypeField = RenderTreeFrameType.Attribute,
|
||||
AttributeNameField = attributeName,
|
||||
AttributeValueField = attributeValue,
|
||||
};
|
||||
}
|
||||
|
||||
public void AppendComponent(int sequence, Type componentType)
|
||||
{
|
||||
if (_itemsInUse == _items.Length)
|
||||
{
|
||||
GrowBuffer(_items.Length * 2);
|
||||
}
|
||||
|
||||
_items[_itemsInUse++] = new RenderTreeFrame
|
||||
{
|
||||
SequenceField = sequence,
|
||||
FrameTypeField = RenderTreeFrameType.Component,
|
||||
ComponentTypeField = componentType,
|
||||
};
|
||||
}
|
||||
|
||||
public void AppendElementReferenceCapture(int sequence, Action<ElementReference> elementReferenceCaptureAction)
|
||||
{
|
||||
if (_itemsInUse == _items.Length)
|
||||
{
|
||||
GrowBuffer(_items.Length * 2);
|
||||
}
|
||||
|
||||
_items[_itemsInUse++] = new RenderTreeFrame
|
||||
{
|
||||
SequenceField = sequence,
|
||||
FrameTypeField = RenderTreeFrameType.ElementReferenceCapture,
|
||||
ElementReferenceCaptureActionField = elementReferenceCaptureAction,
|
||||
};
|
||||
}
|
||||
|
||||
public void AppendComponentReferenceCapture(int sequence, Action<object?> componentReferenceCaptureAction, int parentFrameIndexValue)
|
||||
{
|
||||
if (_itemsInUse == _items.Length)
|
||||
{
|
||||
GrowBuffer(_items.Length * 2);
|
||||
}
|
||||
|
||||
_items[_itemsInUse++] = new RenderTreeFrame
|
||||
{
|
||||
SequenceField = sequence,
|
||||
FrameTypeField = RenderTreeFrameType.ComponentReferenceCapture,
|
||||
ComponentReferenceCaptureActionField = componentReferenceCaptureAction,
|
||||
ComponentReferenceCaptureParentFrameIndexField = parentFrameIndexValue,
|
||||
};
|
||||
}
|
||||
|
||||
public void AppendRegion(int sequence)
|
||||
{
|
||||
if (_itemsInUse == _items.Length)
|
||||
{
|
||||
GrowBuffer(_items.Length * 2);
|
||||
}
|
||||
|
||||
_items[_itemsInUse++] = new RenderTreeFrame
|
||||
{
|
||||
SequenceField = sequence,
|
||||
FrameTypeField = RenderTreeFrameType.Region,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -8,7 +8,6 @@ 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.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
|
@ -247,7 +246,6 @@ 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))
|
||||
|
|
@ -275,7 +273,6 @@ namespace Microsoft.AspNetCore.Components.RenderTree
|
|||
catch (Exception e)
|
||||
{
|
||||
HandleException(e);
|
||||
ComponentsProfiling.Instance.End();
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
finally
|
||||
|
|
@ -290,25 +287,25 @@ 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.
|
||||
var result = GetErrorHandledTask(task);
|
||||
ComponentsProfiling.Instance.End();
|
||||
return result;
|
||||
}
|
||||
|
||||
internal void InstantiateChildComponentOnFrame(ref RenderTreeFrame frame, int parentComponentId)
|
||||
{
|
||||
if (frame.FrameType != RenderTreeFrameType.Component)
|
||||
if (frame.FrameTypeField != RenderTreeFrameType.Component)
|
||||
{
|
||||
throw new ArgumentException($"The frame's {nameof(RenderTreeFrame.FrameType)} property must equal {RenderTreeFrameType.Component}", nameof(frame));
|
||||
}
|
||||
|
||||
if (frame.ComponentState != null)
|
||||
if (frame.ComponentStateField != null)
|
||||
{
|
||||
throw new ArgumentException($"The frame already has a non-null component instance", nameof(frame));
|
||||
}
|
||||
|
||||
var newComponent = InstantiateComponent(frame.ComponentType);
|
||||
var newComponent = InstantiateComponent(frame.ComponentTypeField);
|
||||
var newComponentState = AttachAndInitComponent(newComponent, parentComponentId);
|
||||
frame = frame.WithComponent(newComponentState);
|
||||
frame.ComponentStateField = newComponentState;
|
||||
frame.ComponentIdField = newComponentState.ComponentId;
|
||||
}
|
||||
|
||||
internal void AddToPendingTasks(Task task)
|
||||
|
|
@ -346,7 +343,7 @@ namespace Microsoft.AspNetCore.Components.RenderTree
|
|||
{
|
||||
var id = ++_lastEventHandlerId;
|
||||
|
||||
if (frame.AttributeValue is EventCallback callback)
|
||||
if (frame.AttributeValueField is EventCallback callback)
|
||||
{
|
||||
// We hit this case when a EventCallback object is produced that needs an explicit receiver.
|
||||
// Common cases for this are "chained bind" or "chained event handler" when a component
|
||||
|
|
@ -356,7 +353,7 @@ namespace Microsoft.AspNetCore.Components.RenderTree
|
|||
// the receiver.
|
||||
_eventBindings.Add(id, callback);
|
||||
}
|
||||
else if (frame.AttributeValue is MulticastDelegate @delegate)
|
||||
else if (frame.AttributeValueField is MulticastDelegate @delegate)
|
||||
{
|
||||
// This is the common case for a delegate, where the receiver of the event
|
||||
// is the same as delegate.Target. In this case since the receiver is implicit we can
|
||||
|
|
@ -368,7 +365,7 @@ namespace Microsoft.AspNetCore.Components.RenderTree
|
|||
// NOTE: we do not to handle EventCallback<T> here. EventCallback<T> is only used when passing
|
||||
// a callback to a component, and never when used to attaching a DOM event handler.
|
||||
|
||||
frame = frame.WithAttributeEventHandlerId(id);
|
||||
frame.AttributeEventHandlerIdField = id;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -441,7 +438,6 @@ namespace Microsoft.AspNetCore.Components.RenderTree
|
|||
|
||||
private void ProcessRenderQueue()
|
||||
{
|
||||
ComponentsProfiling.Instance.Start();
|
||||
Dispatcher.AssertAccess();
|
||||
|
||||
if (_isBatchInProgress)
|
||||
|
|
@ -456,7 +452,6 @@ namespace Microsoft.AspNetCore.Components.RenderTree
|
|||
{
|
||||
if (_batchBuilder.ComponentRenderQueue.Count == 0)
|
||||
{
|
||||
ComponentsProfiling.Instance.End();
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -468,9 +463,7 @@ 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.
|
||||
|
|
@ -480,7 +473,6 @@ namespace Microsoft.AspNetCore.Components.RenderTree
|
|||
{
|
||||
// Ensure we catch errors while running the render functions of the components.
|
||||
HandleException(e);
|
||||
ComponentsProfiling.Instance.End();
|
||||
return;
|
||||
}
|
||||
finally
|
||||
|
|
@ -498,7 +490,6 @@ namespace Microsoft.AspNetCore.Components.RenderTree
|
|||
{
|
||||
ProcessRenderQueue();
|
||||
}
|
||||
ComponentsProfiling.Instance.End();
|
||||
}
|
||||
|
||||
private Task InvokeRenderCompletedCalls(ArrayRange<RenderTreeDiff> updatedComponents, Task updateDisplayTask)
|
||||
|
|
@ -634,11 +625,43 @@ namespace Microsoft.AspNetCore.Components.RenderTree
|
|||
var disposeComponentId = _batchBuilder.ComponentDisposalQueue.Dequeue();
|
||||
var disposeComponentState = GetRequiredComponentState(disposeComponentId);
|
||||
Log.DisposingComponent(_logger, disposeComponentState);
|
||||
if (!disposeComponentState.TryDisposeInBatch(_batchBuilder, out var exception))
|
||||
if (!(disposeComponentState.Component is IAsyncDisposable))
|
||||
{
|
||||
exceptions ??= new List<Exception>();
|
||||
exceptions.Add(exception);
|
||||
if (!disposeComponentState.TryDisposeInBatch(_batchBuilder, out var exception))
|
||||
{
|
||||
exceptions ??= new List<Exception>();
|
||||
exceptions.Add(exception);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var result = disposeComponentState.DisposeInBatchAsync(_batchBuilder);
|
||||
if (result.IsCompleted)
|
||||
{
|
||||
if (!result.IsCompletedSuccessfully)
|
||||
{
|
||||
exceptions ??= new List<Exception>();
|
||||
exceptions.Add(result.Exception);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AddToPendingTasks(GetHandledAsynchronousDisposalErrorsTask(result));
|
||||
|
||||
async Task GetHandledAsynchronousDisposalErrorsTask(Task result)
|
||||
{
|
||||
try
|
||||
{
|
||||
await result;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
HandleException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_componentStateById.Remove(disposeComponentId);
|
||||
_batchBuilder.DisposedComponentIds.Append(disposeComponentId);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ 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
|
||||
|
|
@ -57,7 +56,6 @@ 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)
|
||||
|
|
@ -69,9 +67,7 @@ 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,
|
||||
|
|
@ -81,7 +77,6 @@ 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)
|
||||
|
|
@ -101,6 +96,13 @@ namespace Microsoft.AspNetCore.Components.Rendering
|
|||
exception = ex;
|
||||
}
|
||||
|
||||
CleanupComponentStateResources(batchBuilder);
|
||||
|
||||
return exception == null;
|
||||
}
|
||||
|
||||
private void CleanupComponentStateResources(RenderBatchBuilder batchBuilder)
|
||||
{
|
||||
// We don't expect these things to throw.
|
||||
RenderTreeDiffBuilder.DisposeFrames(batchBuilder, CurrentRenderTree.GetFrames());
|
||||
|
||||
|
|
@ -110,8 +112,6 @@ namespace Microsoft.AspNetCore.Components.Rendering
|
|||
}
|
||||
|
||||
DisposeBuffers();
|
||||
|
||||
return exception == null;
|
||||
}
|
||||
|
||||
// Callers expect this method to always return a faulted task.
|
||||
|
|
@ -222,5 +222,31 @@ namespace Microsoft.AspNetCore.Components.Rendering
|
|||
((IDisposable)CurrentRenderTree).Dispose();
|
||||
_latestDirectParametersSnapshot?.Dispose();
|
||||
}
|
||||
|
||||
public Task DisposeInBatchAsync(RenderBatchBuilder batchBuilder)
|
||||
{
|
||||
_componentWasDisposed = true;
|
||||
|
||||
CleanupComponentStateResources(batchBuilder);
|
||||
|
||||
try
|
||||
{
|
||||
var result = ((IAsyncDisposable)Component).DisposeAsync();
|
||||
if (result.IsCompletedSuccessfully)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
else
|
||||
{
|
||||
// We know we are dealing with an exception that happened asynchronously, so return a task
|
||||
// to the caller so that he can unwrap it.
|
||||
return result.AsTask();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return Task.FromException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ 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
|
||||
|
|
@ -24,7 +23,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
|
|||
private readonly static object BoxedFalse = false;
|
||||
private readonly static string ComponentReferenceCaptureInvalidParentMessage = $"Component reference captures may only be added as children of frames of type {RenderTreeFrameType.Component}";
|
||||
|
||||
private readonly ArrayBuilder<RenderTreeFrame> _entries = new ArrayBuilder<RenderTreeFrame>();
|
||||
private readonly RenderTreeFrameArrayBuilder _entries = new RenderTreeFrameArrayBuilder();
|
||||
private readonly Stack<int> _openElementIndices = new Stack<int>();
|
||||
private RenderTreeFrameType? _lastNonAttributeFrameType;
|
||||
private bool _hasSeenAddMultipleAttributes;
|
||||
|
|
@ -45,7 +44,6 @@ 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)
|
||||
|
|
@ -55,8 +53,8 @@ namespace Microsoft.AspNetCore.Components.Rendering
|
|||
}
|
||||
|
||||
_openElementIndices.Push(_entries.Count);
|
||||
Append(RenderTreeFrame.Element(sequence, elementName));
|
||||
ProfilingEnd();
|
||||
_entries.AppendElement(sequence, elementName);
|
||||
_lastNonAttributeFrameType = RenderTreeFrameType.Element;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -65,7 +63,6 @@ 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
|
||||
|
|
@ -75,9 +72,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
|
|||
ProcessDuplicateAttributes(first: indexOfEntryBeingClosed + 1);
|
||||
}
|
||||
|
||||
ref var entry = ref _entries.Buffer[indexOfEntryBeingClosed];
|
||||
entry = entry.WithElementSubtreeLength(_entries.Count - indexOfEntryBeingClosed);
|
||||
ProfilingEnd();
|
||||
_entries.Buffer[indexOfEntryBeingClosed].ElementSubtreeLengthField = _entries.Count - indexOfEntryBeingClosed;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -87,9 +82,8 @@ namespace Microsoft.AspNetCore.Components.Rendering
|
|||
/// <param name="markupContent">Content for the new markup frame.</param>
|
||||
public void AddMarkupContent(int sequence, string? markupContent)
|
||||
{
|
||||
ProfilingStart();
|
||||
Append(RenderTreeFrame.Markup(sequence, markupContent ?? string.Empty));
|
||||
ProfilingEnd();
|
||||
_entries.AppendMarkup(sequence, markupContent ?? string.Empty);
|
||||
_lastNonAttributeFrameType = RenderTreeFrameType.Markup;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -99,9 +93,8 @@ namespace Microsoft.AspNetCore.Components.Rendering
|
|||
/// <param name="textContent">Content for the new text frame.</param>
|
||||
public void AddContent(int sequence, string? textContent)
|
||||
{
|
||||
ProfilingStart();
|
||||
Append(RenderTreeFrame.Text(sequence, textContent ?? string.Empty));
|
||||
ProfilingEnd();
|
||||
_entries.AppendText(sequence, textContent ?? string.Empty);
|
||||
_lastNonAttributeFrameType = RenderTreeFrameType.Text;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -111,7 +104,6 @@ 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
|
||||
|
|
@ -122,7 +114,6 @@ namespace Microsoft.AspNetCore.Components.Rendering
|
|||
fragment(this);
|
||||
CloseRegion();
|
||||
}
|
||||
ProfilingEnd();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -133,12 +124,10 @@ 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>
|
||||
|
|
@ -169,15 +158,13 @@ namespace Microsoft.AspNetCore.Components.Rendering
|
|||
/// <param name="name">The name of the attribute.</param>
|
||||
public void AddAttribute(int sequence, string name)
|
||||
{
|
||||
ProfilingStart();
|
||||
|
||||
if (_lastNonAttributeFrameType != RenderTreeFrameType.Element)
|
||||
{
|
||||
throw new InvalidOperationException($"Valueless attributes may only be added immediately after frames of type {RenderTreeFrameType.Element}");
|
||||
}
|
||||
|
||||
Append(RenderTreeFrame.Attribute(sequence, name, BoxedTrue));
|
||||
ProfilingEnd();
|
||||
|
||||
_entries.AppendAttribute(sequence, name, BoxedTrue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -194,23 +181,21 @@ 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)
|
||||
{
|
||||
Append(RenderTreeFrame.Attribute(sequence, name, value ? BoxedTrue : BoxedFalse));
|
||||
_entries.AppendAttribute(sequence, name, value ? BoxedTrue : BoxedFalse);
|
||||
}
|
||||
else if (value)
|
||||
{
|
||||
// Don't add 'false' attributes for elements. We want booleans to map to the presence
|
||||
// or absence of an attribute, and false => "False" which isn't falsy in js.
|
||||
Append(RenderTreeFrame.Attribute(sequence, name, BoxedTrue));
|
||||
_entries.AppendAttribute(sequence, name, BoxedTrue);
|
||||
}
|
||||
else
|
||||
{
|
||||
TrackAttributeName(name);
|
||||
}
|
||||
ProfilingEnd();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -227,17 +212,15 @@ 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)
|
||||
{
|
||||
Append(RenderTreeFrame.Attribute(sequence, name, value));
|
||||
_entries.AppendAttribute(sequence, name, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
TrackAttributeName(name);
|
||||
}
|
||||
ProfilingEnd();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -254,17 +237,15 @@ 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)
|
||||
{
|
||||
Append(RenderTreeFrame.Attribute(sequence, name, value));
|
||||
_entries.AppendAttribute(sequence, name, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
TrackAttributeName(name);
|
||||
}
|
||||
ProfilingEnd();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -285,32 +266,30 @@ namespace Microsoft.AspNetCore.Components.Rendering
|
|||
/// </remarks>
|
||||
public void AddAttribute(int sequence, string name, EventCallback value)
|
||||
{
|
||||
ProfilingStart();
|
||||
AssertCanAddAttribute();
|
||||
if (_lastNonAttributeFrameType == RenderTreeFrameType.Component)
|
||||
{
|
||||
// Since this is a component, we need to preserve the type of the EventCallback, so we have
|
||||
// to box.
|
||||
Append(RenderTreeFrame.Attribute(sequence, name, (object)value));
|
||||
_entries.AppendAttribute(sequence, name, value);
|
||||
}
|
||||
else if (value.RequiresExplicitReceiver)
|
||||
{
|
||||
// If we need to preserve the receiver, we just box the EventCallback
|
||||
// so we can get it out on the other side.
|
||||
Append(RenderTreeFrame.Attribute(sequence, name, (object)value));
|
||||
_entries.AppendAttribute(sequence, name, value);
|
||||
}
|
||||
else if (value.HasDelegate)
|
||||
{
|
||||
// In the common case the receiver is also the delegate's target, so we
|
||||
// just need to retain the delegate. This allows us to avoid an allocation.
|
||||
Append(RenderTreeFrame.Attribute(sequence, name, value.Delegate));
|
||||
_entries.AppendAttribute(sequence, name, value.Delegate);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Track the attribute name if needed since we elided the frame.
|
||||
TrackAttributeName(name);
|
||||
}
|
||||
ProfilingEnd();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -331,32 +310,30 @@ namespace Microsoft.AspNetCore.Components.Rendering
|
|||
/// </remarks>
|
||||
public void AddAttribute<TArgument>(int sequence, string name, EventCallback<TArgument> value)
|
||||
{
|
||||
ProfilingStart();
|
||||
AssertCanAddAttribute();
|
||||
if (_lastNonAttributeFrameType == RenderTreeFrameType.Component)
|
||||
{
|
||||
// Since this is a component, we need to preserve the type of the EventCallback, so we have
|
||||
// to box.
|
||||
Append(RenderTreeFrame.Attribute(sequence, name, (object)value));
|
||||
_entries.AppendAttribute(sequence, name, value);
|
||||
}
|
||||
else if (value.RequiresExplicitReceiver)
|
||||
{
|
||||
// If we need to preserve the receiver - we convert this to an untyped EventCallback. We don't
|
||||
// need to preserve the type of an EventCallback<T> when it's invoked from the DOM.
|
||||
Append(RenderTreeFrame.Attribute(sequence, name, (object)value.AsUntyped()));
|
||||
_entries.AppendAttribute(sequence, name, value.AsUntyped());
|
||||
}
|
||||
else if (value.HasDelegate)
|
||||
{
|
||||
// In the common case the receiver is also the delegate's target, so we
|
||||
// just need to retain the delegate. This allows us to avoid an allocation.
|
||||
Append(RenderTreeFrame.Attribute(sequence, name, value.Delegate));
|
||||
_entries.AppendAttribute(sequence, name, value.Delegate);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Track the attribute name if needed since we elided the frame.
|
||||
TrackAttributeName(name);
|
||||
}
|
||||
ProfilingEnd();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -370,7 +347,6 @@ 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)
|
||||
|
|
@ -384,7 +360,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
|
|||
{
|
||||
if (boolValue)
|
||||
{
|
||||
Append(RenderTreeFrame.Attribute(sequence, name, BoxedTrue));
|
||||
_entries.AppendAttribute(sequence, name, BoxedTrue);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -396,7 +372,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
|
|||
{
|
||||
if (callbackValue.HasDelegate)
|
||||
{
|
||||
Append(RenderTreeFrame.Attribute(sequence, name, callbackValue.UnpackForRenderTree()));
|
||||
_entries.AppendAttribute(sequence, name, callbackValue.UnpackForRenderTree());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -405,25 +381,24 @@ namespace Microsoft.AspNetCore.Components.Rendering
|
|||
}
|
||||
else if (value is MulticastDelegate)
|
||||
{
|
||||
Append(RenderTreeFrame.Attribute(sequence, name, value));
|
||||
_entries.AppendAttribute(sequence, name, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
// The value is either a string, or should be treated as a string.
|
||||
Append(RenderTreeFrame.Attribute(sequence, name, value.ToString()));
|
||||
_entries.AppendAttribute(sequence, name, value.ToString());
|
||||
}
|
||||
}
|
||||
else if (_lastNonAttributeFrameType == RenderTreeFrameType.Component)
|
||||
{
|
||||
// If this is a component, we always want to preserve the original type.
|
||||
Append(RenderTreeFrame.Attribute(sequence, name, value));
|
||||
_entries.AppendAttribute(sequence, name, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
// This is going to throw. Calling it just to get a consistent exception message.
|
||||
AssertCanAddAttribute();
|
||||
}
|
||||
ProfilingEnd();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -436,17 +411,16 @@ namespace Microsoft.AspNetCore.Components.Rendering
|
|||
/// </summary>
|
||||
/// <param name="sequence">An integer that represents the position of the instruction in the source code.</param>
|
||||
/// <param name="frame">A <see cref="RenderTreeFrame"/> holding the name and value of the attribute.</param>
|
||||
public void AddAttribute(int sequence, in RenderTreeFrame frame)
|
||||
public void AddAttribute(int sequence, RenderTreeFrame frame)
|
||||
{
|
||||
ProfilingStart();
|
||||
if (frame.FrameType != RenderTreeFrameType.Attribute)
|
||||
if (frame.FrameTypeField != RenderTreeFrameType.Attribute)
|
||||
{
|
||||
throw new ArgumentException($"The {nameof(frame.FrameType)} must be {RenderTreeFrameType.Attribute}.");
|
||||
}
|
||||
|
||||
AssertCanAddAttribute();
|
||||
Append(frame.WithAttributeSequence(sequence));
|
||||
ProfilingEnd();
|
||||
frame.SequenceField = sequence;
|
||||
_entries.Append(frame);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -456,7 +430,6 @@ 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();
|
||||
|
||||
|
|
@ -473,7 +446,6 @@ namespace Microsoft.AspNetCore.Components.Rendering
|
|||
AddAttribute(sequence, attribute.Key, attribute.Value);
|
||||
}
|
||||
}
|
||||
ProfilingEnd();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -490,20 +462,18 @@ 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.");
|
||||
}
|
||||
|
||||
ref var prevFrame = ref _entries.Buffer[_entries.Count - 1];
|
||||
if (prevFrame.FrameType != RenderTreeFrameType.Attribute)
|
||||
if (prevFrame.FrameTypeField != RenderTreeFrameType.Attribute)
|
||||
{
|
||||
throw new InvalidOperationException($"Incorrect frame type: '{prevFrame.FrameType}'");
|
||||
throw new InvalidOperationException($"Incorrect frame type: '{prevFrame.FrameTypeField}'");
|
||||
}
|
||||
|
||||
prevFrame = prevFrame.WithAttributeEventUpdatesAttributeName(updatesAttributeName);
|
||||
ProfilingEnd();
|
||||
prevFrame.AttributeEventUpdatesAttributeNameField = updatesAttributeName;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -535,12 +505,10 @@ 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;
|
||||
}
|
||||
|
||||
|
|
@ -552,23 +520,21 @@ namespace Microsoft.AspNetCore.Components.Rendering
|
|||
|
||||
var parentFrameIndexValue = parentFrameIndex.Value;
|
||||
ref var parentFrame = ref _entries.Buffer[parentFrameIndexValue];
|
||||
switch (parentFrame.FrameType)
|
||||
switch (parentFrame.FrameTypeField)
|
||||
{
|
||||
case RenderTreeFrameType.Element:
|
||||
parentFrame = parentFrame.WithElementKey(value); // It's a ref var, so this writes to the array
|
||||
parentFrame.ElementKeyField = value; // It's a ref var, so this writes to the array
|
||||
break;
|
||||
case RenderTreeFrameType.Component:
|
||||
parentFrame = parentFrame.WithComponentKey(value); // It's a ref var, so this writes to the array
|
||||
parentFrame.ComponentKeyField = value; // It's a ref var, so this writes to the array
|
||||
break;
|
||||
default:
|
||||
throw new InvalidOperationException($"Cannot set a key on a frame of type {parentFrame.FrameType}.");
|
||||
throw new InvalidOperationException($"Cannot set a key on a frame of type {parentFrame.FrameTypeField}.");
|
||||
}
|
||||
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)
|
||||
|
|
@ -578,8 +544,8 @@ namespace Microsoft.AspNetCore.Components.Rendering
|
|||
}
|
||||
|
||||
_openElementIndices.Push(_entries.Count);
|
||||
Append(RenderTreeFrame.ChildComponent(sequence, componentType));
|
||||
ProfilingEnd();
|
||||
_entries.AppendComponent(sequence, componentType);
|
||||
_lastNonAttributeFrameType = RenderTreeFrameType.Component;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -588,7 +554,6 @@ 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
|
||||
|
|
@ -598,9 +563,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
|
|||
ProcessDuplicateAttributes(first: indexOfEntryBeingClosed + 1);
|
||||
}
|
||||
|
||||
ref var entry = ref _entries.Buffer[indexOfEntryBeingClosed];
|
||||
entry = entry.WithComponentSubtreeLength(_entries.Count - indexOfEntryBeingClosed);
|
||||
ProfilingEnd();
|
||||
_entries.Buffer[indexOfEntryBeingClosed].ComponentSubtreeLengthField = _entries.Count - indexOfEntryBeingClosed;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -610,14 +573,13 @@ 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();
|
||||
_entries.AppendElementReferenceCapture(sequence, elementReferenceCaptureAction);
|
||||
_lastNonAttributeFrameType = RenderTreeFrameType.ElementReferenceCapture;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -627,7 +589,6 @@ 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)
|
||||
{
|
||||
|
|
@ -635,13 +596,13 @@ namespace Microsoft.AspNetCore.Components.Rendering
|
|||
}
|
||||
|
||||
var parentFrameIndexValue = parentFrameIndex.Value;
|
||||
if (_entries.Buffer[parentFrameIndexValue].FrameType != RenderTreeFrameType.Component)
|
||||
if (_entries.Buffer[parentFrameIndexValue].FrameTypeField != RenderTreeFrameType.Component)
|
||||
{
|
||||
throw new InvalidOperationException(ComponentReferenceCaptureInvalidParentMessage);
|
||||
}
|
||||
|
||||
Append(RenderTreeFrame.ComponentReferenceCapture(sequence, componentReferenceCaptureAction, parentFrameIndexValue));
|
||||
ProfilingEnd();
|
||||
_entries.AppendComponentReferenceCapture(sequence, componentReferenceCaptureAction, parentFrameIndexValue);
|
||||
_lastNonAttributeFrameType = RenderTreeFrameType.ComponentReferenceCapture;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -650,7 +611,6 @@ 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)
|
||||
|
|
@ -660,8 +620,8 @@ namespace Microsoft.AspNetCore.Components.Rendering
|
|||
}
|
||||
|
||||
_openElementIndices.Push(_entries.Count);
|
||||
Append(RenderTreeFrame.Region(sequence));
|
||||
ProfilingEnd();
|
||||
_entries.AppendRegion(sequence);
|
||||
_lastNonAttributeFrameType = RenderTreeFrameType.Region;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -670,11 +630,8 @@ 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();
|
||||
_entries.Buffer[indexOfEntryBeingClosed].RegionSubtreeLengthField = _entries.Count - indexOfEntryBeingClosed;
|
||||
}
|
||||
|
||||
private void AssertCanAddAttribute()
|
||||
|
|
@ -693,7 +650,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
|
|||
{
|
||||
var parentIndex = GetCurrentParentFrameIndex();
|
||||
return parentIndex.HasValue
|
||||
? _entries.Buffer[parentIndex.Value].FrameType
|
||||
? _entries.Buffer[parentIndex.Value].FrameTypeField
|
||||
: (RenderTreeFrameType?)null;
|
||||
}
|
||||
|
||||
|
|
@ -702,29 +659,24 @@ 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>
|
||||
|
|
@ -734,21 +686,9 @@ namespace Microsoft.AspNetCore.Components.Rendering
|
|||
public ArrayRange<RenderTreeFrame> GetFrames() =>
|
||||
_entries.ToRange();
|
||||
|
||||
private void Append(in RenderTreeFrame frame)
|
||||
{
|
||||
var frameType = frame.FrameType;
|
||||
_entries.Append(frame);
|
||||
|
||||
if (frameType != RenderTreeFrameType.Attribute)
|
||||
{
|
||||
_lastNonAttributeFrameType = frame.FrameType;
|
||||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
|
|
@ -759,7 +699,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
|
|||
|
||||
for (var i = first; i <= last; i++)
|
||||
{
|
||||
if (buffer[i].FrameType != RenderTreeFrameType.Attribute)
|
||||
if (buffer[i].FrameTypeField != RenderTreeFrameType.Attribute)
|
||||
{
|
||||
last = i - 1;
|
||||
break;
|
||||
|
|
@ -771,12 +711,12 @@ namespace Microsoft.AspNetCore.Components.Rendering
|
|||
for (var i = last; i >= first; i--)
|
||||
{
|
||||
ref var frame = ref buffer[i];
|
||||
Debug.Assert(frame.FrameType == RenderTreeFrameType.Attribute, $"Frame type is {frame.FrameType} at {i}");
|
||||
Debug.Assert(frame.FrameTypeField == RenderTreeFrameType.Attribute, $"Frame type is {frame.FrameTypeField} at {i}");
|
||||
|
||||
if (!seenAttributeNames.TryGetValue(frame.AttributeName, out var index))
|
||||
if (!seenAttributeNames.TryGetValue(frame.AttributeNameField, out var index))
|
||||
{
|
||||
// This is the first time seeing this attribute name. Add to the dictionary and move on.
|
||||
seenAttributeNames.Add(frame.AttributeName, i);
|
||||
seenAttributeNames.Add(frame.AttributeNameField, i);
|
||||
}
|
||||
else if (index < i)
|
||||
{
|
||||
|
|
@ -784,7 +724,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
|
|||
// This is the case for a null event handler, or bool false value.
|
||||
//
|
||||
// We need to update our tracking, in case the attribute appeared 3 or more times.
|
||||
seenAttributeNames[frame.AttributeName] = i;
|
||||
seenAttributeNames[frame.AttributeNameField] = i;
|
||||
}
|
||||
else if (index > i)
|
||||
{
|
||||
|
|
@ -815,7 +755,7 @@ namespace Microsoft.AspNetCore.Components.Rendering
|
|||
for (var i = first; i < _entries.Count; i++)
|
||||
{
|
||||
ref var frame = ref buffer[i];
|
||||
if (frame.FrameType != RenderTreeFrameType.None)
|
||||
if (frame.FrameTypeField != RenderTreeFrameType.None)
|
||||
{
|
||||
buffer[offset++] = frame;
|
||||
}
|
||||
|
|
@ -830,7 +770,6 @@ namespace Microsoft.AspNetCore.Components.Rendering
|
|||
|
||||
seenAttributeNames.Clear();
|
||||
_hasSeenAddMultipleAttributes = false;
|
||||
ProfilingEnd();
|
||||
}
|
||||
|
||||
// Internal for testing
|
||||
|
|
@ -847,22 +786,7 @@ 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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,21 +24,21 @@ namespace Microsoft.AspNetCore.Components.Rendering
|
|||
for (var frameIndex = 0; frameIndex < framesLength; frameIndex++)
|
||||
{
|
||||
ref var frame = ref framesArray[frameIndex];
|
||||
switch (frame.FrameType)
|
||||
switch (frame.FrameTypeField)
|
||||
{
|
||||
case RenderTreeFrameType.Element:
|
||||
closestElementFrameIndex = frameIndex;
|
||||
break;
|
||||
case RenderTreeFrameType.Attribute:
|
||||
if (frame.AttributeEventHandlerId == eventHandlerId)
|
||||
if (frame.AttributeEventHandlerIdField == eventHandlerId)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(frame.AttributeEventUpdatesAttributeName))
|
||||
if (!string.IsNullOrEmpty(frame.AttributeEventUpdatesAttributeNameField))
|
||||
{
|
||||
UpdateFrameToMatchClientState(
|
||||
renderTreeBuilder,
|
||||
framesArray,
|
||||
closestElementFrameIndex,
|
||||
frame.AttributeEventUpdatesAttributeName,
|
||||
frame.AttributeEventUpdatesAttributeNameField,
|
||||
newFieldValue);
|
||||
}
|
||||
|
||||
|
|
@ -55,20 +55,20 @@ namespace Microsoft.AspNetCore.Components.Rendering
|
|||
{
|
||||
// Find the attribute frame
|
||||
ref var elementFrame = ref framesArray[elementFrameIndex];
|
||||
var elementSubtreeEndIndexExcl = elementFrameIndex + elementFrame.ElementSubtreeLength;
|
||||
var elementSubtreeEndIndexExcl = elementFrameIndex + elementFrame.ElementSubtreeLengthField;
|
||||
for (var attributeFrameIndex = elementFrameIndex + 1; attributeFrameIndex < elementSubtreeEndIndexExcl; attributeFrameIndex++)
|
||||
{
|
||||
ref var attributeFrame = ref framesArray[attributeFrameIndex];
|
||||
if (attributeFrame.FrameType != RenderTreeFrameType.Attribute)
|
||||
if (attributeFrame.FrameTypeField != RenderTreeFrameType.Attribute)
|
||||
{
|
||||
// We're now looking at the descendants not attributes, so the search is over
|
||||
break;
|
||||
}
|
||||
|
||||
if (attributeFrame.AttributeName == attributeName)
|
||||
if (attributeFrame.AttributeNameField == attributeName)
|
||||
{
|
||||
// Found an existing attribute we can update
|
||||
attributeFrame = attributeFrame.WithAttributeValue(attributeValue);
|
||||
attributeFrame.AttributeValueField = attributeValue;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -84,25 +84,25 @@ namespace Microsoft.AspNetCore.Components.Rendering
|
|||
for (var otherFrameIndex = elementFrameIndex; otherFrameIndex >= 0; otherFrameIndex--)
|
||||
{
|
||||
ref var otherFrame = ref framesArray[otherFrameIndex];
|
||||
switch (otherFrame.FrameType)
|
||||
switch (otherFrame.FrameTypeField)
|
||||
{
|
||||
case RenderTreeFrameType.Element:
|
||||
{
|
||||
var otherFrameSubtreeLength = otherFrame.ElementSubtreeLength;
|
||||
var otherFrameSubtreeLength = otherFrame.ElementSubtreeLengthField;
|
||||
var otherFrameEndIndexExcl = otherFrameIndex + otherFrameSubtreeLength;
|
||||
if (otherFrameEndIndexExcl > elementFrameIndex) // i.e., contains the element we're inserting into
|
||||
{
|
||||
otherFrame = otherFrame.WithElementSubtreeLength(otherFrameSubtreeLength + 1);
|
||||
otherFrame.ElementSubtreeLengthField = otherFrameSubtreeLength + 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case RenderTreeFrameType.Region:
|
||||
{
|
||||
var otherFrameSubtreeLength = otherFrame.RegionSubtreeLength;
|
||||
var otherFrameSubtreeLength = otherFrame.RegionSubtreeLengthField;
|
||||
var otherFrameEndIndexExcl = otherFrameIndex + otherFrameSubtreeLength;
|
||||
if (otherFrameEndIndexExcl > elementFrameIndex) // i.e., contains the element we're inserting into
|
||||
{
|
||||
otherFrame = otherFrame.WithRegionSubtreeLength(otherFrameSubtreeLength + 1);
|
||||
otherFrame.RegionSubtreeLengthField = otherFrameSubtreeLength + 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ namespace Microsoft.AspNetCore.Components.Routing
|
|||
public override bool Match(string pathSegment, out object? convertedValue)
|
||||
{
|
||||
// Unset values are set to null in the Parameters object created in
|
||||
// the RouteContext. To match this pattern, unset optional parmeters
|
||||
// the RouteContext. To match this pattern, unset optional parameters
|
||||
// are converted to null.
|
||||
if (string.IsNullOrEmpty(pathSegment))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -29,10 +29,20 @@ namespace Microsoft.AspNetCore.Components.Routing
|
|||
|
||||
internal void Match(RouteContext context)
|
||||
{
|
||||
string? catchAllValue = null;
|
||||
|
||||
// If this template contains a catch-all parameter, we can concatenate the pathSegments
|
||||
// at and beyond the catch-all segment's position. For example:
|
||||
// Template: /foo/bar/{*catchAll}
|
||||
// PathSegments: /foo/bar/one/two/three
|
||||
if (Template.ContainsCatchAllSegment && context.Segments.Length >= Template.Segments.Length)
|
||||
{
|
||||
catchAllValue = string.Join('/', context.Segments[Range.StartAt(Template.Segments.Length - 1)]);
|
||||
}
|
||||
// If there are no optional segments on the route and the length of the route
|
||||
// and the template do not match, then there is no chance of this matching and
|
||||
// we can bail early.
|
||||
if (Template.OptionalSegmentsCount == 0 && Template.Segments.Length != context.Segments.Length)
|
||||
else if (Template.OptionalSegmentsCount == 0 && Template.Segments.Length != context.Segments.Length)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
@ -43,7 +53,15 @@ namespace Microsoft.AspNetCore.Components.Routing
|
|||
for (var i = 0; i < Template.Segments.Length; i++)
|
||||
{
|
||||
var segment = Template.Segments[i];
|
||||
|
||||
|
||||
if (segment.IsCatchAll)
|
||||
{
|
||||
numMatchingSegments += 1;
|
||||
parameters ??= new Dictionary<string, object>(StringComparer.Ordinal);
|
||||
parameters[segment.Value] = catchAllValue;
|
||||
break;
|
||||
}
|
||||
|
||||
// If the template contains more segments than the path, then
|
||||
// we may need to break out of this for-loop. This can happen
|
||||
// in one of two cases:
|
||||
|
|
@ -86,7 +104,7 @@ namespace Microsoft.AspNetCore.Components.Routing
|
|||
// In addition to extracting parameter values from the URL, each route entry
|
||||
// also knows which other parameters should be supplied with null values. These
|
||||
// are parameters supplied by other route entries matching the same handler.
|
||||
if (UnusedRouteParameterNames.Length > 0)
|
||||
if (!Template.ContainsCatchAllSegment && UnusedRouteParameterNames.Length > 0)
|
||||
{
|
||||
parameters ??= new Dictionary<string, object>(StringComparer.Ordinal);
|
||||
for (var i = 0; i < UnusedRouteParameterNames.Length; i++)
|
||||
|
|
@ -116,7 +134,7 @@ namespace Microsoft.AspNetCore.Components.Routing
|
|||
// `/this/is/a/template` and the route `/this/`. In that case, we want to ensure
|
||||
// that all non-optional segments have matched as well.
|
||||
var allNonOptionalSegmentsMatch = numMatchingSegments >= (Template.Segments.Length - Template.OptionalSegmentsCount);
|
||||
if (allRouteSegmentsMatch && allNonOptionalSegmentsMatch)
|
||||
if (Template.ContainsCatchAllSegment || (allRouteSegmentsMatch && allNonOptionalSegmentsMatch))
|
||||
{
|
||||
context.Parameters = parameters;
|
||||
context.Handler = Handler;
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ namespace Microsoft.AspNetCore.Components.Routing
|
|||
TemplateText = templateText;
|
||||
Segments = segments;
|
||||
OptionalSegmentsCount = segments.Count(template => template.IsOptional);
|
||||
ContainsCatchAllSegment = segments.Any(template => template.IsCatchAll);
|
||||
}
|
||||
|
||||
public string TemplateText { get; }
|
||||
|
|
@ -22,5 +23,7 @@ namespace Microsoft.AspNetCore.Components.Routing
|
|||
public TemplateSegment[] Segments { get; }
|
||||
|
||||
public int OptionalSegmentsCount { get; }
|
||||
|
||||
public bool ContainsCatchAllSegment { get; }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -152,6 +152,19 @@ namespace Microsoft.AspNetCore.Components.Routing
|
|||
|
||||
internal virtual void Refresh(bool isNavigationIntercepted)
|
||||
{
|
||||
// If an `OnNavigateAsync` task is currently in progress, then wait
|
||||
// for it to complete before rendering. Note: because _previousOnNavigateTask
|
||||
// is initialized to a CompletedTask on initialization, this will still
|
||||
// allow first-render to complete successfully.
|
||||
if (_previousOnNavigateTask.Status != TaskStatus.RanToCompletion)
|
||||
{
|
||||
if (Navigating != null)
|
||||
{
|
||||
_renderHandle.Render(Navigating);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
RefreshRouteTable();
|
||||
|
||||
var locationPath = NavigationManager.ToBaseRelativePath(_locationAbsolute);
|
||||
|
|
@ -248,19 +261,15 @@ namespace Microsoft.AspNetCore.Components.Routing
|
|||
var previousTask = _previousOnNavigateTask;
|
||||
var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
|
||||
_previousOnNavigateTask = tcs.Task;
|
||||
try
|
||||
|
||||
// And pass an indicator for the previous task to the currently running one.
|
||||
var shouldRefresh = await RunOnNavigateAsync(path, previousTask);
|
||||
tcs.SetResult();
|
||||
if (shouldRefresh)
|
||||
{
|
||||
// And pass an indicator for the previous task to the currently running one.
|
||||
var shouldRefresh = await RunOnNavigateAsync(path, previousTask);
|
||||
if (shouldRefresh)
|
||||
{
|
||||
Refresh(isNavigationIntercepted);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
tcs.SetResult();
|
||||
Refresh(isNavigationIntercepted);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void OnLocationChanged(object sender, LocationChangedEventArgs args)
|
||||
|
|
|
|||
|
|
@ -12,15 +12,15 @@ namespace Microsoft.AspNetCore.Components.Routing
|
|||
// The class in here just takes care of parsing a route and extracting
|
||||
// simple parameters from it.
|
||||
// Some differences with ASP.NET Core routes are:
|
||||
// * We don't support catch all parameter segments.
|
||||
// * We don't support complex segments.
|
||||
// The things that we support are:
|
||||
// * Literal path segments. (Like /Path/To/Some/Page)
|
||||
// * Parameter path segments (Like /Customer/{Id}/Orders/{OrderId})
|
||||
// * Catch-all parameters (Like /blog/{*slug})
|
||||
internal class TemplateParser
|
||||
{
|
||||
public static readonly char[] InvalidParameterNameCharacters =
|
||||
new char[] { '*', '{', '}', '=', '.' };
|
||||
new char[] { '{', '}', '=', '.' };
|
||||
|
||||
internal static RouteTemplate ParseTemplate(string template)
|
||||
{
|
||||
|
|
@ -80,6 +80,12 @@ namespace Microsoft.AspNetCore.Components.Routing
|
|||
for (int i = 0; i < templateSegments.Length; i++)
|
||||
{
|
||||
var currentSegment = templateSegments[i];
|
||||
|
||||
if (currentSegment.IsCatchAll && i != templateSegments.Length - 1)
|
||||
{
|
||||
throw new InvalidOperationException($"Invalid template '{template}'. A catch-all parameter can only appear as the last segment of the route template.");
|
||||
}
|
||||
|
||||
if (!currentSegment.IsParameter)
|
||||
{
|
||||
continue;
|
||||
|
|
|
|||
|
|
@ -12,34 +12,48 @@ namespace Microsoft.AspNetCore.Components.Routing
|
|||
{
|
||||
IsParameter = isParameter;
|
||||
|
||||
IsCatchAll = segment.StartsWith('*');
|
||||
|
||||
if (IsCatchAll)
|
||||
{
|
||||
// Only one '*' currently allowed
|
||||
Value = segment.Substring(1);
|
||||
|
||||
var invalidCharacter = Value.IndexOf('*');
|
||||
if (Value.IndexOf('*') != -1)
|
||||
{
|
||||
throw new InvalidOperationException($"Invalid template '{template}'. A catch-all parameter may only have one '*' at the beginning of the segment.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Value = segment;
|
||||
}
|
||||
|
||||
// Process segments that are not parameters or do not contain
|
||||
// a token separating a type constraint.
|
||||
if (!isParameter || segment.IndexOf(':') < 0)
|
||||
if (!isParameter || Value.IndexOf(':') < 0)
|
||||
{
|
||||
// Set the IsOptional flag to true for segments that contain
|
||||
// a parameter with no type constraints but optionality set
|
||||
// via the '?' token.
|
||||
if (segment.IndexOf('?') == segment.Length - 1)
|
||||
if (Value.IndexOf('?') == Value.Length - 1)
|
||||
{
|
||||
IsOptional = true;
|
||||
Value = segment.Substring(0, segment.Length - 1);
|
||||
Value = Value.Substring(0, Value.Length - 1);
|
||||
}
|
||||
// If the `?` optional marker shows up in the segment but not at the very end,
|
||||
// then throw an error.
|
||||
else if (segment.IndexOf('?') >= 0 && segment.IndexOf('?') != segment.Length - 1)
|
||||
else if (Value.IndexOf('?') >= 0 && Value.IndexOf('?') != Value.Length - 1)
|
||||
{
|
||||
throw new ArgumentException($"Malformed parameter '{segment}' in route '{template}'. '?' character can only appear at the end of parameter name.");
|
||||
}
|
||||
else
|
||||
{
|
||||
Value = segment;
|
||||
}
|
||||
|
||||
|
||||
Constraints = Array.Empty<RouteConstraint>();
|
||||
}
|
||||
else
|
||||
{
|
||||
var tokens = segment.Split(':');
|
||||
var tokens = Value.Split(':');
|
||||
if (tokens[0].Length == 0)
|
||||
{
|
||||
throw new ArgumentException($"Malformed parameter '{segment}' in route '{template}' has no name before the constraints list.");
|
||||
|
|
@ -54,6 +68,21 @@ namespace Microsoft.AspNetCore.Components.Routing
|
|||
.Select(token => RouteConstraint.Parse(template, segment, token))
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
if (IsParameter)
|
||||
{
|
||||
if (IsOptional && IsCatchAll)
|
||||
{
|
||||
throw new InvalidOperationException($"Invalid segment '{segment}' in route '{template}'. A catch-all parameter cannot be marked optional.");
|
||||
}
|
||||
|
||||
// Moving the check for this here instead of TemplateParser so we can allow catch-all.
|
||||
// We checked for '*' up above specifically for catch-all segments, this one checks for all others
|
||||
if (Value.IndexOf('*') != -1)
|
||||
{
|
||||
throw new InvalidOperationException($"Invalid template '{template}'. The character '*' in parameter segment '{{{segment}}}' is not allowed.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The value of the segment. The exact text to match when is a literal.
|
||||
|
|
@ -64,6 +93,8 @@ namespace Microsoft.AspNetCore.Components.Routing
|
|||
|
||||
public bool IsOptional { get; }
|
||||
|
||||
public bool IsCatchAll { get; }
|
||||
|
||||
public RouteConstraint[] Constraints { get; }
|
||||
|
||||
public bool Match(string pathSegment, out object? matchedParameterValue)
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ namespace Microsoft.AspNetCore.Components
|
|||
var callback = default(EventCallback);
|
||||
|
||||
// Act & Assert (Does not throw)
|
||||
await callback.InvokeAsync(null);
|
||||
await callback.InvokeAsync();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -27,7 +27,7 @@ namespace Microsoft.AspNetCore.Components
|
|||
var callback = default(EventCallback<EventArgs>);
|
||||
|
||||
// Act & Assert (Does not throw)
|
||||
await callback.InvokeAsync(null);
|
||||
await callback.InvokeAsync();
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -39,7 +39,7 @@ namespace Microsoft.AspNetCore.Components
|
|||
var callback = new EventCallback(null, (Action)(() => runCount++));
|
||||
|
||||
// Act
|
||||
await callback.InvokeAsync(null);
|
||||
await callback.InvokeAsync();
|
||||
|
||||
|
||||
// Assert
|
||||
|
|
@ -54,7 +54,7 @@ namespace Microsoft.AspNetCore.Components
|
|||
var callback = new EventCallback<EventArgs>(null, (Action)(() => runCount++));
|
||||
|
||||
// Act
|
||||
await callback.InvokeAsync(null);
|
||||
await callback.InvokeAsync();
|
||||
|
||||
|
||||
// Assert
|
||||
|
|
@ -71,7 +71,7 @@ namespace Microsoft.AspNetCore.Components
|
|||
var callback = new EventCallback(component, (Action)(() => runCount++));
|
||||
|
||||
// Act
|
||||
await callback.InvokeAsync(null);
|
||||
await callback.InvokeAsync();
|
||||
|
||||
|
||||
// Assert
|
||||
|
|
@ -108,7 +108,7 @@ namespace Microsoft.AspNetCore.Components
|
|||
var callback = new EventCallback(component, (Action<EventArgs>)((e) => { arg = e; runCount++; }));
|
||||
|
||||
// Act
|
||||
await callback.InvokeAsync(null);
|
||||
await callback.InvokeAsync();
|
||||
|
||||
|
||||
// Assert
|
||||
|
|
@ -184,7 +184,7 @@ namespace Microsoft.AspNetCore.Components
|
|||
var callback = new EventCallback(component, (Func<Task>)(() => { runCount++; return Task.CompletedTask; }));
|
||||
|
||||
// Act
|
||||
await callback.InvokeAsync(null);
|
||||
await callback.InvokeAsync();
|
||||
|
||||
|
||||
// Assert
|
||||
|
|
@ -221,7 +221,7 @@ namespace Microsoft.AspNetCore.Components
|
|||
var callback = new EventCallback(component, (Func<EventArgs, Task>)((e) => { arg = e; runCount++; return Task.CompletedTask; }));
|
||||
|
||||
// Act
|
||||
await callback.InvokeAsync(null);
|
||||
await callback.InvokeAsync();
|
||||
|
||||
|
||||
// Assert
|
||||
|
|
@ -297,7 +297,7 @@ namespace Microsoft.AspNetCore.Components
|
|||
var callback = new EventCallback<EventArgs>(component, (Action)(() => runCount++));
|
||||
|
||||
// Act
|
||||
await callback.InvokeAsync(null);
|
||||
await callback.InvokeAsync();
|
||||
|
||||
|
||||
// Assert
|
||||
|
|
@ -334,7 +334,7 @@ namespace Microsoft.AspNetCore.Components
|
|||
var callback = new EventCallback<EventArgs>(component, (Action<EventArgs>)((e) => { arg = e; runCount++; }));
|
||||
|
||||
// Act
|
||||
await callback.InvokeAsync(null);
|
||||
await callback.InvokeAsync();
|
||||
|
||||
|
||||
// Assert
|
||||
|
|
@ -373,7 +373,7 @@ namespace Microsoft.AspNetCore.Components
|
|||
var callback = new EventCallback<EventArgs>(component, (Func<Task>)(() => { runCount++; return Task.CompletedTask; }));
|
||||
|
||||
// Act
|
||||
await callback.InvokeAsync(null);
|
||||
await callback.InvokeAsync();
|
||||
|
||||
|
||||
// Assert
|
||||
|
|
@ -410,7 +410,7 @@ namespace Microsoft.AspNetCore.Components
|
|||
var callback = new EventCallback<EventArgs>(component, (Func<EventArgs, Task>)((e) => { arg = e; runCount++; return Task.CompletedTask; }));
|
||||
|
||||
// Act
|
||||
await callback.InvokeAsync(null);
|
||||
await callback.InvokeAsync();
|
||||
|
||||
|
||||
// Assert
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ namespace Microsoft.AspNetCore.Components
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void IncomingParameterMatchesOverridenParameter_ThatDoesNotHasAttribute()
|
||||
public void IncomingParameterMatchesOverriddenParameter_ThatDoesNotHaveAttribute()
|
||||
{
|
||||
// Test for https://github.com/dotnet/aspnetcore/issues/13162
|
||||
// Arrange
|
||||
|
|
|
|||
|
|
@ -340,7 +340,7 @@ namespace Microsoft.AspNetCore.Components.Test
|
|||
|
||||
// Act/Assert
|
||||
var ex = Assert.Throws<InvalidOperationException>(() => GetSingleUpdatedComponent());
|
||||
Assert.Equal("More than one sibling has the same key value, 'key1'. Key values must be unique.", ex.Message);
|
||||
Assert.Equal("More than one sibling of element 'el' has the same key value, 'key1'. Key values must be unique.", ex.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -357,7 +357,7 @@ namespace Microsoft.AspNetCore.Components.Test
|
|||
|
||||
// Act/Assert
|
||||
var ex = Assert.Throws<InvalidOperationException>(() => GetSingleUpdatedComponent());
|
||||
Assert.Equal("More than one sibling has the same key value, 'key1'. Key values must be unique.", ex.Message);
|
||||
Assert.Equal("More than one sibling of element 'el' has the same key value, 'key1'. Key values must be unique.", ex.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -374,7 +374,7 @@ namespace Microsoft.AspNetCore.Components.Test
|
|||
|
||||
// Act/Assert
|
||||
var ex = Assert.Throws<InvalidOperationException>(() => GetSingleUpdatedComponent());
|
||||
Assert.Equal("More than one sibling has the same key value, 'key1'. Key values must be unique.", ex.Message);
|
||||
Assert.Equal("More than one sibling of element 'el' has the same key value, 'key1'. Key values must be unique.", ex.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
|
|||
|
|
@ -487,7 +487,8 @@ namespace Microsoft.AspNetCore.Components.Test
|
|||
public void DispatchEventHandlesSynchronousExceptionsFromEventHandlers()
|
||||
{
|
||||
// Arrange: Render a component with an event handler
|
||||
var renderer = new TestRenderer {
|
||||
var renderer = new TestRenderer
|
||||
{
|
||||
ShouldHandleExceptions = true
|
||||
};
|
||||
|
||||
|
|
@ -2086,6 +2087,238 @@ namespace Microsoft.AspNetCore.Components.Test
|
|||
Assert.Contains(exception2, aex.InnerExceptions);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RenderBatch_HandlesSynchronousExceptionsInAsyncDisposableComponents()
|
||||
{
|
||||
// Arrange
|
||||
var renderer = new TestRenderer { ShouldHandleExceptions = true };
|
||||
var exception1 = new InvalidOperationException();
|
||||
|
||||
var firstRender = true;
|
||||
var component = new TestComponent(builder =>
|
||||
{
|
||||
if (firstRender)
|
||||
{
|
||||
builder.AddContent(0, "Hello");
|
||||
builder.OpenComponent<AsyncDisposableComponent>(1);
|
||||
builder.AddAttribute(1, nameof(AsyncDisposableComponent.AsyncDisposeAction), (Func<ValueTask>)(() => throw exception1));
|
||||
builder.CloseComponent();
|
||||
}
|
||||
});
|
||||
var componentId = renderer.AssignRootComponentId(component);
|
||||
component.TriggerRender();
|
||||
|
||||
// Act: Second render
|
||||
firstRender = false;
|
||||
component.TriggerRender();
|
||||
|
||||
// Assert: Applicable children are included in disposal list
|
||||
Assert.Equal(2, renderer.Batches.Count);
|
||||
Assert.Equal(new[] { 1, }, renderer.Batches[1].DisposedComponentIDs);
|
||||
|
||||
// Outer component is still alive and not disposed.
|
||||
Assert.False(component.Disposed);
|
||||
var aex = Assert.IsType<AggregateException>(Assert.Single(renderer.HandledExceptions));
|
||||
var innerException = Assert.Single(aex.Flatten().InnerExceptions);
|
||||
Assert.Same(exception1, innerException);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RenderBatch_CanDisposeSynchronousAsyncDisposableImplementations()
|
||||
{
|
||||
// Arrange
|
||||
var renderer = new TestRenderer { ShouldHandleExceptions = true };
|
||||
|
||||
var firstRender = true;
|
||||
var component = new TestComponent(builder =>
|
||||
{
|
||||
if (firstRender)
|
||||
{
|
||||
builder.AddContent(0, "Hello");
|
||||
builder.OpenComponent<AsyncDisposableComponent>(1);
|
||||
builder.AddAttribute(1, nameof(AsyncDisposableComponent.AsyncDisposeAction), (Func<ValueTask>)(() => default));
|
||||
builder.CloseComponent();
|
||||
}
|
||||
});
|
||||
var componentId = renderer.AssignRootComponentId(component);
|
||||
component.TriggerRender();
|
||||
|
||||
// Act: Second render
|
||||
firstRender = false;
|
||||
component.TriggerRender();
|
||||
|
||||
// Assert: Applicable children are included in disposal list
|
||||
Assert.Equal(2, renderer.Batches.Count);
|
||||
Assert.Equal(new[] { 1, }, renderer.Batches[1].DisposedComponentIDs);
|
||||
|
||||
// Outer component is still alive and not disposed.
|
||||
Assert.False(component.Disposed);
|
||||
Assert.Empty(renderer.HandledExceptions);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RenderBatch_CanDisposeAsynchronousAsyncDisposables()
|
||||
{
|
||||
// Arrange
|
||||
var semaphore = new Semaphore(0, 1);
|
||||
var renderer = new TestRenderer { ShouldHandleExceptions = true };
|
||||
renderer.OnExceptionHandled = () => semaphore.Release();
|
||||
var exception1 = new InvalidOperationException();
|
||||
var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
|
||||
|
||||
var firstRender = true;
|
||||
var component = new TestComponent(builder =>
|
||||
{
|
||||
if (firstRender)
|
||||
{
|
||||
builder.AddContent(0, "Hello");
|
||||
builder.OpenComponent<AsyncDisposableComponent>(1);
|
||||
builder.AddAttribute(1, nameof(AsyncDisposableComponent.AsyncDisposeAction), (Func<ValueTask>)(async () => { await tcs.Task; }));
|
||||
builder.CloseComponent();
|
||||
}
|
||||
});
|
||||
|
||||
var componentId = renderer.AssignRootComponentId(component);
|
||||
component.TriggerRender();
|
||||
// Act: Second render
|
||||
firstRender = false;
|
||||
component.TriggerRender();
|
||||
|
||||
// Assert: Applicable children are included in disposal list
|
||||
Assert.Equal(2, renderer.Batches.Count);
|
||||
Assert.Equal(new[] { 1, }, renderer.Batches[1].DisposedComponentIDs);
|
||||
|
||||
// Outer component is still alive and not disposed.
|
||||
Assert.False(component.Disposed);
|
||||
Assert.Empty(renderer.HandledExceptions);
|
||||
|
||||
// Continue execution
|
||||
tcs.SetResult();
|
||||
Assert.False(semaphore.WaitOne(10));
|
||||
Assert.Empty(renderer.HandledExceptions);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RenderBatch_HandlesAsynchronousExceptionsInAsyncDisposableComponents()
|
||||
{
|
||||
// Arrange
|
||||
var semaphore = new Semaphore(0, 1);
|
||||
var renderer = new TestRenderer { ShouldHandleExceptions = true };
|
||||
renderer.OnExceptionHandled = () => semaphore.Release();
|
||||
var exception1 = new InvalidOperationException();
|
||||
var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
|
||||
|
||||
var firstRender = true;
|
||||
var component = new TestComponent(builder =>
|
||||
{
|
||||
if (firstRender)
|
||||
{
|
||||
builder.AddContent(0, "Hello");
|
||||
builder.OpenComponent<AsyncDisposableComponent>(1);
|
||||
builder.AddAttribute(1, nameof(AsyncDisposableComponent.AsyncDisposeAction), (Func<ValueTask>)(async () => { await tcs.Task; throw exception1; }));
|
||||
builder.CloseComponent();
|
||||
}
|
||||
});
|
||||
var componentId = renderer.AssignRootComponentId(component);
|
||||
component.TriggerRender();
|
||||
// Act: Second render
|
||||
firstRender = false;
|
||||
component.TriggerRender();
|
||||
|
||||
// Assert: Applicable children are included in disposal list
|
||||
Assert.Equal(2, renderer.Batches.Count);
|
||||
Assert.Equal(new[] { 1, }, renderer.Batches[1].DisposedComponentIDs);
|
||||
|
||||
// Outer component is still alive and not disposed.
|
||||
Assert.False(component.Disposed);
|
||||
Assert.Empty(renderer.HandledExceptions);
|
||||
|
||||
// Continue execution
|
||||
tcs.SetResult();
|
||||
semaphore.WaitOne();
|
||||
var aex = Assert.IsType<InvalidOperationException>(Assert.Single(renderer.HandledExceptions));
|
||||
Assert.Same(exception1, aex);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RenderBatch_ReportsSynchronousCancelationsAsErrors()
|
||||
{
|
||||
// Arrange
|
||||
var renderer = new TestRenderer { ShouldHandleExceptions = true };
|
||||
var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
|
||||
|
||||
var firstRender = true;
|
||||
var component = new TestComponent(builder =>
|
||||
{
|
||||
if (firstRender)
|
||||
{
|
||||
builder.AddContent(0, "Hello");
|
||||
builder.OpenComponent<AsyncDisposableComponent>(1);
|
||||
builder.AddAttribute(1, nameof(AsyncDisposableComponent.AsyncDisposeAction), (Func<ValueTask>)(() => throw new TaskCanceledException()));
|
||||
builder.CloseComponent();
|
||||
}
|
||||
});
|
||||
var componentId = renderer.AssignRootComponentId(component);
|
||||
component.TriggerRender();
|
||||
|
||||
// Act: Second render
|
||||
firstRender = false;
|
||||
component.TriggerRender();
|
||||
|
||||
// Assert: Applicable children are included in disposal list
|
||||
Assert.Equal(2, renderer.Batches.Count);
|
||||
Assert.Equal(new[] { 1, }, renderer.Batches[1].DisposedComponentIDs);
|
||||
|
||||
// Outer component is still alive and not disposed.
|
||||
Assert.False(component.Disposed);
|
||||
var aex = Assert.IsType<AggregateException>(Assert.Single(renderer.HandledExceptions));
|
||||
Assert.IsType<TaskCanceledException>(Assert.Single(aex.Flatten().InnerExceptions));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RenderBatch_ReportsAsynchronousCancelationsAsErrors()
|
||||
{
|
||||
// Arrange
|
||||
var semaphore = new Semaphore(0, 1);
|
||||
var renderer = new TestRenderer { ShouldHandleExceptions = true };
|
||||
renderer.OnExceptionHandled += () => semaphore.Release();
|
||||
var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
|
||||
var firstRender = true;
|
||||
var component = new TestComponent(builder =>
|
||||
{
|
||||
if (firstRender)
|
||||
{
|
||||
builder.AddContent(0, "Hello");
|
||||
builder.OpenComponent<AsyncDisposableComponent>(1);
|
||||
builder.AddAttribute(
|
||||
1,
|
||||
nameof(AsyncDisposableComponent.AsyncDisposeAction),
|
||||
(Func<ValueTask>)(() => new ValueTask(tcs.Task)));
|
||||
builder.CloseComponent();
|
||||
}
|
||||
});
|
||||
var componentId = renderer.AssignRootComponentId(component);
|
||||
component.TriggerRender();
|
||||
|
||||
// Act: Second render
|
||||
firstRender = false;
|
||||
component.TriggerRender();
|
||||
|
||||
// Assert: Applicable children are included in disposal list
|
||||
Assert.Equal(2, renderer.Batches.Count);
|
||||
Assert.Equal(new[] { 1, }, renderer.Batches[1].DisposedComponentIDs);
|
||||
|
||||
// Outer component is still alive and not disposed.
|
||||
Assert.False(component.Disposed);
|
||||
Assert.Empty(renderer.HandledExceptions);
|
||||
|
||||
// Cancel execution
|
||||
tcs.SetCanceled();
|
||||
|
||||
semaphore.WaitOne();
|
||||
var aex = Assert.IsType<TaskCanceledException>(Assert.Single(renderer.HandledExceptions));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RenderBatch_DoesNotDisposeComponentMultipleTimes()
|
||||
{
|
||||
|
|
@ -2589,7 +2822,7 @@ namespace Microsoft.AspNetCore.Components.Test
|
|||
|
||||
// Act: Toggle the checkbox
|
||||
var eventArgs = new ChangeEventArgs { Value = true };
|
||||
var renderTask = renderer.DispatchEventAsync(checkboxChangeEventHandlerId, eventArgs);
|
||||
var renderTask = renderer.DispatchEventAsync(checkboxChangeEventHandlerId, eventArgs);
|
||||
|
||||
Assert.True(renderTask.IsCompletedSuccessfully);
|
||||
var latestBatch = renderer.Batches.Last();
|
||||
|
|
@ -3768,7 +4001,7 @@ namespace Microsoft.AspNetCore.Components.Test
|
|||
requestedType => Assert.Equal(typeof(TestComponent), requestedType));
|
||||
}
|
||||
|
||||
private class TestComponentActivator<TResult> : IComponentActivator where TResult: IComponent, new()
|
||||
private class TestComponentActivator<TResult> : IComponentActivator where TResult : IComponent, new()
|
||||
{
|
||||
public List<Type> RequestedComponentTypes { get; } = new List<Type>();
|
||||
|
||||
|
|
@ -4147,6 +4380,24 @@ namespace Microsoft.AspNetCore.Components.Test
|
|||
}
|
||||
}
|
||||
|
||||
private class AsyncDisposableComponent : AutoRenderComponent, IAsyncDisposable
|
||||
{
|
||||
public bool Disposed { get; private set; }
|
||||
|
||||
[Parameter]
|
||||
public Func<ValueTask> AsyncDisposeAction { get; set; }
|
||||
|
||||
public ValueTask DisposeAsync()
|
||||
{
|
||||
Disposed = true;
|
||||
return AsyncDisposeAction == null ? default : AsyncDisposeAction.Invoke();
|
||||
}
|
||||
|
||||
protected override void BuildRenderTree(RenderTreeBuilder builder)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
class TestAsyncRenderer : TestRenderer
|
||||
{
|
||||
public Task NextUpdateDisplayReturnTask { get; set; }
|
||||
|
|
|
|||
|
|
@ -226,6 +226,23 @@ namespace Microsoft.AspNetCore.Components.Test.Routing
|
|||
Assert.Single(context.Parameters, p => p.Key == "parameter" && (string)p.Value == expectedValue);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("/blog/value1", "value1")]
|
||||
[InlineData("/blog/value1/foo%20bar", "value1/foo bar")]
|
||||
public void CanMatchCatchAllParameterTemplate(string path, string expectedValue)
|
||||
{
|
||||
// Arrange
|
||||
var routeTable = new TestRouteTableBuilder().AddRoute("/blog/{*parameter}").Build();
|
||||
var context = new RouteContext(path);
|
||||
|
||||
// Act
|
||||
routeTable.Route(context);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(context.Handler);
|
||||
Assert.Single(context.Parameters, p => p.Key == "parameter" && (string)p.Value == expectedValue);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CanMatchTemplateWithMultipleParameters()
|
||||
{
|
||||
|
|
@ -247,6 +264,29 @@ namespace Microsoft.AspNetCore.Components.Test.Routing
|
|||
Assert.Equal(expectedParameters, context.Parameters);
|
||||
}
|
||||
|
||||
|
||||
[Fact]
|
||||
public void CanMatchTemplateWithMultipleParametersAndCatchAllParameter()
|
||||
{
|
||||
// Arrange
|
||||
var routeTable = new TestRouteTableBuilder().AddRoute("/{some}/awesome/{route}/with/{*catchAll}").Build();
|
||||
var context = new RouteContext("/an/awesome/path/with/some/catch/all/stuff");
|
||||
|
||||
var expectedParameters = new Dictionary<string, object>
|
||||
{
|
||||
["some"] = "an",
|
||||
["route"] = "path",
|
||||
["catchAll"] = "some/catch/all/stuff"
|
||||
};
|
||||
|
||||
// Act
|
||||
routeTable.Route(context);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(context.Handler);
|
||||
Assert.Equal(expectedParameters, context.Parameters);
|
||||
}
|
||||
|
||||
public static IEnumerable<object[]> CanMatchParameterWithConstraintCases() => new object[][]
|
||||
{
|
||||
new object[] { "/{value:bool}", "/true", true },
|
||||
|
|
@ -476,7 +516,7 @@ namespace Microsoft.AspNetCore.Components.Test.Routing
|
|||
|
||||
|
||||
[Fact]
|
||||
public void PrefersLiteralTemplateOverParmeterizedTemplates()
|
||||
public void PrefersLiteralTemplateOverParameterizedTemplates()
|
||||
{
|
||||
// Arrange
|
||||
var routeTable = new TestRouteTableBuilder()
|
||||
|
|
|
|||
|
|
@ -83,6 +83,45 @@ namespace Microsoft.AspNetCore.Components.Routing
|
|||
Assert.Equal(expected, actual, RouteTemplateTestComparer.Instance);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Parse_SingleCatchAllParameter()
|
||||
{
|
||||
// Arrange
|
||||
var expected = new ExpectedTemplateBuilder().Parameter("p");
|
||||
|
||||
// Act
|
||||
var actual = TemplateParser.ParseTemplate("{*p}");
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expected, actual, RouteTemplateTestComparer.Instance);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Parse_MixedLiteralAndCatchAllParameter()
|
||||
{
|
||||
// Arrange
|
||||
var expected = new ExpectedTemplateBuilder().Literal("awesome").Literal("wow").Parameter("p");
|
||||
|
||||
// Act
|
||||
var actual = TemplateParser.ParseTemplate("awesome/wow/{*p}");
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expected, actual, RouteTemplateTestComparer.Instance);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Parse_MixedLiteralParameterAndCatchAllParameter()
|
||||
{
|
||||
// Arrange
|
||||
var expected = new ExpectedTemplateBuilder().Literal("awesome").Parameter("p1").Parameter("p2");
|
||||
|
||||
// Act
|
||||
var actual = TemplateParser.ParseTemplate("awesome/{p1}/{*p2}");
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expected, actual, RouteTemplateTestComparer.Instance);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InvalidTemplate_WithRepeatedParameter()
|
||||
{
|
||||
|
|
@ -113,7 +152,8 @@ namespace Microsoft.AspNetCore.Components.Routing
|
|||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("{*}", "Invalid template '{*}'. The character '*' in parameter segment '{*}' is not allowed.")]
|
||||
// * is only allowed at beginning for catch-all parameters
|
||||
[InlineData("{p*}", "Invalid template '{p*}'. The character '*' in parameter segment '{p*}' is not allowed.")]
|
||||
[InlineData("{{}", "Invalid template '{{}'. The character '{' in parameter segment '{{}' is not allowed.")]
|
||||
[InlineData("{}}", "Invalid template '{}}'. The character '}' in parameter segment '{}}' is not allowed.")]
|
||||
[InlineData("{=}", "Invalid template '{=}'. The character '=' in parameter segment '{=}' is not allowed.")]
|
||||
|
|
@ -166,6 +206,26 @@ namespace Microsoft.AspNetCore.Components.Routing
|
|||
Assert.Equal(expectedMessage, ex.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InvalidTemplate_CatchAllParamWithMultipleAsterisks()
|
||||
{
|
||||
var ex = Assert.Throws<InvalidOperationException>(() => TemplateParser.ParseTemplate("/test/{a}/{**b}"));
|
||||
|
||||
var expectedMessage = "Invalid template '/test/{a}/{**b}'. A catch-all parameter may only have one '*' at the beginning of the segment.";
|
||||
|
||||
Assert.Equal(expectedMessage, ex.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InvalidTemplate_CatchAllParamNotLast()
|
||||
{
|
||||
var ex = Assert.Throws<InvalidOperationException>(() => TemplateParser.ParseTemplate("/test/{*a}/{b}"));
|
||||
|
||||
var expectedMessage = "Invalid template 'test/{*a}/{b}'. A catch-all parameter can only appear as the last segment of the route template.";
|
||||
|
||||
Assert.Equal(expectedMessage, ex.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InvalidTemplate_BadOptionalCharacterPosition()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@
|
|||
"src\\Components\\WebAssembly\\Sdk\\integrationtests\\Microsoft.NET.Sdk.BlazorWebAssembly.IntegrationTests.csproj",
|
||||
"src\\Components\\Web\\src\\Microsoft.AspNetCore.Components.Web.csproj",
|
||||
"src\\Components\\Web\\test\\Microsoft.AspNetCore.Components.Web.Tests.csproj",
|
||||
"src\\Components\\benchmarkapps\\Wasm.Performance\\ConsoleHost\\Wasm.Performance.ConsoleHost.csproj",
|
||||
"src\\Components\\benchmarkapps\\Wasm.Performance\\Driver\\Wasm.Performance.Driver.csproj",
|
||||
"src\\Components\\benchmarkapps\\Wasm.Performance\\TestApp\\Wasm.Performance.TestApp.csproj",
|
||||
"src\\Components\\test\\E2ETest\\Microsoft.AspNetCore.Components.E2ETests.csproj",
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ app {
|
|||
height: 3.5rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.main {
|
||||
|
|
|
|||
|
|
@ -296,7 +296,7 @@ namespace Microsoft.AspNetCore.Components.Web.Rendering
|
|||
exceptions.Add(e);
|
||||
};
|
||||
|
||||
// Receive the ack for the intial batch
|
||||
// Receive the ack for the initial batch
|
||||
_ = renderer.OnRenderCompletedAsync(2, null);
|
||||
// Receive the ack for the second batch
|
||||
_ = renderer.OnRenderCompletedAsync(2, null);
|
||||
|
|
|
|||
|
|
@ -28,8 +28,8 @@ namespace Microsoft.AspNetCore.Components.RenderTree
|
|||
internal class ArrayBuilder<T> : IDisposable
|
||||
{
|
||||
// The following fields are memory mapped to the WASM client. Do not re-order or use auto-properties.
|
||||
private T[] _items;
|
||||
private int _itemsInUse;
|
||||
protected T[] _items;
|
||||
protected int _itemsInUse;
|
||||
|
||||
private static readonly T[] Empty = Array.Empty<T>();
|
||||
private readonly ArrayPool<T> _arrayPool;
|
||||
|
|
@ -139,7 +139,6 @@ namespace Microsoft.AspNetCore.Components.RenderTree
|
|||
ThrowIndexOutOfBoundsException();
|
||||
}
|
||||
|
||||
// Same expansion logic as elsewhere
|
||||
if (_itemsInUse == _items.Length)
|
||||
{
|
||||
GrowBuffer(_items.Length * 2);
|
||||
|
|
@ -162,7 +161,7 @@ namespace Microsoft.AspNetCore.Components.RenderTree
|
|||
_itemsInUse = 0;
|
||||
}
|
||||
|
||||
private void GrowBuffer(int desiredCapacity)
|
||||
protected void GrowBuffer(int desiredCapacity)
|
||||
{
|
||||
// When we dispose, we set the count back to zero and return the array.
|
||||
//
|
||||
|
|
|
|||
|
|
@ -71,6 +71,7 @@ namespace Microsoft.AspNetCore.Components.Web
|
|||
"touch" => Deserialize<TouchEventArgs>(eventArgsJson),
|
||||
"unknown" => EventArgs.Empty,
|
||||
"wheel" => Deserialize<WheelEventArgs>(eventArgsJson),
|
||||
"toggle" => Deserialize<EventArgs>(eventArgsJson),
|
||||
_ => throw new InvalidOperationException($"Unsupported event type '{eventArgsType}'. EventId: '{eventHandlerId}'."),
|
||||
};
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -12,7 +12,6 @@ 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;
|
||||
|
|
@ -22,7 +21,6 @@ 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);
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ 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;
|
||||
|
||||
|
|
@ -34,8 +33,6 @@ 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');
|
||||
|
||||
// We're going to read directly from the .NET memory heap, so indicate to the platform
|
||||
// that we don't want anything to modify the memory contents during this time. Currently this
|
||||
// is only guaranteed by the fact that .NET code doesn't run during this time, but in the
|
||||
|
|
@ -47,8 +44,6 @@ async function boot(options?: Partial<WebAssemblyStartOptions>): Promise<void> {
|
|||
} finally {
|
||||
heapLock.release();
|
||||
}
|
||||
|
||||
profileEnd('renderBatch');
|
||||
};
|
||||
|
||||
// Configure navigation via JS Interop
|
||||
|
|
@ -66,8 +61,11 @@ async function boot(options?: Partial<WebAssemblyStartOptions>): Promise<void> {
|
|||
);
|
||||
});
|
||||
|
||||
// Get the custom environment setting if defined
|
||||
const environment = options?.environment;
|
||||
|
||||
// Fetch the resources and prepare the Mono runtime
|
||||
const bootConfigResult = await BootConfigResult.initAsync();
|
||||
const bootConfigResult = await BootConfigResult.initAsync(environment);
|
||||
|
||||
const [resourceLoader] = await Promise.all([
|
||||
WebAssemblyResourceLoader.initAsync(bootConfigResult.bootConfig, options || {}),
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { navigateTo, internalFunctions as navigationManagerInternalFunctions } from './Services/NavigationManager';
|
||||
import { attachRootComponentToElement } from './Rendering/Renderer';
|
||||
import { domFunctions } from './DomWrapper';
|
||||
import { setProfilingEnabled } from './Platform/Profiling';
|
||||
import { Virtualize } from './Virtualize';
|
||||
|
||||
// Make the following APIs available in global scope for invocation from JS
|
||||
window['Blazor'] = {
|
||||
|
|
@ -11,6 +11,6 @@ window['Blazor'] = {
|
|||
attachRootComponentToElement,
|
||||
navigationManager: navigationManagerInternalFunctions,
|
||||
domWrapper: domFunctions,
|
||||
setProfilingEnabled: setProfilingEnabled,
|
||||
Virtualize,
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ export class BootConfigResult {
|
|||
private constructor(public bootConfig: BootJsonData, public applicationEnvironment: string) {
|
||||
}
|
||||
|
||||
static async initAsync(): Promise<BootConfigResult> {
|
||||
static async initAsync(environment?: string): Promise<BootConfigResult> {
|
||||
const bootConfigResponse = await fetch('_framework/blazor.boot.json', {
|
||||
method: 'GET',
|
||||
credentials: 'include',
|
||||
|
|
@ -10,8 +10,8 @@ export class BootConfigResult {
|
|||
});
|
||||
|
||||
// While we can expect an ASP.NET Core hosted application to include the environment, other
|
||||
// hosts may not. Assume 'Production' in the absenc of any specified value.
|
||||
const applicationEnvironment = bootConfigResponse.headers.get('Blazor-Environment') || 'Production';
|
||||
// hosts may not. Assume 'Production' in the absence of any specified value.
|
||||
const applicationEnvironment = environment || bootConfigResponse.headers.get('Blazor-Environment') || 'Production';
|
||||
const bootConfig: BootJsonData = await bootConfigResponse.json();
|
||||
|
||||
return new BootConfigResult(bootConfig, applicationEnvironment);
|
||||
|
|
|
|||
|
|
@ -64,6 +64,7 @@ export class DefaultReconnectDisplay implements ReconnectDisplay {
|
|||
this.document.body.appendChild(this.modal);
|
||||
}
|
||||
this.modal.style.display = 'block';
|
||||
this.modal.classList.add('show');
|
||||
this.button.style.display = 'none';
|
||||
this.reloadParagraph.style.display = 'none';
|
||||
this.message.textContent = 'Attempting to reconnect to the server...';
|
||||
|
|
@ -71,6 +72,7 @@ export class DefaultReconnectDisplay implements ReconnectDisplay {
|
|||
|
||||
hide(): void {
|
||||
this.modal.style.display = 'none';
|
||||
this.modal.classList.remove('show');
|
||||
}
|
||||
|
||||
failed(): void {
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ import { WebAssemblyResourceLoader, LoadingResource } from '../WebAssemblyResour
|
|||
import { Platform, System_Array, Pointer, System_Object, System_String, HeapLock } from '../Platform';
|
||||
import { loadTimezoneData } from './TimezoneDataFile';
|
||||
import { WebAssemblyBootResourceType } from '../WebAssemblyStartOptions';
|
||||
import { initializeProfiling } from '../Profiling';
|
||||
|
||||
let mono_wasm_add_assembly: (name: string, heapAddress: number, length: number) => void;
|
||||
const appBinDirName = 'appBinDir';
|
||||
|
|
@ -36,10 +35,6 @@ 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'] = {
|
||||
|
|
@ -363,11 +358,10 @@ function createEmscriptenModuleInstance(resourceLoader: WebAssemblyResourceLoade
|
|||
resourceLoader.purgeUnusedCacheEntriesAsync(); // Don't await - it's fine to run in background
|
||||
|
||||
MONO.mono_wasm_setenv("MONO_URI_DOTNETRELATIVEORABSOLUTE", "true");
|
||||
|
||||
MONO.mono_wasm_setenv("DOTNET_SYSTEM_GLOBALIZATION_INVARIANT", "1");
|
||||
// Turn off full-gc to prevent browser freezing.
|
||||
const mono_wasm_enable_on_demand_gc = cwrap('mono_wasm_enable_on_demand_gc', null, ['number']);
|
||||
mono_wasm_enable_on_demand_gc(0);
|
||||
|
||||
const load_runtime = cwrap('mono_wasm_load_runtime', null, ['string', 'number']);
|
||||
// -1 enables debugging with logging disabled. 0 disables debugging entirely.
|
||||
load_runtime(appBinDirName, hasDebuggingEnabled() ? -1 : 0);
|
||||
|
|
|
|||
|
|
@ -1,134 +0,0 @@
|
|||
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;
|
||||
|
|
@ -165,6 +165,12 @@ async function getCacheToUseIfEnabled(bootConfig: BootJsonData): Promise<Cache |
|
|||
return null;
|
||||
}
|
||||
|
||||
// cache integrity is compromised if the first request has been served over http
|
||||
// in this case, we want to disable caching and integrity validation
|
||||
if (document.location.protocol !== 'https:') {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Define a separate cache for each base href, so we're isolated from any other
|
||||
// Blazor application running on the same origin. We need this so that we're free
|
||||
// to purge from the cache anything we're not using and don't let it keep growing,
|
||||
|
|
|
|||
|
|
@ -9,6 +9,11 @@ export interface WebAssemblyStartOptions {
|
|||
* @returns A URI string or a Response promise to override the loading process, or null/undefined to allow the default loading behavior.
|
||||
*/
|
||||
loadBootResource(type: WebAssemblyBootResourceType, name: string, defaultUri: string, integrity: string) : string | Promise<Response> | null | undefined;
|
||||
|
||||
/**
|
||||
* Override built-in environment setting on start.
|
||||
*/
|
||||
environment?: string;
|
||||
}
|
||||
|
||||
// This type doesn't have to align with anything in BootConfig.
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ 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');
|
||||
|
|
@ -41,8 +40,6 @@ 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}`);
|
||||
|
|
@ -70,8 +67,6 @@ export class BrowserRenderer {
|
|||
if ((activeElementBefore instanceof HTMLElement) && ownerDocument && ownerDocument.activeElement !== activeElementBefore) {
|
||||
activeElementBefore.focus();
|
||||
}
|
||||
|
||||
profileEnd('updateComponent');
|
||||
}
|
||||
|
||||
public disposeComponent(componentId: number) {
|
||||
|
|
@ -238,7 +233,8 @@ export class BrowserRenderer {
|
|||
document.createElementNS('http://www.w3.org/2000/svg', tagName) :
|
||||
document.createElement(tagName);
|
||||
const newElement = toLogicalElement(newDomElementRaw);
|
||||
insertLogicalChild(newDomElementRaw, parent, childIndex);
|
||||
|
||||
let inserted = false;
|
||||
|
||||
// Apply attributes
|
||||
const descendantsEndIndexExcl = frameIndex + frameReader.subtreeLength(frame);
|
||||
|
|
@ -247,6 +243,8 @@ export class BrowserRenderer {
|
|||
if (frameReader.frameType(descendantFrame) === FrameType.attribute) {
|
||||
this.applyAttribute(batch, componentId, newDomElementRaw, descendantFrame);
|
||||
} else {
|
||||
insertLogicalChild(newDomElementRaw, parent, childIndex);
|
||||
inserted = true;
|
||||
// As soon as we see a non-attribute child, all the subsequent child frames are
|
||||
// not attributes, so bail out and insert the remnants recursively
|
||||
this.insertFrameRange(batch, componentId, newElement, 0, frames, descendantIndex, descendantsEndIndexExcl);
|
||||
|
|
@ -254,17 +252,40 @@ export class BrowserRenderer {
|
|||
}
|
||||
}
|
||||
|
||||
// We handle setting 'value' on a <select> in two different ways:
|
||||
// [1] When inserting a corresponding <option>, in case you're dynamically adding options
|
||||
// this element did not have any children, so it's not inserted yet.
|
||||
if (!inserted) {
|
||||
insertLogicalChild(newDomElementRaw, parent, childIndex);
|
||||
}
|
||||
|
||||
// We handle setting 'value' on a <select> in three different ways:
|
||||
// [1] When inserting a corresponding <option>, in case you're dynamically adding options.
|
||||
// This is the case below.
|
||||
// [2] After we finish inserting the <select>, in case the descendant options are being
|
||||
// added as an opaque markup block rather than individually
|
||||
// Right here we implement [2]
|
||||
if (newDomElementRaw instanceof HTMLSelectElement && selectValuePropname in newDomElementRaw) {
|
||||
// added as an opaque markup block rather than individually. This is the other case below.
|
||||
// [3] In case the the value of the select and the option value is changed in the same batch.
|
||||
// We just receive an attribute frame and have to set the select value afterwards.
|
||||
|
||||
if (newDomElementRaw instanceof HTMLOptionElement)
|
||||
{
|
||||
// Situation 1
|
||||
this.trySetSelectValueFromOptionElement(newDomElementRaw);
|
||||
} else if (newDomElementRaw instanceof HTMLSelectElement && selectValuePropname in newDomElementRaw) {
|
||||
// Situation 2
|
||||
const selectValue: string | null = newDomElementRaw[selectValuePropname];
|
||||
setSelectElementValue(newDomElementRaw, selectValue);
|
||||
}
|
||||
}
|
||||
|
||||
private trySetSelectValueFromOptionElement(optionElement: HTMLOptionElement) {
|
||||
const selectElem = this.findClosestAncestorSelectElement(optionElement);
|
||||
if (selectElem && (selectValuePropname in selectElem) && selectElem[selectValuePropname] === optionElement.value) {
|
||||
setSelectElementValue(selectElem, optionElement.value);
|
||||
delete selectElem[selectValuePropname];
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private insertComponent(batch: RenderBatch, parent: LogicalElement, childIndex: number, frame: RenderTreeFrame) {
|
||||
const containerElement = createAndInsertLogicalContainer(parent, childIndex);
|
||||
|
||||
|
|
@ -385,13 +406,10 @@ export class BrowserRenderer {
|
|||
} else {
|
||||
element.removeAttribute('value');
|
||||
}
|
||||
|
||||
// See above for why we have this special handling for <select>/<option>
|
||||
// Note that this is only one of the two cases where we set the value on a <select>
|
||||
const selectElem = this.findClosestAncestorSelectElement(element);
|
||||
if (selectElem && (selectValuePropname in selectElem) && selectElem[selectValuePropname] === value) {
|
||||
this.tryApplyValueProperty(batch, selectElem, attributeFrame);
|
||||
delete selectElem[selectValuePropname];
|
||||
}
|
||||
// Situation 3
|
||||
this.trySetSelectValueFromOptionElement(<HTMLOptionElement>element);
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ const nonBubblingEvents = toLookup([
|
|||
'scroll',
|
||||
'submit',
|
||||
'unload',
|
||||
'toggle',
|
||||
'DOMNodeInsertedIntoDocument',
|
||||
'DOMNodeRemovedFromDocument',
|
||||
]);
|
||||
|
|
|
|||
|
|
@ -89,6 +89,9 @@ export class EventForDotNet<TData extends UIEventArgs> {
|
|||
case 'mousewheel':
|
||||
return new EventForDotNet<UIWheelEventArgs>('wheel', parseWheelEvent(event as WheelEvent));
|
||||
|
||||
case 'toggle':
|
||||
return new EventForDotNet<UIEventArgs>('toggle', { type: event.type });
|
||||
|
||||
default:
|
||||
return new EventForDotNet<UIEventArgs>('unknown', { type: event.type });
|
||||
}
|
||||
|
|
@ -248,7 +251,7 @@ function normalizeTimeBasedValue(element: HTMLInputElement): string {
|
|||
|
||||
// The following interfaces must be kept in sync with the UIEventArgs C# classes
|
||||
|
||||
export type EventArgsType = 'change' | 'clipboard' | 'drag' | 'error' | 'focus' | 'keyboard' | 'mouse' | 'pointer' | 'progress' | 'touch' | 'unknown' | 'wheel';
|
||||
export type EventArgsType = 'change' | 'clipboard' | 'drag' | 'error' | 'focus' | 'keyboard' | 'mouse' | 'pointer' | 'progress' | 'touch' | 'unknown' | 'wheel' | 'toggle';
|
||||
|
||||
export interface UIEventArgs {
|
||||
type: string;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,86 @@
|
|||
export const Virtualize = {
|
||||
init,
|
||||
dispose,
|
||||
};
|
||||
|
||||
const observersByDotNetId = {};
|
||||
|
||||
function findClosestScrollContainer(element: Element | null): Element | null {
|
||||
if (!element) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const style = getComputedStyle(element);
|
||||
|
||||
if (style.overflowY !== 'visible') {
|
||||
return element;
|
||||
}
|
||||
|
||||
return findClosestScrollContainer(element.parentElement);
|
||||
}
|
||||
|
||||
function init(dotNetHelper: any, spacerBefore: HTMLElement, spacerAfter: HTMLElement, rootMargin = 50): void {
|
||||
const intersectionObserver = new IntersectionObserver(intersectionCallback, {
|
||||
root: findClosestScrollContainer(spacerBefore),
|
||||
rootMargin: `${rootMargin}px`,
|
||||
});
|
||||
|
||||
intersectionObserver.observe(spacerBefore);
|
||||
intersectionObserver.observe(spacerAfter);
|
||||
|
||||
const mutationObserverBefore = createSpacerMutationObserver(spacerBefore);
|
||||
const mutationObserverAfter = createSpacerMutationObserver(spacerAfter);
|
||||
|
||||
observersByDotNetId[dotNetHelper._id] = {
|
||||
intersectionObserver,
|
||||
mutationObserverBefore,
|
||||
mutationObserverAfter,
|
||||
};
|
||||
|
||||
function createSpacerMutationObserver(spacer: HTMLElement): MutationObserver {
|
||||
// Without the use of thresholds, IntersectionObserver only detects binary changes in visibility,
|
||||
// so if a spacer gets resized but remains visible, no additional callbacks will occur. By unobserving
|
||||
// and reobserving spacers when they get resized, the intersection callback will re-run if they remain visible.
|
||||
const mutationObserver = new MutationObserver((): void => {
|
||||
intersectionObserver.unobserve(spacer);
|
||||
intersectionObserver.observe(spacer);
|
||||
});
|
||||
|
||||
mutationObserver.observe(spacer, { attributes: true });
|
||||
|
||||
return mutationObserver;
|
||||
}
|
||||
|
||||
function intersectionCallback(entries: IntersectionObserverEntry[]): void {
|
||||
entries.forEach((entry): void => {
|
||||
if (!entry.isIntersecting) {
|
||||
return;
|
||||
}
|
||||
|
||||
const containerSize = entry.rootBounds?.height;
|
||||
|
||||
if (entry.target === spacerBefore) {
|
||||
dotNetHelper.invokeMethodAsync('OnSpacerBeforeVisible', entry.intersectionRect.top - entry.boundingClientRect.top, containerSize);
|
||||
} else if (entry.target === spacerAfter && spacerAfter.offsetHeight > 0) {
|
||||
// When we first start up, both the "before" and "after" spacers will be visible, but it's only relevant to raise a
|
||||
// single event to load the initial data. To avoid raising two events, skip the one for the "after" spacer if we know
|
||||
// it's meaningless to talk about any overlap into it.
|
||||
dotNetHelper.invokeMethodAsync('OnSpacerAfterVisible', entry.boundingClientRect.bottom - entry.intersectionRect.bottom, containerSize);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function dispose(dotNetHelper: any): void {
|
||||
const observers = observersByDotNetId[dotNetHelper._id];
|
||||
|
||||
if (observers) {
|
||||
observers.intersectionObserver.disconnect();
|
||||
observers.mutationObserverBefore.disconnect();
|
||||
observers.mutationObserverAfter.disconnect();
|
||||
|
||||
dotNetHelper.dispose();
|
||||
|
||||
delete observersByDotNetId[dotNetHelper._id];
|
||||
}
|
||||
}
|
||||
|
|
@ -14,6 +14,7 @@ describe('DefaultReconnectDisplay', () => {
|
|||
expect(element).toBeDefined();
|
||||
expect(element!.id).toBe('test-dialog-id');
|
||||
expect(element!.style.display).toBe('block');
|
||||
expect(element!.classList).toContain('show');
|
||||
|
||||
expect(display.message.textContent).toBe('Attempting to reconnect to the server...');
|
||||
expect(display.button.style.display).toBe('none');
|
||||
|
|
@ -36,6 +37,7 @@ describe('DefaultReconnectDisplay', () => {
|
|||
display.hide();
|
||||
|
||||
expect(display.modal.style.display).toBe('none');
|
||||
expect(display.modal.classList).not.toContain('show');
|
||||
});
|
||||
|
||||
it ('updates message on fail', () => {
|
||||
|
|
@ -46,6 +48,7 @@ describe('DefaultReconnectDisplay', () => {
|
|||
display.failed();
|
||||
|
||||
expect(display.modal.style.display).toBe('block');
|
||||
expect(display.modal.classList).toContain('show');
|
||||
expect(display.message.innerHTML).toBe('Reconnection failed. Try <a href=\"\">reloading</a> the page if you\'re unable to reconnect.');
|
||||
expect(display.button.style.display).toBe('block');
|
||||
});
|
||||
|
|
@ -58,6 +61,7 @@ describe('DefaultReconnectDisplay', () => {
|
|||
display.rejected();
|
||||
|
||||
expect(display.modal.style.display).toBe('block');
|
||||
expect(display.modal.classList).toContain('show');
|
||||
expect(display.message.innerHTML).toBe('Could not reconnect to the server. <a href=\"\">Reload</a> the page to restore functionality.');
|
||||
expect(display.button.style.display).toBe('none');
|
||||
});
|
||||
|
|
|
|||
|
|
@ -16,7 +16,8 @@ namespace Microsoft.AspNetCore.Components.Forms
|
|||
{
|
||||
private readonly Func<Task> _handleSubmitDelegate; // Cache to avoid per-render allocations
|
||||
|
||||
private EditContext? _fixedEditContext;
|
||||
private EditContext? _editContext;
|
||||
private bool _hasSetEditContextExplicitly;
|
||||
|
||||
/// <summary>
|
||||
/// Constructs an instance of <see cref="EditForm"/>.
|
||||
|
|
@ -36,7 +37,16 @@ namespace Microsoft.AspNetCore.Components.Forms
|
|||
/// also supply <see cref="Model"/>, since the model value will be taken
|
||||
/// from the <see cref="EditContext.Model"/> property.
|
||||
/// </summary>
|
||||
[Parameter] public EditContext? EditContext { get; set; }
|
||||
[Parameter]
|
||||
public EditContext? EditContext
|
||||
{
|
||||
get => _editContext;
|
||||
set
|
||||
{
|
||||
_editContext = value;
|
||||
_hasSetEditContextExplicitly = value != null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the top-level model object for the form. An edit context will
|
||||
|
|
@ -73,11 +83,16 @@ namespace Microsoft.AspNetCore.Components.Forms
|
|||
/// <inheritdoc />
|
||||
protected override void OnParametersSet()
|
||||
{
|
||||
if ((EditContext == null) == (Model == null))
|
||||
if (_hasSetEditContextExplicitly && Model != null)
|
||||
{
|
||||
throw new InvalidOperationException($"{nameof(EditForm)} requires a {nameof(Model)} " +
|
||||
$"parameter, or an {nameof(EditContext)} parameter, but not both.");
|
||||
}
|
||||
else if (!_hasSetEditContextExplicitly && Model == null)
|
||||
{
|
||||
throw new InvalidOperationException($"{nameof(EditForm)} requires either a {nameof(Model)} " +
|
||||
$"parameter, or an {nameof(EditContext)} parameter, please provide one of these.");
|
||||
}
|
||||
|
||||
// If you're using OnSubmit, it becomes your responsibility to trigger validation manually
|
||||
// (e.g., so you can display a "pending" state in the UI). In that case you don't want the
|
||||
|
|
@ -89,31 +104,31 @@ namespace Microsoft.AspNetCore.Components.Forms
|
|||
$"{nameof(EditForm)}, do not also supply {nameof(OnValidSubmit)} or {nameof(OnInvalidSubmit)}.");
|
||||
}
|
||||
|
||||
// Update _fixedEditContext if we don't have one yet, or if they are supplying a
|
||||
// Update _editContext if we don't have one yet, or if they are supplying a
|
||||
// potentially new EditContext, or if they are supplying a different Model
|
||||
if (_fixedEditContext == null || EditContext != null || Model != _fixedEditContext.Model)
|
||||
if (Model != null && Model != _editContext?.Model)
|
||||
{
|
||||
_fixedEditContext = EditContext ?? new EditContext(Model!);
|
||||
_editContext = new EditContext(Model!);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void BuildRenderTree(RenderTreeBuilder builder)
|
||||
{
|
||||
Debug.Assert(_fixedEditContext != null);
|
||||
Debug.Assert(_editContext != null);
|
||||
|
||||
// If _fixedEditContext changes, tear down and recreate all descendants.
|
||||
// If _editContext changes, tear down and recreate all descendants.
|
||||
// This is so we can safely use the IsFixed optimization on CascadingValue,
|
||||
// optimizing for the common case where _fixedEditContext never changes.
|
||||
builder.OpenRegion(_fixedEditContext.GetHashCode());
|
||||
// optimizing for the common case where _editContext never changes.
|
||||
builder.OpenRegion(_editContext.GetHashCode());
|
||||
|
||||
builder.OpenElement(0, "form");
|
||||
builder.AddMultipleAttributes(1, AdditionalAttributes);
|
||||
builder.AddAttribute(2, "onsubmit", _handleSubmitDelegate);
|
||||
builder.OpenComponent<CascadingValue<EditContext>>(3);
|
||||
builder.AddAttribute(4, "IsFixed", true);
|
||||
builder.AddAttribute(5, "Value", _fixedEditContext);
|
||||
builder.AddAttribute(6, "ChildContent", ChildContent?.Invoke(_fixedEditContext));
|
||||
builder.AddAttribute(5, "Value", _editContext);
|
||||
builder.AddAttribute(6, "ChildContent", ChildContent?.Invoke(_editContext));
|
||||
builder.CloseComponent();
|
||||
builder.CloseElement();
|
||||
|
||||
|
|
@ -122,26 +137,26 @@ namespace Microsoft.AspNetCore.Components.Forms
|
|||
|
||||
private async Task HandleSubmitAsync()
|
||||
{
|
||||
Debug.Assert(_fixedEditContext != null);
|
||||
Debug.Assert(_editContext != null);
|
||||
|
||||
if (OnSubmit.HasDelegate)
|
||||
{
|
||||
// When using OnSubmit, the developer takes control of the validation lifecycle
|
||||
await OnSubmit.InvokeAsync(_fixedEditContext);
|
||||
await OnSubmit.InvokeAsync(_editContext);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Otherwise, the system implicitly runs validation on form submission
|
||||
var isValid = _fixedEditContext.Validate(); // This will likely become ValidateAsync later
|
||||
var isValid = _editContext.Validate(); // This will likely become ValidateAsync later
|
||||
|
||||
if (isValid && OnValidSubmit.HasDelegate)
|
||||
{
|
||||
await OnValidSubmit.InvokeAsync(_fixedEditContext);
|
||||
await OnValidSubmit.InvokeAsync(_editContext);
|
||||
}
|
||||
|
||||
if (!isValid && OnInvalidSubmit.HasDelegate)
|
||||
{
|
||||
await OnInvalidSubmit.InvokeAsync(_fixedEditContext);
|
||||
await OnInvalidSubmit.InvokeAsync(_editContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,6 +50,12 @@ namespace Microsoft.AspNetCore.Components.Forms
|
|||
/// </summary>
|
||||
[Parameter] public Expression<Func<TValue>>? ValueExpression { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the display name for this field.
|
||||
/// <para>This value is used when generating error messages when the input value fails to parse correctly.</para>
|
||||
/// </summary>
|
||||
[Parameter] public string? DisplayName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the associated <see cref="Forms.EditContext"/>.
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ namespace Microsoft.AspNetCore.Components.Forms
|
|||
}
|
||||
else
|
||||
{
|
||||
validationErrorMessage = string.Format(ParsingErrorMessage, FieldIdentifier.FieldName);
|
||||
validationErrorMessage = string.Format(ParsingErrorMessage, DisplayName ?? FieldIdentifier.FieldName);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ namespace Microsoft.AspNetCore.Components.Forms
|
|||
else
|
||||
{
|
||||
result = default;
|
||||
validationErrorMessage = $"The {input.FieldIdentifier.FieldName} field is not valid.";
|
||||
validationErrorMessage = $"The {input.DisplayName ?? input.FieldIdentifier.FieldName} field is not valid.";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ namespace Microsoft.AspNetCore.Components.Forms
|
|||
}
|
||||
else
|
||||
{
|
||||
validationErrorMessage = string.Format(ParsingErrorMessage, FieldIdentifier.FieldName);
|
||||
validationErrorMessage = string.Format(ParsingErrorMessage, DisplayName ?? FieldIdentifier.FieldName);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
// 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.Web.Virtualization
|
||||
{
|
||||
internal interface IVirtualizeJsCallbacks
|
||||
{
|
||||
void OnBeforeSpacerVisible(float spacerSize, float containerSize);
|
||||
void OnAfterSpacerVisible(float spacerSize, float containerSize);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.Web.Virtualization
|
||||
{
|
||||
/// <summary>
|
||||
/// A function that provides items to a virtualized source.
|
||||
/// </summary>
|
||||
/// <typeparam name="TItem">The type of the context for each item in the list.</typeparam>
|
||||
/// <param name="request">The <see cref="ItemsProviderRequest"/> defining the request details.</param>
|
||||
/// <returns>A <see cref="ValueTask"/> whose result is a <see cref="ItemsProviderResult{TItem}"/> upon successful completion.</returns>
|
||||
public delegate ValueTask<ItemsProviderResult<TItem>> ItemsProviderDelegate<TItem>(ItemsProviderRequest request);
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Threading;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.Web.Virtualization
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a request to an <see cref="ItemsProviderDelegate{TItem}"/>.
|
||||
/// </summary>
|
||||
public readonly struct ItemsProviderRequest
|
||||
{
|
||||
/// <summary>
|
||||
/// The start index of the data segment requested.
|
||||
/// </summary>
|
||||
public int StartIndex { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The requested number of items to be provided. The actual number of provided items does not need to match
|
||||
/// this value.
|
||||
/// </summary>
|
||||
public int Count { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="System.Threading.CancellationToken"/> used to relay cancellation of the request.
|
||||
/// </summary>
|
||||
public CancellationToken CancellationToken { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a new <see cref="ItemsProviderRequest"/> instance.
|
||||
/// </summary>
|
||||
/// <param name="startIndex">The start index of the data segment requested.</param>
|
||||
/// <param name="count">The requested number of items to be provided.</param>
|
||||
/// <param name="cancellationToken">
|
||||
/// The <see cref="System.Threading.CancellationToken"/> used to relay cancellation of the request.
|
||||
/// </param>
|
||||
public ItemsProviderRequest(int startIndex, int count, CancellationToken cancellationToken)
|
||||
{
|
||||
StartIndex = startIndex;
|
||||
Count = count;
|
||||
CancellationToken = cancellationToken;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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.Collections.Generic;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.Web.Virtualization
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the result of a <see cref="ItemsProviderDelegate{TItem}"/>.
|
||||
/// </summary>
|
||||
/// <typeparam name="TItem">The type of the context for each item in the list.</typeparam>
|
||||
public readonly struct ItemsProviderResult<TItem>
|
||||
{
|
||||
/// <summary>
|
||||
/// The items to provide.
|
||||
/// </summary>
|
||||
public IEnumerable<TItem> Items { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The total item count in the source generating the items provided.
|
||||
/// </summary>
|
||||
public int TotalItemCount { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Instantiates a new <see cref="ItemsProviderResult{TItem}"/> instance.
|
||||
/// </summary>
|
||||
/// <param name="items">The items to provide.</param>
|
||||
/// <param name="totalItemCount">The total item count in the source generating the items provided.</param>
|
||||
public ItemsProviderResult(IEnumerable<TItem> items, int totalItemCount)
|
||||
{
|
||||
Items = items;
|
||||
TotalItemCount = totalItemCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
// 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.Web.Virtualization
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains context for a placeholder in a virtualized list.
|
||||
/// </summary>
|
||||
public readonly struct PlaceholderContext
|
||||
{
|
||||
/// <summary>
|
||||
/// The item index of the placeholder.
|
||||
/// </summary>
|
||||
public int Index { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a new <see cref="PlaceholderContext"/> instance.
|
||||
/// </summary>
|
||||
/// <param name="index">The item index of the placeholder.</param>
|
||||
public PlaceholderContext(int index)
|
||||
{
|
||||
Index = index;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,303 @@
|
|||
// 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.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Components.Rendering;
|
||||
using Microsoft.JSInterop;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.Web.Virtualization
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides functionality for rendering a virtualized list of items.
|
||||
/// </summary>
|
||||
/// <typeparam name="TItem">The <c>context</c> type for the items being rendered.</typeparam>
|
||||
public sealed class Virtualize<TItem> : ComponentBase, IVirtualizeJsCallbacks, IAsyncDisposable
|
||||
{
|
||||
private VirtualizeJsInterop? _jsInterop;
|
||||
|
||||
private ElementReference _spacerBefore;
|
||||
|
||||
private ElementReference _spacerAfter;
|
||||
|
||||
private int _itemsBefore;
|
||||
|
||||
private int _visibleItemCapacity;
|
||||
|
||||
private int _itemCount;
|
||||
|
||||
private int _loadedItemsStartIndex;
|
||||
|
||||
private IEnumerable<TItem>? _loadedItems;
|
||||
|
||||
private CancellationTokenSource? _refreshCts;
|
||||
|
||||
private Exception? _refreshException;
|
||||
|
||||
private ItemsProviderDelegate<TItem> _itemsProvider = default!;
|
||||
|
||||
private RenderFragment<TItem>? _itemTemplate;
|
||||
|
||||
private RenderFragment<PlaceholderContext>? _placeholder;
|
||||
|
||||
[Inject]
|
||||
private IJSRuntime JSRuntime { get; set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the item template for the list.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public RenderFragment<TItem>? ChildContent { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the item template for the list.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public RenderFragment<TItem>? ItemContent { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the template for items that have not yet been loaded in memory.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public RenderFragment<PlaceholderContext>? Placeholder { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the size of each item in pixels.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public float ItemSize { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the function providing items to the list.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public ItemsProviderDelegate<TItem>? ItemsProvider { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the fixed item source.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public ICollection<TItem>? Items { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void OnParametersSet()
|
||||
{
|
||||
if (ItemSize <= 0)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
$"{GetType()} requires a positive value for parameter '{nameof(ItemSize)}' to perform virtualization.");
|
||||
}
|
||||
|
||||
if (ItemsProvider != null)
|
||||
{
|
||||
if (Items != null)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
$"{GetType()} can only accept one item source from its parameters. " +
|
||||
$"Do not supply both '{nameof(Items)}' and '{nameof(ItemsProvider)}'.");
|
||||
}
|
||||
|
||||
_itemsProvider = ItemsProvider;
|
||||
}
|
||||
else if (Items != null)
|
||||
{
|
||||
_itemsProvider = DefaultItemsProvider;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
$"{GetType()} requires either the '{nameof(Items)}' or '{nameof(ItemsProvider)}' parameters to be specified " +
|
||||
$"and non-null.");
|
||||
}
|
||||
|
||||
_itemTemplate = ItemContent ?? ChildContent;
|
||||
_placeholder = Placeholder ?? DefaultPlaceholder;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||
{
|
||||
if (firstRender)
|
||||
{
|
||||
_jsInterop = new VirtualizeJsInterop(this, JSRuntime);
|
||||
await _jsInterop.InitializeAsync(_spacerBefore, _spacerAfter);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void BuildRenderTree(RenderTreeBuilder builder)
|
||||
{
|
||||
if (_refreshException != null)
|
||||
{
|
||||
var oldRefreshException = _refreshException;
|
||||
_refreshException = null;
|
||||
|
||||
throw oldRefreshException;
|
||||
}
|
||||
|
||||
builder.OpenElement(0, "div");
|
||||
builder.AddAttribute(1, "style", GetSpacerStyle(_itemsBefore));
|
||||
builder.AddElementReferenceCapture(2, elementReference => _spacerBefore = elementReference);
|
||||
builder.CloseElement();
|
||||
|
||||
var lastItemIndex = Math.Min(_itemsBefore + _visibleItemCapacity, _itemCount);
|
||||
var renderIndex = _itemsBefore;
|
||||
var placeholdersBeforeCount = Math.Min(_loadedItemsStartIndex, lastItemIndex);
|
||||
|
||||
builder.OpenRegion(3);
|
||||
|
||||
// Render placeholders before the loaded items.
|
||||
for (; renderIndex < placeholdersBeforeCount; renderIndex++)
|
||||
{
|
||||
// This is a rare case where it's valid for the sequence number to be programmatically incremented.
|
||||
// This is only true because we know for certain that no other content will be alongside it.
|
||||
builder.AddContent(renderIndex, _placeholder, new PlaceholderContext(renderIndex));
|
||||
}
|
||||
|
||||
builder.CloseRegion();
|
||||
|
||||
// Render the loaded items.
|
||||
if (_loadedItems != null && _itemTemplate != null)
|
||||
{
|
||||
var itemsToShow = _loadedItems
|
||||
.Skip(_itemsBefore - _loadedItemsStartIndex)
|
||||
.Take(lastItemIndex - _loadedItemsStartIndex);
|
||||
|
||||
builder.OpenRegion(4);
|
||||
|
||||
foreach (var item in itemsToShow)
|
||||
{
|
||||
_itemTemplate(item)(builder);
|
||||
renderIndex++;
|
||||
}
|
||||
|
||||
builder.CloseRegion();
|
||||
}
|
||||
|
||||
builder.OpenRegion(5);
|
||||
|
||||
// Render the placeholders after the loaded items.
|
||||
for (; renderIndex < lastItemIndex; renderIndex++)
|
||||
{
|
||||
builder.AddContent(renderIndex, _placeholder, new PlaceholderContext(renderIndex));
|
||||
}
|
||||
|
||||
builder.CloseRegion();
|
||||
|
||||
var itemsAfter = Math.Max(0, _itemCount - _visibleItemCapacity - _itemsBefore);
|
||||
|
||||
builder.OpenElement(6, "div");
|
||||
builder.AddAttribute(7, "style", GetSpacerStyle(itemsAfter));
|
||||
builder.AddElementReferenceCapture(8, elementReference => _spacerAfter = elementReference);
|
||||
|
||||
builder.CloseElement();
|
||||
}
|
||||
|
||||
private string GetSpacerStyle(int itemsInSpacer)
|
||||
=> $"height: {itemsInSpacer * ItemSize}px;";
|
||||
|
||||
void IVirtualizeJsCallbacks.OnBeforeSpacerVisible(float spacerSize, float containerSize)
|
||||
{
|
||||
CalcualteItemDistribution(spacerSize, containerSize, out var itemsBefore, out var visibleItemCapacity);
|
||||
|
||||
UpdateItemDistribution(itemsBefore, visibleItemCapacity);
|
||||
}
|
||||
|
||||
void IVirtualizeJsCallbacks.OnAfterSpacerVisible(float spacerSize, float containerSize)
|
||||
{
|
||||
CalcualteItemDistribution(spacerSize, containerSize, out var itemsAfter, out var visibleItemCapacity);
|
||||
|
||||
var itemsBefore = Math.Max(0, _itemCount - itemsAfter - visibleItemCapacity);
|
||||
|
||||
UpdateItemDistribution(itemsBefore, visibleItemCapacity);
|
||||
}
|
||||
|
||||
private void CalcualteItemDistribution(float spacerSize, float containerSize, out int itemsInSpacer, out int visibleItemCapacity)
|
||||
{
|
||||
itemsInSpacer = Math.Max(0, (int)Math.Floor(spacerSize / ItemSize) - 1);
|
||||
visibleItemCapacity = (int)Math.Ceiling(containerSize / ItemSize) + 2;
|
||||
}
|
||||
|
||||
private void UpdateItemDistribution(int itemsBefore, int visibleItemCapacity)
|
||||
{
|
||||
if (itemsBefore != _itemsBefore || visibleItemCapacity != _visibleItemCapacity)
|
||||
{
|
||||
_itemsBefore = itemsBefore;
|
||||
_visibleItemCapacity = visibleItemCapacity;
|
||||
var refreshTask = RefreshDataAsync();
|
||||
|
||||
if (!refreshTask.IsCompleted)
|
||||
{
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async Task RefreshDataAsync()
|
||||
{
|
||||
_refreshCts?.Cancel();
|
||||
_refreshCts = new CancellationTokenSource();
|
||||
|
||||
var cancellationToken = _refreshCts.Token;
|
||||
var request = new ItemsProviderRequest(_itemsBefore, _visibleItemCapacity, cancellationToken);
|
||||
|
||||
try
|
||||
{
|
||||
var result = await _itemsProvider(request);
|
||||
|
||||
// Only apply result if the task was not canceled.
|
||||
if (!cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
_itemCount = result.TotalItemCount;
|
||||
_loadedItems = result.Items;
|
||||
_loadedItemsStartIndex = request.StartIndex;
|
||||
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (e is OperationCanceledException oce && oce.CancellationToken == cancellationToken)
|
||||
{
|
||||
// No-op; we canceled the operation, so it's fine to suppress this exception.
|
||||
}
|
||||
else
|
||||
{
|
||||
// Cache this exception so the renderer can throw it.
|
||||
_refreshException = e;
|
||||
|
||||
// Re-render the component to throw the exception.
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ValueTask<ItemsProviderResult<TItem>> DefaultItemsProvider(ItemsProviderRequest request)
|
||||
{
|
||||
return ValueTask.FromResult(new ItemsProviderResult<TItem>(
|
||||
Items!.Skip(request.StartIndex).Take(request.Count),
|
||||
Items!.Count));
|
||||
}
|
||||
|
||||
private RenderFragment DefaultPlaceholder(PlaceholderContext context) => (builder) =>
|
||||
{
|
||||
builder.OpenElement(0, "div");
|
||||
builder.AddAttribute(1, "style", $"height: {ItemSize}px;");
|
||||
builder.CloseElement();
|
||||
};
|
||||
|
||||
/// <inheritdoc />
|
||||
public async ValueTask DisposeAsync()
|
||||
{
|
||||
_refreshCts?.Cancel();
|
||||
|
||||
if (_jsInterop != null)
|
||||
{
|
||||
await _jsInterop.DisposeAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
// 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.Web.Virtualization
|
||||
{
|
||||
internal class VirtualizeJsInterop : IAsyncDisposable
|
||||
{
|
||||
private const string JsFunctionsPrefix = "Blazor._internal.Virtualize";
|
||||
|
||||
private readonly IVirtualizeJsCallbacks _owner;
|
||||
|
||||
private readonly IJSRuntime _jsRuntime;
|
||||
|
||||
private DotNetObjectReference<VirtualizeJsInterop>? _selfReference;
|
||||
|
||||
public VirtualizeJsInterop(IVirtualizeJsCallbacks owner, IJSRuntime jsRuntime)
|
||||
{
|
||||
_owner = owner;
|
||||
_jsRuntime = jsRuntime;
|
||||
}
|
||||
|
||||
public async ValueTask InitializeAsync(ElementReference spacerBefore, ElementReference spacerAfter)
|
||||
{
|
||||
_selfReference = DotNetObjectReference.Create(this);
|
||||
await _jsRuntime.InvokeVoidAsync($"{JsFunctionsPrefix}.init", _selfReference, spacerBefore, spacerAfter);
|
||||
}
|
||||
|
||||
[JSInvokable]
|
||||
public void OnSpacerBeforeVisible(float spacerSize, float containerSize)
|
||||
{
|
||||
_owner.OnBeforeSpacerVisible(spacerSize, containerSize);
|
||||
}
|
||||
|
||||
[JSInvokable]
|
||||
public void OnSpacerAfterVisible(float spacerSize, float containerSize)
|
||||
{
|
||||
_owner.OnAfterSpacerVisible(spacerSize, containerSize);
|
||||
}
|
||||
|
||||
public async ValueTask DisposeAsync()
|
||||
{
|
||||
if (_selfReference != null)
|
||||
{
|
||||
await _jsRuntime.InvokeVoidAsync($"{JsFunctionsPrefix}.dispose", _selfReference);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -122,6 +122,8 @@ namespace Microsoft.AspNetCore.Components.Web
|
|||
[EventHandler("onpointerlockerror", typeof(EventArgs), true, true)]
|
||||
[EventHandler("onreadystatechange", typeof(EventArgs), true, true)]
|
||||
[EventHandler("onscroll", typeof(EventArgs), true, true)]
|
||||
|
||||
[EventHandler("ontoggle", typeof(EventArgs), true, true)]
|
||||
public static class EventHandlers
|
||||
{
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,120 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.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 EditFormTest
|
||||
{
|
||||
|
||||
[Fact]
|
||||
public async Task ThrowsIfBothEditContextAndModelAreSupplied()
|
||||
{
|
||||
// Arrange
|
||||
var editForm = new EditForm
|
||||
{
|
||||
EditContext = new EditContext(new TestModel()),
|
||||
Model = new TestModel()
|
||||
};
|
||||
var testRenderer = new TestRenderer();
|
||||
var componentId = testRenderer.AssignRootComponentId(editForm);
|
||||
|
||||
// Act/Assert
|
||||
var ex = await Assert.ThrowsAsync<InvalidOperationException>(
|
||||
() => testRenderer.RenderRootComponentAsync(componentId));
|
||||
Assert.StartsWith($"{nameof(EditForm)} requires a {nameof(EditForm.Model)} parameter, or an {nameof(EditContext)} parameter, but not both.", ex.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ThrowsIfBothEditContextAndModelAreNull()
|
||||
{
|
||||
// Arrange
|
||||
var editForm = new EditForm();
|
||||
var testRenderer = new TestRenderer();
|
||||
var componentId = testRenderer.AssignRootComponentId(editForm);
|
||||
|
||||
// Act/Assert
|
||||
var ex = await Assert.ThrowsAsync<InvalidOperationException>(
|
||||
() => testRenderer.RenderRootComponentAsync(componentId));
|
||||
Assert.StartsWith($"{nameof(EditForm)} requires either a {nameof(EditForm.Model)} parameter, or an {nameof(EditContext)} parameter, please provide one of these.", ex.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ReturnsEditContextWhenModelParameterUsed()
|
||||
{
|
||||
// Arrange
|
||||
var model = new TestModel();
|
||||
var rootComponent = new TestEditFormHostComponent
|
||||
{
|
||||
Model = model
|
||||
};
|
||||
var editFormComponent = await RenderAndGetTestEditFormComponentAsync(rootComponent);
|
||||
|
||||
// Act
|
||||
var returnedEditContext = editFormComponent.EditContext;
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(returnedEditContext);
|
||||
Assert.Same(model, returnedEditContext.Model);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ReturnsEditContextWhenEditContextParameterUsed()
|
||||
{
|
||||
// Arrange
|
||||
var editContext = new EditContext(new TestModel());
|
||||
var rootComponent = new TestEditFormHostComponent
|
||||
{
|
||||
EditContext = editContext
|
||||
};
|
||||
var editFormComponent = await RenderAndGetTestEditFormComponentAsync(rootComponent);
|
||||
|
||||
// Act
|
||||
var returnedEditContext = editFormComponent.EditContext;
|
||||
|
||||
// Assert
|
||||
Assert.Same(editContext, returnedEditContext);
|
||||
}
|
||||
|
||||
private static EditForm FindEditFormComponent(CapturedBatch batch)
|
||||
=> batch.ReferenceFrames
|
||||
.Where(f => f.FrameType == RenderTreeFrameType.Component)
|
||||
.Select(f => f.Component)
|
||||
.OfType<EditForm>()
|
||||
.Single();
|
||||
|
||||
private static async Task<EditForm> RenderAndGetTestEditFormComponentAsync(TestEditFormHostComponent hostComponent)
|
||||
{
|
||||
var testRenderer = new TestRenderer();
|
||||
var componentId = testRenderer.AssignRootComponentId(hostComponent);
|
||||
await testRenderer.RenderRootComponentAsync(componentId);
|
||||
return FindEditFormComponent(testRenderer.Batches.Single());
|
||||
}
|
||||
|
||||
class TestModel
|
||||
{
|
||||
public string StringProperty { get; set; }
|
||||
}
|
||||
|
||||
class TestEditFormHostComponent : AutoRenderComponent
|
||||
{
|
||||
public EditContext EditContext { get; set; }
|
||||
public TestModel Model { get; set; }
|
||||
|
||||
protected override void BuildRenderTree(RenderTreeBuilder builder)
|
||||
{
|
||||
builder.OpenComponent<EditForm>(0);
|
||||
builder.AddAttribute(1, "Model", Model);
|
||||
builder.AddAttribute(2, "EditContext", EditContext);
|
||||
builder.CloseComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4,10 +4,7 @@
|
|||
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;
|
||||
|
||||
|
|
@ -35,7 +32,7 @@ namespace Microsoft.AspNetCore.Components.Forms
|
|||
// Arrange
|
||||
var model = new TestModel();
|
||||
var rootComponent = new TestInputHostComponent<string, TestInputComponent<string>> { EditContext = new EditContext(model), ValueExpression = () => model.StringProperty };
|
||||
await RenderAndGetTestInputComponentAsync(rootComponent);
|
||||
await InputRenderer.RenderAndGetComponent(rootComponent);
|
||||
|
||||
// Act/Assert
|
||||
rootComponent.EditContext = new EditContext(model);
|
||||
|
|
@ -51,7 +48,7 @@ namespace Microsoft.AspNetCore.Components.Forms
|
|||
var rootComponent = new TestInputHostComponent<string, TestInputComponent<string>> { EditContext = new EditContext(model) };
|
||||
|
||||
// Act/Assert
|
||||
var ex = await Assert.ThrowsAsync<InvalidOperationException>(() => RenderAndGetTestInputComponentAsync(rootComponent));
|
||||
var ex = await Assert.ThrowsAsync<InvalidOperationException>(() => InputRenderer.RenderAndGetComponent(rootComponent));
|
||||
Assert.Contains($"{typeof(TestInputComponent<string>)} requires a value for the 'ValueExpression' parameter. Normally this is provided automatically when using 'bind-Value'.", ex.Message);
|
||||
}
|
||||
|
||||
|
|
@ -68,7 +65,7 @@ namespace Microsoft.AspNetCore.Components.Forms
|
|||
};
|
||||
|
||||
// Act
|
||||
var inputComponent = await RenderAndGetTestInputComponentAsync(rootComponent);
|
||||
var inputComponent = await InputRenderer.RenderAndGetComponent(rootComponent);
|
||||
|
||||
// Assert
|
||||
Assert.Equal("some value", inputComponent.CurrentValue);
|
||||
|
|
@ -87,7 +84,7 @@ namespace Microsoft.AspNetCore.Components.Forms
|
|||
};
|
||||
|
||||
// Act
|
||||
var inputComponent = await RenderAndGetTestInputComponentAsync(rootComponent);
|
||||
var inputComponent = await InputRenderer.RenderAndGetComponent(rootComponent);
|
||||
|
||||
// Assert
|
||||
Assert.Same(rootComponent.EditContext, inputComponent.EditContext);
|
||||
|
|
@ -106,7 +103,7 @@ namespace Microsoft.AspNetCore.Components.Forms
|
|||
};
|
||||
|
||||
// Act
|
||||
var inputComponent = await RenderAndGetTestInputComponentAsync(rootComponent);
|
||||
var inputComponent = await InputRenderer.RenderAndGetComponent(rootComponent);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(FieldIdentifier.Create(() => model.StringProperty), inputComponent.FieldIdentifier);
|
||||
|
|
@ -123,7 +120,7 @@ namespace Microsoft.AspNetCore.Components.Forms
|
|||
Value = "initial value",
|
||||
ValueExpression = () => model.StringProperty
|
||||
};
|
||||
var inputComponent = await RenderAndGetTestInputComponentAsync(rootComponent);
|
||||
var inputComponent = await InputRenderer.RenderAndGetComponent(rootComponent);
|
||||
Assert.Equal("initial value", inputComponent.CurrentValue);
|
||||
|
||||
// Act
|
||||
|
|
@ -146,7 +143,7 @@ namespace Microsoft.AspNetCore.Components.Forms
|
|||
ValueChanged = val => valueChangedCallLog.Add(val),
|
||||
ValueExpression = () => model.StringProperty
|
||||
};
|
||||
var inputComponent = await RenderAndGetTestInputComponentAsync(rootComponent);
|
||||
var inputComponent = await InputRenderer.RenderAndGetComponent(rootComponent);
|
||||
Assert.Empty(valueChangedCallLog);
|
||||
|
||||
// Act
|
||||
|
|
@ -169,7 +166,7 @@ namespace Microsoft.AspNetCore.Components.Forms
|
|||
ValueChanged = val => valueChangedCallLog.Add(val),
|
||||
ValueExpression = () => model.StringProperty
|
||||
};
|
||||
var inputComponent = await RenderAndGetTestInputComponentAsync(rootComponent);
|
||||
var inputComponent = await InputRenderer.RenderAndGetComponent(rootComponent);
|
||||
Assert.Empty(valueChangedCallLog);
|
||||
|
||||
// Act
|
||||
|
|
@ -190,7 +187,7 @@ namespace Microsoft.AspNetCore.Components.Forms
|
|||
Value = "initial value",
|
||||
ValueExpression = () => model.StringProperty
|
||||
};
|
||||
var inputComponent = await RenderAndGetTestInputComponentAsync(rootComponent);
|
||||
var inputComponent = await InputRenderer.RenderAndGetComponent(rootComponent);
|
||||
Assert.False(rootComponent.EditContext.IsModified(() => model.StringProperty));
|
||||
|
||||
// Act
|
||||
|
|
@ -213,7 +210,7 @@ namespace Microsoft.AspNetCore.Components.Forms
|
|||
var fieldIdentifier = FieldIdentifier.Create(() => model.StringProperty);
|
||||
|
||||
// Act/Assert: Initially, it's valid and unmodified
|
||||
var inputComponent = await RenderAndGetTestInputComponentAsync(rootComponent);
|
||||
var inputComponent = await InputRenderer.RenderAndGetComponent(rootComponent);
|
||||
Assert.Equal("valid", inputComponent.CssClass); // no Class was specified
|
||||
|
||||
// Act/Assert: Modify the field
|
||||
|
|
@ -251,7 +248,7 @@ namespace Microsoft.AspNetCore.Components.Forms
|
|||
var fieldIdentifier = FieldIdentifier.Create(() => model.StringProperty);
|
||||
|
||||
// Act/Assert
|
||||
var inputComponent = await RenderAndGetTestInputComponentAsync(rootComponent);
|
||||
var inputComponent = await InputRenderer.RenderAndGetComponent(rootComponent);
|
||||
Assert.Equal("my-class other-class valid", inputComponent.CssClass);
|
||||
|
||||
// Act/Assert: Retains custom class when changing field class
|
||||
|
|
@ -270,7 +267,7 @@ namespace Microsoft.AspNetCore.Components.Forms
|
|||
Value = new DateTime(1915, 3, 2),
|
||||
ValueExpression = () => model.DateProperty
|
||||
};
|
||||
var inputComponent = await RenderAndGetTestInputComponentAsync(rootComponent);
|
||||
var inputComponent = await InputRenderer.RenderAndGetComponent(rootComponent);
|
||||
|
||||
// Act/Assert
|
||||
Assert.Equal("1915/03/02", inputComponent.CurrentValueAsString);
|
||||
|
|
@ -289,7 +286,7 @@ namespace Microsoft.AspNetCore.Components.Forms
|
|||
ValueExpression = () => model.DateProperty
|
||||
};
|
||||
var fieldIdentifier = FieldIdentifier.Create(() => model.DateProperty);
|
||||
var inputComponent = await RenderAndGetTestInputComponentAsync(rootComponent);
|
||||
var inputComponent = await InputRenderer.RenderAndGetComponent(rootComponent);
|
||||
var numValidationStateChanges = 0;
|
||||
rootComponent.EditContext.OnValidationStateChanged += (sender, eventArgs) => { numValidationStateChanges++; };
|
||||
|
||||
|
|
@ -319,7 +316,7 @@ namespace Microsoft.AspNetCore.Components.Forms
|
|||
ValueExpression = () => model.DateProperty
|
||||
};
|
||||
var fieldIdentifier = FieldIdentifier.Create(() => model.DateProperty);
|
||||
var inputComponent = await RenderAndGetTestInputComponentAsync(rootComponent);
|
||||
var inputComponent = await InputRenderer.RenderAndGetComponent(rootComponent);
|
||||
var numValidationStateChanges = 0;
|
||||
rootComponent.EditContext.OnValidationStateChanged += (sender, eventArgs) => { numValidationStateChanges++; };
|
||||
|
||||
|
|
@ -470,21 +467,6 @@ namespace Microsoft.AspNetCore.Components.Forms
|
|||
Assert.Equal("userSpecifiedValue", component.AdditionalAttributes["aria-invalid"]);
|
||||
}
|
||||
|
||||
private static TComponent FindComponent<TComponent>(CapturedBatch batch)
|
||||
=> batch.ReferenceFrames
|
||||
.Where(f => f.FrameType == RenderTreeFrameType.Component)
|
||||
.Select(f => f.Component)
|
||||
.OfType<TComponent>()
|
||||
.Single();
|
||||
|
||||
private static async Task<TComponent> RenderAndGetTestInputComponentAsync<TValue, TComponent>(TestInputHostComponent<TValue, TComponent> hostComponent) where TComponent : TestInputComponent<TValue>
|
||||
{
|
||||
var testRenderer = new TestRenderer();
|
||||
var componentId = testRenderer.AssignRootComponentId(hostComponent);
|
||||
await testRenderer.RenderRootComponentAsync(componentId);
|
||||
return FindComponent<TComponent>(testRenderer.Batches.Single());
|
||||
}
|
||||
|
||||
class TestModel
|
||||
{
|
||||
public string StringProperty { get; set; }
|
||||
|
|
@ -530,7 +512,7 @@ namespace Microsoft.AspNetCore.Components.Forms
|
|||
}
|
||||
}
|
||||
|
||||
class TestDateInputComponent : TestInputComponent<DateTime>
|
||||
private class TestDateInputComponent : TestInputComponent<DateTime>
|
||||
{
|
||||
protected override string FormatValueAsString(DateTime value)
|
||||
=> value.ToString("yyyy/MM/dd");
|
||||
|
|
@ -549,35 +531,5 @@ namespace Microsoft.AspNetCore.Components.Forms
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
class TestInputHostComponent<TValue, TComponent> : AutoRenderComponent where TComponent : TestInputComponent<TValue>
|
||||
{
|
||||
public Dictionary<string, object> AdditionalAttributes { get; set; }
|
||||
|
||||
public EditContext EditContext { get; set; }
|
||||
|
||||
public TValue Value { get; set; }
|
||||
|
||||
public Action<TValue> ValueChanged { get; set; }
|
||||
|
||||
public Expression<Func<TValue>> ValueExpression { get; set; }
|
||||
|
||||
protected override void BuildRenderTree(RenderTreeBuilder builder)
|
||||
{
|
||||
builder.OpenComponent<CascadingValue<EditContext>>(0);
|
||||
builder.AddAttribute(1, "Value", EditContext);
|
||||
builder.AddAttribute(2, "ChildContent", new RenderFragment(childBuilder =>
|
||||
{
|
||||
childBuilder.OpenComponent<TComponent>(0);
|
||||
childBuilder.AddAttribute(0, "Value", Value);
|
||||
childBuilder.AddAttribute(1, "ValueChanged",
|
||||
EventCallback.Factory.Create(this, ValueChanged));
|
||||
childBuilder.AddAttribute(2, "ValueExpression", ValueExpression);
|
||||
childBuilder.AddMultipleAttributes(3, AdditionalAttributes);
|
||||
childBuilder.CloseComponent();
|
||||
}));
|
||||
builder.CloseComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,56 @@
|
|||
// 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.Threading.Tasks;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.Forms
|
||||
{
|
||||
public class InputDateTest
|
||||
{
|
||||
[Fact]
|
||||
public async Task ValidationErrorUsesDisplayAttributeName()
|
||||
{
|
||||
// Arrange
|
||||
var model = new TestModel();
|
||||
var rootComponent = new TestInputHostComponent<DateTime, TestInputDateComponent>
|
||||
{
|
||||
EditContext = new EditContext(model),
|
||||
ValueExpression = () => model.DateProperty,
|
||||
AdditionalAttributes = new Dictionary<string, object>
|
||||
{
|
||||
{ "DisplayName", "Date property" }
|
||||
}
|
||||
};
|
||||
var fieldIdentifier = FieldIdentifier.Create(() => model.DateProperty);
|
||||
var inputComponent = await InputRenderer.RenderAndGetComponent(rootComponent);
|
||||
|
||||
// Act
|
||||
await inputComponent.SetCurrentValueAsStringAsync("invalidDate");
|
||||
|
||||
// Assert
|
||||
var validationMessages = rootComponent.EditContext.GetValidationMessages(fieldIdentifier);
|
||||
Assert.NotEmpty(validationMessages);
|
||||
Assert.Contains("The Date property field must be a date.", validationMessages);
|
||||
}
|
||||
|
||||
private class TestModel
|
||||
{
|
||||
public DateTime DateProperty { get; set; }
|
||||
}
|
||||
|
||||
private class TestInputDateComponent : InputDate<DateTime>
|
||||
{
|
||||
public async Task SetCurrentValueAsStringAsync(string value)
|
||||
{
|
||||
// This is equivalent to the subclass writing to CurrentValueAsString
|
||||
// (e.g., from @bind), except to simplify the test code there's an InvokeAsync
|
||||
// here. In production code it wouldn't normally be required because @bind
|
||||
// calls run on the sync context anyway.
|
||||
await InvokeAsync(() => { base.CurrentValueAsString = value; });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.Forms
|
||||
{
|
||||
public class InputNumberTest
|
||||
{
|
||||
[Fact]
|
||||
public async Task ValidationErrorUsesDisplayAttributeName()
|
||||
{
|
||||
// Arrange
|
||||
var model = new TestModel();
|
||||
var rootComponent = new TestInputHostComponent<int, TestInputNumberComponent>
|
||||
{
|
||||
EditContext = new EditContext(model),
|
||||
ValueExpression = () => model.SomeNumber,
|
||||
AdditionalAttributes = new Dictionary<string, object>
|
||||
{
|
||||
{ "DisplayName", "Some number" }
|
||||
}
|
||||
};
|
||||
var fieldIdentifier = FieldIdentifier.Create(() => model.SomeNumber);
|
||||
var inputComponent = await InputRenderer.RenderAndGetComponent(rootComponent);
|
||||
|
||||
// Act
|
||||
await inputComponent.SetCurrentValueAsStringAsync("notANumber");
|
||||
|
||||
// Assert
|
||||
var validationMessages = rootComponent.EditContext.GetValidationMessages(fieldIdentifier);
|
||||
Assert.NotEmpty(validationMessages);
|
||||
Assert.Contains("The Some number field must be a number.", validationMessages);
|
||||
}
|
||||
|
||||
private class TestModel
|
||||
{
|
||||
public int SomeNumber { get; set; }
|
||||
}
|
||||
|
||||
private class TestInputNumberComponent : InputNumber<int>
|
||||
{
|
||||
public async Task SetCurrentValueAsStringAsync(string value)
|
||||
{
|
||||
// This is equivalent to the subclass writing to CurrentValueAsString
|
||||
// (e.g., from @bind), except to simplify the test code there's an InvokeAsync
|
||||
// here. In production code it wouldn't normally be required because @bind
|
||||
// calls run on the sync context anyway.
|
||||
await InvokeAsync(() => { base.CurrentValueAsString = value; });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Components.RenderTree;
|
||||
using Microsoft.AspNetCore.Components.Test.Helpers;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.Forms
|
||||
{
|
||||
internal static class InputRenderer
|
||||
{
|
||||
public static async Task<TComponent> RenderAndGetComponent<TValue, TComponent>(TestInputHostComponent<TValue, TComponent> hostComponent)
|
||||
where TComponent : InputBase<TValue>
|
||||
{
|
||||
var testRenderer = new TestRenderer();
|
||||
var componentId = testRenderer.AssignRootComponentId(hostComponent);
|
||||
await testRenderer.RenderRootComponentAsync(componentId);
|
||||
return FindComponent<TComponent>(testRenderer.Batches.Single());
|
||||
}
|
||||
|
||||
private static TComponent FindComponent<TComponent>(CapturedBatch batch)
|
||||
=> batch.ReferenceFrames
|
||||
.Where(f => f.FrameType == RenderTreeFrameType.Component)
|
||||
.Select(f => f.Component)
|
||||
.OfType<TComponent>()
|
||||
.Single();
|
||||
}
|
||||
}
|
||||
|
|
@ -2,12 +2,8 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Collections.Generic;
|
||||
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
|
||||
|
|
@ -19,12 +15,12 @@ namespace Microsoft.AspNetCore.Components.Forms
|
|||
{
|
||||
// Arrange
|
||||
var model = new TestModel();
|
||||
var rootComponent = new TestInputSelectHostComponent<TestEnum>
|
||||
var rootComponent = new TestInputHostComponent<TestEnum, TestInputSelect<TestEnum>>
|
||||
{
|
||||
EditContext = new EditContext(model),
|
||||
ValueExpression = () => model.NotNullableEnum
|
||||
};
|
||||
var inputSelectComponent = await RenderAndGetTestInputComponentAsync(rootComponent);
|
||||
var inputSelectComponent = await InputRenderer.RenderAndGetComponent(rootComponent);
|
||||
|
||||
// Act
|
||||
inputSelectComponent.CurrentValueAsString = "Two";
|
||||
|
|
@ -38,12 +34,12 @@ namespace Microsoft.AspNetCore.Components.Forms
|
|||
{
|
||||
// Arrange
|
||||
var model = new TestModel();
|
||||
var rootComponent = new TestInputSelectHostComponent<TestEnum>
|
||||
var rootComponent = new TestInputHostComponent<TestEnum, TestInputSelect<TestEnum>>
|
||||
{
|
||||
EditContext = new EditContext(model),
|
||||
ValueExpression = () => model.NotNullableEnum
|
||||
};
|
||||
var inputSelectComponent = await RenderAndGetTestInputComponentAsync(rootComponent);
|
||||
var inputSelectComponent = await InputRenderer.RenderAndGetComponent(rootComponent);
|
||||
|
||||
// Act
|
||||
inputSelectComponent.CurrentValueAsString = "";
|
||||
|
|
@ -57,12 +53,12 @@ namespace Microsoft.AspNetCore.Components.Forms
|
|||
{
|
||||
// Arrange
|
||||
var model = new TestModel();
|
||||
var rootComponent = new TestInputSelectHostComponent<TestEnum?>
|
||||
var rootComponent = new TestInputHostComponent<TestEnum?, TestInputSelect<TestEnum?>>
|
||||
{
|
||||
EditContext = new EditContext(model),
|
||||
ValueExpression = () => model.NullableEnum
|
||||
};
|
||||
var inputSelectComponent = await RenderAndGetTestInputComponentAsync(rootComponent);
|
||||
var inputSelectComponent = await InputRenderer.RenderAndGetComponent(rootComponent);
|
||||
|
||||
// Act
|
||||
inputSelectComponent.CurrentValueAsString = "Two";
|
||||
|
|
@ -76,12 +72,12 @@ namespace Microsoft.AspNetCore.Components.Forms
|
|||
{
|
||||
// Arrange
|
||||
var model = new TestModel();
|
||||
var rootComponent = new TestInputSelectHostComponent<TestEnum?>
|
||||
var rootComponent = new TestInputHostComponent<TestEnum?, TestInputSelect<TestEnum?>>
|
||||
{
|
||||
EditContext = new EditContext(model),
|
||||
ValueExpression = () => model.NullableEnum
|
||||
};
|
||||
var inputSelectComponent = await RenderAndGetTestInputComponentAsync(rootComponent);
|
||||
var inputSelectComponent = await InputRenderer.RenderAndGetComponent(rootComponent);
|
||||
|
||||
// Act
|
||||
inputSelectComponent.CurrentValueAsString = "";
|
||||
|
|
@ -96,12 +92,12 @@ namespace Microsoft.AspNetCore.Components.Forms
|
|||
{
|
||||
// Arrange
|
||||
var model = new TestModel();
|
||||
var rootComponent = new TestInputSelectHostComponent<Guid>
|
||||
var rootComponent = new TestInputHostComponent<Guid, TestInputSelect<Guid>>
|
||||
{
|
||||
EditContext = new EditContext(model),
|
||||
ValueExpression = () => model.NotNullableGuid
|
||||
};
|
||||
var inputSelectComponent = await RenderAndGetTestInputComponentAsync(rootComponent);
|
||||
var inputSelectComponent = await InputRenderer.RenderAndGetComponent(rootComponent);
|
||||
|
||||
// Act
|
||||
var guid = Guid.NewGuid();
|
||||
|
|
@ -117,12 +113,12 @@ namespace Microsoft.AspNetCore.Components.Forms
|
|||
{
|
||||
// Arrange
|
||||
var model = new TestModel();
|
||||
var rootComponent = new TestInputSelectHostComponent<Guid?>
|
||||
var rootComponent = new TestInputHostComponent<Guid?, TestInputSelect<Guid?>>
|
||||
{
|
||||
EditContext = new EditContext(model),
|
||||
ValueExpression = () => model.NullableGuid
|
||||
};
|
||||
var inputSelectComponent = await RenderAndGetTestInputComponentAsync(rootComponent);
|
||||
var inputSelectComponent = await InputRenderer.RenderAndGetComponent(rootComponent);
|
||||
|
||||
// Act
|
||||
var guid = Guid.NewGuid();
|
||||
|
|
@ -138,12 +134,12 @@ namespace Microsoft.AspNetCore.Components.Forms
|
|||
{
|
||||
// Arrange
|
||||
var model = new TestModel();
|
||||
var rootComponent = new TestInputSelectHostComponent<int>
|
||||
var rootComponent = new TestInputHostComponent<int, TestInputSelect<int>>
|
||||
{
|
||||
EditContext = new EditContext(model),
|
||||
ValueExpression = () => model.NotNullableInt
|
||||
};
|
||||
var inputSelectComponent = await RenderAndGetTestInputComponentAsync(rootComponent);
|
||||
var inputSelectComponent = await InputRenderer.RenderAndGetComponent(rootComponent);
|
||||
|
||||
// Act
|
||||
inputSelectComponent.CurrentValueAsString = "42";
|
||||
|
|
@ -158,12 +154,12 @@ namespace Microsoft.AspNetCore.Components.Forms
|
|||
{
|
||||
// Arrange
|
||||
var model = new TestModel();
|
||||
var rootComponent = new TestInputSelectHostComponent<int?>
|
||||
var rootComponent = new TestInputHostComponent<int?, TestInputSelect<int?>>
|
||||
{
|
||||
EditContext = new EditContext(model),
|
||||
ValueExpression = () => model.NullableInt
|
||||
};
|
||||
var inputSelectComponent = await RenderAndGetTestInputComponentAsync(rootComponent);
|
||||
var inputSelectComponent = await InputRenderer.RenderAndGetComponent(rootComponent);
|
||||
|
||||
// Act
|
||||
inputSelectComponent.CurrentValueAsString = "42";
|
||||
|
|
@ -172,19 +168,30 @@ namespace Microsoft.AspNetCore.Components.Forms
|
|||
Assert.Equal(42, inputSelectComponent.CurrentValue);
|
||||
}
|
||||
|
||||
private static TestInputSelect<TValue> FindInputSelectComponent<TValue>(CapturedBatch batch)
|
||||
=> batch.ReferenceFrames
|
||||
.Where(f => f.FrameType == RenderTreeFrameType.Component)
|
||||
.Select(f => f.Component)
|
||||
.OfType<TestInputSelect<TValue>>()
|
||||
.Single();
|
||||
|
||||
private static async Task<TestInputSelect<TValue>> RenderAndGetTestInputComponentAsync<TValue>(TestInputSelectHostComponent<TValue> hostComponent)
|
||||
[Fact]
|
||||
public async Task ValidationErrorUsesDisplayAttributeName()
|
||||
{
|
||||
var testRenderer = new TestRenderer();
|
||||
var componentId = testRenderer.AssignRootComponentId(hostComponent);
|
||||
await testRenderer.RenderRootComponentAsync(componentId);
|
||||
return FindInputSelectComponent<TValue>(testRenderer.Batches.Single());
|
||||
// Arrange
|
||||
var model = new TestModel();
|
||||
var rootComponent = new TestInputHostComponent<int, TestInputSelect<int>>
|
||||
{
|
||||
EditContext = new EditContext(model),
|
||||
ValueExpression = () => model.NotNullableInt,
|
||||
AdditionalAttributes = new Dictionary<string, object>
|
||||
{
|
||||
{ "DisplayName", "Some number" }
|
||||
}
|
||||
};
|
||||
var fieldIdentifier = FieldIdentifier.Create(() => model.NotNullableInt);
|
||||
var inputSelectComponent = await InputRenderer.RenderAndGetComponent(rootComponent);
|
||||
|
||||
// Act
|
||||
await inputSelectComponent.SetCurrentValueAsStringAsync("invalidNumber");
|
||||
|
||||
// Assert
|
||||
var validationMessages = rootComponent.EditContext.GetValidationMessages(fieldIdentifier);
|
||||
Assert.NotEmpty(validationMessages);
|
||||
Assert.Contains("The Some number field is not valid.", validationMessages);
|
||||
}
|
||||
|
||||
enum TestEnum
|
||||
|
|
@ -218,25 +225,13 @@ namespace Microsoft.AspNetCore.Components.Forms
|
|||
get => base.CurrentValueAsString;
|
||||
set => base.CurrentValueAsString = value;
|
||||
}
|
||||
}
|
||||
|
||||
class TestInputSelectHostComponent<TValue> : AutoRenderComponent
|
||||
{
|
||||
public EditContext EditContext { get; set; }
|
||||
|
||||
public Expression<Func<TValue>> ValueExpression { get; set; }
|
||||
|
||||
protected override void BuildRenderTree(RenderTreeBuilder builder)
|
||||
public async Task SetCurrentValueAsStringAsync(string value)
|
||||
{
|
||||
builder.OpenComponent<CascadingValue<EditContext>>(0);
|
||||
builder.AddAttribute(1, "Value", EditContext);
|
||||
builder.AddAttribute(2, "ChildContent", new RenderFragment(childBuilder =>
|
||||
{
|
||||
childBuilder.OpenComponent<TestInputSelect<TValue>>(0);
|
||||
childBuilder.AddAttribute(0, "ValueExpression", ValueExpression);
|
||||
childBuilder.CloseComponent();
|
||||
}));
|
||||
builder.CloseComponent();
|
||||
// This is equivalent to the subclass writing to CurrentValueAsString
|
||||
// (e.g., from @bind), except to simplify the test code there's an InvokeAsync
|
||||
// here. In production code it wouldn't normally be required because @bind
|
||||
// calls run on the sync context anyway.
|
||||
await InvokeAsync(() => { base.CurrentValueAsString = value; });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue