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

This commit is contained in:
Pranav K 2020-07-21 19:40:32 -07:00 committed by GitHub
commit e1fcdcaa86
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
120 changed files with 2221 additions and 891 deletions

66
.github/ISSUE_TEMPLATE/razor_tooling.md vendored Normal file
View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -151,9 +151,7 @@
Include="$(RepoRoot)src\Analyzers\Internal.AspNetCore.Analyzers\src\Internal.AspNetCore.Analyzers.csproj" Include="$(RepoRoot)src\Analyzers\Internal.AspNetCore.Analyzers\src\Internal.AspNetCore.Analyzers.csproj"
ReferenceOutputAssembly="false" ReferenceOutputAssembly="false"
OutputItemType="Analyzer" OutputItemType="Analyzer"
PrivateAssets="All" PrivateAssets="All" />
Version="$(InternalAspNetCoreAnalyzersPackageVersion)"
IsImplicitlyDefined="true" />
</ItemGroup> </ItemGroup>
<!-- Compilation options which apply to all languages. Language-specific options should be set in eng/targets/$(lang).Common.props --> <!-- Compilation options which apply to all languages. Language-specific options should be set in eng/targets/$(lang).Common.props -->

View File

@ -133,10 +133,14 @@ docker run \
-t \ -t \
-e TF_BUILD \ -e TF_BUILD \
-e BUILD_NUMBER \ -e BUILD_NUMBER \
-e BUILD_BUILDID \
-e SYSTEM_TEAMPROJECT \
-e BUILD_BUILDNUMBER \ -e BUILD_BUILDNUMBER \
-e BUILD_REPOSITORY_URI \ -e BUILD_REPOSITORY_URI \
-e BUILD_SOURCEVERSION \ -e BUILD_SOURCEVERSION \
-e BUILD_SOURCEBRANCH \ -e BUILD_SOURCEBRANCH \
-e SYSTEM_DEFINITIONID \
-e SYSTEM_TEAMFOUNDATIONCOLLECTIONURI \
-e DOTNET_CLI_TELEMETRY_OPTOUT \ -e DOTNET_CLI_TELEMETRY_OPTOUT \
-e Configuration \ -e Configuration \
-v "$DIR:$DIR" \ -v "$DIR:$DIR" \

View File

@ -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. 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 ## Install pre-requisites
### Windows ### 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) 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. 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> * 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: * Java Development Kit 11 or newer. Either:
* OpenJDK <https://jdk.java.net/> * OpenJDK <https://jdk.java.net/>
* Oracle's JDK <https://www.oracle.com/technetwork/java/javase/downloads/index.html> * 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/> * OpenJDK <https://jdk.java.net/>
* Oracle's JDK <https://www.oracle.com/technetwork/java/javase/downloads/index.html> * 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> **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 ## 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 > :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. > 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. > 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 2. Use the `startvs.cmd` script to open Visual Studio .sln/.slnf files. This script first sets the required
environment variables. environment variables.

View File

@ -44,10 +44,6 @@
<!-- Project selection can be overridden on the command line by passing in -projects. --> <!-- Project selection can be overridden on the command line by passing in -projects. -->
<When Condition="'$(ProjectToBuild)' != ''"> <When Condition="'$(ProjectToBuild)' != ''">
<ItemGroup> <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\**\*"> <ProjectToBuild Include="$(ProjectToBuild)" Exclude="@(ProjectToExclude);$(RepoRoot)**\bin\**\*;$(RepoRoot)**\obj\**\*">
<RestoreInParallel Condition="'%(Extension)' == '.npmproj'">false</RestoreInParallel> <RestoreInParallel Condition="'%(Extension)' == '.npmproj'">false</RestoreInParallel>
</ProjectToBuild> </ProjectToBuild>
@ -125,11 +121,8 @@
<!-- <!--
Use caution to avoid deep recursion. If the globbing pattern picks up something which exceeds MAX_PATH, 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. the entire pattern will silently fail to evaluate correctly.
Include RTMVersions.csproj when building any managed projects.
--> -->
<DotNetProjects Include=" <DotNetProjects Include="
$(RepoRoot)eng\RTMVersions\RTMVersions.csproj;
$(RepoRoot)src\Framework\App.Ref\src\Microsoft.AspNetCore.App.Ref.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.Runtime\src\Microsoft.AspNetCore.App.Runtime.csproj;
$(RepoRoot)src\Framework\App.Ref.Internal\src\Microsoft.AspNetCore.App.Ref.Internal.csproj; $(RepoRoot)src\Framework\App.Ref.Internal\src\Microsoft.AspNetCore.App.Ref.Internal.csproj;
@ -178,7 +171,6 @@
$(RepoRoot)**\obj\**\*;" $(RepoRoot)**\obj\**\*;"
Condition=" '$(BuildMainlyReferenceProviders)' != 'true' " /> Condition=" '$(BuildMainlyReferenceProviders)' != 'true' " />
<DotNetProjects Include=" <DotNetProjects Include="
$(RepoRoot)eng\RTMVersions\RTMVersions.csproj;
$(RepoRoot)src\DefaultBuilder\**\src\*.csproj; $(RepoRoot)src\DefaultBuilder\**\src\*.csproj;
$(RepoRoot)src\Features\JsonPatch\**\src\*.csproj; $(RepoRoot)src\Features\JsonPatch\**\src\*.csproj;
$(RepoRoot)src\DataProtection\**\src\*.csproj; $(RepoRoot)src\DataProtection\**\src\*.csproj;

View File

@ -71,6 +71,8 @@ and are generated based on the last package release.
<LatestPackageReference Include="System.Reflection.Metadata" /> <LatestPackageReference Include="System.Reflection.Metadata" />
<LatestPackageReference Include="System.Runtime.CompilerServices.Unsafe" /> <LatestPackageReference Include="System.Runtime.CompilerServices.Unsafe" />
<LatestPackageReference Include="System.Runtime.InteropServices.RuntimeInformation" /> <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.Cng" />
<LatestPackageReference Include="System.Security.Cryptography.Pkcs" /> <LatestPackageReference Include="System.Security.Cryptography.Pkcs" />
<LatestPackageReference Include="System.Security.Cryptography.Xml" /> <LatestPackageReference Include="System.Security.Cryptography.Xml" />

View File

@ -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>

View File

@ -1 +0,0 @@
<Project />

View File

@ -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>

View File

@ -13,292 +13,297 @@
<Uri>https://github.com/dotnet/blazor</Uri> <Uri>https://github.com/dotnet/blazor</Uri>
<Sha>cc449601d638ffaab58ae9487f0fd010bb178a12</Sha> <Sha>cc449601d638ffaab58ae9487f0fd010bb178a12</Sha>
</Dependency> </Dependency>
<Dependency Name="dotnet-ef" Version="5.0.0-preview.8.20360.8"> <Dependency Name="dotnet-ef" Version="5.0.0-rc.1.20367.2">
<Uri>https://github.com/dotnet/efcore</Uri> <Uri>https://github.com/dotnet/efcore</Uri>
<Sha>58abc390e0e3eb849b5773da3f5ed2982ade521d</Sha> <Sha>1aac0aec91bb6e5baa682450b7157331f2226173</Sha>
</Dependency> </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.20367.2">
<Uri>https://github.com/dotnet/efcore</Uri> <Uri>https://github.com/dotnet/efcore</Uri>
<Sha>58abc390e0e3eb849b5773da3f5ed2982ade521d</Sha> <Sha>1aac0aec91bb6e5baa682450b7157331f2226173</Sha>
</Dependency> </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.20367.2">
<Uri>https://github.com/dotnet/efcore</Uri> <Uri>https://github.com/dotnet/efcore</Uri>
<Sha>58abc390e0e3eb849b5773da3f5ed2982ade521d</Sha> <Sha>1aac0aec91bb6e5baa682450b7157331f2226173</Sha>
</Dependency> </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.20367.2">
<Uri>https://github.com/dotnet/efcore</Uri> <Uri>https://github.com/dotnet/efcore</Uri>
<Sha>58abc390e0e3eb849b5773da3f5ed2982ade521d</Sha> <Sha>1aac0aec91bb6e5baa682450b7157331f2226173</Sha>
</Dependency> </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.20367.2">
<Uri>https://github.com/dotnet/efcore</Uri> <Uri>https://github.com/dotnet/efcore</Uri>
<Sha>58abc390e0e3eb849b5773da3f5ed2982ade521d</Sha> <Sha>1aac0aec91bb6e5baa682450b7157331f2226173</Sha>
</Dependency> </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.20367.2">
<Uri>https://github.com/dotnet/efcore</Uri> <Uri>https://github.com/dotnet/efcore</Uri>
<Sha>58abc390e0e3eb849b5773da3f5ed2982ade521d</Sha> <Sha>1aac0aec91bb6e5baa682450b7157331f2226173</Sha>
</Dependency> </Dependency>
<Dependency Name="Microsoft.EntityFrameworkCore" Version="5.0.0-preview.8.20360.8"> <Dependency Name="Microsoft.EntityFrameworkCore" Version="5.0.0-rc.1.20367.2">
<Uri>https://github.com/dotnet/efcore</Uri> <Uri>https://github.com/dotnet/efcore</Uri>
<Sha>58abc390e0e3eb849b5773da3f5ed2982ade521d</Sha> <Sha>1aac0aec91bb6e5baa682450b7157331f2226173</Sha>
</Dependency> </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> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha> <Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
</Dependency> </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> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha> <Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
</Dependency> </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> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha> <Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
</Dependency> </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> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha> <Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
</Dependency> </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> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha> <Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
</Dependency> </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> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha> <Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
</Dependency> </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> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha> <Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
</Dependency> </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> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha> <Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
</Dependency> </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> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha> <Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
</Dependency> </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> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha> <Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
</Dependency> </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> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha> <Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
</Dependency> </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> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha> <Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
</Dependency> </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> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha> <Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
</Dependency> </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> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha> <Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
</Dependency> </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> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha> <Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
</Dependency> </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> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha> <Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
</Dependency> </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> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha> <Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
</Dependency> </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> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha> <Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
</Dependency> </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> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha> <Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
</Dependency> </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> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha> <Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
</Dependency> </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> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha> <Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
</Dependency> </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> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha> <Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
</Dependency> </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> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha> <Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
</Dependency> </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> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha> <Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
</Dependency> </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> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha> <Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
</Dependency> </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> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha> <Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
</Dependency> </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> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha> <Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
</Dependency> </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> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha> <Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
</Dependency> </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> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha> <Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
</Dependency> </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> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha> <Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
</Dependency> </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> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha> <Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
</Dependency> </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> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha> <Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
</Dependency> </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> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha> <Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
</Dependency> </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> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha> <Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
</Dependency> </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> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha> <Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
</Dependency> </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> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha> <Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
</Dependency> </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> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha> <Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
</Dependency> </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> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha> <Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
</Dependency> </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> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha> <Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
</Dependency> </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> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha> <Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
</Dependency> </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> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha> <Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
</Dependency> </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> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha> <Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
</Dependency> </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> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha> <Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
</Dependency> </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> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha> <Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
</Dependency> </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> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha> <Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
</Dependency> </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> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha> <Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
</Dependency> </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> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha> <Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
</Dependency> </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> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha> <Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
</Dependency> </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> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha> <Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
</Dependency> </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> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha> <Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
</Dependency> </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> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha> <Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
</Dependency> </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> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha> <Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
</Dependency> </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> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha> <Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
</Dependency> </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> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha> <Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
</Dependency> </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> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha> <Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
</Dependency> </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> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha> <Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
</Dependency> </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> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha> <Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
</Dependency> </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> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha> <Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
</Dependency> </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> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha> <Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
</Dependency> </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> <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> </Dependency>
<!-- <!--
Win-x64 is used here because we have picked an arbitrary runtime identifier to flow the version of the latest NETCore.App runtime. 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. 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> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha> <Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
</Dependency> </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> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha> <Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
</Dependency> </Dependency>
</ProductDependencies> </ProductDependencies>
<ToolsetDependencies> <ToolsetDependencies>
<!-- Listed explicitly to workaround https://github.com/dotnet/cli/issues/10528 --> <!-- Listed explicitly to workaround https://github.com/dotnet/cli/issues/10528 -->
<Dependency Name="Microsoft.NETCore.Platforms" Version="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> <Uri>https://github.com/dotnet/runtime</Uri>
<Sha>f37dd6fc8595e130909dcb3085a56342d04aa20c</Sha> <Sha>0e0e648770e54b12c2fa81a77538ce1a72fca8af</Sha>
</Dependency> </Dependency>
<Dependency Name="Microsoft.DotNet.Arcade.Sdk" Version="5.0.0-beta.20364.3"> <Dependency Name="Microsoft.DotNet.Arcade.Sdk" Version="5.0.0-beta.20364.3">
<Uri>https://github.com/dotnet/arcade</Uri> <Uri>https://github.com/dotnet/arcade</Uri>
@ -308,9 +313,9 @@
<Uri>https://github.com/dotnet/arcade</Uri> <Uri>https://github.com/dotnet/arcade</Uri>
<Sha>ff5d4b6c8dbdaeacb6e6159d3f8185118dffd915</Sha> <Sha>ff5d4b6c8dbdaeacb6e6159d3f8185118dffd915</Sha>
</Dependency> </Dependency>
<Dependency Name="Microsoft.Net.Compilers.Toolset" Version="3.8.0-1.20361.1"> <Dependency Name="Microsoft.Net.Compilers.Toolset" Version="3.8.0-1.20367.11">
<Uri>https://github.com/dotnet/roslyn</Uri> <Uri>https://github.com/dotnet/roslyn</Uri>
<Sha>f24d2c5c98211908ab90d6f1f42e7592411d6058</Sha> <Sha>fb7b2e716d163b7abebf57db505e01a4a521ddae</Sha>
</Dependency> </Dependency>
</ToolsetDependencies> </ToolsetDependencies>
</Dependencies> </Dependencies>

View File

@ -9,14 +9,14 @@
<AspNetCoreMajorVersion>5</AspNetCoreMajorVersion> <AspNetCoreMajorVersion>5</AspNetCoreMajorVersion>
<AspNetCoreMinorVersion>0</AspNetCoreMinorVersion> <AspNetCoreMinorVersion>0</AspNetCoreMinorVersion>
<AspNetCorePatchVersion>0</AspNetCorePatchVersion> <AspNetCorePatchVersion>0</AspNetCorePatchVersion>
<PreReleaseVersionIteration>8</PreReleaseVersionIteration> <PreReleaseVersionIteration>1</PreReleaseVersionIteration>
<!-- <!--
When StabilizePackageVersion is set to 'true', this branch will produce stable outputs for 'Shipping' packages When StabilizePackageVersion is set to 'true', this branch will produce stable outputs for 'Shipping' packages
--> -->
<StabilizePackageVersion Condition="'$(StabilizePackageVersion)' == ''">false</StabilizePackageVersion> <StabilizePackageVersion Condition="'$(StabilizePackageVersion)' == ''">false</StabilizePackageVersion>
<DotNetFinalVersionKind Condition="'$(StabilizePackageVersion)' == 'true'">release</DotNetFinalVersionKind> <DotNetFinalVersionKind Condition="'$(StabilizePackageVersion)' == 'true'">release</DotNetFinalVersionKind>
<PreReleaseVersionLabel>preview</PreReleaseVersionLabel> <PreReleaseVersionLabel>rc</PreReleaseVersionLabel>
<PreReleaseBrandingLabel>Preview $(PreReleaseVersionIteration)</PreReleaseBrandingLabel> <PreReleaseBrandingLabel>RC $(PreReleaseVersionIteration)</PreReleaseBrandingLabel>
<IncludePreReleaseLabelInPackageVersion>true</IncludePreReleaseLabelInPackageVersion> <IncludePreReleaseLabelInPackageVersion>true</IncludePreReleaseLabelInPackageVersion>
<IncludePreReleaseLabelInPackageVersion Condition=" '$(DotNetFinalVersionKind)' == 'release' ">false</IncludePreReleaseLabelInPackageVersion> <IncludePreReleaseLabelInPackageVersion Condition=" '$(DotNetFinalVersionKind)' == 'release' ">false</IncludePreReleaseLabelInPackageVersion>
<AspNetCoreMajorMinorVersion>$(AspNetCoreMajorVersion).$(AspNetCoreMinorVersion)</AspNetCoreMajorMinorVersion> <AspNetCoreMajorMinorVersion>$(AspNetCoreMajorVersion).$(AspNetCoreMinorVersion)</AspNetCoreMajorMinorVersion>
@ -62,82 +62,84 @@
--> -->
<PropertyGroup Label="Automated"> <PropertyGroup Label="Automated">
<!-- Packages from dotnet/roslyn --> <!-- Packages from dotnet/roslyn -->
<MicrosoftNetCompilersToolsetPackageVersion>3.8.0-1.20361.1</MicrosoftNetCompilersToolsetPackageVersion> <MicrosoftNetCompilersToolsetPackageVersion>3.8.0-1.20367.11</MicrosoftNetCompilersToolsetPackageVersion>
<!-- Packages from dotnet/runtime --> <!-- Packages from dotnet/runtime -->
<MicrosoftExtensionsDependencyModelPackageVersion>5.0.0-preview.8.20361.2</MicrosoftExtensionsDependencyModelPackageVersion> <MicrosoftExtensionsDependencyModelPackageVersion>5.0.0-rc.1.20370.4</MicrosoftExtensionsDependencyModelPackageVersion>
<MicrosoftNETCoreAppInternalPackageVersion>5.0.0-preview.8.20361.2</MicrosoftNETCoreAppInternalPackageVersion> <MicrosoftNETCoreAppInternalPackageVersion>5.0.0-rc.1.20370.4</MicrosoftNETCoreAppInternalPackageVersion>
<MicrosoftNETCoreAppRefPackageVersion>5.0.0-preview.8.20361.2</MicrosoftNETCoreAppRefPackageVersion> <MicrosoftNETCoreAppRefPackageVersion>5.0.0-rc.1.20370.4</MicrosoftNETCoreAppRefPackageVersion>
<MicrosoftNETCoreAppRuntimewinx64PackageVersion>5.0.0-preview.8.20361.2</MicrosoftNETCoreAppRuntimewinx64PackageVersion> <MicrosoftNETCoreAppRuntimewinx64PackageVersion>5.0.0-rc.1.20370.4</MicrosoftNETCoreAppRuntimewinx64PackageVersion>
<MicrosoftWin32RegistryPackageVersion>5.0.0-preview.8.20361.2</MicrosoftWin32RegistryPackageVersion> <MicrosoftWin32RegistryPackageVersion>5.0.0-rc.1.20370.4</MicrosoftWin32RegistryPackageVersion>
<MicrosoftWin32SystemEventsPackageVersion>5.0.0-preview.8.20361.2</MicrosoftWin32SystemEventsPackageVersion> <MicrosoftWin32SystemEventsPackageVersion>5.0.0-rc.1.20370.4</MicrosoftWin32SystemEventsPackageVersion>
<MicrosoftExtensionsCachingAbstractionsPackageVersion>5.0.0-preview.8.20361.2</MicrosoftExtensionsCachingAbstractionsPackageVersion> <MicrosoftExtensionsCachingAbstractionsPackageVersion>5.0.0-rc.1.20370.4</MicrosoftExtensionsCachingAbstractionsPackageVersion>
<MicrosoftExtensionsCachingMemoryPackageVersion>5.0.0-preview.8.20361.2</MicrosoftExtensionsCachingMemoryPackageVersion> <MicrosoftExtensionsCachingMemoryPackageVersion>5.0.0-rc.1.20370.4</MicrosoftExtensionsCachingMemoryPackageVersion>
<MicrosoftExtensionsConfigurationAbstractionsPackageVersion>5.0.0-preview.8.20361.2</MicrosoftExtensionsConfigurationAbstractionsPackageVersion> <MicrosoftExtensionsConfigurationAbstractionsPackageVersion>5.0.0-rc.1.20370.4</MicrosoftExtensionsConfigurationAbstractionsPackageVersion>
<MicrosoftExtensionsConfigurationBinderPackageVersion>5.0.0-preview.8.20361.2</MicrosoftExtensionsConfigurationBinderPackageVersion> <MicrosoftExtensionsConfigurationBinderPackageVersion>5.0.0-rc.1.20370.4</MicrosoftExtensionsConfigurationBinderPackageVersion>
<MicrosoftExtensionsConfigurationCommandLinePackageVersion>5.0.0-preview.8.20361.2</MicrosoftExtensionsConfigurationCommandLinePackageVersion> <MicrosoftExtensionsConfigurationCommandLinePackageVersion>5.0.0-rc.1.20370.4</MicrosoftExtensionsConfigurationCommandLinePackageVersion>
<MicrosoftExtensionsConfigurationEnvironmentVariablesPackageVersion>5.0.0-preview.8.20361.2</MicrosoftExtensionsConfigurationEnvironmentVariablesPackageVersion> <MicrosoftExtensionsConfigurationEnvironmentVariablesPackageVersion>5.0.0-rc.1.20370.4</MicrosoftExtensionsConfigurationEnvironmentVariablesPackageVersion>
<MicrosoftExtensionsConfigurationFileExtensionsPackageVersion>5.0.0-preview.8.20361.2</MicrosoftExtensionsConfigurationFileExtensionsPackageVersion> <MicrosoftExtensionsConfigurationFileExtensionsPackageVersion>5.0.0-rc.1.20370.4</MicrosoftExtensionsConfigurationFileExtensionsPackageVersion>
<MicrosoftExtensionsConfigurationIniPackageVersion>5.0.0-preview.8.20361.2</MicrosoftExtensionsConfigurationIniPackageVersion> <MicrosoftExtensionsConfigurationIniPackageVersion>5.0.0-rc.1.20370.4</MicrosoftExtensionsConfigurationIniPackageVersion>
<MicrosoftExtensionsConfigurationJsonPackageVersion>5.0.0-preview.8.20361.2</MicrosoftExtensionsConfigurationJsonPackageVersion> <MicrosoftExtensionsConfigurationJsonPackageVersion>5.0.0-rc.1.20370.4</MicrosoftExtensionsConfigurationJsonPackageVersion>
<MicrosoftExtensionsConfigurationPackageVersion>5.0.0-preview.8.20361.2</MicrosoftExtensionsConfigurationPackageVersion> <MicrosoftExtensionsConfigurationPackageVersion>5.0.0-rc.1.20370.4</MicrosoftExtensionsConfigurationPackageVersion>
<MicrosoftExtensionsConfigurationUserSecretsPackageVersion>5.0.0-preview.8.20361.2</MicrosoftExtensionsConfigurationUserSecretsPackageVersion> <MicrosoftExtensionsConfigurationUserSecretsPackageVersion>5.0.0-rc.1.20370.4</MicrosoftExtensionsConfigurationUserSecretsPackageVersion>
<MicrosoftExtensionsConfigurationXmlPackageVersion>5.0.0-preview.8.20361.2</MicrosoftExtensionsConfigurationXmlPackageVersion> <MicrosoftExtensionsConfigurationXmlPackageVersion>5.0.0-rc.1.20370.4</MicrosoftExtensionsConfigurationXmlPackageVersion>
<MicrosoftExtensionsDependencyInjectionAbstractionsPackageVersion>5.0.0-preview.8.20361.2</MicrosoftExtensionsDependencyInjectionAbstractionsPackageVersion> <MicrosoftExtensionsDependencyInjectionAbstractionsPackageVersion>5.0.0-rc.1.20370.4</MicrosoftExtensionsDependencyInjectionAbstractionsPackageVersion>
<MicrosoftExtensionsDependencyInjectionPackageVersion>5.0.0-preview.8.20361.2</MicrosoftExtensionsDependencyInjectionPackageVersion> <MicrosoftExtensionsDependencyInjectionPackageVersion>5.0.0-rc.1.20370.4</MicrosoftExtensionsDependencyInjectionPackageVersion>
<MicrosoftExtensionsFileProvidersAbstractionsPackageVersion>5.0.0-preview.8.20361.2</MicrosoftExtensionsFileProvidersAbstractionsPackageVersion> <MicrosoftExtensionsFileProvidersAbstractionsPackageVersion>5.0.0-rc.1.20370.4</MicrosoftExtensionsFileProvidersAbstractionsPackageVersion>
<MicrosoftExtensionsFileProvidersCompositePackageVersion>5.0.0-preview.8.20361.2</MicrosoftExtensionsFileProvidersCompositePackageVersion> <MicrosoftExtensionsFileProvidersCompositePackageVersion>5.0.0-rc.1.20370.4</MicrosoftExtensionsFileProvidersCompositePackageVersion>
<MicrosoftExtensionsFileProvidersPhysicalPackageVersion>5.0.0-preview.8.20361.2</MicrosoftExtensionsFileProvidersPhysicalPackageVersion> <MicrosoftExtensionsFileProvidersPhysicalPackageVersion>5.0.0-rc.1.20370.4</MicrosoftExtensionsFileProvidersPhysicalPackageVersion>
<MicrosoftExtensionsFileSystemGlobbingPackageVersion>5.0.0-preview.8.20361.2</MicrosoftExtensionsFileSystemGlobbingPackageVersion> <MicrosoftExtensionsFileSystemGlobbingPackageVersion>5.0.0-rc.1.20370.4</MicrosoftExtensionsFileSystemGlobbingPackageVersion>
<MicrosoftExtensionsHostFactoryResolverSourcesPackageVersion>5.0.0-preview.8.20361.2</MicrosoftExtensionsHostFactoryResolverSourcesPackageVersion> <MicrosoftExtensionsHostFactoryResolverSourcesPackageVersion>5.0.0-rc.1.20370.4</MicrosoftExtensionsHostFactoryResolverSourcesPackageVersion>
<MicrosoftExtensionsHostingAbstractionsPackageVersion>5.0.0-preview.8.20361.2</MicrosoftExtensionsHostingAbstractionsPackageVersion> <MicrosoftExtensionsHostingAbstractionsPackageVersion>5.0.0-rc.1.20370.4</MicrosoftExtensionsHostingAbstractionsPackageVersion>
<MicrosoftExtensionsHostingPackageVersion>5.0.0-preview.8.20361.2</MicrosoftExtensionsHostingPackageVersion> <MicrosoftExtensionsHostingPackageVersion>5.0.0-rc.1.20370.4</MicrosoftExtensionsHostingPackageVersion>
<MicrosoftExtensionsHttpPackageVersion>5.0.0-preview.8.20361.2</MicrosoftExtensionsHttpPackageVersion> <MicrosoftExtensionsHttpPackageVersion>5.0.0-rc.1.20370.4</MicrosoftExtensionsHttpPackageVersion>
<MicrosoftExtensionsLoggingAbstractionsPackageVersion>5.0.0-preview.8.20361.2</MicrosoftExtensionsLoggingAbstractionsPackageVersion> <MicrosoftExtensionsLoggingAbstractionsPackageVersion>5.0.0-rc.1.20370.4</MicrosoftExtensionsLoggingAbstractionsPackageVersion>
<MicrosoftExtensionsLoggingConfigurationPackageVersion>5.0.0-preview.8.20361.2</MicrosoftExtensionsLoggingConfigurationPackageVersion> <MicrosoftExtensionsLoggingConfigurationPackageVersion>5.0.0-rc.1.20370.4</MicrosoftExtensionsLoggingConfigurationPackageVersion>
<MicrosoftExtensionsLoggingConsolePackageVersion>5.0.0-preview.8.20361.2</MicrosoftExtensionsLoggingConsolePackageVersion> <MicrosoftExtensionsLoggingConsolePackageVersion>5.0.0-rc.1.20370.4</MicrosoftExtensionsLoggingConsolePackageVersion>
<MicrosoftExtensionsLoggingDebugPackageVersion>5.0.0-preview.8.20361.2</MicrosoftExtensionsLoggingDebugPackageVersion> <MicrosoftExtensionsLoggingDebugPackageVersion>5.0.0-rc.1.20370.4</MicrosoftExtensionsLoggingDebugPackageVersion>
<MicrosoftExtensionsLoggingEventSourcePackageVersion>5.0.0-preview.8.20361.2</MicrosoftExtensionsLoggingEventSourcePackageVersion> <MicrosoftExtensionsLoggingEventSourcePackageVersion>5.0.0-rc.1.20370.4</MicrosoftExtensionsLoggingEventSourcePackageVersion>
<MicrosoftExtensionsLoggingEventLogPackageVersion>5.0.0-preview.8.20361.2</MicrosoftExtensionsLoggingEventLogPackageVersion> <MicrosoftExtensionsLoggingEventLogPackageVersion>5.0.0-rc.1.20370.4</MicrosoftExtensionsLoggingEventLogPackageVersion>
<MicrosoftExtensionsLoggingPackageVersion>5.0.0-preview.8.20361.2</MicrosoftExtensionsLoggingPackageVersion> <MicrosoftExtensionsLoggingPackageVersion>5.0.0-rc.1.20370.4</MicrosoftExtensionsLoggingPackageVersion>
<MicrosoftExtensionsLoggingTraceSourcePackageVersion>5.0.0-preview.8.20361.2</MicrosoftExtensionsLoggingTraceSourcePackageVersion> <MicrosoftExtensionsLoggingTraceSourcePackageVersion>5.0.0-rc.1.20370.4</MicrosoftExtensionsLoggingTraceSourcePackageVersion>
<MicrosoftExtensionsOptionsConfigurationExtensionsPackageVersion>5.0.0-preview.8.20361.2</MicrosoftExtensionsOptionsConfigurationExtensionsPackageVersion> <MicrosoftExtensionsOptionsConfigurationExtensionsPackageVersion>5.0.0-rc.1.20370.4</MicrosoftExtensionsOptionsConfigurationExtensionsPackageVersion>
<MicrosoftExtensionsOptionsDataAnnotationsPackageVersion>5.0.0-preview.8.20361.2</MicrosoftExtensionsOptionsDataAnnotationsPackageVersion> <MicrosoftExtensionsOptionsDataAnnotationsPackageVersion>5.0.0-rc.1.20370.4</MicrosoftExtensionsOptionsDataAnnotationsPackageVersion>
<MicrosoftExtensionsOptionsPackageVersion>5.0.0-preview.8.20361.2</MicrosoftExtensionsOptionsPackageVersion> <MicrosoftExtensionsOptionsPackageVersion>5.0.0-rc.1.20370.4</MicrosoftExtensionsOptionsPackageVersion>
<MicrosoftExtensionsPrimitivesPackageVersion>5.0.0-preview.8.20361.2</MicrosoftExtensionsPrimitivesPackageVersion> <MicrosoftExtensionsPrimitivesPackageVersion>5.0.0-rc.1.20370.4</MicrosoftExtensionsPrimitivesPackageVersion>
<MicrosoftExtensionsInternalTransportPackageVersion>5.0.0-preview.8.20361.2</MicrosoftExtensionsInternalTransportPackageVersion> <MicrosoftExtensionsInternalTransportPackageVersion>5.0.0-rc.1.20370.4</MicrosoftExtensionsInternalTransportPackageVersion>
<SystemComponentModelAnnotationsPackageVersion>5.0.0-preview.8.20361.2</SystemComponentModelAnnotationsPackageVersion> <SystemComponentModelAnnotationsPackageVersion>5.0.0-rc.1.20370.4</SystemComponentModelAnnotationsPackageVersion>
<SystemDiagnosticsDiagnosticSourcePackageVersion>5.0.0-preview.8.20361.2</SystemDiagnosticsDiagnosticSourcePackageVersion> <SystemDiagnosticsDiagnosticSourcePackageVersion>5.0.0-rc.1.20370.4</SystemDiagnosticsDiagnosticSourcePackageVersion>
<SystemDiagnosticsEventLogPackageVersion>5.0.0-preview.8.20361.2</SystemDiagnosticsEventLogPackageVersion> <SystemDiagnosticsEventLogPackageVersion>5.0.0-rc.1.20370.4</SystemDiagnosticsEventLogPackageVersion>
<SystemDrawingCommonPackageVersion>5.0.0-preview.8.20361.2</SystemDrawingCommonPackageVersion> <SystemDrawingCommonPackageVersion>5.0.0-rc.1.20370.4</SystemDrawingCommonPackageVersion>
<SystemIOPipelinesPackageVersion>5.0.0-preview.8.20361.2</SystemIOPipelinesPackageVersion> <SystemIOPipelinesPackageVersion>5.0.0-rc.1.20370.4</SystemIOPipelinesPackageVersion>
<SystemNetHttpJsonPackageVersion>5.0.0-preview.8.20361.2</SystemNetHttpJsonPackageVersion> <SystemNetHttpJsonPackageVersion>5.0.0-rc.1.20370.4</SystemNetHttpJsonPackageVersion>
<SystemNetHttpWinHttpHandlerPackageVersion>5.0.0-preview.8.20361.2</SystemNetHttpWinHttpHandlerPackageVersion> <SystemNetHttpWinHttpHandlerPackageVersion>5.0.0-rc.1.20370.4</SystemNetHttpWinHttpHandlerPackageVersion>
<SystemNetWebSocketsWebSocketProtocolPackageVersion>5.0.0-preview.8.20361.2</SystemNetWebSocketsWebSocketProtocolPackageVersion> <SystemNetWebSocketsWebSocketProtocolPackageVersion>5.0.0-rc.1.20370.4</SystemNetWebSocketsWebSocketProtocolPackageVersion>
<SystemReflectionMetadataPackageVersion>5.0.0-preview.8.20361.2</SystemReflectionMetadataPackageVersion> <SystemReflectionMetadataPackageVersion>5.0.0-rc.1.20370.4</SystemReflectionMetadataPackageVersion>
<SystemResourcesExtensionsPackageVersion>5.0.0-preview.8.20361.2</SystemResourcesExtensionsPackageVersion> <SystemResourcesExtensionsPackageVersion>5.0.0-rc.1.20370.4</SystemResourcesExtensionsPackageVersion>
<SystemRuntimeCompilerServicesUnsafePackageVersion>5.0.0-preview.8.20361.2</SystemRuntimeCompilerServicesUnsafePackageVersion> <SystemRuntimeCompilerServicesUnsafePackageVersion>5.0.0-rc.1.20370.4</SystemRuntimeCompilerServicesUnsafePackageVersion>
<SystemSecurityCryptographyCngPackageVersion>5.0.0-preview.8.20361.2</SystemSecurityCryptographyCngPackageVersion> <!-- System.Security.AccessControl should only be referenced in Dependencies.props and RTMVersions.csproj. -->
<SystemSecurityCryptographyPkcsPackageVersion>5.0.0-preview.8.20361.2</SystemSecurityCryptographyPkcsPackageVersion> <SystemSecurityAccessControlPackageVersion>5.0.0-rc.1.20370.4</SystemSecurityAccessControlPackageVersion>
<SystemSecurityCryptographyXmlPackageVersion>5.0.0-preview.8.20361.2</SystemSecurityCryptographyXmlPackageVersion> <SystemSecurityCryptographyCngPackageVersion>5.0.0-rc.1.20370.4</SystemSecurityCryptographyCngPackageVersion>
<SystemSecurityPermissionsPackageVersion>5.0.0-preview.8.20361.2</SystemSecurityPermissionsPackageVersion> <SystemSecurityCryptographyPkcsPackageVersion>5.0.0-rc.1.20370.4</SystemSecurityCryptographyPkcsPackageVersion>
<SystemSecurityPrincipalWindowsPackageVersion>5.0.0-preview.8.20361.2</SystemSecurityPrincipalWindowsPackageVersion> <SystemSecurityCryptographyXmlPackageVersion>5.0.0-rc.1.20370.4</SystemSecurityCryptographyXmlPackageVersion>
<SystemServiceProcessServiceControllerPackageVersion>5.0.0-preview.8.20361.2</SystemServiceProcessServiceControllerPackageVersion> <SystemSecurityPermissionsPackageVersion>5.0.0-rc.1.20370.4</SystemSecurityPermissionsPackageVersion>
<SystemTextEncodingsWebPackageVersion>5.0.0-preview.8.20361.2</SystemTextEncodingsWebPackageVersion> <SystemSecurityPrincipalWindowsPackageVersion>5.0.0-rc.1.20370.4</SystemSecurityPrincipalWindowsPackageVersion>
<SystemTextJsonPackageVersion>5.0.0-preview.8.20361.2</SystemTextJsonPackageVersion> <SystemServiceProcessServiceControllerPackageVersion>5.0.0-rc.1.20370.4</SystemServiceProcessServiceControllerPackageVersion>
<SystemThreadingChannelsPackageVersion>5.0.0-preview.8.20361.2</SystemThreadingChannelsPackageVersion> <SystemTextEncodingsWebPackageVersion>5.0.0-rc.1.20370.4</SystemTextEncodingsWebPackageVersion>
<SystemWindowsExtensionsPackageVersion>5.0.0-preview.8.20361.2</SystemWindowsExtensionsPackageVersion> <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 --> <!-- 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 --> <!-- Packages from dotnet/blazor -->
<MicrosoftAspNetCoreComponentsWebAssemblyRuntimePackageVersion>3.2.0</MicrosoftAspNetCoreComponentsWebAssemblyRuntimePackageVersion> <MicrosoftAspNetCoreComponentsWebAssemblyRuntimePackageVersion>3.2.0</MicrosoftAspNetCoreComponentsWebAssemblyRuntimePackageVersion>
<!-- Packages from dotnet/efcore --> <!-- Packages from dotnet/efcore -->
<dotnetefPackageVersion>5.0.0-preview.8.20360.8</dotnetefPackageVersion> <dotnetefPackageVersion>5.0.0-rc.1.20367.2</dotnetefPackageVersion>
<MicrosoftEntityFrameworkCoreInMemoryPackageVersion>5.0.0-preview.8.20360.8</MicrosoftEntityFrameworkCoreInMemoryPackageVersion> <MicrosoftEntityFrameworkCoreInMemoryPackageVersion>5.0.0-rc.1.20367.2</MicrosoftEntityFrameworkCoreInMemoryPackageVersion>
<MicrosoftEntityFrameworkCoreRelationalPackageVersion>5.0.0-preview.8.20360.8</MicrosoftEntityFrameworkCoreRelationalPackageVersion> <MicrosoftEntityFrameworkCoreRelationalPackageVersion>5.0.0-rc.1.20367.2</MicrosoftEntityFrameworkCoreRelationalPackageVersion>
<MicrosoftEntityFrameworkCoreSqlitePackageVersion>5.0.0-preview.8.20360.8</MicrosoftEntityFrameworkCoreSqlitePackageVersion> <MicrosoftEntityFrameworkCoreSqlitePackageVersion>5.0.0-rc.1.20367.2</MicrosoftEntityFrameworkCoreSqlitePackageVersion>
<MicrosoftEntityFrameworkCoreSqlServerPackageVersion>5.0.0-preview.8.20360.8</MicrosoftEntityFrameworkCoreSqlServerPackageVersion> <MicrosoftEntityFrameworkCoreSqlServerPackageVersion>5.0.0-rc.1.20367.2</MicrosoftEntityFrameworkCoreSqlServerPackageVersion>
<MicrosoftEntityFrameworkCoreToolsPackageVersion>5.0.0-preview.8.20360.8</MicrosoftEntityFrameworkCoreToolsPackageVersion> <MicrosoftEntityFrameworkCoreToolsPackageVersion>5.0.0-rc.1.20367.2</MicrosoftEntityFrameworkCoreToolsPackageVersion>
<MicrosoftEntityFrameworkCorePackageVersion>5.0.0-preview.8.20360.8</MicrosoftEntityFrameworkCorePackageVersion> <MicrosoftEntityFrameworkCorePackageVersion>5.0.0-rc.1.20367.2</MicrosoftEntityFrameworkCorePackageVersion>
</PropertyGroup> </PropertyGroup>
<!-- <!--
@ -155,7 +157,6 @@
--> -->
<MicrosoftNETCoreAppRuntimeVersion>$(MicrosoftNETCoreAppRuntimewinx64PackageVersion)</MicrosoftNETCoreAppRuntimeVersion> <MicrosoftNETCoreAppRuntimeVersion>$(MicrosoftNETCoreAppRuntimewinx64PackageVersion)</MicrosoftNETCoreAppRuntimeVersion>
</PropertyGroup> </PropertyGroup>
<!-- <!--
We ship ref/ assemblies for runtime packages in our targeting targeting pack. When servicing that targeting pack, 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 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 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 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. 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' "> <PropertyGroup Condition=" '$(IsServicingBuild)' == 'true' ">
<MicrosoftWin32RegistryV0PackageVersion>$(MicrosoftWin32RegistryPackageVersion.Split('.')[0]).$(MicrosoftWin32RegistryPackageVersion.Split('.')[1]).0</MicrosoftWin32RegistryV0PackageVersion> <MicrosoftWin32RegistryV0PackageVersion>$(MicrosoftWin32RegistryPackageVersion.Split('.')[0]).$(MicrosoftWin32RegistryPackageVersion.Split('.')[1]).0</MicrosoftWin32RegistryV0PackageVersion>
@ -178,7 +187,6 @@
<SystemSecurityPrincipalWindowsV0PackageVersion>$(SystemSecurityPrincipalWindowsPackageVersion.Split('.')[0]).$(SystemSecurityPrincipalWindowsPackageVersion.Split('.')[1]).0</SystemSecurityPrincipalWindowsV0PackageVersion> <SystemSecurityPrincipalWindowsV0PackageVersion>$(SystemSecurityPrincipalWindowsPackageVersion.Split('.')[0]).$(SystemSecurityPrincipalWindowsPackageVersion.Split('.')[1]).0</SystemSecurityPrincipalWindowsV0PackageVersion>
<SystemWindowsExtensionsV0PackageVersion>$(SystemWindowsExtensionsPackageVersion.Split('.')[0]).$(SystemWindowsExtensionsPackageVersion.Split('.')[1]).0</SystemWindowsExtensionsV0PackageVersion> <SystemWindowsExtensionsV0PackageVersion>$(SystemWindowsExtensionsPackageVersion.Split('.')[0]).$(SystemWindowsExtensionsPackageVersion.Split('.')[1]).0</SystemWindowsExtensionsV0PackageVersion>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Label="Manual"> <PropertyGroup Label="Manual">
<!-- DiagnosticAdapter package pinned temporarily until migrated/deprecated --> <!-- DiagnosticAdapter package pinned temporarily until migrated/deprecated -->
<MicrosoftExtensionsDiagnosticAdapterPackageVersion>5.0.0-preview.4.20180.4</MicrosoftExtensionsDiagnosticAdapterPackageVersion> <MicrosoftExtensionsDiagnosticAdapterPackageVersion>5.0.0-preview.4.20180.4</MicrosoftExtensionsDiagnosticAdapterPackageVersion>
@ -252,9 +260,6 @@
<MonoCecilPackageVersion>0.11.2</MonoCecilPackageVersion> <MonoCecilPackageVersion>0.11.2</MonoCecilPackageVersion>
<NewtonsoftJsonBsonPackageVersion>1.0.2</NewtonsoftJsonBsonPackageVersion> <NewtonsoftJsonBsonPackageVersion>1.0.2</NewtonsoftJsonBsonPackageVersion>
<NewtonsoftJsonPackageVersion>12.0.2</NewtonsoftJsonPackageVersion> <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> <NSwagApiDescriptionClientPackageVersion>13.0.4</NSwagApiDescriptionClientPackageVersion>
<SeleniumSupportPackageVersion>3.12.1</SeleniumSupportPackageVersion> <SeleniumSupportPackageVersion>3.12.1</SeleniumSupportPackageVersion>
<SeleniumWebDriverMicrosoftDriverPackageVersion>17.17134.0</SeleniumWebDriverMicrosoftDriverPackageVersion> <SeleniumWebDriverMicrosoftDriverPackageVersion>17.17134.0</SeleniumWebDriverMicrosoftDriverPackageVersion>

View File

@ -127,7 +127,7 @@
</Target> </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 target resolves remaining Reference 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 executes on NuGet restore and during DesignTimeBuild. It should not run in the outer, cross-targeting build.
--> -->
<Target Name="ResolveCustomReferences" <Target Name="ResolveCustomReferences"
@ -205,21 +205,23 @@
</Target> </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 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. 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. 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 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 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". about the "invalid strong name".
--> -->
<Target Name="_UseRTMReferenceAssemblies" <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" BeforeTargets="GenerateBuildDependencyFile;GeneratePublishDependencyFile;ILLink;ResolveLockFileReferences"
DependsOnTargets="ResolvePackageAssets"> 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)" <JoinItems Left="@(ResolvedCompileFileDefinitions)"
Right="@(LatestPackageReference->HasMetadata('RTMVersion'))" Right="@(LatestPackageReference->HasMetadata('RTMVersion'))"
LeftKey="Filename" LeftKey="Filename"

View File

@ -36,5 +36,15 @@
<Reference Include="Microsoft.Deployment.WindowsInstaller.Package"> <Reference Include="Microsoft.Deployment.WindowsInstaller.Package">
<HintPath>$(WiXSdkPath)\Microsoft.Deployment.WindowsInstaller.Package.dll</HintPath> <HintPath>$(WiXSdkPath)\Microsoft.Deployment.WindowsInstaller.Package.dll</HintPath>
</Reference> </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> </ItemGroup>
</Project> </Project>

View File

@ -34,7 +34,7 @@ namespace A.Internal.Namespace
[Theory] [Theory]
[MemberData(nameof(PublicMemberDefinitions))] [MemberData(nameof(PublicMemberDefinitions))]
[QuarantinedTest] [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/22440")]
public async Task PublicExposureOfPubternalTypeProducesPUB0001(string member) public async Task PublicExposureOfPubternalTypeProducesPUB0001(string member)
{ {
var code = GetSourceFromNamespaceDeclaration($@" var code = GetSourceFromNamespaceDeclaration($@"

View File

@ -54,6 +54,12 @@ namespace Microsoft.AspNetCore.Components.Authorization
[Parameter] [Parameter]
public RenderFragment Authorizing { get; set; } public RenderFragment Authorizing { get; set; }
/// <summary>
/// The resource to which access is being controlled.
/// </summary>
[Parameter]
public object Resource { get; set; }
[CascadingParameter] [CascadingParameter]
private Task<AuthenticationState> ExistingCascadedAuthenticationState { get; set; } private Task<AuthenticationState> ExistingCascadedAuthenticationState { get; set; }
@ -82,6 +88,7 @@ namespace Microsoft.AspNetCore.Components.Authorization
builder.AddAttribute(2, nameof(AuthorizeRouteViewCore.Authorized), _renderAuthorizedDelegate); builder.AddAttribute(2, nameof(AuthorizeRouteViewCore.Authorized), _renderAuthorizedDelegate);
builder.AddAttribute(3, nameof(AuthorizeRouteViewCore.Authorizing), _renderAuthorizingDelegate); builder.AddAttribute(3, nameof(AuthorizeRouteViewCore.Authorizing), _renderAuthorizingDelegate);
builder.AddAttribute(4, nameof(AuthorizeRouteViewCore.NotAuthorized), _renderNotAuthorizedDelegate); builder.AddAttribute(4, nameof(AuthorizeRouteViewCore.NotAuthorized), _renderNotAuthorizedDelegate);
builder.AddAttribute(5, nameof(AuthorizeRouteViewCore.Resource), Resource);
builder.CloseComponent(); builder.CloseComponent();
} }

View File

@ -76,6 +76,78 @@ namespace Microsoft.AspNetCore.Components.Authorization
edit => AssertPrependText(batch, edit, "Hello from the page with message: Hello, world!")); 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] [Fact]
public void WhenNotAuthorized_RendersDefaultNotAuthorizedContentInsideLayout() public void WhenNotAuthorized_RendersDefaultNotAuthorizedContentInsideLayout()
{ {

View File

@ -61,6 +61,13 @@ namespace Microsoft.AspNetCore.Components
return Receiver.HandleEventAsync(new EventCallbackWorkItem(Delegate), arg); 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() object? IEventCallback.UnpackForRenderTree()
{ {
return RequiresExplicitReceiver ? (object)this : Delegate; return RequiresExplicitReceiver ? (object)this : Delegate;

View File

@ -56,6 +56,13 @@ namespace Microsoft.AspNetCore.Components
return Receiver.HandleEventAsync(new EventCallbackWorkItem(Delegate), arg); 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() internal EventCallback AsUntyped()
{ {
return new EventCallback(Receiver ?? Delegate?.Target as IHandleEvent, Delegate); return new EventCallback(Receiver ?? Delegate?.Target as IHandleEvent, Delegate);

View File

@ -498,6 +498,7 @@ namespace Microsoft.AspNetCore.Components.RenderTree
{ {
ProcessRenderQueue(); ProcessRenderQueue();
} }
ComponentsProfiling.Instance.End(); ComponentsProfiling.Instance.End();
} }
@ -634,11 +635,43 @@ namespace Microsoft.AspNetCore.Components.RenderTree
var disposeComponentId = _batchBuilder.ComponentDisposalQueue.Dequeue(); var disposeComponentId = _batchBuilder.ComponentDisposalQueue.Dequeue();
var disposeComponentState = GetRequiredComponentState(disposeComponentId); var disposeComponentState = GetRequiredComponentState(disposeComponentId);
Log.DisposingComponent(_logger, disposeComponentState); Log.DisposingComponent(_logger, disposeComponentState);
if (!disposeComponentState.TryDisposeInBatch(_batchBuilder, out var exception)) if (!(disposeComponentState.Component is IAsyncDisposable))
{ {
exceptions ??= new List<Exception>(); if (!disposeComponentState.TryDisposeInBatch(_batchBuilder, out var exception))
exceptions.Add(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); _componentStateById.Remove(disposeComponentId);
_batchBuilder.DisposedComponentIds.Append(disposeComponentId); _batchBuilder.DisposedComponentIds.Append(disposeComponentId);
} }

View File

@ -101,6 +101,13 @@ namespace Microsoft.AspNetCore.Components.Rendering
exception = ex; exception = ex;
} }
CleanupComponentStateResources(batchBuilder);
return exception == null;
}
private void CleanupComponentStateResources(RenderBatchBuilder batchBuilder)
{
// We don't expect these things to throw. // We don't expect these things to throw.
RenderTreeDiffBuilder.DisposeFrames(batchBuilder, CurrentRenderTree.GetFrames()); RenderTreeDiffBuilder.DisposeFrames(batchBuilder, CurrentRenderTree.GetFrames());
@ -110,8 +117,6 @@ namespace Microsoft.AspNetCore.Components.Rendering
} }
DisposeBuffers(); DisposeBuffers();
return exception == null;
} }
// Callers expect this method to always return a faulted task. // Callers expect this method to always return a faulted task.
@ -222,5 +227,31 @@ namespace Microsoft.AspNetCore.Components.Rendering
((IDisposable)CurrentRenderTree).Dispose(); ((IDisposable)CurrentRenderTree).Dispose();
_latestDirectParametersSnapshot?.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);
}
}
} }
} }

View File

@ -22,7 +22,7 @@ namespace Microsoft.AspNetCore.Components.Routing
public override bool Match(string pathSegment, out object? convertedValue) public override bool Match(string pathSegment, out object? convertedValue)
{ {
// Unset values are set to null in the Parameters object created in // 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. // are converted to null.
if (string.IsNullOrEmpty(pathSegment)) if (string.IsNullOrEmpty(pathSegment))
{ {

View File

@ -29,10 +29,20 @@ namespace Microsoft.AspNetCore.Components.Routing
internal void Match(RouteContext context) 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 // 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 // and the template do not match, then there is no chance of this matching and
// we can bail early. // 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; return;
} }
@ -43,7 +53,15 @@ namespace Microsoft.AspNetCore.Components.Routing
for (var i = 0; i < Template.Segments.Length; i++) for (var i = 0; i < Template.Segments.Length; i++)
{ {
var segment = Template.Segments[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 // If the template contains more segments than the path, then
// we may need to break out of this for-loop. This can happen // we may need to break out of this for-loop. This can happen
// in one of two cases: // 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 // In addition to extracting parameter values from the URL, each route entry
// also knows which other parameters should be supplied with null values. These // also knows which other parameters should be supplied with null values. These
// are parameters supplied by other route entries matching the same handler. // 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); parameters ??= new Dictionary<string, object>(StringComparer.Ordinal);
for (var i = 0; i < UnusedRouteParameterNames.Length; i++) 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 // `/this/is/a/template` and the route `/this/`. In that case, we want to ensure
// that all non-optional segments have matched as well. // that all non-optional segments have matched as well.
var allNonOptionalSegmentsMatch = numMatchingSegments >= (Template.Segments.Length - Template.OptionalSegmentsCount); var allNonOptionalSegmentsMatch = numMatchingSegments >= (Template.Segments.Length - Template.OptionalSegmentsCount);
if (allRouteSegmentsMatch && allNonOptionalSegmentsMatch) if (Template.ContainsCatchAllSegment || (allRouteSegmentsMatch && allNonOptionalSegmentsMatch))
{ {
context.Parameters = parameters; context.Parameters = parameters;
context.Handler = Handler; context.Handler = Handler;

View File

@ -15,6 +15,7 @@ namespace Microsoft.AspNetCore.Components.Routing
TemplateText = templateText; TemplateText = templateText;
Segments = segments; Segments = segments;
OptionalSegmentsCount = segments.Count(template => template.IsOptional); OptionalSegmentsCount = segments.Count(template => template.IsOptional);
ContainsCatchAllSegment = segments.Any(template => template.IsCatchAll);
} }
public string TemplateText { get; } public string TemplateText { get; }
@ -22,5 +23,7 @@ namespace Microsoft.AspNetCore.Components.Routing
public TemplateSegment[] Segments { get; } public TemplateSegment[] Segments { get; }
public int OptionalSegmentsCount { get; } public int OptionalSegmentsCount { get; }
public bool ContainsCatchAllSegment { get; }
} }
} }

View File

@ -12,15 +12,15 @@ namespace Microsoft.AspNetCore.Components.Routing
// The class in here just takes care of parsing a route and extracting // The class in here just takes care of parsing a route and extracting
// simple parameters from it. // simple parameters from it.
// Some differences with ASP.NET Core routes are: // Some differences with ASP.NET Core routes are:
// * We don't support catch all parameter segments.
// * We don't support complex segments. // * We don't support complex segments.
// The things that we support are: // The things that we support are:
// * Literal path segments. (Like /Path/To/Some/Page) // * Literal path segments. (Like /Path/To/Some/Page)
// * Parameter path segments (Like /Customer/{Id}/Orders/{OrderId}) // * Parameter path segments (Like /Customer/{Id}/Orders/{OrderId})
// * Catch-all parameters (Like /blog/{*slug})
internal class TemplateParser internal class TemplateParser
{ {
public static readonly char[] InvalidParameterNameCharacters = public static readonly char[] InvalidParameterNameCharacters =
new char[] { '*', '{', '}', '=', '.' }; new char[] { '{', '}', '=', '.' };
internal static RouteTemplate ParseTemplate(string template) internal static RouteTemplate ParseTemplate(string template)
{ {
@ -80,6 +80,12 @@ namespace Microsoft.AspNetCore.Components.Routing
for (int i = 0; i < templateSegments.Length; i++) for (int i = 0; i < templateSegments.Length; i++)
{ {
var currentSegment = templateSegments[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) if (!currentSegment.IsParameter)
{ {
continue; continue;

View File

@ -12,34 +12,48 @@ namespace Microsoft.AspNetCore.Components.Routing
{ {
IsParameter = isParameter; 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 // Process segments that are not parameters or do not contain
// a token separating a type constraint. // 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 // Set the IsOptional flag to true for segments that contain
// a parameter with no type constraints but optionality set // a parameter with no type constraints but optionality set
// via the '?' token. // via the '?' token.
if (segment.IndexOf('?') == segment.Length - 1) if (Value.IndexOf('?') == Value.Length - 1)
{ {
IsOptional = true; 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, // If the `?` optional marker shows up in the segment but not at the very end,
// then throw an error. // 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."); 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>(); Constraints = Array.Empty<RouteConstraint>();
} }
else else
{ {
var tokens = segment.Split(':'); var tokens = Value.Split(':');
if (tokens[0].Length == 0) if (tokens[0].Length == 0)
{ {
throw new ArgumentException($"Malformed parameter '{segment}' in route '{template}' has no name before the constraints list."); 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)) .Select(token => RouteConstraint.Parse(template, segment, token))
.ToArray(); .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. // 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 IsOptional { get; }
public bool IsCatchAll { get; }
public RouteConstraint[] Constraints { get; } public RouteConstraint[] Constraints { get; }
public bool Match(string pathSegment, out object? matchedParameterValue) public bool Match(string pathSegment, out object? matchedParameterValue)

View File

@ -17,7 +17,7 @@ namespace Microsoft.AspNetCore.Components
var callback = default(EventCallback); var callback = default(EventCallback);
// Act & Assert (Does not throw) // Act & Assert (Does not throw)
await callback.InvokeAsync(null); await callback.InvokeAsync();
} }
[Fact] [Fact]
@ -27,7 +27,7 @@ namespace Microsoft.AspNetCore.Components
var callback = default(EventCallback<EventArgs>); var callback = default(EventCallback<EventArgs>);
// Act & Assert (Does not throw) // 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++)); var callback = new EventCallback(null, (Action)(() => runCount++));
// Act // Act
await callback.InvokeAsync(null); await callback.InvokeAsync();
// Assert // Assert
@ -54,7 +54,7 @@ namespace Microsoft.AspNetCore.Components
var callback = new EventCallback<EventArgs>(null, (Action)(() => runCount++)); var callback = new EventCallback<EventArgs>(null, (Action)(() => runCount++));
// Act // Act
await callback.InvokeAsync(null); await callback.InvokeAsync();
// Assert // Assert
@ -71,7 +71,7 @@ namespace Microsoft.AspNetCore.Components
var callback = new EventCallback(component, (Action)(() => runCount++)); var callback = new EventCallback(component, (Action)(() => runCount++));
// Act // Act
await callback.InvokeAsync(null); await callback.InvokeAsync();
// Assert // Assert
@ -108,7 +108,7 @@ namespace Microsoft.AspNetCore.Components
var callback = new EventCallback(component, (Action<EventArgs>)((e) => { arg = e; runCount++; })); var callback = new EventCallback(component, (Action<EventArgs>)((e) => { arg = e; runCount++; }));
// Act // Act
await callback.InvokeAsync(null); await callback.InvokeAsync();
// Assert // Assert
@ -184,7 +184,7 @@ namespace Microsoft.AspNetCore.Components
var callback = new EventCallback(component, (Func<Task>)(() => { runCount++; return Task.CompletedTask; })); var callback = new EventCallback(component, (Func<Task>)(() => { runCount++; return Task.CompletedTask; }));
// Act // Act
await callback.InvokeAsync(null); await callback.InvokeAsync();
// Assert // Assert
@ -221,7 +221,7 @@ namespace Microsoft.AspNetCore.Components
var callback = new EventCallback(component, (Func<EventArgs, Task>)((e) => { arg = e; runCount++; return Task.CompletedTask; })); var callback = new EventCallback(component, (Func<EventArgs, Task>)((e) => { arg = e; runCount++; return Task.CompletedTask; }));
// Act // Act
await callback.InvokeAsync(null); await callback.InvokeAsync();
// Assert // Assert
@ -297,7 +297,7 @@ namespace Microsoft.AspNetCore.Components
var callback = new EventCallback<EventArgs>(component, (Action)(() => runCount++)); var callback = new EventCallback<EventArgs>(component, (Action)(() => runCount++));
// Act // Act
await callback.InvokeAsync(null); await callback.InvokeAsync();
// Assert // Assert
@ -334,7 +334,7 @@ namespace Microsoft.AspNetCore.Components
var callback = new EventCallback<EventArgs>(component, (Action<EventArgs>)((e) => { arg = e; runCount++; })); var callback = new EventCallback<EventArgs>(component, (Action<EventArgs>)((e) => { arg = e; runCount++; }));
// Act // Act
await callback.InvokeAsync(null); await callback.InvokeAsync();
// Assert // Assert
@ -373,7 +373,7 @@ namespace Microsoft.AspNetCore.Components
var callback = new EventCallback<EventArgs>(component, (Func<Task>)(() => { runCount++; return Task.CompletedTask; })); var callback = new EventCallback<EventArgs>(component, (Func<Task>)(() => { runCount++; return Task.CompletedTask; }));
// Act // Act
await callback.InvokeAsync(null); await callback.InvokeAsync();
// Assert // 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; })); var callback = new EventCallback<EventArgs>(component, (Func<EventArgs, Task>)((e) => { arg = e; runCount++; return Task.CompletedTask; }));
// Act // Act
await callback.InvokeAsync(null); await callback.InvokeAsync();
// Assert // Assert

View File

@ -71,7 +71,7 @@ namespace Microsoft.AspNetCore.Components
} }
[Fact] [Fact]
public void IncomingParameterMatchesOverridenParameter_ThatDoesNotHasAttribute() public void IncomingParameterMatchesOverriddenParameter_ThatDoesNotHaveAttribute()
{ {
// Test for https://github.com/dotnet/aspnetcore/issues/13162 // Test for https://github.com/dotnet/aspnetcore/issues/13162
// Arrange // Arrange

View File

@ -487,7 +487,8 @@ namespace Microsoft.AspNetCore.Components.Test
public void DispatchEventHandlesSynchronousExceptionsFromEventHandlers() public void DispatchEventHandlesSynchronousExceptionsFromEventHandlers()
{ {
// Arrange: Render a component with an event handler // Arrange: Render a component with an event handler
var renderer = new TestRenderer { var renderer = new TestRenderer
{
ShouldHandleExceptions = true ShouldHandleExceptions = true
}; };
@ -2086,6 +2087,238 @@ namespace Microsoft.AspNetCore.Components.Test
Assert.Contains(exception2, aex.InnerExceptions); 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] [Fact]
public void RenderBatch_DoesNotDisposeComponentMultipleTimes() public void RenderBatch_DoesNotDisposeComponentMultipleTimes()
{ {
@ -2589,7 +2822,7 @@ namespace Microsoft.AspNetCore.Components.Test
// Act: Toggle the checkbox // Act: Toggle the checkbox
var eventArgs = new ChangeEventArgs { Value = true }; var eventArgs = new ChangeEventArgs { Value = true };
var renderTask = renderer.DispatchEventAsync(checkboxChangeEventHandlerId, eventArgs); var renderTask = renderer.DispatchEventAsync(checkboxChangeEventHandlerId, eventArgs);
Assert.True(renderTask.IsCompletedSuccessfully); Assert.True(renderTask.IsCompletedSuccessfully);
var latestBatch = renderer.Batches.Last(); var latestBatch = renderer.Batches.Last();
@ -3768,7 +4001,7 @@ namespace Microsoft.AspNetCore.Components.Test
requestedType => Assert.Equal(typeof(TestComponent), requestedType)); 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>(); 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 class TestAsyncRenderer : TestRenderer
{ {
public Task NextUpdateDisplayReturnTask { get; set; } public Task NextUpdateDisplayReturnTask { get; set; }

View File

@ -226,6 +226,23 @@ namespace Microsoft.AspNetCore.Components.Test.Routing
Assert.Single(context.Parameters, p => p.Key == "parameter" && (string)p.Value == expectedValue); 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] [Fact]
public void CanMatchTemplateWithMultipleParameters() public void CanMatchTemplateWithMultipleParameters()
{ {
@ -247,6 +264,29 @@ namespace Microsoft.AspNetCore.Components.Test.Routing
Assert.Equal(expectedParameters, context.Parameters); 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[][] public static IEnumerable<object[]> CanMatchParameterWithConstraintCases() => new object[][]
{ {
new object[] { "/{value:bool}", "/true", true }, new object[] { "/{value:bool}", "/true", true },
@ -476,7 +516,7 @@ namespace Microsoft.AspNetCore.Components.Test.Routing
[Fact] [Fact]
public void PrefersLiteralTemplateOverParmeterizedTemplates() public void PrefersLiteralTemplateOverParameterizedTemplates()
{ {
// Arrange // Arrange
var routeTable = new TestRouteTableBuilder() var routeTable = new TestRouteTableBuilder()

View File

@ -83,6 +83,45 @@ namespace Microsoft.AspNetCore.Components.Routing
Assert.Equal(expected, actual, RouteTemplateTestComparer.Instance); 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] [Fact]
public void InvalidTemplate_WithRepeatedParameter() public void InvalidTemplate_WithRepeatedParameter()
{ {
@ -113,7 +152,8 @@ namespace Microsoft.AspNetCore.Components.Routing
} }
[Theory] [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.")] [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); 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] [Fact]
public void InvalidTemplate_BadOptionalCharacterPosition() public void InvalidTemplate_BadOptionalCharacterPosition()
{ {

View File

@ -24,6 +24,7 @@ app {
height: 3.5rem; height: 3.5rem;
display: flex; display: flex;
align-items: center; align-items: center;
z-index: 10;
} }
.main { .main {

View File

@ -296,7 +296,7 @@ namespace Microsoft.AspNetCore.Components.Web.Rendering
exceptions.Add(e); exceptions.Add(e);
}; };
// Receive the ack for the intial batch // Receive the ack for the initial batch
_ = renderer.OnRenderCompletedAsync(2, null); _ = renderer.OnRenderCompletedAsync(2, null);
// Receive the ack for the second batch // Receive the ack for the second batch
_ = renderer.OnRenderCompletedAsync(2, null); _ = renderer.OnRenderCompletedAsync(2, null);

View File

@ -71,6 +71,7 @@ namespace Microsoft.AspNetCore.Components.Web
"touch" => Deserialize<TouchEventArgs>(eventArgsJson), "touch" => Deserialize<TouchEventArgs>(eventArgsJson),
"unknown" => EventArgs.Empty, "unknown" => EventArgs.Empty,
"wheel" => Deserialize<WheelEventArgs>(eventArgsJson), "wheel" => Deserialize<WheelEventArgs>(eventArgsJson),
"toggle" => Deserialize<EventArgs>(eventArgsJson),
_ => throw new InvalidOperationException($"Unsupported event type '{eventArgsType}'. EventId: '{eventHandlerId}'."), _ => 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

View File

@ -66,8 +66,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 // Fetch the resources and prepare the Mono runtime
const bootConfigResult = await BootConfigResult.initAsync(); const bootConfigResult = await BootConfigResult.initAsync(environment);
const [resourceLoader] = await Promise.all([ const [resourceLoader] = await Promise.all([
WebAssemblyResourceLoader.initAsync(bootConfigResult.bootConfig, options || {}), WebAssemblyResourceLoader.initAsync(bootConfigResult.bootConfig, options || {}),

View File

@ -2,7 +2,7 @@ export class BootConfigResult {
private constructor(public bootConfig: BootJsonData, public applicationEnvironment: string) { 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', { const bootConfigResponse = await fetch('_framework/blazor.boot.json', {
method: 'GET', method: 'GET',
credentials: 'include', credentials: 'include',
@ -10,8 +10,8 @@ export class BootConfigResult {
}); });
// While we can expect an ASP.NET Core hosted application to include the environment, other // 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. // hosts may not. Assume 'Production' in the absence of any specified value.
const applicationEnvironment = bootConfigResponse.headers.get('Blazor-Environment') || 'Production'; const applicationEnvironment = environment || bootConfigResponse.headers.get('Blazor-Environment') || 'Production';
const bootConfig: BootJsonData = await bootConfigResponse.json(); const bootConfig: BootJsonData = await bootConfigResponse.json();
return new BootConfigResult(bootConfig, applicationEnvironment); return new BootConfigResult(bootConfig, applicationEnvironment);

View File

@ -356,6 +356,7 @@ function createEmscriptenModuleInstance(resourceLoader: WebAssemblyResourceLoade
resourceLoader.purgeUnusedCacheEntriesAsync(); // Don't await - it's fine to run in background resourceLoader.purgeUnusedCacheEntriesAsync(); // Don't await - it's fine to run in background
MONO.mono_wasm_setenv("MONO_URI_DOTNETRELATIVEORABSOLUTE", "true"); MONO.mono_wasm_setenv("MONO_URI_DOTNETRELATIVEORABSOLUTE", "true");
MONO.mono_wasm_setenv("DOTNET_SYSTEM_GLOBALIZATION_INVARIANT", "1");
const load_runtime = cwrap('mono_wasm_load_runtime', null, ['string', 'number']); const load_runtime = cwrap('mono_wasm_load_runtime', null, ['string', 'number']);
// -1 enables debugging with logging disabled. 0 disables debugging entirely. // -1 enables debugging with logging disabled. 0 disables debugging entirely.
load_runtime(appBinDirName, hasDebuggingEnabled() ? -1 : 0); load_runtime(appBinDirName, hasDebuggingEnabled() ? -1 : 0);

View File

@ -1,3 +1,6 @@
// Import type definitions to ensure that the global declaration
// is of BINDING is included when tests run
import './Mono/MonoTypes';
import { System_String } from './Platform'; import { System_String } from './Platform';
interface TimingEntry { interface TimingEntry {

View File

@ -165,6 +165,12 @@ async function getCacheToUseIfEnabled(bootConfig: BootJsonData): Promise<Cache |
return null; 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 // 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 // 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, // to purge from the cache anything we're not using and don't let it keep growing,

View File

@ -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. * @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; 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. // This type doesn't have to align with anything in BootConfig.

View File

@ -238,7 +238,8 @@ export class BrowserRenderer {
document.createElementNS('http://www.w3.org/2000/svg', tagName) : document.createElementNS('http://www.w3.org/2000/svg', tagName) :
document.createElement(tagName); document.createElement(tagName);
const newElement = toLogicalElement(newDomElementRaw); const newElement = toLogicalElement(newDomElementRaw);
insertLogicalChild(newDomElementRaw, parent, childIndex);
let inserted = false;
// Apply attributes // Apply attributes
const descendantsEndIndexExcl = frameIndex + frameReader.subtreeLength(frame); const descendantsEndIndexExcl = frameIndex + frameReader.subtreeLength(frame);
@ -247,6 +248,8 @@ export class BrowserRenderer {
if (frameReader.frameType(descendantFrame) === FrameType.attribute) { if (frameReader.frameType(descendantFrame) === FrameType.attribute) {
this.applyAttribute(batch, componentId, newDomElementRaw, descendantFrame); this.applyAttribute(batch, componentId, newDomElementRaw, descendantFrame);
} else { } else {
insertLogicalChild(newDomElementRaw, parent, childIndex);
inserted = true;
// As soon as we see a non-attribute child, all the subsequent child frames are // 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 // not attributes, so bail out and insert the remnants recursively
this.insertFrameRange(batch, componentId, newElement, 0, frames, descendantIndex, descendantsEndIndexExcl); this.insertFrameRange(batch, componentId, newElement, 0, frames, descendantIndex, descendantsEndIndexExcl);
@ -254,17 +257,40 @@ export class BrowserRenderer {
} }
} }
// We handle setting 'value' on a <select> in two different ways: // this element did not have any children, so it's not inserted yet.
// [1] When inserting a corresponding <option>, in case you're dynamically adding options 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 // [2] After we finish inserting the <select>, in case the descendant options are being
// added as an opaque markup block rather than individually // added as an opaque markup block rather than individually. This is the other case below.
// Right here we implement [2] // [3] In case the the value of the select and the option value is changed in the same batch.
if (newDomElementRaw instanceof HTMLSelectElement && selectValuePropname in newDomElementRaw) { // 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]; const selectValue: string | null = newDomElementRaw[selectValuePropname];
setSelectElementValue(newDomElementRaw, selectValue); 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) { private insertComponent(batch: RenderBatch, parent: LogicalElement, childIndex: number, frame: RenderTreeFrame) {
const containerElement = createAndInsertLogicalContainer(parent, childIndex); const containerElement = createAndInsertLogicalContainer(parent, childIndex);
@ -385,13 +411,10 @@ export class BrowserRenderer {
} else { } else {
element.removeAttribute('value'); element.removeAttribute('value');
} }
// See above for why we have this special handling for <select>/<option> // 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> // Situation 3
const selectElem = this.findClosestAncestorSelectElement(element); this.trySetSelectValueFromOptionElement(<HTMLOptionElement>element);
if (selectElem && (selectValuePropname in selectElem) && selectElem[selectValuePropname] === value) {
this.tryApplyValueProperty(batch, selectElem, attributeFrame);
delete selectElem[selectValuePropname];
}
return true; return true;
} }
default: default:

View File

@ -17,6 +17,7 @@ const nonBubblingEvents = toLookup([
'scroll', 'scroll',
'submit', 'submit',
'unload', 'unload',
'toggle',
'DOMNodeInsertedIntoDocument', 'DOMNodeInsertedIntoDocument',
'DOMNodeRemovedFromDocument', 'DOMNodeRemovedFromDocument',
]); ]);

View File

@ -89,6 +89,9 @@ export class EventForDotNet<TData extends UIEventArgs> {
case 'mousewheel': case 'mousewheel':
return new EventForDotNet<UIWheelEventArgs>('wheel', parseWheelEvent(event as WheelEvent)); return new EventForDotNet<UIWheelEventArgs>('wheel', parseWheelEvent(event as WheelEvent));
case 'toggle':
return new EventForDotNet<UIEventArgs>('toggle', { type: event.type });
default: default:
return new EventForDotNet<UIEventArgs>('unknown', { type: event.type }); 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 // 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 { export interface UIEventArgs {
type: string; type: string;

View File

@ -16,7 +16,8 @@ namespace Microsoft.AspNetCore.Components.Forms
{ {
private readonly Func<Task> _handleSubmitDelegate; // Cache to avoid per-render allocations private readonly Func<Task> _handleSubmitDelegate; // Cache to avoid per-render allocations
private EditContext? _fixedEditContext; private EditContext? _editContext;
private bool _hasSetEditContextExplicitly;
/// <summary> /// <summary>
/// Constructs an instance of <see cref="EditForm"/>. /// 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 /// also supply <see cref="Model"/>, since the model value will be taken
/// from the <see cref="EditContext.Model"/> property. /// from the <see cref="EditContext.Model"/> property.
/// </summary> /// </summary>
[Parameter] public EditContext? EditContext { get; set; } [Parameter]
public EditContext? EditContext
{
get => _editContext;
set
{
_editContext = value;
_hasSetEditContextExplicitly = value != null;
}
}
/// <summary> /// <summary>
/// Specifies the top-level model object for the form. An edit context will /// Specifies the top-level model object for the form. An edit context will
@ -73,11 +83,16 @@ namespace Microsoft.AspNetCore.Components.Forms
/// <inheritdoc /> /// <inheritdoc />
protected override void OnParametersSet() protected override void OnParametersSet()
{ {
if ((EditContext == null) == (Model == null)) if (_hasSetEditContextExplicitly && Model != null)
{ {
throw new InvalidOperationException($"{nameof(EditForm)} requires a {nameof(Model)} " + throw new InvalidOperationException($"{nameof(EditForm)} requires a {nameof(Model)} " +
$"parameter, or an {nameof(EditContext)} parameter, but not both."); $"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 // 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 // (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)}."); $"{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 // 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 /> /// <inheritdoc />
protected override void BuildRenderTree(RenderTreeBuilder builder) 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, // This is so we can safely use the IsFixed optimization on CascadingValue,
// optimizing for the common case where _fixedEditContext never changes. // optimizing for the common case where _editContext never changes.
builder.OpenRegion(_fixedEditContext.GetHashCode()); builder.OpenRegion(_editContext.GetHashCode());
builder.OpenElement(0, "form"); builder.OpenElement(0, "form");
builder.AddMultipleAttributes(1, AdditionalAttributes); builder.AddMultipleAttributes(1, AdditionalAttributes);
builder.AddAttribute(2, "onsubmit", _handleSubmitDelegate); builder.AddAttribute(2, "onsubmit", _handleSubmitDelegate);
builder.OpenComponent<CascadingValue<EditContext>>(3); builder.OpenComponent<CascadingValue<EditContext>>(3);
builder.AddAttribute(4, "IsFixed", true); builder.AddAttribute(4, "IsFixed", true);
builder.AddAttribute(5, "Value", _fixedEditContext); builder.AddAttribute(5, "Value", _editContext);
builder.AddAttribute(6, "ChildContent", ChildContent?.Invoke(_fixedEditContext)); builder.AddAttribute(6, "ChildContent", ChildContent?.Invoke(_editContext));
builder.CloseComponent(); builder.CloseComponent();
builder.CloseElement(); builder.CloseElement();
@ -122,26 +137,26 @@ namespace Microsoft.AspNetCore.Components.Forms
private async Task HandleSubmitAsync() private async Task HandleSubmitAsync()
{ {
Debug.Assert(_fixedEditContext != null); Debug.Assert(_editContext != null);
if (OnSubmit.HasDelegate) if (OnSubmit.HasDelegate)
{ {
// When using OnSubmit, the developer takes control of the validation lifecycle // When using OnSubmit, the developer takes control of the validation lifecycle
await OnSubmit.InvokeAsync(_fixedEditContext); await OnSubmit.InvokeAsync(_editContext);
} }
else else
{ {
// Otherwise, the system implicitly runs validation on form submission // 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) if (isValid && OnValidSubmit.HasDelegate)
{ {
await OnValidSubmit.InvokeAsync(_fixedEditContext); await OnValidSubmit.InvokeAsync(_editContext);
} }
if (!isValid && OnInvalidSubmit.HasDelegate) if (!isValid && OnInvalidSubmit.HasDelegate)
{ {
await OnInvalidSubmit.InvokeAsync(_fixedEditContext); await OnInvalidSubmit.InvokeAsync(_editContext);
} }
} }
} }

View File

@ -50,6 +50,12 @@ namespace Microsoft.AspNetCore.Components.Forms
/// </summary> /// </summary>
[Parameter] public Expression<Func<TValue>>? ValueExpression { get; set; } [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> /// <summary>
/// Gets the associated <see cref="Forms.EditContext"/>. /// Gets the associated <see cref="Forms.EditContext"/>.
/// </summary> /// </summary>

View File

@ -75,7 +75,7 @@ namespace Microsoft.AspNetCore.Components.Forms
} }
else else
{ {
validationErrorMessage = string.Format(ParsingErrorMessage, FieldIdentifier.FieldName); validationErrorMessage = string.Format(ParsingErrorMessage, DisplayName ?? FieldIdentifier.FieldName);
return false; return false;
} }
} }

View File

@ -22,7 +22,7 @@ namespace Microsoft.AspNetCore.Components.Forms
else else
{ {
result = default; result = default;
validationErrorMessage = $"The {input.FieldIdentifier.FieldName} field is not valid."; validationErrorMessage = $"The {input.DisplayName ?? input.FieldIdentifier.FieldName} field is not valid.";
return false; return false;
} }
} }

View File

@ -64,7 +64,7 @@ namespace Microsoft.AspNetCore.Components.Forms
} }
else else
{ {
validationErrorMessage = string.Format(ParsingErrorMessage, FieldIdentifier.FieldName); validationErrorMessage = string.Format(ParsingErrorMessage, DisplayName ?? FieldIdentifier.FieldName);
return false; return false;
} }
} }

View File

@ -122,6 +122,8 @@ namespace Microsoft.AspNetCore.Components.Web
[EventHandler("onpointerlockerror", typeof(EventArgs), true, true)] [EventHandler("onpointerlockerror", typeof(EventArgs), true, true)]
[EventHandler("onreadystatechange", typeof(EventArgs), true, true)] [EventHandler("onreadystatechange", typeof(EventArgs), true, true)]
[EventHandler("onscroll", typeof(EventArgs), true, true)] [EventHandler("onscroll", typeof(EventArgs), true, true)]
[EventHandler("ontoggle", typeof(EventArgs), true, true)]
public static class EventHandlers public static class EventHandlers
{ {
} }

View File

@ -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();
}
}
}
}

View File

@ -4,10 +4,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Components.Rendering;
using Microsoft.AspNetCore.Components.RenderTree;
using Microsoft.AspNetCore.Components.Test.Helpers; using Microsoft.AspNetCore.Components.Test.Helpers;
using Xunit; using Xunit;
@ -35,7 +32,7 @@ namespace Microsoft.AspNetCore.Components.Forms
// Arrange // Arrange
var model = new TestModel(); var model = new TestModel();
var rootComponent = new TestInputHostComponent<string, TestInputComponent<string>> { EditContext = new EditContext(model), ValueExpression = () => model.StringProperty }; var rootComponent = new TestInputHostComponent<string, TestInputComponent<string>> { EditContext = new EditContext(model), ValueExpression = () => model.StringProperty };
await RenderAndGetTestInputComponentAsync(rootComponent); await InputRenderer.RenderAndGetComponent(rootComponent);
// Act/Assert // Act/Assert
rootComponent.EditContext = new EditContext(model); 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) }; var rootComponent = new TestInputHostComponent<string, TestInputComponent<string>> { EditContext = new EditContext(model) };
// Act/Assert // 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); 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 // Act
var inputComponent = await RenderAndGetTestInputComponentAsync(rootComponent); var inputComponent = await InputRenderer.RenderAndGetComponent(rootComponent);
// Assert // Assert
Assert.Equal("some value", inputComponent.CurrentValue); Assert.Equal("some value", inputComponent.CurrentValue);
@ -87,7 +84,7 @@ namespace Microsoft.AspNetCore.Components.Forms
}; };
// Act // Act
var inputComponent = await RenderAndGetTestInputComponentAsync(rootComponent); var inputComponent = await InputRenderer.RenderAndGetComponent(rootComponent);
// Assert // Assert
Assert.Same(rootComponent.EditContext, inputComponent.EditContext); Assert.Same(rootComponent.EditContext, inputComponent.EditContext);
@ -106,7 +103,7 @@ namespace Microsoft.AspNetCore.Components.Forms
}; };
// Act // Act
var inputComponent = await RenderAndGetTestInputComponentAsync(rootComponent); var inputComponent = await InputRenderer.RenderAndGetComponent(rootComponent);
// Assert // Assert
Assert.Equal(FieldIdentifier.Create(() => model.StringProperty), inputComponent.FieldIdentifier); Assert.Equal(FieldIdentifier.Create(() => model.StringProperty), inputComponent.FieldIdentifier);
@ -123,7 +120,7 @@ namespace Microsoft.AspNetCore.Components.Forms
Value = "initial value", Value = "initial value",
ValueExpression = () => model.StringProperty ValueExpression = () => model.StringProperty
}; };
var inputComponent = await RenderAndGetTestInputComponentAsync(rootComponent); var inputComponent = await InputRenderer.RenderAndGetComponent(rootComponent);
Assert.Equal("initial value", inputComponent.CurrentValue); Assert.Equal("initial value", inputComponent.CurrentValue);
// Act // Act
@ -146,7 +143,7 @@ namespace Microsoft.AspNetCore.Components.Forms
ValueChanged = val => valueChangedCallLog.Add(val), ValueChanged = val => valueChangedCallLog.Add(val),
ValueExpression = () => model.StringProperty ValueExpression = () => model.StringProperty
}; };
var inputComponent = await RenderAndGetTestInputComponentAsync(rootComponent); var inputComponent = await InputRenderer.RenderAndGetComponent(rootComponent);
Assert.Empty(valueChangedCallLog); Assert.Empty(valueChangedCallLog);
// Act // Act
@ -169,7 +166,7 @@ namespace Microsoft.AspNetCore.Components.Forms
ValueChanged = val => valueChangedCallLog.Add(val), ValueChanged = val => valueChangedCallLog.Add(val),
ValueExpression = () => model.StringProperty ValueExpression = () => model.StringProperty
}; };
var inputComponent = await RenderAndGetTestInputComponentAsync(rootComponent); var inputComponent = await InputRenderer.RenderAndGetComponent(rootComponent);
Assert.Empty(valueChangedCallLog); Assert.Empty(valueChangedCallLog);
// Act // Act
@ -190,7 +187,7 @@ namespace Microsoft.AspNetCore.Components.Forms
Value = "initial value", Value = "initial value",
ValueExpression = () => model.StringProperty ValueExpression = () => model.StringProperty
}; };
var inputComponent = await RenderAndGetTestInputComponentAsync(rootComponent); var inputComponent = await InputRenderer.RenderAndGetComponent(rootComponent);
Assert.False(rootComponent.EditContext.IsModified(() => model.StringProperty)); Assert.False(rootComponent.EditContext.IsModified(() => model.StringProperty));
// Act // Act
@ -213,7 +210,7 @@ namespace Microsoft.AspNetCore.Components.Forms
var fieldIdentifier = FieldIdentifier.Create(() => model.StringProperty); var fieldIdentifier = FieldIdentifier.Create(() => model.StringProperty);
// Act/Assert: Initially, it's valid and unmodified // 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 Assert.Equal("valid", inputComponent.CssClass); // no Class was specified
// Act/Assert: Modify the field // Act/Assert: Modify the field
@ -251,7 +248,7 @@ namespace Microsoft.AspNetCore.Components.Forms
var fieldIdentifier = FieldIdentifier.Create(() => model.StringProperty); var fieldIdentifier = FieldIdentifier.Create(() => model.StringProperty);
// Act/Assert // Act/Assert
var inputComponent = await RenderAndGetTestInputComponentAsync(rootComponent); var inputComponent = await InputRenderer.RenderAndGetComponent(rootComponent);
Assert.Equal("my-class other-class valid", inputComponent.CssClass); Assert.Equal("my-class other-class valid", inputComponent.CssClass);
// Act/Assert: Retains custom class when changing field class // Act/Assert: Retains custom class when changing field class
@ -270,7 +267,7 @@ namespace Microsoft.AspNetCore.Components.Forms
Value = new DateTime(1915, 3, 2), Value = new DateTime(1915, 3, 2),
ValueExpression = () => model.DateProperty ValueExpression = () => model.DateProperty
}; };
var inputComponent = await RenderAndGetTestInputComponentAsync(rootComponent); var inputComponent = await InputRenderer.RenderAndGetComponent(rootComponent);
// Act/Assert // Act/Assert
Assert.Equal("1915/03/02", inputComponent.CurrentValueAsString); Assert.Equal("1915/03/02", inputComponent.CurrentValueAsString);
@ -289,7 +286,7 @@ namespace Microsoft.AspNetCore.Components.Forms
ValueExpression = () => model.DateProperty ValueExpression = () => model.DateProperty
}; };
var fieldIdentifier = FieldIdentifier.Create(() => model.DateProperty); var fieldIdentifier = FieldIdentifier.Create(() => model.DateProperty);
var inputComponent = await RenderAndGetTestInputComponentAsync(rootComponent); var inputComponent = await InputRenderer.RenderAndGetComponent(rootComponent);
var numValidationStateChanges = 0; var numValidationStateChanges = 0;
rootComponent.EditContext.OnValidationStateChanged += (sender, eventArgs) => { numValidationStateChanges++; }; rootComponent.EditContext.OnValidationStateChanged += (sender, eventArgs) => { numValidationStateChanges++; };
@ -319,7 +316,7 @@ namespace Microsoft.AspNetCore.Components.Forms
ValueExpression = () => model.DateProperty ValueExpression = () => model.DateProperty
}; };
var fieldIdentifier = FieldIdentifier.Create(() => model.DateProperty); var fieldIdentifier = FieldIdentifier.Create(() => model.DateProperty);
var inputComponent = await RenderAndGetTestInputComponentAsync(rootComponent); var inputComponent = await InputRenderer.RenderAndGetComponent(rootComponent);
var numValidationStateChanges = 0; var numValidationStateChanges = 0;
rootComponent.EditContext.OnValidationStateChanged += (sender, eventArgs) => { numValidationStateChanges++; }; rootComponent.EditContext.OnValidationStateChanged += (sender, eventArgs) => { numValidationStateChanges++; };
@ -470,21 +467,6 @@ namespace Microsoft.AspNetCore.Components.Forms
Assert.Equal("userSpecifiedValue", component.AdditionalAttributes["aria-invalid"]); 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 class TestModel
{ {
public string StringProperty { get; set; } 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) protected override string FormatValueAsString(DateTime value)
=> value.ToString("yyyy/MM/dd"); => 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();
}
}
} }
} }

View File

@ -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; });
}
}
}
}

View File

@ -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; });
}
}
}
}

View File

@ -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();
}
}

View File

@ -2,12 +2,8 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System; using System;
using System.Linq; using System.Collections.Generic;
using System.Linq.Expressions;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Components.Rendering;
using Microsoft.AspNetCore.Components.RenderTree;
using Microsoft.AspNetCore.Components.Test.Helpers;
using Xunit; using Xunit;
namespace Microsoft.AspNetCore.Components.Forms namespace Microsoft.AspNetCore.Components.Forms
@ -19,12 +15,12 @@ namespace Microsoft.AspNetCore.Components.Forms
{ {
// Arrange // Arrange
var model = new TestModel(); var model = new TestModel();
var rootComponent = new TestInputSelectHostComponent<TestEnum> var rootComponent = new TestInputHostComponent<TestEnum, TestInputSelect<TestEnum>>
{ {
EditContext = new EditContext(model), EditContext = new EditContext(model),
ValueExpression = () => model.NotNullableEnum ValueExpression = () => model.NotNullableEnum
}; };
var inputSelectComponent = await RenderAndGetTestInputComponentAsync(rootComponent); var inputSelectComponent = await InputRenderer.RenderAndGetComponent(rootComponent);
// Act // Act
inputSelectComponent.CurrentValueAsString = "Two"; inputSelectComponent.CurrentValueAsString = "Two";
@ -38,12 +34,12 @@ namespace Microsoft.AspNetCore.Components.Forms
{ {
// Arrange // Arrange
var model = new TestModel(); var model = new TestModel();
var rootComponent = new TestInputSelectHostComponent<TestEnum> var rootComponent = new TestInputHostComponent<TestEnum, TestInputSelect<TestEnum>>
{ {
EditContext = new EditContext(model), EditContext = new EditContext(model),
ValueExpression = () => model.NotNullableEnum ValueExpression = () => model.NotNullableEnum
}; };
var inputSelectComponent = await RenderAndGetTestInputComponentAsync(rootComponent); var inputSelectComponent = await InputRenderer.RenderAndGetComponent(rootComponent);
// Act // Act
inputSelectComponent.CurrentValueAsString = ""; inputSelectComponent.CurrentValueAsString = "";
@ -57,12 +53,12 @@ namespace Microsoft.AspNetCore.Components.Forms
{ {
// Arrange // Arrange
var model = new TestModel(); var model = new TestModel();
var rootComponent = new TestInputSelectHostComponent<TestEnum?> var rootComponent = new TestInputHostComponent<TestEnum?, TestInputSelect<TestEnum?>>
{ {
EditContext = new EditContext(model), EditContext = new EditContext(model),
ValueExpression = () => model.NullableEnum ValueExpression = () => model.NullableEnum
}; };
var inputSelectComponent = await RenderAndGetTestInputComponentAsync(rootComponent); var inputSelectComponent = await InputRenderer.RenderAndGetComponent(rootComponent);
// Act // Act
inputSelectComponent.CurrentValueAsString = "Two"; inputSelectComponent.CurrentValueAsString = "Two";
@ -76,12 +72,12 @@ namespace Microsoft.AspNetCore.Components.Forms
{ {
// Arrange // Arrange
var model = new TestModel(); var model = new TestModel();
var rootComponent = new TestInputSelectHostComponent<TestEnum?> var rootComponent = new TestInputHostComponent<TestEnum?, TestInputSelect<TestEnum?>>
{ {
EditContext = new EditContext(model), EditContext = new EditContext(model),
ValueExpression = () => model.NullableEnum ValueExpression = () => model.NullableEnum
}; };
var inputSelectComponent = await RenderAndGetTestInputComponentAsync(rootComponent); var inputSelectComponent = await InputRenderer.RenderAndGetComponent(rootComponent);
// Act // Act
inputSelectComponent.CurrentValueAsString = ""; inputSelectComponent.CurrentValueAsString = "";
@ -96,12 +92,12 @@ namespace Microsoft.AspNetCore.Components.Forms
{ {
// Arrange // Arrange
var model = new TestModel(); var model = new TestModel();
var rootComponent = new TestInputSelectHostComponent<Guid> var rootComponent = new TestInputHostComponent<Guid, TestInputSelect<Guid>>
{ {
EditContext = new EditContext(model), EditContext = new EditContext(model),
ValueExpression = () => model.NotNullableGuid ValueExpression = () => model.NotNullableGuid
}; };
var inputSelectComponent = await RenderAndGetTestInputComponentAsync(rootComponent); var inputSelectComponent = await InputRenderer.RenderAndGetComponent(rootComponent);
// Act // Act
var guid = Guid.NewGuid(); var guid = Guid.NewGuid();
@ -117,12 +113,12 @@ namespace Microsoft.AspNetCore.Components.Forms
{ {
// Arrange // Arrange
var model = new TestModel(); var model = new TestModel();
var rootComponent = new TestInputSelectHostComponent<Guid?> var rootComponent = new TestInputHostComponent<Guid?, TestInputSelect<Guid?>>
{ {
EditContext = new EditContext(model), EditContext = new EditContext(model),
ValueExpression = () => model.NullableGuid ValueExpression = () => model.NullableGuid
}; };
var inputSelectComponent = await RenderAndGetTestInputComponentAsync(rootComponent); var inputSelectComponent = await InputRenderer.RenderAndGetComponent(rootComponent);
// Act // Act
var guid = Guid.NewGuid(); var guid = Guid.NewGuid();
@ -138,12 +134,12 @@ namespace Microsoft.AspNetCore.Components.Forms
{ {
// Arrange // Arrange
var model = new TestModel(); var model = new TestModel();
var rootComponent = new TestInputSelectHostComponent<int> var rootComponent = new TestInputHostComponent<int, TestInputSelect<int>>
{ {
EditContext = new EditContext(model), EditContext = new EditContext(model),
ValueExpression = () => model.NotNullableInt ValueExpression = () => model.NotNullableInt
}; };
var inputSelectComponent = await RenderAndGetTestInputComponentAsync(rootComponent); var inputSelectComponent = await InputRenderer.RenderAndGetComponent(rootComponent);
// Act // Act
inputSelectComponent.CurrentValueAsString = "42"; inputSelectComponent.CurrentValueAsString = "42";
@ -158,12 +154,12 @@ namespace Microsoft.AspNetCore.Components.Forms
{ {
// Arrange // Arrange
var model = new TestModel(); var model = new TestModel();
var rootComponent = new TestInputSelectHostComponent<int?> var rootComponent = new TestInputHostComponent<int?, TestInputSelect<int?>>
{ {
EditContext = new EditContext(model), EditContext = new EditContext(model),
ValueExpression = () => model.NullableInt ValueExpression = () => model.NullableInt
}; };
var inputSelectComponent = await RenderAndGetTestInputComponentAsync(rootComponent); var inputSelectComponent = await InputRenderer.RenderAndGetComponent(rootComponent);
// Act // Act
inputSelectComponent.CurrentValueAsString = "42"; inputSelectComponent.CurrentValueAsString = "42";
@ -172,19 +168,30 @@ namespace Microsoft.AspNetCore.Components.Forms
Assert.Equal(42, inputSelectComponent.CurrentValue); Assert.Equal(42, inputSelectComponent.CurrentValue);
} }
private static TestInputSelect<TValue> FindInputSelectComponent<TValue>(CapturedBatch batch) [Fact]
=> batch.ReferenceFrames public async Task ValidationErrorUsesDisplayAttributeName()
.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)
{ {
var testRenderer = new TestRenderer(); // Arrange
var componentId = testRenderer.AssignRootComponentId(hostComponent); var model = new TestModel();
await testRenderer.RenderRootComponentAsync(componentId); var rootComponent = new TestInputHostComponent<int, TestInputSelect<int>>
return FindInputSelectComponent<TValue>(testRenderer.Batches.Single()); {
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 enum TestEnum
@ -218,25 +225,13 @@ namespace Microsoft.AspNetCore.Components.Forms
get => base.CurrentValueAsString; get => base.CurrentValueAsString;
set => base.CurrentValueAsString = value; set => base.CurrentValueAsString = value;
} }
} public async Task SetCurrentValueAsStringAsync(string value)
class TestInputSelectHostComponent<TValue> : AutoRenderComponent
{
public EditContext EditContext { get; set; }
public Expression<Func<TValue>> ValueExpression { get; set; }
protected override void BuildRenderTree(RenderTreeBuilder builder)
{ {
builder.OpenComponent<CascadingValue<EditContext>>(0); // This is equivalent to the subclass writing to CurrentValueAsString
builder.AddAttribute(1, "Value", EditContext); // (e.g., from @bind), except to simplify the test code there's an InvokeAsync
builder.AddAttribute(2, "ChildContent", new RenderFragment(childBuilder => // here. In production code it wouldn't normally be required because @bind
{ // calls run on the sync context anyway.
childBuilder.OpenComponent<TestInputSelect<TValue>>(0); await InvokeAsync(() => { base.CurrentValueAsString = value; });
childBuilder.AddAttribute(0, "ValueExpression", ValueExpression);
childBuilder.CloseComponent();
}));
builder.CloseComponent();
} }
} }
} }

View File

@ -0,0 +1,41 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using Microsoft.AspNetCore.Components.Rendering;
using Microsoft.AspNetCore.Components.Test.Helpers;
namespace Microsoft.AspNetCore.Components.Forms
{
internal class TestInputHostComponent<TValue, TComponent> : AutoRenderComponent where TComponent : InputBase<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();
}
}
}

View File

@ -44,6 +44,15 @@ namespace Microsoft.AspNetCore.Components.E2ETest.ServerExecutionTests
Browser.Equal("1", () => Browser.FindElement(By.Id("count")).Text); Browser.Equal("1", () => Browser.FindElement(By.Id("count")).Text);
} }
[Fact]
public void PrerenderingWaitsForAsyncDisposableComponents()
{
Navigate("/prerendered/prerendered-async-disposal");
// Prerendered output shows "not connected"
Browser.Equal("After async disposal", () => Browser.FindElement(By.Id("disposal-message")).Text);
}
[Fact] [Fact]
public void CanUseJSInteropFromOnAfterRenderAsync() public void CanUseJSInteropFromOnAfterRenderAsync()
{ {

View File

@ -216,6 +216,10 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Tests
Browser.Equal("Fourth", () => boundValue.Text); Browser.Equal("Fourth", () => boundValue.Text);
Assert.Equal("Fourth choice", target.SelectedOption.Text); Assert.Equal("Fourth choice", target.SelectedOption.Text);
// verify that changing an option value and selected value at the same time works.
Browser.FindElement(By.Id("change-variable-value")).Click();
Browser.Equal("Sixth", () => boundValue.Text);
// Verify we can select options whose value is empty // Verify we can select options whose value is empty
// https://github.com/dotnet/aspnetcore/issues/17735 // https://github.com/dotnet/aspnetcore/issues/17735
target.SelectByText("Empty value"); target.SelectByText("Empty value");

View File

@ -115,6 +115,24 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Tests
Browser.Equal("onmousedown,onmouseup,", () => output.Text); Browser.Equal("onmousedown,onmouseup,", () => output.Text);
} }
[Fact]
public void Toggle_CanTrigger()
{
Browser.MountTestComponent<ToggleEventComponent>();
var detailsToggle = Browser.FindElement(By.Id("details-toggle"));
var output = Browser.FindElement(By.Id("output"));
Assert.Equal(string.Empty, output.Text);
// Click
var actions = new Actions(Browser).Click(detailsToggle);
actions.Perform();
Browser.Equal("ontoggle,", () => output.Text);
}
[Fact] [Fact]
public void PointerDown_CanTrigger() public void PointerDown_CanTrigger()
{ {
@ -270,6 +288,17 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Tests
Browser.Contains(expectedMessage, () => errorLog.Text); Browser.Contains(expectedMessage, () => errorLog.Text);
} }
[Fact]
public void RenderAttributesBeforeConnectedCallBack()
{
Browser.MountTestComponent<RenderAttributesBeforeConnectedCallback>();
var element = Browser.FindElement(By.TagName("custom-web-component-data-from-attribute"));
var expectedContent = "success";
Browser.Contains(expectedContent, () => element.Text);
}
void SendKeysSequentially(IWebElement target, string text) void SendKeysSequentially(IWebElement target, string text)
{ {
// Calling it for each character works around some chars being skipped // Calling it for each character works around some chars being skipped

View File

@ -109,6 +109,17 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Tests
Assert.Equal(expected, app.FindElement(By.Id("test-info")).Text); Assert.Equal(expected, app.FindElement(By.Id("test-info")).Text);
} }
[Fact]
public void CanArriveAtPageWithCatchAllParameter()
{
SetUrlViaPushState("/WithCatchAllParameter/life/the/universe/and/everything%20%3D%2042");
var app = Browser.MountTestComponent<TestRouter>();
var expected = $"The answer: life/the/universe/and/everything = 42.";
Assert.Equal(expected, app.FindElement(By.Id("test-info")).Text);
}
[Fact] [Fact]
public void CanArriveAtNonDefaultPage() public void CanArriveAtNonDefaultPage()
{ {

View File

@ -0,0 +1,11 @@
@implements IAsyncDisposable
@code{
[Parameter] public EventCallback<string> SetMessage { get; set; }
public async ValueTask DisposeAsync()
{
await SetMessage.InvokeAsync("Before async disposal");
await Task.Yield();
await SetMessage.InvokeAsync("After async disposal");
}
}

View File

@ -0,0 +1,25 @@
@page "/prerendered-async-disposal"
<p>
This component shows that prerendering will work for components that implement IAsyncDisposable to finish
disposing before rendering the output as html.
</p>
<p id="disposal-message">@_message</p>
@if (!_hideComponent)
{
<AsyncDisposableComponent SetMessage="@SetMessage" />
}
@code {
private bool _hideComponent = false;
private string _message = "Uninitialized";
protected override async Task OnInitializedAsync()
{
await Task.Yield();
_hideComponent = true;
}
private void SetMessage(string message) => _message = message;
}

View File

@ -242,6 +242,7 @@
<optgroup label="Some choices"> <optgroup label="Some choices">
<!-- Show it also works with optgroup --> <!-- Show it also works with optgroup -->
<option value=@string.Empty>Empty value</option> <option value=@string.Empty>Empty value</option>
<option value="@variableValue">Variable value</option>
<option value=@SelectableValue.First>First choice</option> <option value=@SelectableValue.First>First choice</option>
<option value=@SelectableValue.Second>Second choice</option> <option value=@SelectableValue.Second>Second choice</option>
<option value=@SelectableValue.Third>Third choice</option> <option value=@SelectableValue.Third>Third choice</option>
@ -253,6 +254,7 @@
</select> </select>
<span id="select-box-value">@selectValue</span> <span id="select-box-value">@selectValue</span>
<button id="select-box-add-option" @onclick="AddAndSelectNewSelectOption">Add and select new item</button> <button id="select-box-add-option" @onclick="AddAndSelectNewSelectOption">Add and select new item</button>
<button id="change-variable-value" @onclick="ChangeVariableValueToSixth">Change variable value to Sixth.</button>
</p> </p>
<h2>Select (markup block)</h2> <h2>Select (markup block)</h2>
@ -383,13 +385,21 @@
DateTime? timeStepTextboxNullableDateTimeValue = null; DateTime? timeStepTextboxNullableDateTimeValue = null;
bool includeFourthOption = false; bool includeFourthOption = false;
enum SelectableValue { First, Second, Third, Fourth } enum SelectableValue { First, Second, Third, Fourth, Fifth, Sixth }
SelectableValue? selectValue = SelectableValue.Second; SelectableValue? selectValue = SelectableValue.Second;
SelectableValue? selectMarkupValue = SelectableValue.Second; SelectableValue? selectMarkupValue = SelectableValue.Second;
SelectableValue variableValue = SelectableValue.Fifth;
void AddAndSelectNewSelectOption() void AddAndSelectNewSelectOption()
{ {
includeFourthOption = true; includeFourthOption = true;
selectValue = SelectableValue.Fourth; selectValue = SelectableValue.Fourth;
} }
void ChangeVariableValueToSixth()
{
selectValue = SelectableValue.Sixth;
variableValue = SelectableValue.Sixth;
}
} }

View File

@ -70,6 +70,7 @@
<option value="BasicTestApp.RedTextComponent">Red text</option> <option value="BasicTestApp.RedTextComponent">Red text</option>
<option value="BasicTestApp.ReliabilityComponent">Server reliability component</option> <option value="BasicTestApp.ReliabilityComponent">Server reliability component</option>
<option value="BasicTestApp.RenderFragmentToggler">Render fragment renderer</option> <option value="BasicTestApp.RenderFragmentToggler">Render fragment renderer</option>
<option value="BasicTestApp.RenderAttributesBeforeConnectedCallback">Render attributes before ConnectedCallback</option>
<option value="BasicTestApp.ReorderingFocusComponent">Reordering focus retention</option> <option value="BasicTestApp.ReorderingFocusComponent">Reordering focus retention</option>
<option value="BasicTestApp.RouterTest.NavigationManagerComponent">NavigationManager Test</option> <option value="BasicTestApp.RouterTest.NavigationManagerComponent">NavigationManager Test</option>
<option value="BasicTestApp.RouterTest.TestRouter">Router</option> <option value="BasicTestApp.RouterTest.TestRouter">Router</option>
@ -82,6 +83,7 @@
<option value="BasicTestApp.TextOnlyComponent">Plain text</option> <option value="BasicTestApp.TextOnlyComponent">Plain text</option>
<option value="BasicTestApp.TouchEventComponent">Touch events</option> <option value="BasicTestApp.TouchEventComponent">Touch events</option>
<option value="BasicTestApp.SelectVariantsComponent">Select with component options</option> <option value="BasicTestApp.SelectVariantsComponent">Select with component options</option>
<option value="BasicTestApp.ToggleEventComponent">Toggle Event</option>
</select> </select>
<span id="runtime-info"><code><tt>@System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription</tt></code></span> <span id="runtime-info"><code><tt>@System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription</tt></code></span>

View File

@ -0,0 +1,14 @@
<h1>Render Attributes Before connectedCallback</h1>
<p>
When the connectedcallback event fires, it's nice to have the attributes of the HTML element set already,
as data is usually passed to the component using custom attributes.
</p>
<custom-web-component-data-from-attribute myattribute="@attributeString"></custom-web-component-data-from-attribute>
@code {
string attributeString = "success";
}

View File

@ -0,0 +1,7 @@
@page "/WithCatchAllParameter/{*theAnswer}"
<div id="test-info">The answer: @TheAnswer.</div>
@code
{
[Parameter] public string TheAnswer { get; set; }
}

View File

@ -0,0 +1,25 @@
<div>
<p>
Output: <span id="output">@message</span>
</p>
<p>Open the details.</p>
<details id="details-toggle" @ontoggle="OnToggle">
<summary>Summary</summary>
<p></p>
<p>Detailed content</p>
</details>
</div>
@code {
string message { get; set; }
void OnToggle(EventArgs e)
{
message += "ontoggle,";
StateHasChanged();
}
}

View File

@ -23,6 +23,7 @@
<!-- Used for specific test cases --> <!-- Used for specific test cases -->
<script src="js/jsinteroptests.js"></script> <script src="js/jsinteroptests.js"></script>
<script src="js/renderattributestest.js"></script>
<script src="js/webComponentPerformingJsInterop.js"></script> <script src="js/webComponentPerformingJsInterop.js"></script>
<script> <script>

View File

@ -0,0 +1,9 @@
// This web component is used from the RenderAttributesBeforeConnectedCallback test case
window.customElements.define('custom-web-component-data-from-attribute', class extends HTMLElement {
connectedCallback() {
let myattribute = this.getAttribute('myattribute') || 'failed';
this.innerHTML = myattribute;
}
});

View File

@ -16,6 +16,7 @@
<!-- Used for specific test cases --> <!-- Used for specific test cases -->
<script src="js/jsinteroptests.js"></script> <script src="js/jsinteroptests.js"></script>
<script src="js/renderattributestest.js"></script>
<script src="js/webComponentPerformingJsInterop.js"></script> <script src="js/webComponentPerformingJsInterop.js"></script>
<div id="blazor-error-ui"> <div id="blazor-error-ui">

View File

@ -71,7 +71,9 @@ namespace Microsoft.AspNetCore.Cryptography
} }
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
#if NETSTANDARD2_0
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
#endif
public static bool TimeConstantBuffersAreEqual(byte* bufA, byte* bufB, uint count) public static bool TimeConstantBuffersAreEqual(byte* bufA, byte* bufB, uint count)
{ {
bool areEqual = true; bool areEqual = true;

View File

@ -141,7 +141,9 @@ namespace Microsoft.AspNetCore.Cryptography.SafeHandles
// http://msdn.microsoft.com/en-us/library/ms683152(v=vs.85).aspx // http://msdn.microsoft.com/en-us/library/ms683152(v=vs.85).aspx
[return: MarshalAs(UnmanagedType.Bool)] [return: MarshalAs(UnmanagedType.Bool)]
#if NETSTANDARD2_0
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
#endif
[DllImport("kernel32.dll", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Unicode)] [DllImport("kernel32.dll", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Unicode)]
internal static extern bool FreeLibrary(IntPtr hModule); internal static extern bool FreeLibrary(IntPtr hModule);

View File

@ -38,7 +38,9 @@ namespace Microsoft.AspNetCore.Cryptography.SafeHandles
return newHandle; return newHandle;
} }
#if NETSTANDARD2_0
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
#endif
private void AllocateImpl(IntPtr cb) private void AllocateImpl(IntPtr cb)
{ {
handle = Marshal.AllocHGlobal(cb); // actually calls LocalAlloc handle = Marshal.AllocHGlobal(cb); // actually calls LocalAlloc

View File

@ -12,14 +12,18 @@ namespace Microsoft.AspNetCore.Cryptography
internal unsafe static class UnsafeBufferUtil internal unsafe static class UnsafeBufferUtil
{ {
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
#if NETSTANDARD2_0
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
#endif
public static void BlockCopy(void* from, void* to, int byteCount) public static void BlockCopy(void* from, void* to, int byteCount)
{ {
BlockCopy(from, to, checked((uint)byteCount)); // will be checked before invoking the delegate BlockCopy(from, to, checked((uint)byteCount)); // will be checked before invoking the delegate
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
#if NETSTANDARD2_0
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
#endif
public static void BlockCopy(void* from, void* to, uint byteCount) public static void BlockCopy(void* from, void* to, uint byteCount)
{ {
if (byteCount != 0) if (byteCount != 0)
@ -28,7 +32,9 @@ namespace Microsoft.AspNetCore.Cryptography
} }
} }
#if NETSTANDARD2_0
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
#endif
public static void BlockCopy(LocalAllocHandle from, void* to, uint byteCount) public static void BlockCopy(LocalAllocHandle from, void* to, uint byteCount)
{ {
bool refAdded = false; bool refAdded = false;
@ -46,7 +52,9 @@ namespace Microsoft.AspNetCore.Cryptography
} }
} }
#if NETSTANDARD2_0
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
#endif
public static void BlockCopy(void* from, LocalAllocHandle to, uint byteCount) public static void BlockCopy(void* from, LocalAllocHandle to, uint byteCount)
{ {
bool refAdded = false; bool refAdded = false;
@ -64,7 +72,9 @@ namespace Microsoft.AspNetCore.Cryptography
} }
} }
#if NETSTANDARD2_0
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
#endif
public static void BlockCopy(LocalAllocHandle from, LocalAllocHandle to, IntPtr length) public static void BlockCopy(LocalAllocHandle from, LocalAllocHandle to, IntPtr length)
{ {
if (length == IntPtr.Zero) if (length == IntPtr.Zero)
@ -116,7 +126,9 @@ namespace Microsoft.AspNetCore.Cryptography
/// Securely clears a memory buffer. /// Securely clears a memory buffer.
/// </summary> /// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
#if NETSTANDARD2_0
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
#endif
public static void SecureZeroMemory(byte* buffer, int byteCount) public static void SecureZeroMemory(byte* buffer, int byteCount)
{ {
SecureZeroMemory(buffer, checked((uint)byteCount)); SecureZeroMemory(buffer, checked((uint)byteCount));
@ -126,7 +138,9 @@ namespace Microsoft.AspNetCore.Cryptography
/// Securely clears a memory buffer. /// Securely clears a memory buffer.
/// </summary> /// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
#if NETSTANDARD2_0
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
#endif
public static void SecureZeroMemory(byte* buffer, uint byteCount) public static void SecureZeroMemory(byte* buffer, uint byteCount)
{ {
if (byteCount != 0) if (byteCount != 0)
@ -145,7 +159,9 @@ namespace Microsoft.AspNetCore.Cryptography
/// Securely clears a memory buffer. /// Securely clears a memory buffer.
/// </summary> /// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
#if NETSTANDARD2_0
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
#endif
public static void SecureZeroMemory(byte* buffer, ulong byteCount) public static void SecureZeroMemory(byte* buffer, ulong byteCount)
{ {
if (byteCount != 0) if (byteCount != 0)
@ -163,7 +179,9 @@ namespace Microsoft.AspNetCore.Cryptography
/// <summary> /// <summary>
/// Securely clears a memory buffer. /// Securely clears a memory buffer.
/// </summary> /// </summary>
#if NETSTANDARD2_0
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
#endif
public static void SecureZeroMemory(byte* buffer, IntPtr length) public static void SecureZeroMemory(byte* buffer, IntPtr length)
{ {
if (sizeof(IntPtr) == 4) if (sizeof(IntPtr) == 4)

View File

@ -82,13 +82,17 @@ namespace Microsoft.AspNetCore.Cryptography
[In] uint dwFlags); [In] uint dwFlags);
[DllImport(BCRYPT_LIB, CallingConvention = CallingConvention.Winapi)] [DllImport(BCRYPT_LIB, CallingConvention = CallingConvention.Winapi)]
#if NETSTANDARD2_0
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
#endif
// http://msdn.microsoft.com/en-us/library/windows/desktop/aa375399(v=vs.85).aspx // http://msdn.microsoft.com/en-us/library/windows/desktop/aa375399(v=vs.85).aspx
internal static extern int BCryptDestroyHash( internal static extern int BCryptDestroyHash(
[In] IntPtr hHash); [In] IntPtr hHash);
[DllImport(BCRYPT_LIB, CallingConvention = CallingConvention.Winapi)] [DllImport(BCRYPT_LIB, CallingConvention = CallingConvention.Winapi)]
#if NETSTANDARD2_0
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
#endif
// http://msdn.microsoft.com/en-us/library/windows/desktop/aa375404(v=vs.85).aspx // http://msdn.microsoft.com/en-us/library/windows/desktop/aa375404(v=vs.85).aspx
internal static extern int BCryptDestroyKey( internal static extern int BCryptDestroyKey(
[In] IntPtr hKey); [In] IntPtr hKey);
@ -240,7 +244,9 @@ namespace Microsoft.AspNetCore.Cryptography
*/ */
[DllImport(NCRYPT_LIB, CallingConvention = CallingConvention.Winapi)] [DllImport(NCRYPT_LIB, CallingConvention = CallingConvention.Winapi)]
#if NETSTANDARD2_0
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
#endif
// http://msdn.microsoft.com/en-us/library/windows/desktop/hh706799(v=vs.85).aspx // http://msdn.microsoft.com/en-us/library/windows/desktop/hh706799(v=vs.85).aspx
internal static extern int NCryptCloseProtectionDescriptor( internal static extern int NCryptCloseProtectionDescriptor(
[In] IntPtr hDescriptor); [In] IntPtr hDescriptor);

View File

@ -78,7 +78,9 @@ namespace Microsoft.AspNetCore.DataProtection.Cng
}; };
var dataOut = default(DATA_BLOB); var dataOut = default(DATA_BLOB);
#if NETSTANDARD2_0
RuntimeHelpers.PrepareConstrainedRegions(); RuntimeHelpers.PrepareConstrainedRegions();
#endif
try try
{ {
@ -168,7 +170,9 @@ namespace Microsoft.AspNetCore.DataProtection.Cng
{ {
var handleAcquired = false; var handleAcquired = false;
#if NETSTANDARD2_0
RuntimeHelpers.PrepareConstrainedRegions(); RuntimeHelpers.PrepareConstrainedRegions();
#endif
try try
{ {
@ -217,7 +221,9 @@ namespace Microsoft.AspNetCore.DataProtection.Cng
}; };
var dataOut = default(DATA_BLOB); var dataOut = default(DATA_BLOB);
#if NETSTANDARD2_0
RuntimeHelpers.PrepareConstrainedRegions(); RuntimeHelpers.PrepareConstrainedRegions();
#endif
try try
{ {
@ -290,7 +296,9 @@ namespace Microsoft.AspNetCore.DataProtection.Cng
{ {
var handleAcquired = false; var handleAcquired = false;
#if NETSTANDARD2_0
RuntimeHelpers.PrepareConstrainedRegions(); RuntimeHelpers.PrepareConstrainedRegions();
#endif
try try
{ {

View File

@ -3,6 +3,9 @@
<PropertyGroup> <PropertyGroup>
<ContainsFunctionalTestAssets>true</ContainsFunctionalTestAssets> <ContainsFunctionalTestAssets>true</ContainsFunctionalTestAssets>
<TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework> <TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework>
<!-- https://github.com/dotnet/aspnetcore/issues/24182 -->
<BuildHelixPayload>false</BuildHelixPayload>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@ -97,7 +97,7 @@ namespace InteropTestsClient
services.AddLogging(configure => services.AddLogging(configure =>
{ {
configure.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace); configure.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace);
configure.AddConsole(loggerOptions => configure.AddSimpleConsole(loggerOptions =>
{ {
loggerOptions.IncludeScopes = true; loggerOptions.IncludeScopes = true;
loggerOptions.DisableColors = true; loggerOptions.DisableColors = true;

View File

@ -37,7 +37,7 @@ namespace InteropTestsWebsite
Host.CreateDefaultBuilder(args) Host.CreateDefaultBuilder(args)
.ConfigureLogging(builder => .ConfigureLogging(builder =>
{ {
builder.AddConsole(o => o.DisableColors = true); builder.AddSimpleConsole(o => o.DisableColors = true);
builder.SetMinimumLevel(LogLevel.Trace); builder.SetMinimumLevel(LogLevel.Trace);
}) })
.ConfigureWebHostDefaults(webBuilder => .ConfigureWebHostDefaults(webBuilder =>

View File

@ -27,7 +27,8 @@
"src\\Servers\\Kestrel\\Kestrel\\src\\Microsoft.AspNetCore.Server.Kestrel.csproj", "src\\Servers\\Kestrel\\Kestrel\\src\\Microsoft.AspNetCore.Server.Kestrel.csproj",
"src\\Servers\\Kestrel\\Core\\src\\Microsoft.AspNetCore.Server.Kestrel.Core.csproj", "src\\Servers\\Kestrel\\Core\\src\\Microsoft.AspNetCore.Server.Kestrel.Core.csproj",
"src\\Servers\\Kestrel\\Transport.Sockets\\src\\Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.csproj", "src\\Servers\\Kestrel\\Transport.Sockets\\src\\Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.csproj",
"src\\Servers\\Connections.Abstractions\\src\\Microsoft.AspNetCore.Connections.Abstractions.csproj" "src\\Servers\\Connections.Abstractions\\src\\Microsoft.AspNetCore.Connections.Abstractions.csproj",
"src\\ObjectPool\\src\\Microsoft.Extensions.ObjectPool.csproj"
] ]
} }
} }

View File

@ -14,7 +14,6 @@ using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.ObjectPool;
namespace Microsoft.AspNetCore.Hosting namespace Microsoft.AspNetCore.Hosting
{ {

View File

@ -15,7 +15,6 @@ using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.ObjectPool;
namespace Microsoft.AspNetCore.Hosting namespace Microsoft.AspNetCore.Hosting
{ {

View File

@ -19,9 +19,10 @@ namespace Microsoft.AspNetCore.Hosting
/// <param name="timeout">The timeout for stopping gracefully. Once expired the /// <param name="timeout">The timeout for stopping gracefully. Once expired the
/// server may terminate any remaining active connections.</param> /// server may terminate any remaining active connections.</param>
/// <returns>A <see cref="Task"/> that completes when the <see cref="IWebHost"/> stops.</returns> /// <returns>A <see cref="Task"/> that completes when the <see cref="IWebHost"/> stops.</returns>
public static Task StopAsync(this IWebHost host, TimeSpan timeout) public static async Task StopAsync(this IWebHost host, TimeSpan timeout)
{ {
return host.StopAsync(new CancellationTokenSource(timeout).Token); using var cts = new CancellationTokenSource(timeout);
await host.StopAsync(cts.Token);
} }
/// <summary> /// <summary>

View File

@ -21,7 +21,6 @@ using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Logging.Testing; using Microsoft.Extensions.Logging.Testing;
using Microsoft.Extensions.ObjectPool;
using Xunit; using Xunit;
[assembly: HostingStartup(typeof(WebHostBuilderTests.TestHostingStartup))] [assembly: HostingStartup(typeof(WebHostBuilderTests.TestHostingStartup))]

View File

@ -198,7 +198,6 @@ namespace Microsoft.AspNetCore.Hosting
} }
[ConditionalFact] [ConditionalFact]
[QuarantinedTest]
public async Task WebHostStopAsyncUsesDefaultTimeoutIfGivenTokenDoesNotFire() public async Task WebHostStopAsyncUsesDefaultTimeoutIfGivenTokenDoesNotFire()
{ {
var data = new Dictionary<string, string> var data = new Dictionary<string, string>
@ -313,7 +312,6 @@ namespace Microsoft.AspNetCore.Hosting
} }
[ConditionalFact] [ConditionalFact]
[QuarantinedTest]
public void WebHostApplicationLifetimeEventsOrderedCorrectlyDuringShutdown() public void WebHostApplicationLifetimeEventsOrderedCorrectlyDuringShutdown()
{ {
using (var host = CreateBuilder() using (var host = CreateBuilder()

View File

@ -80,9 +80,9 @@ namespace Microsoft.AspNetCore.Http
{ Encoding.BigEndianUnicode }, { Encoding.BigEndianUnicode },
{ Encoding.Unicode }, { Encoding.Unicode },
{ Encoding.UTF32 }, { Encoding.UTF32 },
#pragma warning disable CS0618, MSLIB0001 // Type or member is obsolete #pragma warning disable CS0618, SYSLIB0001 // Type or member is obsolete
{ Encoding.UTF7 }, { Encoding.UTF7 },
#pragma warning restore CS0618, MSLIB0001 // Type or member is obsolete #pragma warning restore CS0618, SYSLIB0001 // Type or member is obsolete
{ Encoding.UTF8 } { Encoding.UTF8 }
}; };

View File

@ -276,9 +276,9 @@ namespace Microsoft.AspNetCore.Http.Features
private static Encoding FilterEncoding(Encoding? encoding) private static Encoding FilterEncoding(Encoding? encoding)
{ {
// UTF-7 is insecure and should not be honored. UTF-8 will succeed for most cases. // UTF-7 is insecure and should not be honored. UTF-8 will succeed for most cases.
#pragma warning disable CS0618, MSLIB0001 // Type or member is obsolete #pragma warning disable CS0618, SYSLIB0001 // Type or member is obsolete
if (encoding == null || Encoding.UTF7.Equals(encoding)) if (encoding == null || Encoding.UTF7.Equals(encoding))
#pragma warning restore CS0618, MSLIB0001 // Type or member is obsolete #pragma warning restore CS0618, SYSLIB0001 // Type or member is obsolete
{ {
return Encoding.UTF8; return Encoding.UTF8;
} }

View File

@ -111,7 +111,7 @@ namespace Microsoft.AspNetCore.Http
} }
/// <summary> /// <summary>
/// This calls StartAsync if it has not previoulsy been called. /// This calls StartAsync if it has not previously been called.
/// It will complete the adapted pipe if it exists. /// It will complete the adapted pipe if it exists.
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
@ -128,6 +128,11 @@ namespace Microsoft.AspNetCore.Http
return; return;
} }
if (!_started)
{
await StartAsync();
}
_completed = true; _completed = true;
if (_pipeWriter != null) if (_pipeWriter != null)

View File

@ -0,0 +1,62 @@
// 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.Buffers;
using System.IO;
using System.IO.Pipelines;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Xunit;
namespace Microsoft.AspNetCore.Http.Features
{
public class StreamResponseBodyFeatureTests
{
[Fact]
public async Task CompleteAsyncCallsStartAsync()
{
// Arrange
var stream = new MemoryStream();
var streamResponseBodyFeature = new TestStreamResponseBodyFeature(stream);
// Act
await streamResponseBodyFeature.CompleteAsync();
//Assert
Assert.Equal(1, streamResponseBodyFeature.StartCalled);
}
[Fact]
public async Task CompleteAsyncWontCallsStartAsyncIfAlreadyStarted()
{
// Arrange
var stream = new MemoryStream();
var streamResponseBodyFeature = new TestStreamResponseBodyFeature(stream);
await streamResponseBodyFeature.StartAsync();
// Act
await streamResponseBodyFeature.CompleteAsync();
//Assert
Assert.Equal(1, streamResponseBodyFeature.StartCalled);
}
}
public class TestStreamResponseBodyFeature : StreamResponseBodyFeature
{
public TestStreamResponseBodyFeature(Stream stream)
: base(stream)
{
}
public override Task StartAsync(CancellationToken cancellationToken = default)
{
StartCalled++;
return base.StartAsync(cancellationToken);
}
public int StartCalled { get; private set; }
}
}

View File

@ -47,10 +47,10 @@ namespace Microsoft.AspNetCore.WebUtilities
public FormPipeReader(PipeReader pipeReader, Encoding encoding) public FormPipeReader(PipeReader pipeReader, Encoding encoding)
{ {
#pragma warning disable CS0618, MSLIB0001 // Type or member is obsolete #pragma warning disable CS0618, SYSLIB0001 // Type or member is obsolete
if (encoding == Encoding.UTF7) if (encoding == Encoding.UTF7)
{ {
#pragma warning restore CS0618, MSLIB0001 // Type or member is obsolete #pragma warning restore CS0618, SYSLIB0001 // Type or member is obsolete
throw new ArgumentException("UTF7 is unsupported and insecure. Please select a different encoding."); throw new ArgumentException("UTF7 is unsupported and insecure. Please select a different encoding.");
} }
@ -271,7 +271,7 @@ namespace Microsoft.AspNetCore.WebUtilities
var keyValueReader = new SequenceReader<byte>(keyValuePair); var keyValueReader = new SequenceReader<byte>(keyValuePair);
ReadOnlySequence<byte> value; ReadOnlySequence<byte> value;
if (keyValueReader.TryReadTo(out var key, equalsDelimiter)) if (keyValueReader.TryReadTo(out ReadOnlySequence<byte> key, equalsDelimiter))
{ {
if (key.Length > KeyLengthLimit) if (key.Length > KeyLengthLimit)
{ {

View File

@ -34,9 +34,9 @@ namespace Microsoft.AspNetCore.WebUtilities
MediaTypeHeaderValue.TryParse(section.ContentType, out var sectionMediaType); MediaTypeHeaderValue.TryParse(section.ContentType, out var sectionMediaType);
var streamEncoding = sectionMediaType?.Encoding; var streamEncoding = sectionMediaType?.Encoding;
#pragma warning disable CS0618, MSLIB0001 // Type or member is obsolete #pragma warning disable CS0618, SYSLIB0001 // Type or member is obsolete
if (streamEncoding == null || streamEncoding == Encoding.UTF7) if (streamEncoding == null || streamEncoding == Encoding.UTF7)
#pragma warning restore CS0618, MSLIB0001 // Type or member is obsolete #pragma warning restore CS0618, SYSLIB0001 // Type or member is obsolete
{ {
streamEncoding = Encoding.UTF8; streamEncoding = Encoding.UTF8;
} }

View File

@ -17,7 +17,7 @@
<button class="btn btn-primary" type="submit">Download</button> <button class="btn btn-primary" type="submit">Download</button>
</form> </form>
<p> <p>
<a id="delete" asp-page="DeletePersonalData" class="btn btn-primary">Delete</a> <a id="delete" asp-page="DeletePersonalData" class="btn btn-secondary">Delete</a>
</p> </p>
</div> </div>
</div> </div>

View File

@ -15,6 +15,7 @@ using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.TestHost; using Microsoft.AspNetCore.TestHost;
using Microsoft.AspNetCore.Testing;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Hosting;
using Xunit; using Xunit;
@ -122,6 +123,7 @@ namespace Microsoft.AspNetCore.Diagnostics
} }
[Fact] [Fact]
[QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/24146")]
public async Task ClearsResponseBuffer_BeforeRequestIsReexecuted() public async Task ClearsResponseBuffer_BeforeRequestIsReexecuted()
{ {
var expectedResponseBody = "New response body"; var expectedResponseBody = "New response body";

View File

@ -132,6 +132,7 @@ namespace Templates.Test
} }
[Fact] [Fact]
[QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/23992")]
public async Task BlazorWasmStandalonePwaTemplate_Works() public async Task BlazorWasmStandalonePwaTemplate_Works()
{ {
var project = await ProjectFactory.GetOrCreateProject("blazorstandalonepwa", Output); var project = await ProjectFactory.GetOrCreateProject("blazorstandalonepwa", Output);
@ -251,6 +252,7 @@ namespace Templates.Test
} }
[ConditionalFact] [ConditionalFact]
[QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/23992")]
// LocalDB doesn't work on non Windows platforms // LocalDB doesn't work on non Windows platforms
[OSSkipCondition(OperatingSystems.Linux | OperatingSystems.MacOSX)] [OSSkipCondition(OperatingSystems.Linux | OperatingSystems.MacOSX)]
public Task BlazorWasmHostedTemplate_IndividualAuth_Works_WithLocalDB() public Task BlazorWasmHostedTemplate_IndividualAuth_Works_WithLocalDB()
@ -259,6 +261,7 @@ namespace Templates.Test
} }
[Fact] [Fact]
[QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/23992")]
public Task BlazorWasmHostedTemplate_IndividualAuth_Works_WithOutLocalDB() public Task BlazorWasmHostedTemplate_IndividualAuth_Works_WithOutLocalDB()
{ {
return BlazorWasmHostedTemplate_IndividualAuth_Works(false); return BlazorWasmHostedTemplate_IndividualAuth_Works(false);

View File

@ -145,7 +145,7 @@ namespace Templates.Test.Helpers
["ASPNETCORE_Logging__Console__LogLevel__Default"] = "Debug", ["ASPNETCORE_Logging__Console__LogLevel__Default"] = "Debug",
["ASPNETCORE_Logging__Console__LogLevel__System"] = "Debug", ["ASPNETCORE_Logging__Console__LogLevel__System"] = "Debug",
["ASPNETCORE_Logging__Console__LogLevel__Microsoft"] = "Debug", ["ASPNETCORE_Logging__Console__LogLevel__Microsoft"] = "Debug",
["ASPNETCORE_Logging__Console__IncludeScopes"] = "true", ["ASPNETCORE_Logging__Console__FormatterOptions__IncludeScopes"] = "true",
}; };
var launchSettingsJson = Path.Combine(TemplateOutputDir, "Properties", "launchSettings.json"); var launchSettingsJson = Path.Combine(TemplateOutputDir, "Properties", "launchSettings.json");
@ -185,7 +185,7 @@ namespace Templates.Test.Helpers
["ASPNETCORE_Logging__Console__LogLevel__Default"] = "Debug", ["ASPNETCORE_Logging__Console__LogLevel__Default"] = "Debug",
["ASPNETCORE_Logging__Console__LogLevel__System"] = "Debug", ["ASPNETCORE_Logging__Console__LogLevel__System"] = "Debug",
["ASPNETCORE_Logging__Console__LogLevel__Microsoft"] = "Debug", ["ASPNETCORE_Logging__Console__LogLevel__Microsoft"] = "Debug",
["ASPNETCORE_Logging__Console__IncludeScopes"] = "true", ["ASPNETCORE_Logging__Console__FormatterOptions__IncludeScopes"] = "true",
}; };
var projectDll = $"{ProjectName}.dll"; var projectDll = $"{ProjectName}.dll";

View File

@ -24,6 +24,7 @@ app {
height: 3.5rem; height: 3.5rem;
display: flex; display: flex;
align-items: center; align-items: center;
z-index: 10;
} }
.main { .main {

View File

@ -24,6 +24,7 @@ app {
height: 3.5rem; height: 3.5rem;
display: flex; display: flex;
align-items: center; align-items: center;
z-index: 10;
} }
.main { .main {

View File

@ -10,6 +10,7 @@ using Microsoft.Extensions.Logging;
namespace ComponentsWebAssembly_CSharp.Server.Pages namespace ComponentsWebAssembly_CSharp.Server.Pages
{ {
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
[IgnoreAntiforgeryToken]
public class ErrorModel : PageModel public class ErrorModel : PageModel
{ {
public string RequestId { get; set; } public string RequestId { get; set; }

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