Merge pull request #17562 from aspnet/prkrishn/merge-blazor-wasm

Merge blazor-wasm -> master
This commit is contained in:
Pranav K 2019-12-05 09:54:10 -08:00 committed by GitHub
commit e72223eaf5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
105 changed files with 3917 additions and 1786 deletions

View File

@ -7,6 +7,7 @@ trigger:
batch: true
branches:
include:
- blazor-wasm
- master
- release/*

View File

@ -2,7 +2,7 @@
<Project>
<PropertyGroup>
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
<AspNetCoreBaselineVersion>3.0.0</AspNetCoreBaselineVersion>
<AspNetCoreBaselineVersion>3.1.0</AspNetCoreBaselineVersion>
</PropertyGroup>
<!-- Package: AspNetCoreRuntime.3.0.x64-->
<PropertyGroup Condition=" '$(PackageId)' == 'AspNetCoreRuntime.3.0.x64' ">
@ -16,132 +16,132 @@
<ItemGroup Condition=" '$(PackageId)' == 'AspNetCoreRuntime.3.0.x86' AND '$(TargetFramework)' == 'net461' " />
<!-- Package: dotnet-sql-cache-->
<PropertyGroup Condition=" '$(PackageId)' == 'dotnet-sql-cache' ">
<BaselinePackageVersion>3.0.0</BaselinePackageVersion>
<BaselinePackageVersion>3.1.0</BaselinePackageVersion>
</PropertyGroup>
<!-- Package: Microsoft.AspNetCore.ApiAuthorization.IdentityServer-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.ApiAuthorization.IdentityServer' ">
<BaselinePackageVersion>3.0.0</BaselinePackageVersion>
<BaselinePackageVersion>3.1.0</BaselinePackageVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.ApiAuthorization.IdentityServer' AND '$(TargetFramework)' == 'netcoreapp3.0' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.AspNetCore.Identity.UI" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="[3.0.0, )" />
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.ApiAuthorization.IdentityServer' AND '$(TargetFramework)' == 'netcoreapp3.1' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="[3.1.0, )" />
<BaselinePackageReference Include="Microsoft.AspNetCore.Identity.UI" Version="[3.1.0, )" />
<BaselinePackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="[3.1.0, )" />
<BaselinePackageReference Include="IdentityServer4" Version="[3.0.0, )" />
<BaselinePackageReference Include="IdentityServer4.AspNetIdentity" Version="[3.0.0, )" />
<BaselinePackageReference Include="IdentityServer4.EntityFramework" Version="[3.0.0, )" />
<BaselinePackageReference Include="IdentityServer4.EntityFramework.Storage" Version="[3.0.0, )" />
<BaselinePackageReference Include="IdentityServer4.Storage" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.Http" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.Http" Version="[3.1.0, )" />
</ItemGroup>
<!-- Package: Microsoft.AspNetCore.App.Runtime.win-x64-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.App.Runtime.win-x64' ">
<BaselinePackageVersion>3.0.0</BaselinePackageVersion>
<BaselinePackageVersion>3.1.0</BaselinePackageVersion>
</PropertyGroup>
<!-- Package: Microsoft.AspNetCore.Authentication.AzureAD.UI-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Authentication.AzureAD.UI' ">
<BaselinePackageVersion>3.0.0</BaselinePackageVersion>
<BaselinePackageVersion>3.1.0</BaselinePackageVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Authentication.AzureAD.UI' AND '$(TargetFramework)' == 'netcoreapp3.0' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="[3.0.0, )" />
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Authentication.AzureAD.UI' AND '$(TargetFramework)' == 'netcoreapp3.1' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="[3.1.0, )" />
<BaselinePackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="[3.1.0, )" />
</ItemGroup>
<!-- Package: Microsoft.AspNetCore.Authentication.AzureADB2C.UI-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Authentication.AzureADB2C.UI' ">
<BaselinePackageVersion>3.0.0</BaselinePackageVersion>
<BaselinePackageVersion>3.1.0</BaselinePackageVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Authentication.AzureADB2C.UI' AND '$(TargetFramework)' == 'netcoreapp3.0' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="[3.0.0, )" />
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Authentication.AzureADB2C.UI' AND '$(TargetFramework)' == 'netcoreapp3.1' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="[3.1.0, )" />
<BaselinePackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="[3.1.0, )" />
</ItemGroup>
<!-- Package: Microsoft.AspNetCore.Authentication.Certificate-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Authentication.Certificate' ">
<BaselinePackageVersion>3.0.0</BaselinePackageVersion>
<BaselinePackageVersion>3.1.0</BaselinePackageVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Authentication.Certificate' AND '$(TargetFramework)' == 'netcoreapp3.0' " />
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Authentication.Certificate' AND '$(TargetFramework)' == 'netcoreapp3.1' " />
<!-- Package: Microsoft.AspNetCore.Authentication.Facebook-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Authentication.Facebook' ">
<BaselinePackageVersion>3.0.0</BaselinePackageVersion>
<BaselinePackageVersion>3.1.0</BaselinePackageVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Authentication.Facebook' AND '$(TargetFramework)' == 'netcoreapp3.0' " />
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Authentication.Facebook' AND '$(TargetFramework)' == 'netcoreapp3.1' " />
<!-- Package: Microsoft.AspNetCore.Authentication.Google-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Authentication.Google' ">
<BaselinePackageVersion>3.0.0</BaselinePackageVersion>
<BaselinePackageVersion>3.1.0</BaselinePackageVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Authentication.Google' AND '$(TargetFramework)' == 'netcoreapp3.0' " />
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Authentication.Google' AND '$(TargetFramework)' == 'netcoreapp3.1' " />
<!-- Package: Microsoft.AspNetCore.Authentication.JwtBearer-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Authentication.JwtBearer' ">
<BaselinePackageVersion>3.0.0</BaselinePackageVersion>
<BaselinePackageVersion>3.1.0</BaselinePackageVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Authentication.JwtBearer' AND '$(TargetFramework)' == 'netcoreapp3.0' ">
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Authentication.JwtBearer' AND '$(TargetFramework)' == 'netcoreapp3.1' ">
<BaselinePackageReference Include="Microsoft.IdentityModel.Protocols.OpenIdConnect" Version="[5.5.0, )" />
</ItemGroup>
<!-- Package: Microsoft.AspNetCore.Authentication.MicrosoftAccount-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Authentication.MicrosoftAccount' ">
<BaselinePackageVersion>3.0.0</BaselinePackageVersion>
<BaselinePackageVersion>3.1.0</BaselinePackageVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Authentication.MicrosoftAccount' AND '$(TargetFramework)' == 'netcoreapp3.0' " />
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Authentication.MicrosoftAccount' AND '$(TargetFramework)' == 'netcoreapp3.1' " />
<!-- Package: Microsoft.AspNetCore.Authentication.Negotiate-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Authentication.Negotiate' ">
<BaselinePackageVersion>3.0.0</BaselinePackageVersion>
<BaselinePackageVersion>3.1.0</BaselinePackageVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Authentication.Negotiate' AND '$(TargetFramework)' == 'netcoreapp3.0' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.Connections.Abstractions" Version="[3.0.0, )" />
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Authentication.Negotiate' AND '$(TargetFramework)' == 'netcoreapp3.1' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.Connections.Abstractions" Version="[3.1.0, )" />
</ItemGroup>
<!-- Package: Microsoft.AspNetCore.Authentication.OpenIdConnect-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Authentication.OpenIdConnect' ">
<BaselinePackageVersion>3.0.0</BaselinePackageVersion>
<BaselinePackageVersion>3.1.0</BaselinePackageVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Authentication.OpenIdConnect' AND '$(TargetFramework)' == 'netcoreapp3.0' ">
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Authentication.OpenIdConnect' AND '$(TargetFramework)' == 'netcoreapp3.1' ">
<BaselinePackageReference Include="Microsoft.IdentityModel.Protocols.OpenIdConnect" Version="[5.5.0, )" />
</ItemGroup>
<!-- Package: Microsoft.AspNetCore.Authentication.Twitter-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Authentication.Twitter' ">
<BaselinePackageVersion>3.0.0</BaselinePackageVersion>
<BaselinePackageVersion>3.1.0</BaselinePackageVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Authentication.Twitter' AND '$(TargetFramework)' == 'netcoreapp3.0' " />
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Authentication.Twitter' AND '$(TargetFramework)' == 'netcoreapp3.1' " />
<!-- Package: Microsoft.AspNetCore.Authentication.WsFederation-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Authentication.WsFederation' ">
<BaselinePackageVersion>3.0.0</BaselinePackageVersion>
<BaselinePackageVersion>3.1.0</BaselinePackageVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Authentication.WsFederation' AND '$(TargetFramework)' == 'netcoreapp3.0' ">
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Authentication.WsFederation' AND '$(TargetFramework)' == 'netcoreapp3.1' ">
<BaselinePackageReference Include="Microsoft.IdentityModel.Protocols.WsFederation" Version="[5.5.0, )" />
<BaselinePackageReference Include="System.IdentityModel.Tokens.Jwt" Version="[5.5.0, )" />
</ItemGroup>
<!-- Package: Microsoft.AspNetCore.Authorization-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Authorization' ">
<BaselinePackageVersion>3.0.0</BaselinePackageVersion>
<BaselinePackageVersion>3.1.0</BaselinePackageVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Authorization' AND '$(TargetFramework)' == 'netcoreapp3.0' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.Metadata" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.Options" Version="[3.0.0, )" />
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Authorization' AND '$(TargetFramework)' == 'netcoreapp3.1' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.Metadata" Version="[3.1.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="[3.1.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.Options" Version="[3.1.0, )" />
</ItemGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Authorization' AND '$(TargetFramework)' == 'netstandard2.0' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.Metadata" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.Options" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.AspNetCore.Metadata" Version="[3.1.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="[3.1.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.Options" Version="[3.1.0, )" />
</ItemGroup>
<!-- Package: Microsoft.AspNetCore.AzureAppServices.HostingStartup-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.AzureAppServices.HostingStartup' ">
<BaselinePackageVersion>3.0.0</BaselinePackageVersion>
<BaselinePackageVersion>3.1.0</BaselinePackageVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.AzureAppServices.HostingStartup' AND '$(TargetFramework)' == 'netcoreapp3.0' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.AzureAppServicesIntegration" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="[3.0.0, )" />
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.AzureAppServices.HostingStartup' AND '$(TargetFramework)' == 'netcoreapp3.1' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.AzureAppServicesIntegration" Version="[3.1.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="[3.1.0, )" />
</ItemGroup>
<!-- Package: Microsoft.AspNetCore.AzureAppServices.SiteExtension-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.AzureAppServices.SiteExtension' ">
<BaselinePackageVersion>3.0.0</BaselinePackageVersion>
<BaselinePackageVersion>3.1.0</BaselinePackageVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.AzureAppServices.SiteExtension' AND '$(TargetFramework)' == 'net461' ">
<BaselinePackageReference Include="Microsoft.Web.Xdt.Extensions" Version="[3.0.0-rc2.19465.2, )" />
<BaselinePackageReference Include="Microsoft.Web.Xdt.Extensions" Version="[3.1.0-rtm.19566.1, )" />
</ItemGroup>
<!-- Package: Microsoft.AspNetCore.AzureAppServicesIntegration-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.AzureAppServicesIntegration' ">
<BaselinePackageVersion>3.0.0</BaselinePackageVersion>
<BaselinePackageVersion>3.1.0</BaselinePackageVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.AzureAppServicesIntegration' AND '$(TargetFramework)' == 'netcoreapp3.0' ">
<BaselinePackageReference Include="Microsoft.Extensions.Logging.AzureAppServices" Version="[3.0.0, )" />
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.AzureAppServicesIntegration' AND '$(TargetFramework)' == 'netcoreapp3.1' ">
<BaselinePackageReference Include="Microsoft.Extensions.Logging.AzureAppServices" Version="[3.1.0, )" />
</ItemGroup>
<!-- Package: Microsoft.AspNetCore.Blazor-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Blazor' ">
@ -186,510 +186,510 @@
</PropertyGroup>
<!-- Package: Microsoft.AspNetCore.Components-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Components' ">
<BaselinePackageVersion>3.0.0</BaselinePackageVersion>
<BaselinePackageVersion>3.1.0</BaselinePackageVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Components' AND '$(TargetFramework)' == 'netstandard2.0' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.Components.Analyzers" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.AspNetCore.Authorization" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.JSInterop" Version="[3.0.0, )" />
<BaselinePackageReference Include="System.ComponentModel.Annotations" Version="[4.6.0, )" />
<BaselinePackageReference Include="Microsoft.AspNetCore.Components.Analyzers" Version="[3.1.0, )" />
<BaselinePackageReference Include="Microsoft.AspNetCore.Authorization" Version="[3.1.0, )" />
<BaselinePackageReference Include="Microsoft.JSInterop" Version="[3.1.0, )" />
<BaselinePackageReference Include="System.ComponentModel.Annotations" Version="[4.7.0, )" />
</ItemGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Components' AND '$(TargetFramework)' == 'netcoreapp3.0' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.Components.Analyzers" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.AspNetCore.Authorization" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.JSInterop" Version="[3.0.0, )" />
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Components' AND '$(TargetFramework)' == 'netcoreapp3.1' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.Components.Analyzers" Version="[3.1.0, )" />
<BaselinePackageReference Include="Microsoft.AspNetCore.Authorization" Version="[3.1.0, )" />
<BaselinePackageReference Include="Microsoft.JSInterop" Version="[3.1.0, )" />
</ItemGroup>
<!-- Package: Microsoft.AspNetCore.Components.Analyzers-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Components.Analyzers' ">
<BaselinePackageVersion>3.0.0</BaselinePackageVersion>
<BaselinePackageVersion>3.1.0</BaselinePackageVersion>
</PropertyGroup>
<!-- Package: Microsoft.AspNetCore.Components.Authorization-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Components.Authorization' ">
<BaselinePackageVersion>3.0.0</BaselinePackageVersion>
<BaselinePackageVersion>3.1.0</BaselinePackageVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Components.Authorization' AND '$(TargetFramework)' == 'netcoreapp3.0' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.Components" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.AspNetCore.Authorization" Version="[3.0.0, )" />
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Components.Authorization' AND '$(TargetFramework)' == 'netcoreapp3.1' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.Components" Version="[3.1.0, )" />
<BaselinePackageReference Include="Microsoft.AspNetCore.Authorization" Version="[3.1.0, )" />
</ItemGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Components.Authorization' AND '$(TargetFramework)' == 'netstandard2.0' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.Components" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.AspNetCore.Authorization" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.AspNetCore.Components" Version="[3.1.0, )" />
<BaselinePackageReference Include="Microsoft.AspNetCore.Authorization" Version="[3.1.0, )" />
</ItemGroup>
<!-- Package: Microsoft.AspNetCore.Components.Forms-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Components.Forms' ">
<BaselinePackageVersion>3.0.0</BaselinePackageVersion>
<BaselinePackageVersion>3.1.0</BaselinePackageVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Components.Forms' AND '$(TargetFramework)' == 'netcoreapp3.0' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.Components" Version="[3.0.0, )" />
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Components.Forms' AND '$(TargetFramework)' == 'netcoreapp3.1' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.Components" Version="[3.1.0, )" />
</ItemGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Components.Forms' AND '$(TargetFramework)' == 'netstandard2.0' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.Components" Version="[3.0.0, )" />
<BaselinePackageReference Include="System.ComponentModel.Annotations" Version="[4.6.0, )" />
<BaselinePackageReference Include="Microsoft.AspNetCore.Components" Version="[3.1.0, )" />
<BaselinePackageReference Include="System.ComponentModel.Annotations" Version="[4.7.0, )" />
</ItemGroup>
<!-- Package: Microsoft.AspNetCore.Components.Web-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Components.Web' ">
<BaselinePackageVersion>3.0.0</BaselinePackageVersion>
<BaselinePackageVersion>3.1.0</BaselinePackageVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Components.Web' AND '$(TargetFramework)' == 'netcoreapp3.0' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.Components" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.AspNetCore.Components.Forms" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.DependencyInjection" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.JSInterop" Version="[3.0.0, )" />
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Components.Web' AND '$(TargetFramework)' == 'netcoreapp3.1' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.Components" Version="[3.1.0, )" />
<BaselinePackageReference Include="Microsoft.AspNetCore.Components.Forms" Version="[3.1.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.DependencyInjection" Version="[3.1.0, )" />
<BaselinePackageReference Include="Microsoft.JSInterop" Version="[3.1.0, )" />
</ItemGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Components.Web' AND '$(TargetFramework)' == 'netstandard2.0' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.Components" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.AspNetCore.Components.Forms" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.DependencyInjection" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.JSInterop" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.AspNetCore.Components" Version="[3.1.0, )" />
<BaselinePackageReference Include="Microsoft.AspNetCore.Components.Forms" Version="[3.1.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.DependencyInjection" Version="[3.1.0, )" />
<BaselinePackageReference Include="Microsoft.JSInterop" Version="[3.1.0, )" />
</ItemGroup>
<!-- Package: Microsoft.AspNetCore.ConcurrencyLimiter-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.ConcurrencyLimiter' ">
<BaselinePackageVersion>3.0.0</BaselinePackageVersion>
<BaselinePackageVersion>3.1.0</BaselinePackageVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.ConcurrencyLimiter' AND '$(TargetFramework)' == 'netcoreapp3.0' ">
<BaselinePackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.Options" Version="[3.0.0, )" />
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.ConcurrencyLimiter' AND '$(TargetFramework)' == 'netcoreapp3.1' ">
<BaselinePackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="[3.1.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.Options" Version="[3.1.0, )" />
</ItemGroup>
<!-- Package: Microsoft.AspNetCore.Connections.Abstractions-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Connections.Abstractions' ">
<BaselinePackageVersion>3.0.0</BaselinePackageVersion>
<BaselinePackageVersion>3.1.0</BaselinePackageVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Connections.Abstractions' AND '$(TargetFramework)' == 'netcoreapp3.0' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.Http.Features" Version="[3.0.0, )" />
<BaselinePackageReference Include="System.IO.Pipelines" Version="[4.6.0, )" />
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Connections.Abstractions' AND '$(TargetFramework)' == 'netcoreapp3.1' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.Http.Features" Version="[3.1.0, )" />
<BaselinePackageReference Include="System.IO.Pipelines" Version="[4.7.0, )" />
</ItemGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Connections.Abstractions' AND '$(TargetFramework)' == 'netstandard2.0' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.Http.Features" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="[1.0.0, )" />
<BaselinePackageReference Include="System.IO.Pipelines" Version="[4.6.0, )" />
<BaselinePackageReference Include="Microsoft.AspNetCore.Http.Features" Version="[3.1.0, )" />
<BaselinePackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="[1.1.0, )" />
<BaselinePackageReference Include="System.IO.Pipelines" Version="[4.7.0, )" />
</ItemGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Connections.Abstractions' AND '$(TargetFramework)' == 'netstandard2.1' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.Http.Features" Version="[3.0.0, )" />
<BaselinePackageReference Include="System.IO.Pipelines" Version="[4.6.0, )" />
<BaselinePackageReference Include="Microsoft.AspNetCore.Http.Features" Version="[3.1.0, )" />
<BaselinePackageReference Include="System.IO.Pipelines" Version="[4.7.0, )" />
</ItemGroup>
<!-- Package: Microsoft.AspNetCore.Cryptography.Internal-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Cryptography.Internal' ">
<BaselinePackageVersion>3.0.0</BaselinePackageVersion>
<BaselinePackageVersion>3.1.0</BaselinePackageVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Cryptography.Internal' AND '$(TargetFramework)' == 'netstandard2.0' " />
<!-- Package: Microsoft.AspNetCore.Cryptography.KeyDerivation-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Cryptography.KeyDerivation' ">
<BaselinePackageVersion>3.0.0</BaselinePackageVersion>
<BaselinePackageVersion>3.1.0</BaselinePackageVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Cryptography.KeyDerivation' AND '$(TargetFramework)' == 'netcoreapp2.0' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.Cryptography.Internal" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.AspNetCore.Cryptography.Internal" Version="[3.1.0, )" />
</ItemGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Cryptography.KeyDerivation' AND '$(TargetFramework)' == 'netstandard2.0' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.Cryptography.Internal" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.AspNetCore.Cryptography.Internal" Version="[3.1.0, )" />
</ItemGroup>
<!-- Package: Microsoft.AspNetCore.DataProtection-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.DataProtection' ">
<BaselinePackageVersion>3.0.0</BaselinePackageVersion>
<BaselinePackageVersion>3.1.0</BaselinePackageVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.DataProtection' AND '$(TargetFramework)' == 'netcoreapp3.0' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.DataProtection.Abstractions" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.AspNetCore.Cryptography.Internal" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.Options" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.Win32.Registry" Version="[4.6.0, )" />
<BaselinePackageReference Include="System.Security.Cryptography.Xml" Version="[4.6.0, )" />
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.DataProtection' AND '$(TargetFramework)' == 'netcoreapp3.1' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.DataProtection.Abstractions" Version="[3.1.0, )" />
<BaselinePackageReference Include="Microsoft.AspNetCore.Cryptography.Internal" Version="[3.1.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="[3.1.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="[3.1.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="[3.1.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.Options" Version="[3.1.0, )" />
<BaselinePackageReference Include="Microsoft.Win32.Registry" Version="[4.7.0, )" />
<BaselinePackageReference Include="System.Security.Cryptography.Xml" Version="[4.7.0, )" />
</ItemGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.DataProtection' AND '$(TargetFramework)' == 'netstandard2.0' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.DataProtection.Abstractions" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.AspNetCore.Cryptography.Internal" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.Options" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.Win32.Registry" Version="[4.6.0, )" />
<BaselinePackageReference Include="System.Security.Cryptography.Xml" Version="[4.6.0, )" />
<BaselinePackageReference Include="System.Security.Principal.Windows" Version="[4.6.0, )" />
<BaselinePackageReference Include="Microsoft.AspNetCore.DataProtection.Abstractions" Version="[3.1.0, )" />
<BaselinePackageReference Include="Microsoft.AspNetCore.Cryptography.Internal" Version="[3.1.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="[3.1.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="[3.1.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="[3.1.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.Options" Version="[3.1.0, )" />
<BaselinePackageReference Include="Microsoft.Win32.Registry" Version="[4.7.0, )" />
<BaselinePackageReference Include="System.Security.Cryptography.Xml" Version="[4.7.0, )" />
<BaselinePackageReference Include="System.Security.Principal.Windows" Version="[4.7.0, )" />
</ItemGroup>
<!-- Package: Microsoft.AspNetCore.DataProtection.Abstractions-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.DataProtection.Abstractions' ">
<BaselinePackageVersion>3.0.0</BaselinePackageVersion>
<BaselinePackageVersion>3.1.0</BaselinePackageVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.DataProtection.Abstractions' AND '$(TargetFramework)' == 'netstandard2.0' " />
<!-- Package: Microsoft.AspNetCore.DataProtection.AzureKeyVault-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.DataProtection.AzureKeyVault' ">
<BaselinePackageVersion>3.0.0</BaselinePackageVersion>
<BaselinePackageVersion>3.1.0</BaselinePackageVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.DataProtection.AzureKeyVault' AND '$(TargetFramework)' == 'netstandard2.0' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.DataProtection" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.AspNetCore.DataProtection" Version="[3.1.0, )" />
<BaselinePackageReference Include="Microsoft.Azure.KeyVault" Version="[2.3.2, )" />
<BaselinePackageReference Include="Microsoft.IdentityModel.Clients.ActiveDirectory" Version="[3.19.8, )" />
</ItemGroup>
<!-- Package: Microsoft.AspNetCore.DataProtection.AzureStorage-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.DataProtection.AzureStorage' ">
<BaselinePackageVersion>3.0.0</BaselinePackageVersion>
<BaselinePackageVersion>3.1.0</BaselinePackageVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.DataProtection.AzureStorage' AND '$(TargetFramework)' == 'netstandard2.0' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.DataProtection" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.AspNetCore.DataProtection" Version="[3.1.0, )" />
<BaselinePackageReference Include="Microsoft.Azure.Storage.Blob" Version="[10.0.1, )" />
<BaselinePackageReference Include="Microsoft.Data.OData" Version="[5.8.4, )" />
</ItemGroup>
<!-- Package: Microsoft.AspNetCore.DataProtection.EntityFrameworkCore-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.DataProtection.EntityFrameworkCore' ">
<BaselinePackageVersion>3.0.0</BaselinePackageVersion>
<BaselinePackageVersion>3.1.0</BaselinePackageVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.DataProtection.EntityFrameworkCore' AND '$(TargetFramework)' == 'netstandard2.1' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.DataProtection" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.EntityFrameworkCore" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.AspNetCore.DataProtection" Version="[3.1.0, )" />
<BaselinePackageReference Include="Microsoft.EntityFrameworkCore" Version="[3.1.0, )" />
</ItemGroup>
<!-- Package: Microsoft.AspNetCore.DataProtection.Extensions-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.DataProtection.Extensions' ">
<BaselinePackageVersion>3.0.0</BaselinePackageVersion>
<BaselinePackageVersion>3.1.0</BaselinePackageVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.DataProtection.Extensions' AND '$(TargetFramework)' == 'netcoreapp3.0' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.DataProtection" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.DependencyInjection" Version="[3.0.0, )" />
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.DataProtection.Extensions' AND '$(TargetFramework)' == 'netcoreapp3.1' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.DataProtection" Version="[3.1.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.DependencyInjection" Version="[3.1.0, )" />
</ItemGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.DataProtection.Extensions' AND '$(TargetFramework)' == 'netstandard2.0' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.DataProtection" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.DependencyInjection" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.AspNetCore.DataProtection" Version="[3.1.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.DependencyInjection" Version="[3.1.0, )" />
</ItemGroup>
<!-- Package: Microsoft.AspNetCore.DataProtection.StackExchangeRedis-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.DataProtection.StackExchangeRedis' ">
<BaselinePackageVersion>3.0.0</BaselinePackageVersion>
<BaselinePackageVersion>3.1.0</BaselinePackageVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.DataProtection.StackExchangeRedis' AND '$(TargetFramework)' == 'netstandard2.0' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.DataProtection" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.AspNetCore.DataProtection" Version="[3.1.0, )" />
<BaselinePackageReference Include="StackExchange.Redis" Version="[2.0.593, )" />
</ItemGroup>
<!-- Package: Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore' ">
<BaselinePackageVersion>3.0.0</BaselinePackageVersion>
<BaselinePackageVersion>3.1.0</BaselinePackageVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore' AND '$(TargetFramework)' == 'netcoreapp3.0' ">
<BaselinePackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="[3.0.0, )" />
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore' AND '$(TargetFramework)' == 'netcoreapp3.1' ">
<BaselinePackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="[3.1.0, )" />
</ItemGroup>
<!-- Package: Microsoft.AspNetCore.HeaderPropagation-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.HeaderPropagation' ">
<BaselinePackageVersion>3.0.0</BaselinePackageVersion>
<BaselinePackageVersion>3.1.0</BaselinePackageVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.HeaderPropagation' AND '$(TargetFramework)' == 'netcoreapp3.0' ">
<BaselinePackageReference Include="Microsoft.Extensions.DependencyInjection" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.Http" Version="[3.0.0, )" />
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.HeaderPropagation' AND '$(TargetFramework)' == 'netcoreapp3.1' ">
<BaselinePackageReference Include="Microsoft.Extensions.DependencyInjection" Version="[3.1.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.Http" Version="[3.1.0, )" />
</ItemGroup>
<!-- Package: Microsoft.AspNetCore.Hosting.WindowsServices-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Hosting.WindowsServices' ">
<BaselinePackageVersion>3.0.0</BaselinePackageVersion>
<BaselinePackageVersion>3.1.0</BaselinePackageVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Hosting.WindowsServices' AND '$(TargetFramework)' == 'netcoreapp3.0' ">
<BaselinePackageReference Include="System.ServiceProcess.ServiceController" Version="[4.6.0, )" />
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Hosting.WindowsServices' AND '$(TargetFramework)' == 'netcoreapp3.1' ">
<BaselinePackageReference Include="System.ServiceProcess.ServiceController" Version="[4.7.0, )" />
</ItemGroup>
<!-- Package: Microsoft.AspNetCore.Http.Connections.Client-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Http.Connections.Client' ">
<BaselinePackageVersion>3.0.0</BaselinePackageVersion>
<BaselinePackageVersion>3.1.0</BaselinePackageVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Http.Connections.Client' AND '$(TargetFramework)' == 'netstandard2.0' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.Http.Connections.Common" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.Options" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.AspNetCore.Http.Connections.Common" Version="[3.1.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="[3.1.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.Options" Version="[3.1.0, )" />
</ItemGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Http.Connections.Client' AND '$(TargetFramework)' == 'netstandard2.1' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.Http.Connections.Common" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.Options" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.AspNetCore.Http.Connections.Common" Version="[3.1.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="[3.1.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.Options" Version="[3.1.0, )" />
</ItemGroup>
<!-- Package: Microsoft.AspNetCore.Http.Connections.Common-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Http.Connections.Common' ">
<BaselinePackageVersion>3.0.0</BaselinePackageVersion>
<BaselinePackageVersion>3.1.0</BaselinePackageVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Http.Connections.Common' AND '$(TargetFramework)' == 'netcoreapp3.0' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.Connections.Abstractions" Version="[3.0.0, )" />
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Http.Connections.Common' AND '$(TargetFramework)' == 'netcoreapp3.1' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.Connections.Abstractions" Version="[3.1.0, )" />
</ItemGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Http.Connections.Common' AND '$(TargetFramework)' == 'netstandard2.0' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.Connections.Abstractions" Version="[3.0.0, )" />
<BaselinePackageReference Include="System.Text.Json" Version="[4.6.0, )" />
<BaselinePackageReference Include="Microsoft.AspNetCore.Connections.Abstractions" Version="[3.1.0, )" />
<BaselinePackageReference Include="System.Text.Json" Version="[4.7.0, )" />
</ItemGroup>
<!-- Package: Microsoft.AspNetCore.Http.Features-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Http.Features' ">
<BaselinePackageVersion>3.0.0</BaselinePackageVersion>
<BaselinePackageVersion>3.1.0</BaselinePackageVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Http.Features' AND '$(TargetFramework)' == 'netcoreapp3.0' ">
<BaselinePackageReference Include="Microsoft.Extensions.Primitives" Version="[3.0.0, )" />
<BaselinePackageReference Include="System.IO.Pipelines" Version="[4.6.0, )" />
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Http.Features' AND '$(TargetFramework)' == 'netcoreapp3.1' ">
<BaselinePackageReference Include="Microsoft.Extensions.Primitives" Version="[3.1.0, )" />
<BaselinePackageReference Include="System.IO.Pipelines" Version="[4.7.0, )" />
</ItemGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Http.Features' AND '$(TargetFramework)' == 'netstandard2.0' ">
<BaselinePackageReference Include="Microsoft.Extensions.Primitives" Version="[3.0.0, )" />
<BaselinePackageReference Include="System.IO.Pipelines" Version="[4.6.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.Primitives" Version="[3.1.0, )" />
<BaselinePackageReference Include="System.IO.Pipelines" Version="[4.7.0, )" />
</ItemGroup>
<!-- Package: Microsoft.AspNetCore.Identity.EntityFrameworkCore-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Identity.EntityFrameworkCore' ">
<BaselinePackageVersion>3.0.0</BaselinePackageVersion>
<BaselinePackageVersion>3.1.0</BaselinePackageVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Identity.EntityFrameworkCore' AND '$(TargetFramework)' == 'netcoreapp3.0' ">
<BaselinePackageReference Include="Microsoft.Extensions.Identity.Stores" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="[3.0.0, )" />
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Identity.EntityFrameworkCore' AND '$(TargetFramework)' == 'netcoreapp3.1' ">
<BaselinePackageReference Include="Microsoft.Extensions.Identity.Stores" Version="[3.1.0, )" />
<BaselinePackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="[3.1.0, )" />
</ItemGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Identity.EntityFrameworkCore' AND '$(TargetFramework)' == 'netstandard2.1' ">
<BaselinePackageReference Include="Microsoft.Extensions.Identity.Stores" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.Identity.Stores" Version="[3.1.0, )" />
<BaselinePackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="[3.1.0, )" />
</ItemGroup>
<!-- Package: Microsoft.AspNetCore.Identity.Specification.Tests-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Identity.Specification.Tests' ">
<BaselinePackageVersion>3.0.0</BaselinePackageVersion>
<BaselinePackageVersion>3.1.0</BaselinePackageVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Identity.Specification.Tests' AND '$(TargetFramework)' == 'netcoreapp3.0' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.Testing" Version="[3.0.0-rc2.19463.5, )" />
<BaselinePackageReference Include="Microsoft.Extensions.Configuration" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.DependencyInjection" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.Logging" Version="[3.0.0, )" />
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Identity.Specification.Tests' AND '$(TargetFramework)' == 'netcoreapp3.1' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.Testing" Version="[3.1.0-rtm.19565.4, )" />
<BaselinePackageReference Include="Microsoft.Extensions.Configuration" Version="[3.1.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.DependencyInjection" Version="[3.1.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.Logging" Version="[3.1.0, )" />
<BaselinePackageReference Include="xunit.assert" Version="[2.4.1, )" />
<BaselinePackageReference Include="xunit.extensibility.core" Version="[2.4.1, )" />
</ItemGroup>
<!-- Package: Microsoft.AspNetCore.Identity.UI-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Identity.UI' ">
<BaselinePackageVersion>3.0.0</BaselinePackageVersion>
<BaselinePackageVersion>3.1.0</BaselinePackageVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Identity.UI' AND '$(TargetFramework)' == 'netcoreapp3.0' ">
<BaselinePackageReference Include="Microsoft.Extensions.Identity.Stores" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="[3.0.0, )" />
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Identity.UI' AND '$(TargetFramework)' == 'netcoreapp3.1' ">
<BaselinePackageReference Include="Microsoft.Extensions.Identity.Stores" Version="[3.1.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="[3.1.0, )" />
<BaselinePackageReference Include="Newtonsoft.Json" Version="[12.0.2, )" />
</ItemGroup>
<!-- Package: Microsoft.AspNetCore.JsonPatch-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.JsonPatch' ">
<BaselinePackageVersion>3.0.0</BaselinePackageVersion>
<BaselinePackageVersion>3.1.0</BaselinePackageVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.JsonPatch' AND '$(TargetFramework)' == 'netstandard2.0' ">
<BaselinePackageReference Include="Microsoft.CSharp" Version="[4.6.0, )" />
<BaselinePackageReference Include="Microsoft.CSharp" Version="[4.7.0, )" />
<BaselinePackageReference Include="Newtonsoft.Json" Version="[12.0.2, )" />
</ItemGroup>
<!-- Package: Microsoft.AspNetCore.Metadata-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Metadata' ">
<BaselinePackageVersion>3.0.0</BaselinePackageVersion>
<BaselinePackageVersion>3.1.0</BaselinePackageVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Metadata' AND '$(TargetFramework)' == 'netstandard2.0' " />
<!-- Package: Microsoft.AspNetCore.MiddlewareAnalysis-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.MiddlewareAnalysis' ">
<BaselinePackageVersion>3.0.0</BaselinePackageVersion>
<BaselinePackageVersion>3.1.0</BaselinePackageVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.MiddlewareAnalysis' AND '$(TargetFramework)' == 'netcoreapp3.0' ">
<BaselinePackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="[3.0.0, )" />
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.MiddlewareAnalysis' AND '$(TargetFramework)' == 'netcoreapp3.1' ">
<BaselinePackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="[3.1.0, )" />
</ItemGroup>
<!-- Package: Microsoft.AspNetCore.Mvc.NewtonsoftJson-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Mvc.NewtonsoftJson' ">
<BaselinePackageVersion>3.0.0</BaselinePackageVersion>
<BaselinePackageVersion>3.1.0</BaselinePackageVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Mvc.NewtonsoftJson' AND '$(TargetFramework)' == 'netcoreapp3.0' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.JsonPatch" Version="[3.0.0, )" />
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Mvc.NewtonsoftJson' AND '$(TargetFramework)' == 'netcoreapp3.1' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.JsonPatch" Version="[3.1.0, )" />
<BaselinePackageReference Include="Newtonsoft.Json" Version="[12.0.2, )" />
<BaselinePackageReference Include="Newtonsoft.Json.Bson" Version="[1.0.2, )" />
</ItemGroup>
<!-- Package: Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation' ">
<BaselinePackageVersion>3.0.0</BaselinePackageVersion>
<BaselinePackageVersion>3.1.0</BaselinePackageVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation' AND '$(TargetFramework)' == 'netcoreapp3.0' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.Mvc.Razor.Extensions" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.CodeAnalysis.Razor" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.DependencyModel" Version="[3.0.0, )" />
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation' AND '$(TargetFramework)' == 'netcoreapp3.1' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.Mvc.Razor.Extensions" Version="[3.1.0, )" />
<BaselinePackageReference Include="Microsoft.CodeAnalysis.Razor" Version="[3.1.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.DependencyModel" Version="[3.1.0, )" />
</ItemGroup>
<!-- Package: Microsoft.AspNetCore.Mvc.Testing-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Mvc.Testing' ">
<BaselinePackageVersion>3.0.0</BaselinePackageVersion>
<BaselinePackageVersion>3.1.0</BaselinePackageVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Mvc.Testing' AND '$(TargetFramework)' == 'netcoreapp3.0' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.TestHost" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.DependencyModel" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.Hosting" Version="[3.0.0, )" />
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Mvc.Testing' AND '$(TargetFramework)' == 'netcoreapp3.1' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.TestHost" Version="[3.1.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.DependencyModel" Version="[3.1.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.Hosting" Version="[3.1.0, )" />
</ItemGroup>
<!-- Package: Microsoft.AspNetCore.NodeServices-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.NodeServices' ">
<BaselinePackageVersion>3.0.0</BaselinePackageVersion>
<BaselinePackageVersion>3.1.0</BaselinePackageVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.NodeServices' AND '$(TargetFramework)' == 'netcoreapp3.0' ">
<BaselinePackageReference Include="Microsoft.Extensions.Logging.Console" Version="[3.0.0, )" />
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.NodeServices' AND '$(TargetFramework)' == 'netcoreapp3.1' ">
<BaselinePackageReference Include="Microsoft.Extensions.Logging.Console" Version="[3.1.0, )" />
<BaselinePackageReference Include="Newtonsoft.Json" Version="[12.0.2, )" />
</ItemGroup>
<!-- Package: Microsoft.AspNetCore.Owin-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Owin' ">
<BaselinePackageVersion>3.0.0</BaselinePackageVersion>
<BaselinePackageVersion>3.1.0</BaselinePackageVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Owin' AND '$(TargetFramework)' == 'netcoreapp3.0' " />
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Owin' AND '$(TargetFramework)' == 'netcoreapp3.1' " />
<!-- Package: Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv' ">
<BaselinePackageVersion>3.0.0</BaselinePackageVersion>
<BaselinePackageVersion>3.1.0</BaselinePackageVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv' AND '$(TargetFramework)' == 'netcoreapp3.0' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.Connections.Abstractions" Version="[3.0.0, )" />
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv' AND '$(TargetFramework)' == 'netcoreapp3.1' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.Connections.Abstractions" Version="[3.1.0, )" />
<BaselinePackageReference Include="Libuv" Version="[1.10.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.Options" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="[3.1.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.Options" Version="[3.1.0, )" />
</ItemGroup>
<!-- Package: Microsoft.AspNetCore.SignalR.Client-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.SignalR.Client' ">
<BaselinePackageVersion>3.0.0</BaselinePackageVersion>
<BaselinePackageVersion>3.1.0</BaselinePackageVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.SignalR.Client' AND '$(TargetFramework)' == 'netstandard2.0' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.SignalR.Client.Core" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.AspNetCore.Http.Connections.Client" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.AspNetCore.SignalR.Client.Core" Version="[3.1.0, )" />
<BaselinePackageReference Include="Microsoft.AspNetCore.Http.Connections.Client" Version="[3.1.0, )" />
</ItemGroup>
<!-- Package: Microsoft.AspNetCore.SignalR.Client.Core-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.SignalR.Client.Core' ">
<BaselinePackageVersion>3.0.0</BaselinePackageVersion>
<BaselinePackageVersion>3.1.0</BaselinePackageVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.SignalR.Client.Core' AND '$(TargetFramework)' == 'netstandard2.0' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.SignalR.Protocols.Json" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.AspNetCore.SignalR.Common" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="[1.0.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.DependencyInjection" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.Logging" Version="[3.0.0, )" />
<BaselinePackageReference Include="System.Threading.Channels" Version="[4.6.0, )" />
<BaselinePackageReference Include="Microsoft.AspNetCore.SignalR.Protocols.Json" Version="[3.1.0, )" />
<BaselinePackageReference Include="Microsoft.AspNetCore.SignalR.Common" Version="[3.1.0, )" />
<BaselinePackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="[1.1.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.DependencyInjection" Version="[3.1.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.Logging" Version="[3.1.0, )" />
<BaselinePackageReference Include="System.Threading.Channels" Version="[4.7.0, )" />
</ItemGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.SignalR.Client.Core' AND '$(TargetFramework)' == 'netstandard2.1' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.SignalR.Protocols.Json" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.AspNetCore.SignalR.Common" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.DependencyInjection" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.Logging" Version="[3.0.0, )" />
<BaselinePackageReference Include="System.Threading.Channels" Version="[4.6.0, )" />
<BaselinePackageReference Include="Microsoft.AspNetCore.SignalR.Protocols.Json" Version="[3.1.0, )" />
<BaselinePackageReference Include="Microsoft.AspNetCore.SignalR.Common" Version="[3.1.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.DependencyInjection" Version="[3.1.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.Logging" Version="[3.1.0, )" />
<BaselinePackageReference Include="System.Threading.Channels" Version="[4.7.0, )" />
</ItemGroup>
<!-- Package: Microsoft.AspNetCore.SignalR.Common-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.SignalR.Common' ">
<BaselinePackageVersion>3.0.0</BaselinePackageVersion>
<BaselinePackageVersion>3.1.0</BaselinePackageVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.SignalR.Common' AND '$(TargetFramework)' == 'netcoreapp3.0' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.Connections.Abstractions" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.Options" Version="[3.0.0, )" />
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.SignalR.Common' AND '$(TargetFramework)' == 'netcoreapp3.1' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.Connections.Abstractions" Version="[3.1.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.Options" Version="[3.1.0, )" />
</ItemGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.SignalR.Common' AND '$(TargetFramework)' == 'netstandard2.0' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.Connections.Abstractions" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.Options" Version="[3.0.0, )" />
<BaselinePackageReference Include="System.Text.Json" Version="[4.6.0, )" />
<BaselinePackageReference Include="Microsoft.AspNetCore.Connections.Abstractions" Version="[3.1.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.Options" Version="[3.1.0, )" />
<BaselinePackageReference Include="System.Text.Json" Version="[4.7.0, )" />
</ItemGroup>
<!-- Package: Microsoft.AspNetCore.SignalR.Protocols.Json-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.SignalR.Protocols.Json' ">
<BaselinePackageVersion>3.0.0</BaselinePackageVersion>
<BaselinePackageVersion>3.1.0</BaselinePackageVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.SignalR.Protocols.Json' AND '$(TargetFramework)' == 'netcoreapp3.0' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.SignalR.Common" Version="[3.0.0, )" />
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.SignalR.Protocols.Json' AND '$(TargetFramework)' == 'netcoreapp3.1' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.SignalR.Common" Version="[3.1.0, )" />
</ItemGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.SignalR.Protocols.Json' AND '$(TargetFramework)' == 'netstandard2.0' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.SignalR.Common" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.AspNetCore.SignalR.Common" Version="[3.1.0, )" />
</ItemGroup>
<!-- Package: Microsoft.AspNetCore.SignalR.Protocols.MessagePack-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.SignalR.Protocols.MessagePack' ">
<BaselinePackageVersion>3.0.0</BaselinePackageVersion>
<BaselinePackageVersion>3.1.0</BaselinePackageVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.SignalR.Protocols.MessagePack' AND '$(TargetFramework)' == 'netstandard2.0' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.SignalR.Common" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.AspNetCore.SignalR.Common" Version="[3.1.0, )" />
<BaselinePackageReference Include="MessagePack" Version="[1.7.3.7, )" />
</ItemGroup>
<!-- Package: Microsoft.AspNetCore.SignalR.Protocols.NewtonsoftJson-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.SignalR.Protocols.NewtonsoftJson' ">
<BaselinePackageVersion>3.0.0</BaselinePackageVersion>
<BaselinePackageVersion>3.1.0</BaselinePackageVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.SignalR.Protocols.NewtonsoftJson' AND '$(TargetFramework)' == 'netstandard2.0' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.SignalR.Common" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.AspNetCore.SignalR.Common" Version="[3.1.0, )" />
<BaselinePackageReference Include="Newtonsoft.Json" Version="[12.0.2, )" />
</ItemGroup>
<!-- Package: Microsoft.AspNetCore.SignalR.Specification.Tests-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.SignalR.Specification.Tests' ">
<BaselinePackageVersion>3.0.0</BaselinePackageVersion>
<BaselinePackageVersion>3.1.0</BaselinePackageVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.SignalR.Specification.Tests' AND '$(TargetFramework)' == 'netcoreapp3.0' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.SignalR.Protocols.Json" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.AspNetCore.SignalR.Protocols.MessagePack" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.AspNetCore.SignalR.Protocols.NewtonsoftJson" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.AspNetCore.SignalR.Common" Version="[3.0.0, )" />
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.SignalR.Specification.Tests' AND '$(TargetFramework)' == 'netcoreapp3.1' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.SignalR.Protocols.Json" Version="[3.1.0, )" />
<BaselinePackageReference Include="Microsoft.AspNetCore.SignalR.Protocols.MessagePack" Version="[3.1.0, )" />
<BaselinePackageReference Include="Microsoft.AspNetCore.SignalR.Protocols.NewtonsoftJson" Version="[3.1.0, )" />
<BaselinePackageReference Include="Microsoft.AspNetCore.SignalR.Common" Version="[3.1.0, )" />
<BaselinePackageReference Include="xunit.assert" Version="[2.4.1, )" />
<BaselinePackageReference Include="xunit.extensibility.core" Version="[2.4.1, )" />
</ItemGroup>
<!-- Package: Microsoft.AspNetCore.SignalR.StackExchangeRedis-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.SignalR.StackExchangeRedis' ">
<BaselinePackageVersion>3.0.0</BaselinePackageVersion>
<BaselinePackageVersion>3.1.0</BaselinePackageVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.SignalR.StackExchangeRedis' AND '$(TargetFramework)' == 'netcoreapp3.0' ">
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.SignalR.StackExchangeRedis' AND '$(TargetFramework)' == 'netcoreapp3.1' ">
<BaselinePackageReference Include="MessagePack" Version="[1.7.3.7, )" />
<BaselinePackageReference Include="Microsoft.Extensions.Options" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.Options" Version="[3.1.0, )" />
<BaselinePackageReference Include="StackExchange.Redis" Version="[2.0.593, )" />
</ItemGroup>
<!-- Package: Microsoft.AspNetCore.SpaServices-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.SpaServices' ">
<BaselinePackageVersion>3.0.0</BaselinePackageVersion>
<BaselinePackageVersion>3.1.0</BaselinePackageVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.SpaServices' AND '$(TargetFramework)' == 'netcoreapp3.0' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.NodeServices" Version="[3.0.0, )" />
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.SpaServices' AND '$(TargetFramework)' == 'netcoreapp3.1' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.NodeServices" Version="[3.1.0, )" />
</ItemGroup>
<!-- Package: Microsoft.AspNetCore.SpaServices.Extensions-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.SpaServices.Extensions' ">
<BaselinePackageVersion>3.0.0</BaselinePackageVersion>
<BaselinePackageVersion>3.1.0</BaselinePackageVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.SpaServices.Extensions' AND '$(TargetFramework)' == 'netcoreapp3.0' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.SpaServices" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.FileProviders.Physical" Version="[3.0.0, )" />
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.SpaServices.Extensions' AND '$(TargetFramework)' == 'netcoreapp3.1' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.SpaServices" Version="[3.1.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.FileProviders.Physical" Version="[3.1.0, )" />
</ItemGroup>
<!-- Package: Microsoft.AspNetCore.TestHost-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.TestHost' ">
<BaselinePackageVersion>3.0.0</BaselinePackageVersion>
<BaselinePackageVersion>3.1.0</BaselinePackageVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.TestHost' AND '$(TargetFramework)' == 'netcoreapp3.0' ">
<BaselinePackageReference Include="System.IO.Pipelines" Version="[4.6.0, )" />
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.AspNetCore.TestHost' AND '$(TargetFramework)' == 'netcoreapp3.1' ">
<BaselinePackageReference Include="System.IO.Pipelines" Version="[4.7.0, )" />
</ItemGroup>
<!-- Package: Microsoft.dotnet-openapi-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.dotnet-openapi' ">
<BaselinePackageVersion>3.0.0</BaselinePackageVersion>
<BaselinePackageVersion>3.1.0</BaselinePackageVersion>
</PropertyGroup>
<!-- Package: Microsoft.DotNet.Web.Client.ItemTemplates-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.DotNet.Web.Client.ItemTemplates' ">
<BaselinePackageVersion>3.0.0</BaselinePackageVersion>
<BaselinePackageVersion>3.1.0</BaselinePackageVersion>
</PropertyGroup>
<!-- Package: Microsoft.DotNet.Web.ItemTemplates-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.DotNet.Web.ItemTemplates' ">
<BaselinePackageVersion>3.0.0</BaselinePackageVersion>
<BaselinePackageVersion>3.1.0</BaselinePackageVersion>
</PropertyGroup>
<!-- Package: Microsoft.DotNet.Web.ProjectTemplates.3.0-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.DotNet.Web.ProjectTemplates.3.0' ">
<BaselinePackageVersion>3.0.0</BaselinePackageVersion>
<!-- Package: Microsoft.DotNet.Web.ProjectTemplates.3.1-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.DotNet.Web.ProjectTemplates.3.1' ">
<BaselinePackageVersion>3.1.0</BaselinePackageVersion>
</PropertyGroup>
<!-- Package: Microsoft.DotNet.Web.Spa.ProjectTemplates.3.0-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.DotNet.Web.Spa.ProjectTemplates.3.0' ">
<BaselinePackageVersion>3.0.0</BaselinePackageVersion>
<!-- Package: Microsoft.DotNet.Web.Spa.ProjectTemplates.3.1-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.DotNet.Web.Spa.ProjectTemplates.3.1' ">
<BaselinePackageVersion>3.1.0</BaselinePackageVersion>
</PropertyGroup>
<!-- Package: Microsoft.Extensions.ApiDescription.Client-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.Extensions.ApiDescription.Client' ">
<BaselinePackageVersion>3.0.0</BaselinePackageVersion>
<BaselinePackageVersion>3.1.0</BaselinePackageVersion>
</PropertyGroup>
<!-- Package: Microsoft.Extensions.ApiDescription.Server-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.Extensions.ApiDescription.Server' ">
<BaselinePackageVersion>3.0.0</BaselinePackageVersion>
<BaselinePackageVersion>3.1.0</BaselinePackageVersion>
</PropertyGroup>
<!-- Package: Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore' ">
<BaselinePackageVersion>3.0.0</BaselinePackageVersion>
<BaselinePackageVersion>3.1.0</BaselinePackageVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore' AND '$(TargetFramework)' == 'netstandard2.1' ">
<BaselinePackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="[3.1.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks" Version="[3.1.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions" Version="[3.1.0, )" />
</ItemGroup>
<!-- Package: Microsoft.Extensions.Identity.Core-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.Extensions.Identity.Core' ">
<BaselinePackageVersion>3.0.0</BaselinePackageVersion>
<BaselinePackageVersion>3.1.0</BaselinePackageVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.Extensions.Identity.Core' AND '$(TargetFramework)' == 'netcoreapp3.0' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.Logging" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.Options" Version="[3.0.0, )" />
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.Extensions.Identity.Core' AND '$(TargetFramework)' == 'netcoreapp3.1' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="[3.1.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.Logging" Version="[3.1.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.Options" Version="[3.1.0, )" />
</ItemGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.Extensions.Identity.Core' AND '$(TargetFramework)' == 'netstandard2.0' ">
<BaselinePackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.Logging" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.Options" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="[3.1.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.Logging" Version="[3.1.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.Options" Version="[3.1.0, )" />
</ItemGroup>
<!-- Package: Microsoft.Extensions.Identity.Stores-->
<PropertyGroup Condition=" '$(PackageId)' == 'Microsoft.Extensions.Identity.Stores' ">
<BaselinePackageVersion>3.0.0</BaselinePackageVersion>
<BaselinePackageVersion>3.1.0</BaselinePackageVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.Extensions.Identity.Stores' AND '$(TargetFramework)' == 'netcoreapp3.0' ">
<BaselinePackageReference Include="Microsoft.Extensions.Identity.Core" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.Logging" Version="[3.0.0, )" />
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.Extensions.Identity.Stores' AND '$(TargetFramework)' == 'netcoreapp3.1' ">
<BaselinePackageReference Include="Microsoft.Extensions.Identity.Core" Version="[3.1.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.Logging" Version="[3.1.0, )" />
</ItemGroup>
<ItemGroup Condition=" '$(PackageId)' == 'Microsoft.Extensions.Identity.Stores' AND '$(TargetFramework)' == 'netstandard2.0' ">
<BaselinePackageReference Include="Microsoft.Extensions.Identity.Core" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.Logging" Version="[3.0.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.Identity.Core" Version="[3.1.0, )" />
<BaselinePackageReference Include="Microsoft.Extensions.Logging" Version="[3.1.0, )" />
</ItemGroup>
</Project>

View File

@ -1,91 +1,89 @@
<!--
This file contains a list of all the packages and their versions which were released in ASP.NET Core 3.0.0.
This file contains a list of all the packages and their versions which were released in ASP.NET Core 3.1.0.
Update this list when preparing for a new patch.
-->
<Baseline Version="3.0.0">
<Baseline Version="3.1.0">
<Package Id="AspNetCoreRuntime.3.0.x64" Version="3.0.0" />
<Package Id="AspNetCoreRuntime.3.0.x86" Version="3.0.0" />
<Package Id="dotnet-sql-cache" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.ApiAuthorization.IdentityServer" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.App.Runtime.win-x64" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Authentication.AzureAD.UI" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Authentication.AzureADB2C.UI" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Authentication.Certificate" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Authentication.Facebook" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Authentication.Google" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Authentication.JwtBearer" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Authentication.MicrosoftAccount" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Authentication.Negotiate" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Authentication.Twitter" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Authentication.WsFederation" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Authorization" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.AzureAppServices.HostingStartup" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.AzureAppServices.SiteExtension" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.AzureAppServicesIntegration" Version="3.0.0" />
<Package Id="dotnet-sql-cache" Version="3.1.0" />
<Package Id="Microsoft.AspNetCore.ApiAuthorization.IdentityServer" Version="3.1.0" />
<Package Id="Microsoft.AspNetCore.App.Runtime.win-x64" Version="3.1.0" />
<Package Id="Microsoft.AspNetCore.Authentication.AzureAD.UI" Version="3.1.0" />
<Package Id="Microsoft.AspNetCore.Authentication.AzureADB2C.UI" Version="3.1.0" />
<Package Id="Microsoft.AspNetCore.Authentication.Certificate" Version="3.1.0" />
<Package Id="Microsoft.AspNetCore.Authentication.Facebook" Version="3.1.0" />
<Package Id="Microsoft.AspNetCore.Authentication.Google" Version="3.1.0" />
<Package Id="Microsoft.AspNetCore.Authentication.JwtBearer" Version="3.1.0" />
<Package Id="Microsoft.AspNetCore.Authentication.MicrosoftAccount" Version="3.1.0" />
<Package Id="Microsoft.AspNetCore.Authentication.Negotiate" Version="3.1.0" />
<Package Id="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="3.1.0" />
<Package Id="Microsoft.AspNetCore.Authentication.Twitter" Version="3.1.0" />
<Package Id="Microsoft.AspNetCore.Authentication.WsFederation" Version="3.1.0" />
<Package Id="Microsoft.AspNetCore.Authorization" Version="3.1.0" />
<Package Id="Microsoft.AspNetCore.AzureAppServices.HostingStartup" Version="3.1.0" />
<Package Id="Microsoft.AspNetCore.AzureAppServices.SiteExtension" Version="3.1.0" />
<Package Id="Microsoft.AspNetCore.AzureAppServicesIntegration" Version="3.1.0" />
<Package Id="Microsoft.AspNetCore.Blazor" Version="3.0.0-preview9.19465.2" />
<Package Id="Microsoft.AspNetCore.Blazor.Build" Version="3.0.0-preview9.19465.2" />
<Package Id="Microsoft.AspNetCore.Blazor.DevServer" Version="3.0.0-preview9.19465.2" />
<Package Id="Microsoft.AspNetCore.Blazor.HttpClient" Version="3.0.0-preview9.19465.2" />
<Package Id="Microsoft.AspNetCore.Blazor.Server" Version="3.0.0-preview9.19465.2" />
<Package Id="Microsoft.AspNetCore.Blazor.Templates" Version="3.0.0-preview9.19465.2" />
<Package Id="Microsoft.AspNetCore.Components" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Components.Analyzers" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Components.Authorization" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Components.Forms" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Components.Web" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.ConcurrencyLimiter" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Connections.Abstractions" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Cryptography.Internal" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.DataProtection" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.DataProtection.Abstractions" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.DataProtection.AzureKeyVault" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.DataProtection.AzureStorage" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.DataProtection.EntityFrameworkCore" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.DataProtection.Extensions" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.HeaderPropagation" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Hosting.WindowsServices" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Http.Connections.Client" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Http.Connections.Common" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Http.Features" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Identity.Specification.Tests" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Identity.UI" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.JsonPatch" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Metadata" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.MiddlewareAnalysis" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Mvc.Testing" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.NodeServices" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Owin" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.SignalR.Client" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.SignalR.Client.Core" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.SignalR.Common" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.SignalR.Protocols.Json" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.SignalR.Protocols.MessagePack" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.SignalR.Protocols.NewtonsoftJson" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.SignalR.Specification.Tests" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.SignalR.StackExchangeRedis" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.SpaServices" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.SpaServices.Extensions" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.TestHost" Version="3.0.0" />
<Package Id="Microsoft.dotnet-openapi" Version="3.0.0" />
<Package Id="Microsoft.DotNet.Web.Client.ItemTemplates" Version="3.0.0" />
<Package Id="Microsoft.DotNet.Web.ItemTemplates" Version="3.0.0" />
<Package Id="Microsoft.DotNet.Web.ProjectTemplates.3.0" Version="3.0.0" />
<Package Id="Microsoft.DotNet.Web.Spa.ProjectTemplates.3.0" Version="3.0.0" />
<Package Id="Microsoft.Extensions.ApiDescription.Client" Version="3.0.0" />
<Package Id="Microsoft.Extensions.ApiDescription.Server" Version="3.0.0" />
<Package Id="Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore" Version="3.0.0" />
<Package Id="Microsoft.Extensions.Identity.Core" Version="3.0.0" />
<Package Id="Microsoft.Extensions.Identity.Stores" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Components" Version="3.1.0" />
<Package Id="Microsoft.AspNetCore.Components.Analyzers" Version="3.1.0" />
<Package Id="Microsoft.AspNetCore.Components.Authorization" Version="3.1.0" />
<Package Id="Microsoft.AspNetCore.Components.Forms" Version="3.1.0" />
<Package Id="Microsoft.AspNetCore.Components.Web" Version="3.1.0" />
<Package Id="Microsoft.AspNetCore.ConcurrencyLimiter" Version="3.1.0" />
<Package Id="Microsoft.AspNetCore.Connections.Abstractions" Version="3.1.0" />
<Package Id="Microsoft.AspNetCore.Cryptography.Internal" Version="3.1.0" />
<Package Id="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="3.1.0" />
<Package Id="Microsoft.AspNetCore.DataProtection" Version="3.1.0" />
<Package Id="Microsoft.AspNetCore.DataProtection.Abstractions" Version="3.1.0" />
<Package Id="Microsoft.AspNetCore.DataProtection.AzureKeyVault" Version="3.1.0" />
<Package Id="Microsoft.AspNetCore.DataProtection.AzureStorage" Version="3.1.0" />
<Package Id="Microsoft.AspNetCore.DataProtection.EntityFrameworkCore" Version="3.1.0" />
<Package Id="Microsoft.AspNetCore.DataProtection.Extensions" Version="3.1.0" />
<Package Id="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" Version="3.1.0" />
<Package Id="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="3.1.0" />
<Package Id="Microsoft.AspNetCore.HeaderPropagation" Version="3.1.0" />
<Package Id="Microsoft.AspNetCore.Hosting.WindowsServices" Version="3.1.0" />
<Package Id="Microsoft.AspNetCore.Http.Connections.Client" Version="3.1.0" />
<Package Id="Microsoft.AspNetCore.Http.Connections.Common" Version="3.1.0" />
<Package Id="Microsoft.AspNetCore.Http.Features" Version="3.1.0" />
<Package Id="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="3.1.0" />
<Package Id="Microsoft.AspNetCore.Identity.Specification.Tests" Version="3.1.0" />
<Package Id="Microsoft.AspNetCore.Identity.UI" Version="3.1.0" />
<Package Id="Microsoft.AspNetCore.JsonPatch" Version="3.1.0" />
<Package Id="Microsoft.AspNetCore.Metadata" Version="3.1.0" />
<Package Id="Microsoft.AspNetCore.MiddlewareAnalysis" Version="3.1.0" />
<Package Id="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.1.0" />
<Package Id="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="3.1.0" />
<Package Id="Microsoft.AspNetCore.Mvc.Testing" Version="3.1.0" />
<Package Id="Microsoft.AspNetCore.NodeServices" Version="3.1.0" />
<Package Id="Microsoft.AspNetCore.Owin" Version="3.1.0" />
<Package Id="Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv" Version="3.1.0" />
<Package Id="Microsoft.AspNetCore.SignalR.Client" Version="3.1.0" />
<Package Id="Microsoft.AspNetCore.SignalR.Client.Core" Version="3.1.0" />
<Package Id="Microsoft.AspNetCore.SignalR.Common" Version="3.1.0" />
<Package Id="Microsoft.AspNetCore.SignalR.Protocols.Json" Version="3.1.0" />
<Package Id="Microsoft.AspNetCore.SignalR.Protocols.MessagePack" Version="3.1.0" />
<Package Id="Microsoft.AspNetCore.SignalR.Protocols.NewtonsoftJson" Version="3.1.0" />
<Package Id="Microsoft.AspNetCore.SignalR.Specification.Tests" Version="3.1.0" />
<Package Id="Microsoft.AspNetCore.SignalR.StackExchangeRedis" Version="3.1.0" />
<Package Id="Microsoft.AspNetCore.SpaServices" Version="3.1.0" />
<Package Id="Microsoft.AspNetCore.SpaServices.Extensions" Version="3.1.0" />
<Package Id="Microsoft.AspNetCore.TestHost" Version="3.1.0" />
<Package Id="Microsoft.dotnet-openapi" Version="3.1.0" />
<Package Id="Microsoft.DotNet.Web.Client.ItemTemplates" Version="3.1.0" />
<Package Id="Microsoft.DotNet.Web.ItemTemplates" Version="3.1.0" />
<Package Id="Microsoft.DotNet.Web.ProjectTemplates.3.1" Version="3.1.0" />
<Package Id="Microsoft.DotNet.Web.Spa.ProjectTemplates.3.1" Version="3.1.0" />
<Package Id="Microsoft.Extensions.ApiDescription.Client" Version="3.1.0" />
<Package Id="Microsoft.Extensions.ApiDescription.Server" Version="3.1.0" />
<Package Id="Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore" Version="3.1.0" />
<Package Id="Microsoft.Extensions.Identity.Core" Version="3.1.0" />
<Package Id="Microsoft.Extensions.Identity.Stores" Version="3.1.0" />
</Baseline>

View File

@ -34,6 +34,7 @@
$(RepoRoot)src\Installers\**\*.*proj;
$(RepoRoot)src\SignalR\clients\ts\**\node_modules\**\*.*proj;
$(RepoRoot)src\Components\Web.JS\node_modules\**\*.*proj;
$(RepoRoot)src\Components\Blazor\Build\testassets\**\*.*proj;
$(RepoRoot)src\Components\Blazor\Templates\src\content\**\*.*proj;
$(RepoRoot)src\ProjectTemplates\Web.ProjectTemplates\content\**\*.csproj;
$(RepoRoot)src\ProjectTemplates\Web.ProjectTemplates\content\**\*.fsproj;

View File

@ -15,6 +15,9 @@
<ProjectReferenceProvider Include="GetDocument.Insider" ProjectPath="$(RepoRoot)src\Tools\GetDocumentInsider\src\GetDocumentInsider.csproj" />
<ProjectReferenceProvider Include="Microsoft.AspNetCore.SignalR.Specification.Tests" ProjectPath="$(RepoRoot)src\SignalR\server\Specification.Tests\src\Microsoft.AspNetCore.SignalR.Specification.Tests.csproj" />
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Blazor.Build" ProjectPath="$(RepoRoot)src\Components\Blazor\Build\src\Microsoft.AspNetCore.Blazor.Build.csproj" />
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Blazor.HttpClient" ProjectPath="$(RepoRoot)src\Components\Blazor\Http\src\Microsoft.AspNetCore.Blazor.HttpClient.csproj" />
<ProjectReferenceProvider Include="Mono.WebAssembly.Interop" ProjectPath="$(RepoRoot)src\Components\Blazor\Mono.WebAssembly.Interop\src\Mono.WebAssembly.Interop.csproj" />
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Blazor.Server" ProjectPath="$(RepoRoot)src\Components\Blazor\Server\src\Microsoft.AspNetCore.Blazor.Server.csproj" />
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Blazor.DataAnnotations.Validation" ProjectPath="$(RepoRoot)src\Components\Blazor\Validation\src\Microsoft.AspNetCore.Blazor.DataAnnotations.Validation.csproj" />
<ProjectReferenceProvider Include="Ignitor" ProjectPath="$(RepoRoot)src\Components\Ignitor\src\Ignitor.csproj" />
<ProjectReferenceProvider Include="BlazorServerApp" ProjectPath="$(RepoRoot)src\Components\Samples\BlazorServerApp\BlazorServerApp.csproj" />
@ -137,8 +140,6 @@
<ProjectReferenceProvider Include="Microsoft.AspNetCore.SignalR.StackExchangeRedis" ProjectPath="$(RepoRoot)src\SignalR\server\StackExchangeRedis\src\Microsoft.AspNetCore.SignalR.StackExchangeRedis.csproj" RefProjectPath="$(RepoRoot)src\SignalR\server\StackExchangeRedis\ref\Microsoft.AspNetCore.SignalR.StackExchangeRedis.csproj" />
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Components.Authorization" ProjectPath="$(RepoRoot)src\Components\Authorization\src\Microsoft.AspNetCore.Components.Authorization.csproj" RefProjectPath="$(RepoRoot)src\Components\Authorization\ref\Microsoft.AspNetCore.Components.Authorization.csproj" />
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Blazor" ProjectPath="$(RepoRoot)src\Components\Blazor\Blazor\src\Microsoft.AspNetCore.Blazor.csproj" RefProjectPath="$(RepoRoot)src\Components\Blazor\Blazor\ref\Microsoft.AspNetCore.Blazor.csproj" />
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Blazor.HttpClient" ProjectPath="$(RepoRoot)src\Components\Blazor\Http\src\Microsoft.AspNetCore.Blazor.HttpClient.csproj" RefProjectPath="$(RepoRoot)src\Components\Blazor\Http\ref\Microsoft.AspNetCore.Blazor.HttpClient.csproj" />
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Blazor.Server" ProjectPath="$(RepoRoot)src\Components\Blazor\Server\src\Microsoft.AspNetCore.Blazor.Server.csproj" RefProjectPath="$(RepoRoot)src\Components\Blazor\Server\ref\Microsoft.AspNetCore.Blazor.Server.csproj" />
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Components" ProjectPath="$(RepoRoot)src\Components\Components\src\Microsoft.AspNetCore.Components.csproj" RefProjectPath="$(RepoRoot)src\Components\Components\ref\Microsoft.AspNetCore.Components.csproj" />
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Components.Forms" ProjectPath="$(RepoRoot)src\Components\Forms\src\Microsoft.AspNetCore.Components.Forms.csproj" RefProjectPath="$(RepoRoot)src\Components\Forms\ref\Microsoft.AspNetCore.Components.Forms.csproj" />
<ProjectReferenceProvider Include="Microsoft.AspNetCore.Components.Server" ProjectPath="$(RepoRoot)src\Components\Server\src\Microsoft.AspNetCore.Components.Server.csproj" RefProjectPath="$(RepoRoot)src\Components\Server\ref\Microsoft.AspNetCore.Components.Server.csproj" />

View File

@ -9,9 +9,9 @@
-->
<Dependencies>
<ProductDependencies>
<Dependency Name="Microsoft.AspNetCore.Blazor.Mono" Version="3.1.0-preview4.19576.1">
<Dependency Name="Microsoft.AspNetCore.Blazor.Mono" Version="3.1.0-preview4.19578.1">
<Uri>https://github.com/aspnet/Blazor</Uri>
<Sha>d1f3a3db8a379cc887cd6dde0acf77dcd5e16c36</Sha>
<Sha>9ff01af4257317a90b64959fe1c87aef3da4a36f</Sha>
</Dependency>
<Dependency Name="Microsoft.AspNetCore.Razor.Language" Version="5.0.0-alpha.1.19603.1">
<Uri>https://github.com/aspnet/AspNetCore-Tooling</Uri>

View File

@ -94,7 +94,7 @@
<!-- Only listed explicitly to workaround https://github.com/dotnet/cli/issues/10528 -->
<MicrosoftNETCorePlatformsPackageVersion>5.0.0-alpha.1.19556.7</MicrosoftNETCorePlatformsPackageVersion>
<!-- Packages from aspnet/Blazor -->
<MicrosoftAspNetCoreBlazorMonoPackageVersion>3.1.0-preview4.19576.1</MicrosoftAspNetCoreBlazorMonoPackageVersion>
<MicrosoftAspNetCoreBlazorMonoPackageVersion>3.1.0-preview4.19578.1</MicrosoftAspNetCoreBlazorMonoPackageVersion>
<!-- Packages from aspnet/Extensions -->
<InternalAspNetCoreAnalyzersPackageVersion>5.0.0-alpha1.19603.1</InternalAspNetCoreAnalyzersPackageVersion>
<MicrosoftAspNetCoreAnalyzerTestingPackageVersion>5.0.0-alpha1.19603.1</MicrosoftAspNetCoreAnalyzerTestingPackageVersion>

View File

@ -3,7 +3,6 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework>
<StartArguments>-s https://api.nuget.org/v3/index.json</StartArguments>
<StartWorkingDirectory>$(MSBuildThisFileDirectory)../../</StartWorkingDirectory>
</PropertyGroup>

View File

@ -1,10 +1,10 @@
<!-- This file is automatically generated. -->
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0</TargetFrameworks>
<TargetFrameworks>netstandard2.1</TargetFrameworks>
</PropertyGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
<Compile Include="Microsoft.AspNetCore.Blazor.netstandard2.0.cs" />
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.1'">
<Compile Include="Microsoft.AspNetCore.Blazor.netstandard2.1.cs" />
<Reference Include="Mono.WebAssembly.Interop" />
<Reference Include="Microsoft.AspNetCore.Components.Web" />
<Reference Include="Microsoft.Extensions.Options" />

View File

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<TargetFramework>netstandard2.1</TargetFramework>
<Description>Build client-side single-page applications (SPAs) with Blazor running under WebAssembly.</Description>
<IsShippingPackage>true</IsShippingPackage>
</PropertyGroup>

View File

@ -1,61 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.IO;
using Microsoft.Extensions.CommandLineUtils;
namespace Microsoft.AspNetCore.Blazor.Build.DevServer.Commands
{
class ResolveRuntimeDependenciesCommand
{
public static void Command(CommandLineApplication command)
{
var referencesFile = command.Option("--references",
"The path to a file that lists the paths to given referenced dll files",
CommandOptionType.SingleValue);
var baseClassLibrary = command.Option("--base-class-library",
"Full path to a directory in which BCL assemblies can be found",
CommandOptionType.MultipleValue);
var outputPath = command.Option("--output",
"Path to the output file that will contain the list with the full paths of the resolved assemblies",
CommandOptionType.SingleValue);
var mainAssemblyPath = command.Argument("assembly",
"Path to the assembly containing the entry point of the application.");
command.OnExecute(() =>
{
if (string.IsNullOrEmpty(mainAssemblyPath.Value) ||
!baseClassLibrary.HasValue() || !outputPath.HasValue())
{
command.ShowHelp(command.Name);
return 1;
}
try
{
var referencesSources = referencesFile.HasValue()
? File.ReadAllLines(referencesFile.Value())
: Array.Empty<string>();
RuntimeDependenciesResolver.ResolveRuntimeDependencies(
mainAssemblyPath.Value,
referencesSources,
baseClassLibrary.Values.ToArray(),
outputPath.Value());
return 0;
}
catch (Exception ex)
{
Console.WriteLine($"ERROR: {ex.Message}");
Console.WriteLine(ex.StackTrace);
return 1;
}
});
}
}
}

View File

@ -1,68 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.Extensions.CommandLineUtils;
using System;
using System.IO;
namespace Microsoft.AspNetCore.Blazor.Build.DevServer.Commands
{
internal class WriteBootJsonCommand
{
public static void Command(CommandLineApplication command)
{
var referencesFile = command.Option("--references",
"The path to a file that lists the paths to given referenced dll files",
CommandOptionType.SingleValue);
var embeddedResourcesFile = command.Option("--embedded-resources",
"The path to a file that lists the paths of .NET assemblies that may contain embedded resources (typically, referenced assemblies in their pre-linked states)",
CommandOptionType.SingleValue);
var outputPath = command.Option("--output",
"Path to the output file",
CommandOptionType.SingleValue);
var mainAssemblyPath = command.Argument("assembly",
"Path to the assembly containing the entry point of the application.");
var linkerEnabledFlag = command.Option("--linker-enabled",
"If set, specifies that the application is being built with linking enabled.",
CommandOptionType.NoValue);
command.OnExecute(() =>
{
if (string.IsNullOrEmpty(mainAssemblyPath.Value) || !outputPath.HasValue())
{
command.ShowHelp(command.Name);
return 1;
}
try
{
var referencesSources = referencesFile.HasValue()
? File.ReadAllLines(referencesFile.Value())
: Array.Empty<string>();
var embeddedResourcesSources = embeddedResourcesFile.HasValue()
? File.ReadAllLines(embeddedResourcesFile.Value())
: Array.Empty<string>();
BootJsonWriter.WriteFile(
mainAssemblyPath.Value,
referencesSources,
embeddedResourcesSources,
linkerEnabledFlag.HasValue(),
outputPath.Value());
return 0;
}
catch (Exception ex)
{
Console.WriteLine($"ERROR: {ex.Message}");
Console.WriteLine(ex.StackTrace);
return 1;
}
});
}
}
}

View File

@ -1,33 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNetCore.Blazor.Build.DevServer.Commands;
using Microsoft.Extensions.CommandLineUtils;
namespace Microsoft.AspNetCore.Blazor.Build
{
static class Program
{
static int Main(string[] args)
{
var app = new CommandLineApplication
{
Name = "Microsoft.AspNetCore.Blazor.Build"
};
app.HelpOption("-?|-h|--help");
app.Command("resolve-dependencies", ResolveRuntimeDependenciesCommand.Command);
app.Command("write-boot-json", WriteBootJsonCommand.Command);
if (args.Length > 0)
{
return app.Execute(args);
}
else
{
app.ShowHelp();
return 0;
}
}
}
}

View File

@ -1,95 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.Json;
using Microsoft.AspNetCore.Components;
using Mono.Cecil;
namespace Microsoft.AspNetCore.Blazor.Build
{
internal class BootJsonWriter
{
public static void WriteFile(
string assemblyPath,
string[] assemblyReferences,
string[] embeddedResourcesSources,
bool linkerEnabled,
string outputPath)
{
var embeddedContent = EmbeddedResourcesProcessor.ExtractEmbeddedResources(
embeddedResourcesSources, Path.GetDirectoryName(outputPath));
var bootJsonText = GetBootJsonContent(
Path.GetFileName(assemblyPath),
GetAssemblyEntryPoint(assemblyPath),
assemblyReferences,
embeddedContent,
linkerEnabled);
var normalizedOutputPath = Path.GetFullPath(outputPath);
Console.WriteLine("Writing boot data to: " + normalizedOutputPath);
File.WriteAllText(normalizedOutputPath, bootJsonText);
}
public static string GetBootJsonContent(string assemblyFileName, string entryPoint, string[] assemblyReferences, IEnumerable<EmbeddedResourceInfo> embeddedContent, bool linkerEnabled)
{
var data = new BootJsonData(
assemblyFileName,
entryPoint,
assemblyReferences,
embeddedContent,
linkerEnabled);
return JsonSerializer.Serialize(data, JsonSerializerOptionsProvider.Options);
}
private static string GetAssemblyEntryPoint(string assemblyPath)
{
using (var assemblyDefinition = AssemblyDefinition.ReadAssembly(assemblyPath))
{
var entryPoint = assemblyDefinition.EntryPoint;
if (entryPoint == null)
{
throw new ArgumentException($"The assembly at {assemblyPath} has no specified entry point.");
}
return $"{entryPoint.DeclaringType.FullName}::{entryPoint.Name}";
}
}
/// <summary>
/// Defines the structure of a Blazor boot JSON file
/// </summary>
class BootJsonData
{
public string Main { get; }
public string EntryPoint { get; }
public IEnumerable<string> AssemblyReferences { get; }
public IEnumerable<string> CssReferences { get; }
public IEnumerable<string> JsReferences { get; }
public bool LinkerEnabled { get; }
public BootJsonData(
string entrypointAssemblyWithExtension,
string entryPoint,
IEnumerable<string> assemblyReferences,
IEnumerable<EmbeddedResourceInfo> embeddedContent,
bool linkerEnabled)
{
Main = entrypointAssemblyWithExtension;
EntryPoint = entryPoint;
AssemblyReferences = assemblyReferences;
LinkerEnabled = linkerEnabled;
CssReferences = embeddedContent
.Where(c => c.Kind == EmbeddedResourceKind.Css)
.Select(c => c.RelativePath);
JsReferences = embeddedContent
.Where(c => c.Kind == EmbeddedResourceKind.JavaScript)
.Select(c => c.RelativePath);
}
}
}
}

View File

@ -1,17 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace Microsoft.AspNetCore.Blazor.Build
{
internal class EmbeddedResourceInfo
{
public EmbeddedResourceKind Kind { get; }
public string RelativePath { get; }
public EmbeddedResourceInfo(EmbeddedResourceKind kind, string relativePath)
{
Kind = kind;
RelativePath = relativePath;
}
}
}

View File

@ -1,12 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace Microsoft.AspNetCore.Blazor.Build
{
internal enum EmbeddedResourceKind
{
JavaScript,
Css,
Static
}
}

View File

@ -1,137 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Mono.Cecil;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace Microsoft.AspNetCore.Blazor.Build
{
internal class EmbeddedResourcesProcessor
{
const string ContentSubdirName = "_content";
private readonly static Dictionary<string, EmbeddedResourceKind> _knownResourceKindsByNamePrefix = new Dictionary<string, EmbeddedResourceKind>
{
{ "blazor:js:", EmbeddedResourceKind.JavaScript },
{ "blazor:css:", EmbeddedResourceKind.Css },
{ "blazor:file:", EmbeddedResourceKind.Static },
};
/// <summary>
/// Finds Blazor-specific embedded resources in the specified assemblies, writes them
/// to disk, and returns a description of those resources in dependency order.
/// </summary>
/// <param name="referencedAssemblyPaths">The paths to assemblies that may contain embedded resources.</param>
/// <param name="outputDir">The path to the directory where output is being written.</param>
/// <returns>A description of the embedded resources that were written to disk.</returns>
public static IReadOnlyList<EmbeddedResourceInfo> ExtractEmbeddedResources(
IEnumerable<string> referencedAssemblyPaths, string outputDir)
{
// Clean away any earlier state
var contentDir = Path.Combine(outputDir, ContentSubdirName);
if (Directory.Exists(contentDir))
{
Directory.Delete(contentDir, recursive: true);
}
// First, get an ordered list of AssemblyDefinition instances
var referencedAssemblyDefinitions = referencedAssemblyPaths
.Where(path => !Path.GetFileName(path).StartsWith("System.", StringComparison.Ordinal)) // Skip System.* because they are never going to contain embedded resources that we want
.Select(path => AssemblyDefinition.ReadAssembly(path))
.ToList();
referencedAssemblyDefinitions.Sort(OrderWithReferenceSubjectFirst);
// Now process them in turn
return referencedAssemblyDefinitions
.SelectMany(def => ExtractEmbeddedResourcesFromSingleAssembly(def, outputDir))
.ToList()
.AsReadOnly();
}
private static IEnumerable<EmbeddedResourceInfo> ExtractEmbeddedResourcesFromSingleAssembly(
AssemblyDefinition assemblyDefinition, string outputDirPath)
{
var assemblyName = assemblyDefinition.Name.Name;
foreach (var res in assemblyDefinition.MainModule.Resources)
{
if (TryExtractEmbeddedResource(assemblyName, res, outputDirPath, out var extractedResourceInfo))
{
yield return extractedResourceInfo;
}
}
}
private static bool TryExtractEmbeddedResource(string assemblyName, Resource resource, string outputDirPath, out EmbeddedResourceInfo extractedResourceInfo)
{
if (resource is EmbeddedResource embeddedResource)
{
if (TryInterpretLogicalName(resource.Name, out var kind, out var name))
{
// Prefix the output path with the assembly name to ensure no clashes
// Also be invariant to the OS on which the package was built
name = Path.Combine(ContentSubdirName, assemblyName, EnsureHasPathSeparators(name, Path.DirectorySeparatorChar));
// Write the file content to disk, ensuring we don't try to write outside the output root
var outputPath = Path.GetFullPath(Path.Combine(outputDirPath, name));
if (!outputPath.StartsWith(outputDirPath))
{
throw new InvalidOperationException($"Cannot write embedded resource from assembly '{assemblyName}' to '{outputPath}' because it is outside the expected directory {outputDirPath}");
}
WriteResourceFile(embeddedResource, outputPath);
// The URLs we write into the boot json file need to use web-style directory separators
extractedResourceInfo = new EmbeddedResourceInfo(kind, EnsureHasPathSeparators(name, '/'));
return true;
}
}
extractedResourceInfo = null;
return false;
}
private static void WriteResourceFile(EmbeddedResource resource, string outputPath)
{
Directory.CreateDirectory(Path.GetDirectoryName(outputPath));
using (var outputStream = File.OpenWrite(outputPath))
{
resource.GetResourceStream().CopyTo(outputStream);
}
}
private static string EnsureHasPathSeparators(string name, char desiredSeparatorChar) => name
.Replace('\\', desiredSeparatorChar)
.Replace('/', desiredSeparatorChar);
private static bool TryInterpretLogicalName(string logicalName, out EmbeddedResourceKind kind, out string resolvedName)
{
foreach (var kvp in _knownResourceKindsByNamePrefix)
{
if (logicalName.StartsWith(kvp.Key, StringComparison.Ordinal))
{
kind = kvp.Value;
resolvedName = logicalName.Substring(kvp.Key.Length);
return true;
}
}
kind = default;
resolvedName = default;
return false;
}
// For each assembly B that references A, we want the resources from A to be loaded before
// the references for B (because B's resources might depend on A's resources)
private static int OrderWithReferenceSubjectFirst(AssemblyDefinition a, AssemblyDefinition b)
=> AssemblyHasReference(a, b) ? 1
: AssemblyHasReference(b, a) ? -1
: 0;
private static bool AssemblyHasReference(AssemblyDefinition from, AssemblyDefinition to)
=> from.MainModule.AssemblyReferences
.Select(reference => reference.Name)
.Contains(to.Name.Name, StringComparer.Ordinal);
}
}

View File

@ -1,165 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using Mono.Cecil;
namespace Microsoft.AspNetCore.Blazor.Build
{
internal class RuntimeDependenciesResolver
{
public static void ResolveRuntimeDependencies(
string entryPoint,
string[] applicationDependencies,
string[] monoBclDirectories,
string outputFile)
{
var paths = ResolveRuntimeDependenciesCore(entryPoint, applicationDependencies, monoBclDirectories);
File.WriteAllLines(outputFile, paths);
}
public static IEnumerable<string> ResolveRuntimeDependenciesCore(
string entryPoint,
string[] applicationDependencies,
string[] monoBclDirectories)
{
var assembly = new AssemblyEntry(entryPoint, AssemblyDefinition.ReadAssembly(entryPoint));
var dependencies = applicationDependencies
.Select(a => new AssemblyEntry(a, AssemblyDefinition.ReadAssembly(a)))
.ToArray();
var bcl = monoBclDirectories
.SelectMany(d => Directory.EnumerateFiles(d, "*.dll").Select(f => Path.Combine(d, f)))
.Select(a => new AssemblyEntry(a, AssemblyDefinition.ReadAssembly(a)))
.ToArray();
var assemblyResolutionContext = new AssemblyResolutionContext(
assembly,
dependencies,
bcl);
assemblyResolutionContext.ResolveAssemblies();
var paths = assemblyResolutionContext.Results.Select(r => r.Path);
return paths.Concat(FindPdbs(paths));
}
private static IEnumerable<string> FindPdbs(IEnumerable<string> dllPaths)
{
return dllPaths
.Select(path => Path.ChangeExtension(path, "pdb"))
.Where(path => File.Exists(path));
}
public class AssemblyResolutionContext
{
public AssemblyResolutionContext(
AssemblyEntry assembly,
AssemblyEntry[] dependencies,
AssemblyEntry[] bcl)
{
Assembly = assembly;
Dependencies = dependencies;
Bcl = bcl;
}
public AssemblyEntry Assembly { get; }
public AssemblyEntry[] Dependencies { get; }
public AssemblyEntry[] Bcl { get; }
public IList<AssemblyEntry> Results { get; } = new List<AssemblyEntry>();
internal void ResolveAssemblies()
{
var visitedAssemblies = new HashSet<string>();
var pendingAssemblies = new Stack<AssemblyNameReference>();
pendingAssemblies.Push(Assembly.Definition.Name);
ResolveAssembliesCore();
void ResolveAssembliesCore()
{
while (pendingAssemblies.TryPop(out var current))
{
if (!visitedAssemblies.Contains(current.Name))
{
visitedAssemblies.Add(current.Name);
// Not all references will be resolvable within the Mono BCL, particularly
// when building for server-side Blazor as you will be running on CoreCLR
// and therefore may depend on System.* BCL assemblies that aren't present
// in Mono WebAssembly. Skipping unresolved assemblies here is equivalent
// to passing "--skip-unresolved true" to the Mono linker.
var resolved = Resolve(current);
if (resolved != null)
{
Results.Add(resolved);
var references = GetAssemblyReferences(resolved);
foreach (var reference in references)
{
pendingAssemblies.Push(reference);
}
}
}
}
}
IEnumerable<AssemblyNameReference> GetAssemblyReferences(AssemblyEntry current) =>
current.Definition.Modules.SelectMany(m => m.AssemblyReferences);
AssemblyEntry Resolve(AssemblyNameReference current)
{
if (Assembly.Definition.Name.Name == current.Name)
{
return Assembly;
}
var referencedAssemblyCandidate = FindCandidate(current, Dependencies);
var bclAssemblyCandidate = FindCandidate(current, Bcl);
// Resolution logic. For right now, we will prefer the mono BCL version of a given
// assembly if there is a candidate assembly and an equivalent mono assembly.
if (bclAssemblyCandidate != null)
{
return bclAssemblyCandidate;
}
return referencedAssemblyCandidate;
}
AssemblyEntry FindCandidate(AssemblyNameReference current, AssemblyEntry[] candidates)
{
// Do simple name match. Assume no duplicates.
foreach (var candidate in candidates)
{
if (current.Name == candidate.Definition.Name.Name)
{
return candidate;
}
}
return null;
}
}
}
[DebuggerDisplay("{ToString(),nq}")]
public class AssemblyEntry
{
public AssemblyEntry(string path, AssemblyDefinition definition)
{
Path = path;
Definition = definition;
}
public string Path { get; set; }
public AssemblyDefinition Definition { get; set; }
public override string ToString() => Definition.FullName;
}
}
}

View File

@ -1,41 +1,71 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework>
<TargetFrameworks>$(DefaultNetCoreTargetFramework);net46</TargetFrameworks>
<TargetName>Microsoft.AspNetCore.Blazor.Build.Tasks</TargetName>
<AssemblyName>Microsoft.AspNetCore.Blazor.Build</AssemblyName>
<Description>Build mechanism for ASP.NET Core Blazor applications.</Description>
<OutputType>Exe</OutputType>
<IsShippingPackage>true</IsShippingPackage>
<HasReferenceAssembly>false</HasReferenceAssembly>
<GenerateDependencyFile>false</GenerateDependencyFile>
</PropertyGroup>
<!-- Pack settings -->
<PropertyGroup>
<!-- Producing this package requires building with NodeJS enabled. -->
<IsPackable Condition="'$(BuildNodeJS)' == 'false'">false</IsPackable>
<GenerateNuspecDependsOn>$(GenerateNuspecDependsOn);Publish</GenerateNuspecDependsOn>
<NoPackageAnalysis>true</NoPackageAnalysis>
<NuspecFile>Microsoft.AspNetCore.Blazor.Build.nuspec</NuspecFile>
</PropertyGroup>
<ItemGroup>
<NuspecProperty Include="configuration=$(Configuration)" />
<NuspecProperty Include="publishDir=$(PublishDir)" />
<NuspecProperty Include="taskskDir=$(OutputPath)tools" />
<NuspecProperty Include="componentsversion=$(ComponentsPackageVersion)" />
<NuspecProperty Include="razorversion=$(MicrosoftAspNetCoreRazorDesignPackageVersion)" />
<NuspecProperty Include="blazormonoversion=$(MicrosoftAspNetCoreBlazorMonoPackageVersion)" />
</ItemGroup>
<ItemGroup>
<ProjectReference Condition="'$(BuildNodeJS)' != 'false' and '$(BuildingInsideVisualStudio)' != 'true'" Include="$(RepoRoot)src\Components\Web.JS\Microsoft.AspNetCore.Components.Web.JS.npmproj" ReferenceOutputAssembly="false" />
<Reference Include="Microsoft.AspNetCore.Components" />
<Reference Include="Microsoft.Extensions.CommandLineUtils.Sources" />
<Reference Include="Microsoft.Extensions.FileProviders.Composite" />
<Reference Include="Microsoft.Extensions.FileProviders.Physical" />
<Reference Include="Mono.Cecil" />
<Reference Include="System.CodeDom" />
<!-- Add a project dependency without reference output assemblies to enforce build order -->
<!-- Applying workaround for https://github.com/microsoft/msbuild/issues/2661 and https://github.com/dotnet/sdk/issues/952 -->
<ProjectReference
Include="$(RepoRoot)src\Components\Web.JS\Microsoft.AspNetCore.Components.Web.JS.npmproj"
ReferenceOutputAssemblies="false"
SkipGetTargetFrameworkProperties="true"
UndefineProperties="TargetFramework"
Private="false"
Condition="'$(BuildNodeJS)' != 'false' and '$(BuildingInsideVisualStudio)' != 'true'" />
<Reference Include="Microsoft.Build.Framework" ExcludeAssets="Runtime" />
<Reference Include="Microsoft.Build.Utilities.Core" ExcludeAssets="Runtime" />
<Reference Include="System.Reflection.Metadata" Condition="'$(TargetFramework)' == 'net46'" />
</ItemGroup>
<ItemGroup>
<Compile Include="..\..\..\Shared\src\JsonSerializerOptionsProvider.cs" />
</ItemGroup>
<Target Name="CopyBuildTask" BeforeTargets="Build" Condition="'$(DotNetBuildFromSource)' != 'true' AND '$(IsInnerBuild)' != 'true'">
<!--
The task produced by this project is referenced within this solution. When building, Visual Studio will lock up the assembly.
Any attempts to overwrite the binary with a newer version will fail. This is particularly grating if a developer "Rebuilds" the project
after an initial build since that would always attempt to overwrite the tasks dll
This target attempts to make this solution more usable at the cost of a more onerous inner-loop build of the Blazor.Build tasks.
We'll copy the tasks to a location other that than the build output and use that in the Blazor.Build.targets. In the most common
case where these tasks aren't being worked on, everything should work great. However, if you're attemping to modify these tasks,
you will need to manaully stop MSBuild.exe processes
-->
<ItemGroup>
<_NetCoreFilesToCopy Include="$(OutputPath)$(DefaultNetCoreTargetFramework)\*" TargetPath="netcoreapp\" />
<_DesktopFilesToCopy Include="$(OutputPath)net46\*" TargetPath="netfx\" />
<_AllFilesToCopy Include="@(_NetCoreFilesToCopy);@(_DesktopFilesToCopy)" />
</ItemGroup>
<Error Text="No files found in $(OutputPath)$(DefaultNetCoreTargetFramework)" Condition="@(_NetCoreFilesToCopy->Count()) == 0" />
<Error Text="No files found in $(OutputPath)net46" Condition="@(_DesktopFilesToCopy->Count()) == 0" />
<Copy SourceFiles="@(_AllFilesToCopy)" DestinationFiles="@(_AllFilesToCopy->'$(OutputPath)tools\%(TargetPath)%(FileName)%(Extension)')" SkipUnchangedFiles="true" Retries="1" ContinueOnError="true">
<Output TaskParameter="CopiedFiles" ItemName="FileWrites" />
</Copy>
</Target>
</Project>

View File

@ -11,7 +11,7 @@
<file src="..\..\..\THIRD-PARTY-NOTICES.txt" />
<file src="build\**" target="build" />
<file src="targets\**" target="targets" />
<file src="$publishdir$**\*" target="tools/" />
<file src="..\..\..\Web.JS\dist\$configuration$\blazor.*.js" target="tools/blazor" />
<file src="$taskskDir$\**" target="tools/" />
<file src="..\..\..\Web.JS\dist\$configuration$\blazor.webassembly.js" target="tools/blazor" />
</files>
</package>

View File

@ -0,0 +1,25 @@
<Project>
<!--
Importing this file is equivalent to having:
<PackageDependency Include="Microsoft.AspNetCore.Blazor.Build" />
... except it's much more convenient when working in this repo, because it consumes the
Blazor.Build targets/exe directly without needing this project to be packed into a .nupkg.
This is only intended for use by other projects in this repo.
-->
<PropertyGroup>
<ComponentsRoot Condition="'$(ComponentsRoot)'==''">$(MSBuildThisFileDirectory)..\..\..\</ComponentsRoot>
<BlazorJsPath>$(ComponentsRoot)Web.JS\dist\$(Configuration)\blazor.webassembly.js</BlazorJsPath>
<BlazorJsMapPath>$(ComponentsRoot)Web.JS\dist\$(Configuration)\blazor.webassembly.js.map</BlazorJsMapPath>
<BlazorToolsDir>$(MSBuildThisFileDirectory)bin\$(Configuration)\tools\</BlazorToolsDir>
</PropertyGroup>
<Target Name="CheckBlazorJSFiles" BeforeTargets="Build">
<Error Text="blazor.webassembly.js file could not be found at $(BlazorJsPath)" Condition="!Exists($(BlazorJsPath))" />
</Target>
<Import Project="$(MSBuildThisFileDirectory)targets/All.props" />
<Import Project="$(MSBuildThisFileDirectory)targets/All.targets" />
</Project>

View File

@ -1,21 +1,6 @@
<Project>
<!--
Importing this file is equivalent to having:
<PackageDependency Include="Microsoft.AspNetCore.Blazor.Build" />
... except it's much more convenient when working in this repo, because it consumes the
Blazor.Build targets/exe directly without needing this project to be packed into a .nupkg.
This is only intended for use by other projects in this repo.
-->
<PropertyGroup>
<BlazorBuildReferenceFromSource>true</BlazorBuildReferenceFromSource>
<BlazorJsPath>$(RepoRoot)src\Components\Web.JS\dist\$(Configuration)\blazor.*.js.*</BlazorJsPath>
</PropertyGroup>
<Import Project="$(MSBuildThisFileDirectory)targets/All.props" />
<Import Project="$(MSBuildThisFileDirectory)targets/All.targets" />
<Import Project="ReferenceBlazorBuildFromSource.props" />
<!--
Debugging support using blazor-devserver serve.
@ -35,6 +20,14 @@
<Reference Include="Microsoft.AspNetCore.Blazor.Mono" />
</ItemGroup>
<Target Name="_BuildBlazorBuildProject" BeforeTargets="ResolveProjectReferences">
<!--
The Blazor.Build project cross-compiles and we need the output of all TFMs to be available in the build output.
We can't represent this in any good way using ProjectReference elements, but we can try and build it instead.
-->
<MSBuild Projects="$(MSBuildThisFileDirectory)Microsoft.AspNetCore.Blazor.Build.csproj" />
</Target>
<!-- This is used as a P2P when building the repo. Normal Blazor projects will get this as a reference through the Blazor.Build package -->
<ItemGroup>
<!-- Ensures these projects are built before the consuming project, but without
@ -42,9 +35,8 @@
given that the packed version of this project wouldn't add a .dll reference) -->
<ProjectReference Include="$(MSBuildThisFileDirectory)Microsoft.AspNetCore.Blazor.Build.csproj">
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
<!-- Optimization. Do not require framework compatibility between these projects. -->
<SkipGetTargetFrameworkProperties>true</SkipGetTargetFrameworkProperties>
<UndefineProperties>TargetFramework</UndefineProperties>
<Properties>TargetFramework=$(DefaultNetCoreTargetFramework)</Properties>
</ProjectReference>
<ProjectReference Include="$(MSBuildThisFileDirectory)..\..\DevServer\src\Microsoft.AspNetCore.Blazor.DevServer.csproj">
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>

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.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml;
using System.Xml.Linq;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
namespace Microsoft.AspNetCore.Blazor.Build
{
// Based on https://github.com/mono/linker/blob/3b329b9481e300bcf4fb88a2eebf8cb5ef8b323b/src/ILLink.Tasks/CreateRootDescriptorFile.cs
public class BlazorCreateRootDescriptorFile : Task
{
[Required]
public ITaskItem[] AssemblyNames { get; set; }
[Required]
public ITaskItem RootDescriptorFilePath { get; set; }
public override bool Execute()
{
using var fileStream = File.Create(RootDescriptorFilePath.ItemSpec);
var assemblyNames = AssemblyNames.Select(a => a.ItemSpec);
WriteRootDescriptor(fileStream, assemblyNames);
return true;
}
internal static void WriteRootDescriptor(Stream stream, IEnumerable<string> assemblyNames)
{
var roots = new XElement("linker");
foreach (var assemblyName in assemblyNames)
{
roots.Add(new XElement("assembly",
new XAttribute("fullname", assemblyName),
new XElement("type",
new XAttribute("fullname", "*"),
new XAttribute("required", "true"))));
}
var xmlWriterSettings = new XmlWriterSettings
{
Indent = true,
OmitXmlDeclaration = true
};
using var writer = XmlWriter.Create(stream, xmlWriterSettings);
var xDocument = new XDocument(roots);
xDocument.Save(writer);
}
}
}

View File

@ -0,0 +1,189 @@
// 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.IO;
using System.Text;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
namespace Microsoft.AspNetCore.Blazor.Build.Tasks
{
// Based on https://github.com/mono/linker/blob/3b329b9481e300bcf4fb88a2eebf8cb5ef8b323b/src/ILLink.Tasks/LinkTask.cs
public class BlazorILLink : ToolTask
{
private const string DotNetHostPathEnvironmentName = "DOTNET_HOST_PATH";
[Required]
public string ILLinkPath { get; set; }
[Required]
public ITaskItem[] AssemblyPaths { get; set; }
public ITaskItem[] ReferenceAssemblyPaths { get; set; }
[Required]
public ITaskItem[] RootAssemblyNames { get; set; }
[Required]
public ITaskItem OutputDirectory { get; set; }
public ITaskItem[] RootDescriptorFiles { get; set; }
public bool ClearInitLocals { get; set; }
public string ClearInitLocalsAssemblies { get; set; }
public string ExtraArgs { get; set; }
public bool DumpDependencies { get; set; }
private string _dotnetPath;
private string DotNetPath
{
get
{
if (!string.IsNullOrEmpty(_dotnetPath))
{
return _dotnetPath;
}
_dotnetPath = Environment.GetEnvironmentVariable(DotNetHostPathEnvironmentName);
if (string.IsNullOrEmpty(_dotnetPath))
{
throw new InvalidOperationException($"{DotNetHostPathEnvironmentName} is not set");
}
return _dotnetPath;
}
}
protected override MessageImportance StandardErrorLoggingImportance => MessageImportance.High;
protected override string ToolName => Path.GetFileName(DotNetPath);
protected override string GenerateFullPathToTool() => DotNetPath;
protected override string GenerateCommandLineCommands() => ILLinkPath;
private static string Quote(string path)
{
return $"\"{path.TrimEnd('\\')}\"";
}
protected override string GenerateResponseFileCommands()
{
var args = new StringBuilder();
if (RootDescriptorFiles != null)
{
foreach (var rootFile in RootDescriptorFiles)
{
args.Append("-x ").AppendLine(Quote(rootFile.ItemSpec));
}
}
foreach (var assemblyItem in RootAssemblyNames)
{
args.Append("-a ").AppendLine(Quote(assemblyItem.ItemSpec));
}
var assemblyNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
foreach (var assembly in AssemblyPaths)
{
var assemblyPath = assembly.ItemSpec;
var assemblyName = Path.GetFileNameWithoutExtension(assemblyPath);
// If there are multiple paths with the same assembly name, only use the first one.
if (!assemblyNames.Add(assemblyName))
{
continue;
}
args.Append("-reference ")
.AppendLine(Quote(assemblyPath));
var action = assembly.GetMetadata("action");
if ((action != null) && (action.Length > 0))
{
args.Append("-p ");
args.Append(action);
args.Append(" ").AppendLine(Quote(assemblyName));
}
}
if (ReferenceAssemblyPaths != null)
{
foreach (var assembly in ReferenceAssemblyPaths)
{
var assemblyPath = assembly.ItemSpec;
var assemblyName = Path.GetFileNameWithoutExtension(assemblyPath);
// Don't process references for which we already have
// implementation assemblies.
if (assemblyNames.Contains(assemblyName))
{
continue;
}
args.Append("-reference ").AppendLine(Quote(assemblyPath));
// Treat reference assemblies as "skip". Ideally we
// would not even look at the IL, but only use them to
// resolve surface area.
args.Append("-p skip ").AppendLine(Quote(assemblyName));
}
}
if (OutputDirectory != null)
{
args.Append("-out ").AppendLine(Quote(OutputDirectory.ItemSpec));
}
if (ClearInitLocals)
{
args.AppendLine("--enable-opt clearinitlocals");
if ((ClearInitLocalsAssemblies != null) && (ClearInitLocalsAssemblies.Length > 0))
{
args.Append("-m ClearInitLocalsAssemblies ");
args.AppendLine(ClearInitLocalsAssemblies);
}
}
if (ExtraArgs != null)
{
args.AppendLine(ExtraArgs);
}
if (DumpDependencies)
{
args.AppendLine("--dump-dependencies");
}
return args.ToString();
}
protected override bool HandleTaskExecutionErrors()
{
// Show a slightly better error than the standard ToolTask message that says "dotnet" failed.
Log.LogError($"ILLink failed with exited code {ExitCode}.");
return false;
}
protected override void LogEventsFromTextOutput(string singleLine, MessageImportance messageImportance)
{
if (!string.IsNullOrEmpty(singleLine) && singleLine.StartsWith("Unhandled exception.", StringComparison.Ordinal))
{
// The Mono linker currently prints out an entire stack trace when the linker fails.
// We want to show something actionable in the VS Error window.
Log.LogError(singleLine);
}
else
{
base.LogEventsFromTextOutput(singleLine, messageImportance);
}
}
}
}

View File

@ -0,0 +1,74 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization.Json;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
namespace Microsoft.AspNetCore.Blazor.Build
{
public class GenerateBlazorBootJson : Task
{
[Required]
public string AssemblyPath { get; set; }
[Required]
public ITaskItem[] References { get; set; }
[Required]
public bool LinkerEnabled { get; set; }
[Required]
public string OutputPath { get; set; }
public override bool Execute()
{
var entryAssemblyName = AssemblyName.GetAssemblyName(AssemblyPath).Name;
var assemblies = References.Select(c => Path.GetFileName(c.ItemSpec)).ToArray();
using var fileStream = File.Create(OutputPath);
WriteBootJson(fileStream, entryAssemblyName, assemblies, LinkerEnabled);
return true;
}
internal static void WriteBootJson(Stream stream, string entryAssemblyName, string[] assemblies, bool linkerEnabled)
{
var data = new BootJsonData
{
entryAssembly = entryAssemblyName,
assemblies = assemblies,
linkerEnabled = linkerEnabled,
};
var serializer = new DataContractJsonSerializer(typeof(BootJsonData));
serializer.WriteObject(stream, data);
}
/// <summary>
/// Defines the structure of a Blazor boot JSON file
/// </summary>
#pragma warning disable IDE1006 // Naming Styles
public class BootJsonData
{
/// <summary>
/// Gets the name of the assembly with the application entry point
/// </summary>
public string entryAssembly { get; set; }
/// <summary>
/// Gets the closure of assemblies to be loaded by Blazor WASM. This includes the application entry assembly.
/// </summary>
public string[] assemblies { get; set; }
/// <summary>
/// Gets a value that determines if the linker is enabled.
/// </summary>
public bool linkerEnabled { get; set; }
}
#pragma warning restore IDE1006 // Naming Styles
}
}

View File

@ -0,0 +1,203 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Metadata;
using System.Reflection.PortableExecutable;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
namespace Microsoft.AspNetCore.Blazor.Build
{
public class ResolveBlazorRuntimeDependencies : Task
{
[Required]
public string EntryPoint { get; set; }
[Required]
public ITaskItem[] ApplicationDependencies { get; set; }
[Required]
public ITaskItem[] WebAssemblyBCLAssemblies { get; set; }
[Output]
public ITaskItem[] Dependencies { get; set; }
public override bool Execute()
{
var paths = ResolveRuntimeDependenciesCore(EntryPoint, ApplicationDependencies.Select(c => c.ItemSpec), WebAssemblyBCLAssemblies.Select(c => c.ItemSpec));
Dependencies = paths.Select(p => new TaskItem(p)).ToArray();
return true;
}
public static IEnumerable<string> ResolveRuntimeDependenciesCore(
string entryPoint,
IEnumerable<string> applicationDependencies,
IEnumerable<string> monoBclAssemblies)
{
var entryAssembly = new AssemblyEntry(entryPoint, GetAssemblyName(entryPoint));
var dependencies = CreateAssemblyLookup(applicationDependencies);
var bcl = CreateAssemblyLookup(monoBclAssemblies);
var assemblyResolutionContext = new AssemblyResolutionContext(
entryAssembly,
dependencies,
bcl);
assemblyResolutionContext.ResolveAssemblies();
var paths = assemblyResolutionContext.Results.Select(r => r.Path);
return paths.Concat(FindPdbs(paths));
static Dictionary<string, AssemblyEntry> CreateAssemblyLookup(IEnumerable<string> assemblyPaths)
{
var dictionary = new Dictionary<string, AssemblyEntry>(StringComparer.Ordinal);
foreach (var path in assemblyPaths)
{
var assemblyName = AssemblyName.GetAssemblyName(path).Name;
if (dictionary.TryGetValue(assemblyName, out var previous))
{
throw new InvalidOperationException($"Multiple assemblies found with the same assembly name '{assemblyName}':" +
Environment.NewLine + string.Join(Environment.NewLine, previous, path));
}
dictionary[assemblyName] = new AssemblyEntry(path, assemblyName);
}
return dictionary;
}
}
private static string GetAssemblyName(string assemblyPath)
{
return AssemblyName.GetAssemblyName(assemblyPath).Name;
}
private static IEnumerable<string> FindPdbs(IEnumerable<string> dllPaths)
{
return dllPaths
.Select(path => Path.ChangeExtension(path, "pdb"))
.Where(path => File.Exists(path));
}
public class AssemblyResolutionContext
{
public AssemblyResolutionContext(
AssemblyEntry entryAssembly,
Dictionary<string, AssemblyEntry> dependencies,
Dictionary<string, AssemblyEntry> bcl)
{
EntryAssembly = entryAssembly;
Dependencies = dependencies;
Bcl = bcl;
}
public AssemblyEntry EntryAssembly { get; }
public Dictionary<string, AssemblyEntry> Dependencies { get; }
public Dictionary<string, AssemblyEntry> Bcl { get; }
public IList<AssemblyEntry> Results { get; } = new List<AssemblyEntry>();
internal void ResolveAssemblies()
{
var visitedAssemblies = new HashSet<string>();
var pendingAssemblies = new Stack<string>();
pendingAssemblies.Push(EntryAssembly.Name);
ResolveAssembliesCore();
void ResolveAssembliesCore()
{
while (pendingAssemblies.Count > 0)
{
var current = pendingAssemblies.Pop();
if (visitedAssemblies.Add(current))
{
// Not all references will be resolvable within the Mono BCL.
// Skipping unresolved assemblies here is equivalent to passing "--skip-unresolved true" to the Mono linker.
if (Resolve(current) is AssemblyEntry resolved)
{
Results.Add(resolved);
var references = GetAssemblyReferences(resolved.Path);
foreach (var reference in references)
{
pendingAssemblies.Push(reference);
}
}
}
}
}
AssemblyEntry? Resolve(string assemblyName)
{
if (EntryAssembly.Name == assemblyName)
{
return EntryAssembly;
}
// Resolution logic. For right now, we will prefer the mono BCL version of a given
// assembly if there is a candidate assembly and an equivalent mono assembly.
if (Bcl.TryGetValue(assemblyName, out var assembly) ||
Dependencies.TryGetValue(assemblyName, out assembly))
{
return assembly;
}
return null;
}
static IReadOnlyList<string> GetAssemblyReferences(string assemblyPath)
{
try
{
using var peReader = new PEReader(File.OpenRead(assemblyPath));
if (!peReader.HasMetadata)
{
return Array.Empty<string>(); // not a managed assembly
}
var metadataReader = peReader.GetMetadataReader();
var references = new List<string>();
foreach (var handle in metadataReader.AssemblyReferences)
{
var reference = metadataReader.GetAssemblyReference(handle);
var referenceName = metadataReader.GetString(reference.Name);
references.Add(referenceName);
}
return references;
}
catch (BadImageFormatException)
{
// not a PE file, or invalid metadata
}
return Array.Empty<string>(); // not a managed assembly
}
}
}
[DebuggerDisplay("{ToString(),nq}")]
public readonly struct AssemblyEntry
{
public AssemblyEntry(string path, string name)
{
Path = path;
Name = name;
}
public string Path { get; }
public string Name { get; }
public override string ToString() => Name;
}
}
}

View File

@ -6,8 +6,10 @@
</PropertyGroup>
<PropertyGroup>
<BlazorToolsDir Condition="'$(BlazorToolsDir)' == ''">$(MSBuildThisFileDirectory)../tools/</BlazorToolsDir>
<BlazorBuildExe>dotnet &quot;$(BlazorToolsDir)Microsoft.AspNetCore.Blazor.Build.dll&quot;</BlazorBuildExe>
<BlazorToolsDir Condition="'$(BlazorToolsDir)' == ''">$(MSBuildThisFileDirectory)..\tools\</BlazorToolsDir>
<_BlazorTasksTFM Condition=" '$(MSBuildRuntimeType)' == 'Core'">netcoreapp</_BlazorTasksTFM>
<_BlazorTasksTFM Condition=" '$(_BlazorTasksTFM)' == ''">netfx</_BlazorTasksTFM>
<BlazorTasksPath>$(BlazorToolsDir)$(_BlazorTasksTFM)\Microsoft.AspNetCore.Blazor.Build.Tasks.dll</BlazorTasksPath>
<!-- The Blazor build code can only find your referenced assemblies if they are in the output directory -->
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
@ -15,32 +17,30 @@
<Import Project="Blazor.MonoRuntime.targets" />
<Import Project="Publish.targets" />
<Import Project="StaticWebAssets.targets" />
<Target Name="GenerateBlazorMetadataFile" BeforeTargets="GetCopyToOutputDirectoryItems">
<Target Name="GenerateBlazorMetadataFile"
BeforeTargets="GetCopyToOutputDirectoryItems">
<PropertyGroup>
<BlazorMetadataFileName>$(AssemblyName).blazor.config</BlazorMetadataFileName>
<BlazorMetadataFilePath>$(TargetDir)$(BlazorMetadataFileName)</BlazorMetadataFilePath>
</PropertyGroup>
<WriteLinesToFile File="$(BlazorMetadataFilePath)" Lines="$(MSBuildProjectFullPath)" Overwrite="true" Encoding="Unicode"/>
<WriteLinesToFile File="$(BlazorMetadataFilePath)" Lines="$(OutDir)$(AssemblyName).dll" Overwrite="false" Encoding="Unicode"/>
<WriteLinesToFile File="$(BlazorMetadataFilePath)" Condition="'$(BlazorRebuildOnFileChange)'=='true'" Lines="autorebuild:true" Overwrite="false" Encoding="Unicode"/>
<WriteLinesToFile File="$(BlazorMetadataFilePath)" Condition="'$(BlazorEnableDebugging)'=='true'" Lines="debug:true" Overwrite="false" Encoding="Unicode"/>
<ItemGroup>
<_BlazorConfigContent Include="$(MSBuildProjectFullPath)" />
<_BlazorConfigContent Include="$(TargetPath)" />
<_BlazorConfigContent Include="debug:true" Condition="'$(BlazorEnableDebugging)'=='true'" />
</ItemGroup>
<WriteLinesToFile
File="$(BlazorMetadataFilePath)"
Lines="@(_BlazorConfigContent)"
Overwrite="true"
WriteOnlyWhenDifferent="True" />
<ItemGroup>
<ContentWithTargetPath Include="$(BlazorMetadataFilePath)" TargetPath="$(BlazorMetadataFileName)" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>
</Target>
<PropertyGroup>
<GetCurrentProjectStaticWebAssetsDependsOn>
$(GetCurrentProjectStaticWebAssetsDependsOn);
_ClearCurrentStaticWebAssetsForReferenceDiscovery
</GetCurrentProjectStaticWebAssetsDependsOn>
</PropertyGroup>
<Target Name="_ClearCurrentStaticWebAssetsForReferenceDiscovery">
<ItemGroup>
<StaticWebAsset Remove="@(StaticWebAsset)" Condition="'%(SourceType)' == ''" />
</ItemGroup>
</Target>
</Project>

View File

@ -1,22 +1,20 @@
<Project>
<PropertyGroup Condition="'$(BlazorBuildReferenceFromSource)'==''">
<BlazorJsPath>$(MSBuildThisFileDirectory)../tools/blazor/blazor.*.js</BlazorJsPath>
<PropertyGroup>
<BlazorJsPath Condition="'$(BlazorJsPath)' == ''">$(MSBuildThisFileDirectory)..\tools\blazor\blazor.webassembly.js</BlazorJsPath>
</PropertyGroup>
<PropertyGroup Label="Blazor build outputs">
<MonoLinkerI18NAssemblies>none</MonoLinkerI18NAssemblies> <!-- See Mono linker docs - allows comma-separated values from: none,all,cjk,mideast,other,rare,west -->
<AdditionalMonoLinkerOptions>--disable-opt unreachablebodies --verbose --strip-security true --exclude-feature com --exclude-feature sre -v false -c link -u link -b true</AdditionalMonoLinkerOptions>
<BaseBlazorDistPath>dist/</BaseBlazorDistPath>
<BaseBlazorPackageContentOutputPath>$(BaseBlazorDistPath)_content/</BaseBlazorPackageContentOutputPath>
<BaseBlazorRuntimeOutputPath>$(BaseBlazorDistPath)_framework/</BaseBlazorRuntimeOutputPath>
<BaseBlazorRuntimeBinOutputPath>$(BaseBlazorRuntimeOutputPath)_bin/</BaseBlazorRuntimeBinOutputPath>
<BaseBlazorRuntimeWasmOutputPath>$(BaseBlazorRuntimeOutputPath)wasm/</BaseBlazorRuntimeWasmOutputPath>
<BaseBlazorJsOutputPath>$(BaseBlazorRuntimeOutputPath)</BaseBlazorJsOutputPath>
<BaseBlazorIntermediateOutputPath>blazor/</BaseBlazorIntermediateOutputPath>
<BlazorWebRootName>wwwroot/</BlazorWebRootName>
<BaseBlazorDistPath>dist\</BaseBlazorDistPath>
<BaseBlazorPackageContentOutputPath>$(BaseBlazorDistPath)_content\</BaseBlazorPackageContentOutputPath>
<BaseBlazorRuntimeOutputPath>$(BaseBlazorDistPath)_framework\</BaseBlazorRuntimeOutputPath>
<BlazorRuntimeBinOutputPath>$(BaseBlazorRuntimeOutputPath)_bin\</BlazorRuntimeBinOutputPath>
<BlazorRuntimeWasmOutputPath>$(BaseBlazorRuntimeOutputPath)wasm\</BlazorRuntimeWasmOutputPath>
<BlazorWebRootName>wwwroot\</BlazorWebRootName>
<BlazorBootJsonName>blazor.boot.json</BlazorBootJsonName>
<BlazorBootJsonOutputPath>$(BaseBlazorRuntimeOutputPath)$(BlazorBootJsonName)</BlazorBootJsonOutputPath>
<_BlazorBuiltInBclLinkerDescriptor>$(MSBuildThisFileDirectory)BuiltInBclLinkerDescriptor.xml</_BlazorBuiltInBclLinkerDescriptor>
</PropertyGroup>
</Project>

View File

@ -1,206 +1,85 @@
<Project>
<PropertyGroup>
<BlazorLinkOnBuild Condition="$(BlazorLinkOnBuild) == ''">true</BlazorLinkOnBuild>
</PropertyGroup>
<PropertyGroup>
<!-- Stop-gap until we can migrate Blazor.Mono package to use better naming convention -->
<DotNetWebAssemblyBCLPath Condition="'$(DotNetWebAssemblyBCLPath)' == '' AND '$(MonoBaseClassLibraryPath)' != ''">$(MonoBaseClassLibraryPath)</DotNetWebAssemblyBCLPath>
<DotNetWebAssemblyBCLFacadesPath Condition="'$(DotNetWebAssemblyBCLFacadesPath)' == '' AND '$(MonoBaseClassLibraryFacadesPath)' != ''">$(MonoBaseClassLibraryFacadesPath)</DotNetWebAssemblyBCLFacadesPath>
<DotNetWebAssemblyRuntimePath Condition="'$(DotNetWebAssemblyRuntimePath)' == '' AND '$(MonoWasmRuntimePath)' != ''">$(MonoWasmRuntimePath)</DotNetWebAssemblyRuntimePath>
<DotNetWebAssemblyFrameworkPath Condition="'$(DotNetWebAssemblyFrameworkPath)' == '' AND '$(MonoWasmFrameworkPath)' != ''">$(MonoWasmFrameworkPath)</DotNetWebAssemblyFrameworkPath>
</PropertyGroup>
<PropertyGroup Condition="'$(DotNetWebAssemblyArtifactsRoot)' != ''">
<!-- Compute paths given a path to DotNet WASM artifacts. This is meant to make it easy to test WASM builds -->
<DotNetWebAssemblyBCLPath>$(DotNetWebAssemblyArtifactsRoot)\wasm-bcl\wasm\</DotNetWebAssemblyBCLPath>
<DotNetWebAssemblyBCLFacadesPath>$(DotNetWebAssemblyBCLPath)\Facades\</DotNetWebAssemblyBCLFacadesPath>
<DotNetWebAssemblyRuntimePath>$(DotNetWebAssemblyArtifactsRoot)\builds\debug\</DotNetWebAssemblyRuntimePath>
<DotNetWebAssemblyFrameworkPath>$(DotNetWebAssemblyArtifactsRoot)\framework\</DotNetWebAssemblyFrameworkPath>
</PropertyGroup>
<Target
Name="_BlazorCopyFilesToOutputDirectory"
DependsOnTargets="PrepareBlazorOutputs"
Inputs="@(BlazorItemOutput)"
Outputs="@(BlazorItemOutput->'%(TargetOutputPath)')"
Inputs="@(BlazorOutputWithTargetPath)"
Outputs="@(BlazorOutputWithTargetPath->'$(TargetDir)%(TargetOutputPath)')"
AfterTargets="CopyFilesToOutputDirectory"
Condition="'$(OutputType.ToLowerInvariant())'=='exe'">
<!-- Copy the blazor output files -->
<Copy
SourceFiles="@(BlazorItemOutput)"
DestinationFiles="@(BlazorItemOutput->'%(TargetOutputPath)')"
SourceFiles="@(BlazorOutputWithTargetPath)"
DestinationFiles="@(BlazorOutputWithTargetPath->'$(TargetDir)%(TargetOutputPath)')"
SkipUnchangedFiles="$(SkipCopyUnchangedFiles)"
OverwriteReadOnlyFiles="$(OverwriteReadOnlyFiles)"
Retries="$(CopyRetryCount)"
RetryDelayMilliseconds="$(CopyRetryDelayMilliseconds)"
UseHardlinksIfPossible="$(CreateHardLinksForCopyFilesToOutputDirectoryIfPossible)"
UseSymboliclinksIfPossible="$(CreateSymbolicLinksForCopyFilesToOutputDirectoryIfPossible)"
Condition="'@(BlazorItemOutput)' != '' and '$(CopyBuildOutputToOutputDirectory)' == 'true' and '$(SkipCopyBuildProduct)' != 'true'">
Condition="'@(BlazorOutputWithTargetPath)' != '' and '$(CopyBuildOutputToOutputDirectory)' == 'true' and '$(SkipCopyBuildProduct)' != 'true'">
</Copy>
<ItemGroup>
<FileWrites Include="@(BlazorItemOutput->'%(TargetOutputPath)')" />
<FileWrites Include="@(BlazorOutputWithTargetPath->'$(TargetDir)%(TargetOutputPath)')" />
</ItemGroup>
</Target>
<Target Name="_BlazorTrackResolveReferencesDidRun" AfterTargets="ResolveReferences">
<PropertyGroup>
<!-- So we know we can trust @(ReferenceCopyLocalPaths) later -->
<_BlazorResolveReferencesDidRun>true</_BlazorResolveReferencesDidRun>
</PropertyGroup>
</Target>
<Target Name="_BlazorBuildReport"
AfterTargets="_BlazorCopyFilesToOutputDirectory">
<ItemGroup>
<_BlazorStatisticsOutput Include="@(BlazorItemOutput->'%(TargetOutputPath)')" />
<_BlazorStatisticsOutput Include="@(BlazorOutputWithTargetPath->'%(TargetOutputPath)')" />
</ItemGroup>
<PropertyGroup>
<_BlazorStatisticsReportImportance Condition="'$(BlazorOutputStatistics)' == ''">normal</_BlazorStatisticsReportImportance>
<_BlazorStatisticsReportImportance Condition="'$(BlazorOutputStatistics)' != ''">high</_BlazorStatisticsReportImportance>
</PropertyGroup>
<Message Importance="high" Text="Blazor Build result -> @(_BlazorStatisticsOutput->Distinct()->Count()) files in $(TargetDir)dist" />
<Message Importance="$(_BlazorStatisticsReportImportance)" Text="%(_BlazorStatisticsOutput.Identity)" />
<Message Importance="high" Text="$(TargetName) (Blazor output) -> $(TargetDir)dist" />
</Target>
<!-- Preparing blazor files for output:
PrepareBlazorOutputs
_PrepareBlazorOutputConfiguration
_DefineBlazorCommonInputs
_BlazorResolveOutputBinaries
When link on build:
_GenerateLinkerDescriptor
_CollectBlazorLinkerDescriptors
_LinkBlazorApplication
_CollectLinkerOutputs
When don't link on build:
_CollectResolvedAssemblies
_ResolveBlazorApplicationAssemblies
_ReadResolvedBlazorApplicationAssemblies
_IntermediateCopyBlazorApplicationAssemblies
_TouchBlazorApplicationAssemblies
_GenerateBlazorBootJson
_BlazorCopyFilesToOutputDirectory
<Target
Name="PrepareBlazorOutputs"
DependsOnTargets="_ResolveBlazorInputs;_ResolveBlazorOutputs;_GenerateBlazorBootJson">
The process for doing builds goes as follows:
Produce a hash file with the Hash SDK task and write that hash to a marker file.
Produce a marker file that saves whether we are linking or not in this build so that we can take that as
input in future builds and do the correct thing for incremental builds.
We only produce marker files when the input changes, if the input doesn't change the marker stays the
same.
<ItemGroup>
<MonoWasmFile Include="$(DotNetWebAssemblyRuntimePath)*" />
<BlazorJSFile Include="$(BlazorJSPath)" />
<BlazorJSFile Include="$(BlazorJSMapPath)" Condition="Exists('$(BlazorJSMapPath)')" />
If we are linking on this build the process is as follows:
1) We determine if there are linker descriptors available, if not generate one.
2) Collect the list of linker descriptors and create a marker for the linker if it doesn't exist or changed
from a previous build.
3) Run the linker in case the linker inputs marker is newer than the linker result file.
4) Collect the outputs from the linker.
If we are not linking in this build the process is as follows:
1) Resolve the assemblies for the application only if the inputs marker is newer than the resolved assemblies
result file.
2) Read the result file with the resolved assemblies.
3) Copy the resolved assemblies to an intermediate folder.
4) In case we are switching from linking to not linking, touch the files in the intermediate folder to ensure
that updated versions of the files get copied to the output folder.
Once the binary outputs are resolved:
1) Create a marker file with the resolved assemblies and the boot json data as inputs.
2) If the marker file is newer than the boot json in the output folder, regenerate the
boot json
Once all the outputs are resolved (static content + binary outputs + boot json)
Copy all the files to the output folder.
-->
<PropertyGroup>
<PrepareBlazorOutputs>
_PrepareBlazorOutputConfiguration;
_DefineBlazorCommonInputs;
_BlazorResolveOutputBinaries;
_GenerateBlazorBootJson;
</PrepareBlazorOutputs>
</PropertyGroup>
<Target Name="PrepareBlazorOutputs" DependsOnTargets="$(PrepareBlazorOutputs)" />
<!--
Prepare blazor outputs preamble:
* Creates updated marker files (if necessary) for incremental builds.
* Computes intermediate and final output paths.
* Computes the list of static items to copy to the output folder.
-->
<Target Name="_PrepareBlazorOutputConfiguration">
<!--
This task produces all the "final" paths for all the files we need to produce the final output.
The final folder is something like bin/<<Configuration>>/<<TargetFramework>>/dist
/_framework/_bin <- This will contain either the BCL + app assemblies or the result of linking the app.
/_framework/wasm <- This will contain the wsm runtime copied from the nuget package.
/_framework/blazor.js <- This is the blazor.js file copied from the nuget package.
/_framework/blazor.boot.json <- This is the boot json file
This task also defines some intermediate paths that we will use:
/obj/<<configuration>>/<<targetframework>>/blazor/blazor/linker <- This will be used to create the output from the linker.
/obj/<<configuration>>/<<targetframework>>/blazor/blazor/linked.assemblies.txt <- This will be used to save the output files from
the linker and use that as marker to identify whether or not we need to run the linker.
/obj/<<configuration>>/<<targetframework>>/blazor/blazor/linker.descriptor.xml <- This will be used to generate an XML descriptor
for the mono linker.
/obj/<<configuration>>/<<targetframework>>/blazor/inputs.basic.cache <- This is the marker file to track the inputs common
inputs to the output generation process.
/obj/<<configuration>>/<<targetframework>>/blazor/inputs.copylocal.txt <- Paths to all the copy-local referenced assemblies found
during the build process (i.e., the @(ReferenceCopyLocalPaths) values). We need this because when publishing, the build doesn't
necessarily also run so this is the only way we know which assemblies to include in linking/resolveassemblies.
/obj/<<configuration>>/<<targetframework>>/blazor/inputs.linkerswitch.cache <- This is the marker file to track the
switch from linking to not linking and viceversa.
/obj/<<configuration>>/<<targetframework>>/blazor/inputs.linker.cache <- This is the marker file to track the inputs
to the linker.
/obj/<<configuration>>/<<targetframework>>/blazor/resolvedassemblies/ <- This will be used to store the resolved assemblies
before copying them to the output when linking is not enabled.
/obj/<<configuration>>/<<targetframework>>/blazor/resolved.assemblies.txt <- This keeps track of all the resolved assemblies.
/obj/<<configuration>>/<<targetframework>>/blazor/blazor.boot.json <- The generated boot json file
/obj/<<configuration>>/<<targetframework>>/blazor/inputs.bootjson.cache <- The marker file that track whether boot json needs to
be regenerated.
-->
<PropertyGroup Label="Build properties">
<_BlazorShouldLinkApplicationAssemblies Condition="$(BlazorLinkOnBuild) == 'false'"></_BlazorShouldLinkApplicationAssemblies>
<_BlazorShouldLinkApplicationAssemblies Condition="$(BlazorLinkOnBuild) == 'true'">true</_BlazorShouldLinkApplicationAssemblies>
<_BlazorBuiltInBclLinkerDescriptor>$(MSBuildThisFileDirectory)BuiltInBclLinkerDescriptor.xml</_BlazorBuiltInBclLinkerDescriptor>
</PropertyGroup>
<ItemGroup Label="Static content to copy to the output folder">
<MonoWasmFile Include="$(MonoWasmRuntimePath)**/*.*" />
<BlazorJsFile Include="$(BlazorJsPath)" />
<BlazorItemOutput Include="@(MonoWasmFile)">
<TargetOutputPath>$(TargetDir)$(BaseBlazorRuntimeWasmOutputPath)%(FileName)%(Extension)</TargetOutputPath>
<Type>WebAssembly</Type>
<IsStatic>true</IsStatic>
</BlazorItemOutput>
<BlazorItemOutput Include="@(BlazorJsFile)">
<TargetOutputPath>$(TargetDir)$(BaseBlazorJsOutputPath)%(FileName)%(Extension)</TargetOutputPath>
<Type>BlazorRuntime</Type>
<IsStatic>true</IsStatic>
</BlazorItemOutput>
<BlazorOutputWithTargetPath Include="@(MonoWasmFile)">
<TargetOutputPath>$(BlazorRuntimeWasmOutputPath)%(FileName)%(Extension)</TargetOutputPath>
</BlazorOutputWithTargetPath>
<BlazorOutputWithTargetPath Include="@(BlazorJSFile)">
<TargetOutputPath>$(BaseBlazorRuntimeOutputPath)%(FileName)%(Extension)</TargetOutputPath>
</BlazorOutputWithTargetPath>
</ItemGroup>
<Error Condition="'@(BlazorJsFile->Count())' == '0'" Text="No JS files found in '$(BlazorJsPath)'" />
<ItemGroup Label="Static content supplied by NuGet packages">
<_BlazorPackageContentOutput Include="@(BlazorPackageContentFile)" Condition="%(SourcePackage) != ''">
<TargetOutputPath>$(TargetDir)$(BaseBlazorPackageContentOutputPath)%(SourcePackage)\%(RecursiveDir)\%(Filename)%(Extension)</TargetOutputPath>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<TargetOutputPath>$(BaseBlazorPackageContentOutputPath)%(SourcePackage)\%(RecursiveDir)\%(Filename)%(Extension)</TargetOutputPath>
</_BlazorPackageContentOutput>
<BlazorItemOutput Include="@(_BlazorPackageContentOutput)" />
<BlazorOutputWithTargetPath Include="@(_BlazorPackageContentOutput)" />
</ItemGroup>
</Target>
<PropertyGroup Label="Intermediate output paths">
<Target Name="_ResolveBlazorInputs">
<PropertyGroup>
<!-- /obj/<<configuration>>/<<targetframework>>/blazor -->
<BlazorIntermediateOutputPath>$(IntermediateOutputPath)$(BaseBlazorIntermediateOutputPath)</BlazorIntermediateOutputPath>
<BlazorIntermediateOutputPath Condition="! $([System.IO.Path]::IsPathRooted($(BlazorIntermediateOutputPath)))">$([MSBuild]::Escape($([System.IO.Path]::GetFullPath('$([System.IO.Path]::Combine('$(MSBuildProjectDirectory)', '$(BlazorIntermediateOutputPath)'))'))))</BlazorIntermediateOutputPath>
<!-- Common marker files paths -->
<!-- /obj/<<configuration>>/<<targetframework>>/blazor/inputs.basic.cache -->
<BlazorBuildCommonInputsCache>$(BlazorIntermediateOutputPath)inputs.basic.cache</BlazorBuildCommonInputsCache>
<!-- /obj/<<configuration>>/<<targetframework>>/blazor/inputs.copylocal.txt -->
<BlazorLocalReferencesOutputPath>$(BlazorIntermediateOutputPath)inputs.copylocal.txt</BlazorLocalReferencesOutputPath>
<!-- /obj/<<configuration>>/<<targetframework>>/blazor/inputs.linkerswitch.cache -->
<BlazorBuildLinkerSwitchInputsCache>$(BlazorIntermediateOutputPath)inputs.linkerswitch.cache</BlazorBuildLinkerSwitchInputsCache>
<!-- Linker paths and marker files -->
<!-- /obj/<<configuration>>/<<targetframework>>/blazor/inputs.linker.cache -->
<BlazorBuildLinkerInputsCache>$(BlazorIntermediateOutputPath)inputs.linker.cache</BlazorBuildLinkerInputsCache>
<BlazorIntermediateOutputPath>$(IntermediateOutputPath)blazor\</BlazorIntermediateOutputPath>
<!-- /obj/<<configuration>>/<<targetframework>>/blazor/linker.descriptor.xml -->
<GeneratedBlazorLinkerDescriptor>$(BlazorIntermediateOutputPath)linker.descriptor.xml</GeneratedBlazorLinkerDescriptor>
@ -208,452 +87,202 @@
<!-- /obj/<<configuration>>/<<targetframework>>/blazor/linker/ -->
<BlazorIntermediateLinkerOutputPath>$(BlazorIntermediateOutputPath)linker/</BlazorIntermediateLinkerOutputPath>
<!-- /obj/<<configuration>>/<<targetframework>>/blazor/linked.assemblies.txt -->
<BlazorIntermediateLinkerResultFilePath>$(BlazorIntermediateOutputPath)linked.assemblies.txt</BlazorIntermediateLinkerResultFilePath>
<!-- Resolved assemblies paths and marker files -->
<!-- /obj/<<configuration>>/<<targetframework>>/blazor/resolvedassemblies/ -->
<BlazorIntermediateResolvedApplicationAssembliesOutputPath>$(BlazorIntermediateOutputPath)resolvedassemblies/</BlazorIntermediateResolvedApplicationAssembliesOutputPath>
<!-- /obj/<<configuration>>/<<targetframework>>/blazor/resolved.assemblies.txt -->
<BlazorResolvedAssembliesOutputPath>$(BlazorIntermediateOutputPath)resolved.assemblies.txt</BlazorResolvedAssembliesOutputPath>
<!-- boot json related paths and markers -->
<!-- /obj/<<configuration>>/<<targetframework>>/blazor/ -->
<BlazorBootJsonIntermediateOutputDir>$(BlazorIntermediateOutputPath)</BlazorBootJsonIntermediateOutputDir>
<!-- /obj/<<configuration>>/<<targetframework>>/blazor/blazor.boot.json -->
<BlazorBootJsonIntermediateOutputPath>$(BlazorBootJsonIntermediateOutputDir)$(BlazorBootJsonName)</BlazorBootJsonIntermediateOutputPath>
<BlazorBootJsonIntermediateOutputPath>$(BlazorIntermediateOutputPath)$(BlazorBootJsonName)</BlazorBootJsonIntermediateOutputPath>
<!-- /obj/<<configuration>>/<<targetframework>>/blazor/inputs.bootjson.cache -->
<BlazorBuildBootJsonInputsCache>$(BlazorIntermediateOutputPath)inputs.bootjson.cache</BlazorBuildBootJsonInputsCache>
<!-- /obj/<<configuration>>/<<targetframework>>/blazor/resolve-dependencies.txt -->
<BlazorResolveDependenciesFilePath>$(BlazorIntermediateOutputPath)resolve-dependencies.txt</BlazorResolveDependenciesFilePath>
<!-- /obj/<<configuration>>/<<targetframework>>/blazor/bootjson-references.txt -->
<BlazorBootJsonReferencesFilePath>$(BlazorIntermediateOutputPath)bootjson-references.txt</BlazorBootJsonReferencesFilePath>
<!-- /obj/<<configuration>>/<<targetframework>>/blazor/embedded.resources.txt -->
<BlazorEmbeddedResourcesConfigFilePath>$(BlazorIntermediateOutputPath)embedded.resources.txt</BlazorEmbeddedResourcesConfigFilePath>
<_BlazorLinkerOutputCache>$(BlazorIntermediateOutputPath)linker.output</_BlazorLinkerOutputCache>
<_BlazorApplicationAssembliesCacheFile>$(BlazorIntermediateOutputPath)unlinked.output</_BlazorApplicationAssembliesCacheFile>
</PropertyGroup>
<PropertyGroup Label="Final output paths">
<BlazorRuntimeBinOutputPath>$(TargetDir)$(BaseBlazorRuntimeBinOutputPath)</BlazorRuntimeBinOutputPath>
</PropertyGroup>
<ItemGroup>
<_BlazorDependencyInput Include="@(ReferenceCopyLocalPaths->WithMetadataValue('Extension','.dll')->'%(FullPath)')" />
<_WebAssemblyBCLFolder Include="
$(DotNetWebAssemblyBCLPath);
$(DotNetWebAssemblyBCLFacadesPath);
$(DotNetWebAssemblyFrameworkPath)" />
<_WebAssemblyBCLAssembly Include="%(_WebAssemblyBCLFolder.Identity)*.dll" />
</ItemGroup>
<MakeDir Directories="$(BlazorIntermediateOutputPath)" />
</Target>
<Target Name="_DefineBlazorCommonInputs">
<!-- If ResolveReferences hasn't yet run, we must be inside a VS publish process
that doesn't also do a build, so use the stored information. -->
<ReadLinesFromFile
Condition="'$(_BlazorResolveReferencesDidRun)'!='true'"
File="$(BlazorLocalReferencesOutputPath)">
<Output TaskParameter="Lines" ItemName="_BlazorDependencyInput"/>
</ReadLinesFromFile>
<ItemGroup Condition="'$(_BlazorResolveReferencesDidRun)'=='true'">
<!-- ... otherwise we can get the fresh info from @(ReferenceCopyLocalPaths) -->
<_BlazorDependencyInput Include="@(ReferenceCopyLocalPaths->WithMetadataValue('Extension','.dll')->'%(FullPath)')" />
</ItemGroup>
<ItemGroup>
<_BlazorCommonInput Include="@(IntermediateAssembly)" />
<_BlazorCommonInput Include="@(_BlazorDependencyInput)" />
<_BlazorCommonInput Include="$(_BlazorShouldLinkApplicationAssemblies)" />
<_BlazorCommonInput Include="$(BlazorEnableDebugging)" />
<_BlazorLinkingOption Condition="'$(_BlazorShouldLinkApplicationAssemblies)' == ''" Include="false" />
<_BlazorLinkingOption Condition="'$(_BlazorShouldLinkApplicationAssemblies)' != ''" Include="true" />
</ItemGroup>
<Hash ItemsToHash="@(_BlazorCommonInput)">
<Output TaskParameter="HashResult" PropertyName="_BlazorBuildBasicInputHash" />
</Hash>
<WriteLinesToFile
Lines="$(_BlazorBuildBasicInputHash)"
File="$(BlazorBuildCommonInputsCache)"
Overwrite="True"
WriteOnlyWhenDifferent="True" />
<WriteLinesToFile
Lines="@(_BlazorDependencyInput)"
File="$(BlazorLocalReferencesOutputPath)"
Overwrite="True"
WriteOnlyWhenDifferent="True" />
<!-- Switch to detect when we switch from linking to not linking and viceversa -->
<WriteLinesToFile
Lines="@(_BlazorLinkingOption)"
File="$(BlazorBuildLinkerSwitchInputsCache)"
Overwrite="True"
WriteOnlyWhenDifferent="True" />
<ItemGroup>
<FileWrites Include="$(BlazorBuildLinkerSwitchInputsCache)" />
<FileWrites Include="$(BlazorBuildCommonInputsCache)" />
<FileWrites Include="$(BlazorLocalReferencesOutputPath)" />
</ItemGroup>
<Target Name="_ResolveBlazorOutputs" DependsOnTargets="_ResolveBlazorOutputsWhenLinked;_ResolveBlazorOutputsWhenNotLinked">
<Error
Message="Unrecongnized value for BlazorLinkOnBuild: '$(BlazorLinkOnBuild)'. Valid values are 'true' or 'false'."
Condition="'$(BlazorLinkOnBuild)' != 'true' AND '$(BlazorLinkOnBuild)' != 'false'" />
</Target>
<Target Name="_BlazorResolveOutputBinaries" DependsOnTargets="_CollectLinkerOutputs;_CollectResolvedAssemblies" />
<!--
Linker enabled part of the pipeline:
* If there are no descriptors defined, generate a new linker descriptor.
* Collect the list of descriptors and produce a marker file to determine when the
inputs to the linker change in future builds.
* Invoke the linker if the linker inputs marker file is newer than the linker outputs.
* Read the outputs from the linker and add them to the list of blazor outputs.
* Invoke the linker and write linked files to a well-known directory.
* Collect the outputs of the linker.
-->
<PropertyGroup>
<_CollectLinkerOutputsDependsOn>
_GenerateLinkerDescriptor;
_CollectBlazorLinkerDescriptors;
_LinkBlazorApplication
</_CollectLinkerOutputsDependsOn>
</PropertyGroup>
<Target
Name="_CollectLinkerOutputs"
Condition="'$(_BlazorShouldLinkApplicationAssemblies)' != ''"
DependsOnTargets="$(_CollectLinkerOutputsDependsOn)">
<!--
Read the outputs from the linker (from this run or a previous run) and set them in an item group for
later use.
-->
<ReadLinesFromFile File="$(BlazorIntermediateLinkerResultFilePath)">
<Output TaskParameter="Lines" ItemName="_OptimizedFiles"/>
Name="_ResolveBlazorOutputsWhenLinked"
Condition="'$(BlazorLinkOnBuild)' == 'true'"
DependsOnTargets="_GenerateBlazorLinkerDescriptor;_LinkBlazorApplication">
<!-- _BlazorLinkerOutputCache records files linked during the last incremental build of the target. Read the contents and assign linked files to be copied to the output. -->
<ReadLinesFromFile File="$(_BlazorLinkerOutputCache)">
<Output TaskParameter="Lines" ItemName="_BlazorLinkedFile"/>
</ReadLinesFromFile>
<ItemGroup>
<BlazorItemOutput Include="@(_OptimizedFiles->WithMetadataValue('Extension','.dll'))">
<BlazorOutputWithTargetPath Include="%(_BlazorLinkedFile.Identity)">
<TargetOutputPath>$(BlazorRuntimeBinOutputPath)%(FileName)%(Extension)</TargetOutputPath>
<Type>Assembly</Type>
<PrimaryOutput Condition="'%(FileName)' == @(IntermediateAssembly->'%(FileName)')">true</PrimaryOutput>
</BlazorItemOutput>
<BlazorItemOutput Include="@(_OptimizedFiles->WithMetadataValue('Extension','.pdb'))">
<TargetOutputPath>$(BlazorRuntimeBinOutputPath)%(FileName)%(Extension)</TargetOutputPath>
<Type>Pdb</Type>
</BlazorItemOutput>
<FileWrites Include="@(BlazorItemOutput->WithMetadataValue('Type','Assembly')->'%(TargetOutputPath)')" />
</BlazorOutputWithTargetPath>
</ItemGroup>
</Target>
<Target Name="_GenerateLinkerDescriptor"
Inputs="$(BlazorBuildCommonInputsCache)"
<UsingTask TaskName="BlazorCreateRootDescriptorFile" AssemblyFile="$(BlazorTasksPath)" />
<Target Name="_GenerateBlazorLinkerDescriptor"
Inputs="@(IntermediateAssembly)"
Outputs="$(GeneratedBlazorLinkerDescriptor)"
Condition="$(_BlazorShouldLinkApplicationAssemblies) != '' and '@(BlazorLinkerDescriptor)' == ''">
Condition="'@(BlazorLinkerDescriptor)' == ''">
<!-- Generate linker descriptors if the project doesn't explicitly provide one. -->
<BlazorCreateRootDescriptorFile
AssemblyNames="@(IntermediateAssembly->'%(Filename)')"
RootDescriptorFilePath="$(GeneratedBlazorLinkerDescriptor)" />
<ItemGroup>
<_PrepareLinkerDescriptorAssemblyLine Include="@(IntermediateAssembly->'%(FileName)')" />
<_GeneratedLinkerDescriptorLine Include="&lt;linker&gt;" />
<_GeneratedLinkerDescriptorLine Include="@(_PrepareLinkerDescriptorAssemblyLine->'&lt;assembly fullname=&quot;%(Identity)&quot; /&gt;')" />
<_GeneratedLinkerDescriptorLine Include="&lt;/linker&gt;" />
</ItemGroup>
<WriteLinesToFile
Lines="@(_GeneratedLinkerDescriptorLine)"
File="$(GeneratedBlazorLinkerDescriptor)"
Overwrite="true"
WriteOnlyWhenDifferent="True" />
</Target>
<Target Name="_CollectBlazorLinkerDescriptors">
<ItemGroup Condition="@(BlazorLinkerDescriptor) == ''">
<BlazorLinkerDescriptor Include="$(_BlazorBuiltInBclLinkerDescriptor)" />
<BlazorLinkerDescriptor Include="$(GeneratedBlazorLinkerDescriptor)" />
<FileWrites Include="$(GeneratedBlazorLinkerDescriptor)" />
<BlazorLinkerDescriptor Include="$(GeneratedBlazorLinkerDescriptor)" />
<BlazorLinkerDescriptor Include="$(_BlazorBuiltInBclLinkerDescriptor)" />
</ItemGroup>
<ItemGroup>
<_BlazorLinkerInput Include="@(IntermediateAssembly)" />
<_BlazorLinkerInput Include="@(_BlazorDependencyInput)" />
<_BlazorLinkerInput Include="@(BlazorLinkerDescriptor)" />
<_BlazorLinkerInput Include="$(AdditionalMonoLinkerOptions)" />
</ItemGroup>
<Hash ItemsToHash="@(_BlazorLinkerInput)">
<Output TaskParameter="HashResult" PropertyName="_BlazorLinkerInputHash" />
</Hash>
<WriteLinesToFile
Lines="$(_BlazorLinkerInputHash)"
File="$(BlazorBuildLinkerInputsCache)"
Overwrite="True"
WriteOnlyWhenDifferent="True" />
<ItemGroup>
<FileWrites Include="$(BlazorBuildLinkerInputsCache)" />
</ItemGroup>
</Target>
<UsingTask TaskName="BlazorILLink" AssemblyFile="$(BlazorTasksPath)" />
<Target
Name="_LinkBlazorApplication"
Condition="$(_BlazorShouldLinkApplicationAssemblies) != ''"
Inputs="$(BlazorBuildLinkerInputsCache);
Inputs="$(ProjectAssetsFile);
@(IntermediateAssembly);
@(_BlazorDependencyInput);
@(BlazorLinkerDescriptor)"
Outputs="$(BlazorIntermediateLinkerResultFilePath)"
>
<!--
At this point we have decided to run the mono linker on the Blazor assembly and its dependencies.
The steps to run the mono linker are the following:
1) Clear the linker output directory if not clean before hand, as we don't know what the outputs of
the linker will be.
2) Run the linker on the main assembly, its dependencies and pass in the BCL folders to do the lookup
for framework assemblies.
3) Once we've run the linker we need to capture the produced output and generate a marker file containing
the list of produced files. This file will act as a marker to skip running the linker if none of the inputs
has changed.
4) Add the file we just created to the list of file writes, to support incremental builds.
-->
@(BlazorLinkerDescriptor);
$(MSBuildAllProjects)"
Outputs="$(_BlazorLinkerOutputCache)">
<ItemGroup>
<_MonoBaseClassLibraryFolder Include="$(MonoBaseClassLibraryPath);$(MonoBaseClassLibraryFacadesPath);$(MonoWasmFrameworkPath)" />
<_BlazorAssembliesToLink Include="@(_BlazorDependencyInput->'-a &quot;%(Identity)&quot;')" />
<_BlazorAssembliesToLink Include="@(IntermediateAssembly->'-a &quot;%(FullPath)&quot;')" />
<_BlazorFolderLookupPaths Include="@(_MonoBaseClassLibraryFolder->'-d &quot;%(Identity)&quot;')" />
<_BlazorAssemblyDescriptorFiles
Include="@(BlazorLinkerDescriptor->'-x &quot;%(FullPath)&quot;')" Condition="'@(BlazorLinkerDescriptor)' != ''" />
<_BlazorDependencyAssembly Include="@(_BlazorDependencyInput)" IsLinkable="$([System.String]::Copy('%(FileName)').StartsWith('System.'))" />
<_BlazorAssemblyToLink Include="@(_WebAssemblyBCLAssembly)" />
<_BlazorAssemblyToLink Include="@(_BlazorDependencyAssembly)" Condition="'%(_BlazorDependencyAssembly.IsLinkable)' == 'true'" />
<_BlazorLinkerRoot Include="@(IntermediateAssembly)" />
<_BlazorLinkerRoot Include="@(_BlazorDependencyAssembly)" Condition="'%(_BlazorDependencyAssembly.IsLinkable)' != 'true'" />
</ItemGroup>
<PropertyGroup>
<_BlazorLinkerAdditionalOptions>-l $(MonoLinkerI18NAssemblies) $(AdditionalMonoLinkerOptions)</_BlazorLinkerAdditionalOptions>
</PropertyGroup>
<!-- Clear the contents of /obj/<<configuration>>/<<targetframework>>/blazor/blazor/linker -->
<Delete Files="$(BlazorIntermediateLinkerOutputPath)*.dll" />
<PropertyGroup>
<_MonoLinkerDotNetPath>$(DOTNET_HOST_PATH)</_MonoLinkerDotNetPath>
<_MonoLinkerDotNetPath Condition="'$(_MonoLinkerDotNetPath)' == ''">dotnet</_MonoLinkerDotNetPath>
</PropertyGroup>
<!-- Run the linker and put the results in /obj/<<configuration>>/<<targetframework>>/blazor/blazor/linker -->
<Exec Command="$(_MonoLinkerDotNetPath) &quot;$(MonoLinkerPath)&quot; $(_BlazorLinkerAdditionalOptions) @(_BlazorFolderLookupPaths, ' ') -o &quot;$(BlazorIntermediateLinkerOutputPath)&quot; @(_BlazorAssemblyDescriptorFiles, ' ') @(_BlazorAssembliesToLink, ' ')" />
<!-- Collect the contents of /obj/<<configuration>>/<<targetframework>>/blazor/blazor/linker/ -->
<ItemGroup>
<_BlazorLinkerOutput Include="$(BlazorIntermediateLinkerOutputPath)*.dll" />
<_BlazorLinkerOutput Include="$(BlazorIntermediateLinkerOutputPath)*.pdb" />
<_OldLinkedFile Include="$(BlazorIntermediateLinkerOutputPath)*.dll" />
<_OldLinkedFile Include="$(BlazorIntermediateLinkerOutputPath)*.pdb" />
</ItemGroup>
<!--
Write the list of files in /obj/<<configuration>>/<<targetframework>>/blazor/blazor/linker/ into
/obj/<<configuration>>/<<targetframework>>/blazor/blazor/linked.assemblies.txt
-->
<WriteLinesToFile
File="$(BlazorIntermediateLinkerResultFilePath)"
Lines="@(_BlazorLinkerOutput)"
Overwrite="true" />
<Delete Files="@(_OldLinkedFile)" />
<!--
When running from Desktop MSBuild, DOTNET_HOST_PATH is not set.
In this case, explicitly specify the path to the dotnet host.
-->
<PropertyGroup Condition=" '$(DOTNET_HOST_PATH)' == '' ">
<_DotNetHostDirectory>$(NetCoreRoot)</_DotNetHostDirectory>
<_DotNetHostFileName>dotnet</_DotNetHostFileName>
<_DotNetHostFileName Condition=" '$(OS)' == 'Windows_NT' ">dotnet.exe</_DotNetHostFileName>
</PropertyGroup>
<BlazorILLink
ILLinkPath="$(MonoLinkerPath)"
AssemblyPaths="@(_BlazorAssemblyToLink)"
RootAssemblyNames="@(_BlazorLinkerRoot)"
RootDescriptorFiles="@(BlazorLinkerDescriptor)"
OutputDirectory="$(BlazorIntermediateLinkerOutputPath)"
ExtraArgs="$(_BlazorLinkerAdditionalOptions)"
ToolExe="$(_DotNetHostFileName)"
ToolPath="$(_DotNetHostDirectory)" />
<!-- Add /obj/<<configuration>>/<<targetframework>>/blazor/blazor/linked.assemblies.txt to the list of written files. -->
<!-- Add /obj/<<configuration>>/<<targetframework>>/blazor/blazor/linker/*.dll to the list of written files. -->
<ItemGroup>
<FileWrites Include="$(BlazorIntermediateLinkerResultFilePath)" />
<FileWrites Include="@(_BlazorLinkerOutput)" />
<_LinkerResult Include="$(BlazorIntermediateLinkerOutputPath)*.dll" />
<_LinkerResult Include="$(BlazorIntermediateLinkerOutputPath)*.pdb" Condition="'$(BlazorEnableDebugging)' == 'true'" />
</ItemGroup>
<WriteLinesToFile File="$(_BlazorLinkerOutputCache)" Lines="@(_LinkerResult)" Overwrite="true" />
</Target>
<UsingTask TaskName="ResolveBlazorRuntimeDependencies" AssemblyFile="$(BlazorTasksPath)" />
<Target
Name="_ResolveBlazorOutputsWhenNotLinked"
DependsOnTargets="_ResolveBlazorRuntimeDependencies"
Condition="'$(BlazorLinkOnBuild)' != 'true'">
<ReadLinesFromFile File="$(_BlazorApplicationAssembliesCacheFile)" Condition="'@(_BlazorResolvedRuntimeDependencies->Count())' == '0'">
<Output TaskParameter="Lines" ItemName="_BlazorResolvedRuntimeDependencies"/>
</ReadLinesFromFile>
<ItemGroup>
<BlazorOutputWithTargetPath Include="@(_BlazorResolvedRuntimeDependencies)">
<TargetOutputPath>$(BlazorRuntimeBinOutputPath)%(FileName)%(Extension)</TargetOutputPath>
</BlazorOutputWithTargetPath>
</ItemGroup>
</Target>
<!--
Linker disabled part of the pipeline:
* Run a CLI tool to produce the transitive closure of application references using the main application
as entry point.
* Read the list of resolved application references from the file produced by the previous step.
* Copy the resolved application references into an intermediate folder.
* If we are switching from linking to not linking
Touch the files in the intermediate folder to ensure they are copied to the output and replace
the linked versions with the same name.
* Collect the list of resolved assemblies in the intermediate output folder and prepare them to be
copied to their final destination in the output folder.
-->
<PropertyGroup>
<_CollectResolvedAssembliesDependsOn>
_ResolveBlazorApplicationAssemblies;
_ReadResolvedBlazorApplicationAssemblies;
_IntermediateCopyBlazorApplicationAssemblies;
_TouchBlazorApplicationAssemblies
</_CollectResolvedAssembliesDependsOn>
</PropertyGroup>
<Target
Name="_CollectResolvedAssemblies"
DependsOnTargets="$(_CollectResolvedAssembliesDependsOn)"
Condition="'$(_BlazorShouldLinkApplicationAssemblies)' == ''">
Name="_ResolveBlazorRuntimeDependencies"
Inputs="$(ProjectAssetsFile);
@(IntermediateAssembly);
@(_BlazorDependencyInput)"
Outputs="$(_BlazorApplicationAssembliesCacheFile)">
<!--
At this point we have decided not to run the linker and instead to just copy the assemblies
from the BCL referenced by the app the nuget package into the _framework/_bin folder.
The only thing we need to do here is collect the list of items that will go into _framework/_bin.
-->
<ResolveBlazorRuntimeDependencies
EntryPoint="@(IntermediateAssembly)"
ApplicationDependencies="@(_BlazorDependencyInput)"
WebAssemblyBCLAssemblies="@(_WebAssemblyBCLAssembly)">
<Output TaskParameter="Dependencies" ItemName="_BlazorResolvedRuntimeDependencies" />
</ResolveBlazorRuntimeDependencies>
<ItemGroup>
<BlazorItemOutput Include="@(_IntermediateResolvedRuntimeDependencies->WithMetadataValue('Extension','.dll'))">
<TargetOutputPath>$(BlazorRuntimeBinOutputPath)%(FileName)%(Extension)</TargetOutputPath>
<Type>Assembly</Type>
<PrimaryOutput Condition="'%(FileName)' == @(IntermediateAssembly->'%(FileName)')">true</PrimaryOutput>
</BlazorItemOutput>
<BlazorItemOutput Include="@(_IntermediateResolvedRuntimeDependencies->WithMetadataValue('Extension','.pdb'))">
<TargetOutputPath>$(BlazorRuntimeBinOutputPath)%(FileName)%(Extension)</TargetOutputPath>
<Type>Pdb</Type>
</BlazorItemOutput>
<FileWrites Include="@(BlazorItemOutput->WithMetadataValue('Type','Assembly')->'%(TargetOutputPath)')" />
<FileWrites Include="$(_BlazorApplicationAssembliesCacheFile)" />
</ItemGroup>
</Target>
<Target
Name="_ResolveBlazorApplicationAssemblies"
Condition="'$(_BlazorShouldLinkApplicationAssemblies)' == ''"
Inputs="$(BlazorBuildCommonInputsCache);
@(IntermediateAssembly);
@(_BlazorDependencyInput)"
Outputs="$(BlazorResolvedAssembliesOutputPath)"
>
<PropertyGroup>
<_ReferencesArg Condition="'@(_BlazorDependencyInput)' != ''">--references &quot;$(BlazorResolveDependenciesFilePath)&quot;</_ReferencesArg>
<_BclParameter>--base-class-library &quot;$(MonoBaseClassLibraryPath)&quot; --base-class-library &quot;$(MonoBaseClassLibraryFacadesPath)&quot; --base-class-library &quot;$(MonoWasmFrameworkPath)&quot;</_BclParameter>
</PropertyGroup>
<WriteLinesToFile
File="$(BlazorResolveDependenciesFilePath)"
Lines="@(_BlazorDependencyInput)"
Overwrite="true" />
<Exec Command="$(BlazorBuildExe) resolve-dependencies &quot;@(IntermediateAssembly->'%(FullPath)')&quot; $(_ReferencesArg) $(_BclParameter) --output &quot;$(BlazorResolvedAssembliesOutputPath)&quot;" />
</Target>
<Target Name="_ReadResolvedBlazorApplicationAssemblies">
<ReadLinesFromFile File="$(BlazorResolvedAssembliesOutputPath)">
<Output TaskParameter="Lines" ItemName="_BlazorResolvedRuntimeDependencies"/>
</ReadLinesFromFile>
<ItemGroup>
<_IntermediateResolvedRuntimeDependencies Include="@(_BlazorResolvedRuntimeDependencies->'$(BlazorIntermediateResolvedApplicationAssembliesOutputPath)%(FileName)%(Extension)')" />
</ItemGroup>
<ItemGroup>
<FileWrites Include="$(BlazorResolvedAssembliesOutputPath)" />
<FileWrites Include="@(_IntermediateResolvedRuntimeDependencies)" />
</ItemGroup>
</Target>
<Target
Name="_IntermediateCopyBlazorApplicationAssemblies"
Inputs="@(_BlazorResolvedRuntimeDependencies)"
Outputs="@(_BlazorResolvedRuntimeDependencies->'$(BlazorIntermediateResolvedApplicationAssembliesOutputPath)%(FileName)%(Extension)')">
<Copy
SourceFiles="@(_BlazorResolvedRuntimeDependencies)"
DestinationFiles="@(_BlazorResolvedRuntimeDependencies->'$(BlazorIntermediateResolvedApplicationAssembliesOutputPath)%(FileName)%(Extension)')"
SkipUnchangedFiles="$(SkipCopyUnchangedFiles)"
OverwriteReadOnlyFiles="$(OverwriteReadOnlyFiles)"
Retries="$(CopyRetryCount)"
RetryDelayMilliseconds="$(CopyRetryDelayMilliseconds)"
UseHardlinksIfPossible="$(CreateHardLinksForCopyFilesToOutputDirectoryIfPossible)"
UseSymboliclinksIfPossible="$(CreateSymbolicLinksForCopyFilesToOutputDirectoryIfPossible)" />
</Target>
<Target
Name="_TouchBlazorApplicationAssemblies"
Inputs="$(BlazorBuildLinkerSwitchInputsCache)"
Outputs="@(_IntermediateResolvedRuntimeDependencies)">
<Touch Files="@(_IntermediateResolvedRuntimeDependencies)" ForceTouch="true" />
</Target>
<!--
Final part of the build pipeline:
* Collect the blazor application assemblies to be copied to the output and create a marker file.
* Call our CLI tool to generate the boot json if the list of assemblies has changed.
-->
<Target Name="_ResolveBlazorBootJsonInputs">
<ItemGroup>
<BlazorBootJsonInput Include="$(Configuration)" />
<BlazorBootJsonInput Include="@(BlazorItemOutput->WithMetadataValue('Type','Assembly')->'%(FullPath)')" />
<BlazorBootJsonInput Include="@(BlazorItemOutput->WithMetadataValue('Type','Pdb')->'%(FullPath)')" />
<BlazorBootJsonInput Include="@(_BlazorLinkingOption)" />
<BlazorBootJsonInput Include="$(BlazorEnableDebugging)" />
</ItemGroup>
<WriteLinesToFile
File="$(BlazorBuildBootJsonInputsCache)"
Lines="@(BlazorBootJsonInput)"
Overwrite="true"
WriteOnlyWhenDifferent="True" />
<ItemGroup>
<FileWrites Include="$(BlazorBuildBootJsonInputsCache)" />
</ItemGroup>
</Target>
<UsingTask TaskName="GenerateBlazorBootJson" AssemblyFile="$(BlazorTasksPath)" />
<Target
Name="_GenerateBlazorBootJson"
DependsOnTargets="_ResolveBlazorBootJsonInputs"
Inputs="$(BlazorBuildBootJsonInputsCache);@(_BlazorDependencyInput)"
Inputs="@(BlazorOutputWithTargetPath)"
Outputs="$(BlazorBootJsonIntermediateOutputPath)">
<ItemGroup>
<_UnlinkedAppReferencesPaths Include="@(_BlazorDependencyInput)" />
<_AppReferences Include="@(BlazorItemOutput->WithMetadataValue('Type','Assembly')->WithMetadataValue('PrimaryOutput','')->'%(FileName)%(Extension)')" />
<_AppReferences Include="@(BlazorItemOutput->WithMetadataValue('Type','Pdb')->'%(FileName)%(Extension)')" Condition="'$(BlazorEnableDebugging)' == 'true'" />
<_AppReferences Include="@(BlazorOutputWithTargetPath->WithMetadataValue('Extension','.dll'))" />
<_AppReferences Include="@(BlazorOutputWithTargetPath->WithMetadataValue('Extension','.pdb'))" Condition="'$(BlazorEnableDebugging)' == 'true'" />
</ItemGroup>
<PropertyGroup>
<_LinkerEnabledFlag Condition="'$(_BlazorShouldLinkApplicationAssemblies)' != ''">--linker-enabled</_LinkerEnabledFlag>
<_ReferencesArg Condition="'@(_AppReferences)' != ''">--references &quot;$(BlazorBootJsonReferencesFilePath)&quot;</_ReferencesArg>
<_EmbeddedResourcesArg Condition="'@(_UnlinkedAppReferencesPaths)' != ''">--embedded-resources &quot;$(BlazorEmbeddedResourcesConfigFilePath)&quot;</_EmbeddedResourcesArg>
</PropertyGroup>
<WriteLinesToFile
File="$(BlazorBootJsonReferencesFilePath)"
Lines="@(_AppReferences)"
Overwrite="true" />
<GenerateBlazorBootJson
AssemblyPath="@(IntermediateAssembly)"
References="@(_AppReferences)"
LinkerEnabled="$(BlazorLinkOnBuild)"
OutputPath="$(BlazorBootJsonIntermediateOutputPath)" />
<WriteLinesToFile
Condition="'@(_UnlinkedAppReferencesPaths)' != ''"
File="$(BlazorEmbeddedResourcesConfigFilePath)"
Lines="@(_UnlinkedAppReferencesPaths)"
Overwrite="true" />
<Exec Command="$(BlazorBuildExe) write-boot-json &quot;@(IntermediateAssembly)&quot; $(_ReferencesArg) $(_EmbeddedResourcesArg) $(_LinkerEnabledFlag) --output &quot;$(BlazorBootJsonIntermediateOutputPath)&quot;" />
<ItemGroup Condition="Exists('$(BlazorBootJsonIntermediateOutputPath)')">
<_BlazorBootJson Include="$(BlazorBootJsonIntermediateOutputPath)" />
<_BlazorBootJsonEmbeddedContentFile Include="$(BlazorBootJsonIntermediateOutputDir)_content\**\*.*" />
<BlazorItemOutput Include="@(_BlazorBootJson)">
<TargetOutputPath>$(TargetDir)$(BlazorBootJsonOutputPath)</TargetOutputPath>
<Type>BootJson</Type>
</BlazorItemOutput>
<BlazorItemOutput Include="@(_BlazorBootJsonEmbeddedContentFile)">
<TargetOutputPath>$(TargetDir)dist/_content/%(RecursiveDir)%(FileName)%(Extension)</TargetOutputPath>
</BlazorItemOutput>
<ItemGroup>
<BlazorOutputWithTargetPath Include="$(BlazorBootJsonIntermediateOutputPath)" TargetOutputPath="$(BaseBlazorRuntimeOutputPath)$(BlazorBootJsonName)" />
<FileWrites Include="$(BlazorBootJsonIntermediateOutputPath)" />
<FileWrites Include="@(_BlazorBootJsonEmbeddedContentFile)" />
</ItemGroup>
</Target>
</Project>

View File

@ -26,9 +26,8 @@
</ContentWithTargetPath>
<!-- Publish all the 'dist' files -->
<_BlazorGCTPDIDistFiles Include="@(BlazorItemOutput->'%(TargetOutputPath)')" />
<_BlazorGCTPDI Include="@(_BlazorGCTPDIDistFiles)">
<TargetPath>$(BlazorPublishDistDir)$([MSBuild]::MakeRelative('$(TargetDir)dist\', %(Identity)))</TargetPath>
<_BlazorGCTPDI Include="%(BlazorOutputWithTargetPath.Identity)">
<TargetPath>$(AssemblyName)\%(TargetOutputPath)</TargetPath>
</_BlazorGCTPDI>
<ContentWithTargetPath Include="@(_BlazorGCTPDI)">
@ -41,8 +40,17 @@
<PropertyGroup>
<_BlazorConfigPath>$(OutDir)$(AssemblyName).blazor.config</_BlazorConfigPath>
</PropertyGroup>
<WriteLinesToFile File="$(_BlazorConfigPath)" Lines="." Overwrite="true" />
<WriteLinesToFile File="$(_BlazorConfigPath)" Lines="$(AssemblyName)/" Overwrite="false" />
<ItemGroup>
<_BlazorPublishConfigContent Include="." />
<_BlazorPublishConfigContent Include="$(AssemblyName)/" />
</ItemGroup>
<WriteLinesToFile
File="$(_BlazorConfigPath)"
Lines="@(_BlazorPublishConfigContent)"
Overwrite="true"
WriteOnlyWhenDifferent="true" />
</Target>
<!-- The following target runs only for standalone publishing -->

View File

@ -0,0 +1,37 @@
<Project>
<PropertyGroup>
<ResolveStaticWebAssetsInputsDependsOn>
$(ResolveStaticWebAssetsInputsDependsOn);
_RemoveBlazorCurrentProjectAssetsFromStaticWebAssets;
</ResolveStaticWebAssetsInputsDependsOn>
<GetCurrentProjectStaticWebAssetsDependsOn>
$(GetCurrentProjectStaticWebAssetsDependsOn);
_RemoveBlazorCurrentProjectAssetsFromStaticWebAssets;
</GetCurrentProjectStaticWebAssetsDependsOn>
</PropertyGroup>
<Target Name="_RemoveBlazorCurrentProjectAssetsFromStaticWebAssets">
<ItemGroup>
<StaticWebAsset Remove="@(StaticWebAsset)" Condition="'%(SourceType)' == ''" />
</ItemGroup>
</Target>
<Target Name="BlazorStaticWebAssetsComputeFilesToPublish"
AfterTargets="_StaticWebAssetsComputeFilesToPublish">
<ItemGroup>
<!-- We need to update the external static web assets to follow the blazor publish output convention that puts them inside $(TargetName)/dist instead of wwwroot -->
<_StandaloneExternalPublishStaticWebAsset Include="@(_ExternalPublishStaticWebAsset)" Condition="'%(RelativePath)' != ''">
<RelativePath>$([MSBuild]::MakeRelative('$(MSBuildProjectDirectory)', '$([MSBuild]::NormalizePath('$([System.Text.RegularExpressions.Regex]::Replace('%(RelativePath)','^wwwroot\\?\/?(.*)','$(BlazorPublishDistDir)$1'))'))'))</RelativePath>
</_StandaloneExternalPublishStaticWebAsset>
<!-- Update doesn't work inside targets so we need to remove the items and re-add them. See https://github.com/microsoft/msbuild/issues/2835 for details -->
<ResolvedFileToPublish Remove="@(_StandaloneExternalPublishStaticWebAsset)" />
<ResolvedFileToPublish Include="@(_StandaloneExternalPublishStaticWebAsset)" />
</ItemGroup>
</Target>
</Project>

View File

@ -0,0 +1,38 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.IO;
using System.Xml.Linq;
using Xunit;
namespace Microsoft.AspNetCore.Blazor.Build
{
public class BlazorCreateRootDescriptorFileTest
{
[Fact]
public void ProducesRootDescriptor()
{
// Arrange/Act
using var stream = new MemoryStream();
// Act
BlazorCreateRootDescriptorFile.WriteRootDescriptor(
stream,
new[] { "MyApp.dll" });
// Assert
stream.Position = 0;
var document = XDocument.Load(stream);
var rootElement = document.Root;
var assemblyElement = Assert.Single(rootElement.Elements());
Assert.Equal("assembly", assemblyElement.Name.ToString());
Assert.Equal("MyApp.dll", assemblyElement.Attribute("fullname").Value);
var typeElement = Assert.Single(assemblyElement.Elements());
Assert.Equal("type", typeElement.Name.ToString());
Assert.Equal("*", typeElement.Attribute("fullname").Value);
Assert.Equal("true", typeElement.Attribute("required").Value);
}
}
}

View File

@ -1,62 +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 Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Linq;
using System.IO;
using System.Text.Json;
using System.Threading.Tasks;
using Xunit;
namespace Microsoft.AspNetCore.Blazor.Build.Test
namespace Microsoft.AspNetCore.Blazor.Build
{
public class BootJsonWriterTest
{
[Fact]
public void ProducesJsonReferencingAssemblyAndDependencies()
public async Task ProducesJsonReferencingAssemblyAndDependencies()
{
// Arrange/Act
var assemblyReferences = new string[] { "System.Abc.dll", "MyApp.ClassLib.dll", };
var content = BootJsonWriter.GetBootJsonContent(
var assemblyReferences = new string[] { "MyApp.EntryPoint.dll", "System.Abc.dll", "MyApp.ClassLib.dll", };
using var stream = new MemoryStream();
// Act
GenerateBlazorBootJson.WriteBootJson(
stream,
"MyApp.Entrypoint.dll",
"MyNamespace.MyType::MyMethod",
assemblyReferences,
Enumerable.Empty<EmbeddedResourceInfo>(),
linkerEnabled: true);
// Assert
var parsedContent = JsonConvert.DeserializeObject<JObject>(content);
Assert.Equal("MyApp.Entrypoint.dll", parsedContent["main"].Value<string>());
Assert.Equal("MyNamespace.MyType::MyMethod", parsedContent["entryPoint"].Value<string>());
Assert.Equal(assemblyReferences, parsedContent["assemblyReferences"].Values<string>());
}
[Fact]
public void IncludesReferencesToEmbeddedContent()
{
// Arrange/Act
var embeddedContent = new[]
stream.Position = 0;
using var parsedContent = await JsonDocument.ParseAsync(stream);
var rootElement = parsedContent.RootElement;
Assert.Equal("MyApp.Entrypoint.dll", rootElement.GetProperty("entryAssembly").GetString());
var assembliesElement = rootElement.GetProperty("assemblies");
Assert.Equal(assemblyReferences.Length, assembliesElement.GetArrayLength());
for (var i = 0; i < assemblyReferences.Length; i++)
{
new EmbeddedResourceInfo(EmbeddedResourceKind.Static, "my/static/file"),
new EmbeddedResourceInfo(EmbeddedResourceKind.Css, "css/first.css"),
new EmbeddedResourceInfo(EmbeddedResourceKind.JavaScript, "javascript/first.js"),
new EmbeddedResourceInfo(EmbeddedResourceKind.Css, "css/second.css"),
new EmbeddedResourceInfo(EmbeddedResourceKind.JavaScript, "javascript/second.js"),
};
var content = BootJsonWriter.GetBootJsonContent(
"MyApp.Entrypoint",
"MyNamespace.MyType::MyMethod",
assemblyReferences: new[] { "Something.dll" },
embeddedContent: embeddedContent,
linkerEnabled: true);
// Assert
var parsedContent = JsonConvert.DeserializeObject<JObject>(content);
Assert.Equal(
new[] { "css/first.css", "css/second.css" },
parsedContent["cssReferences"].Values<string>());
Assert.Equal(
new[] { "javascript/first.js", "javascript/second.js" },
parsedContent["jsReferences"].Values<string>());
Assert.Equal(assemblyReferences[i], assembliesElement[i].GetString());
}
Assert.True(rootElement.GetProperty("linkerEnabled").GetBoolean());
}
}
}

View File

@ -0,0 +1,950 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Reflection.Metadata;
using System.Reflection.PortableExecutable;
using System.Text;
using System.Text.RegularExpressions;
namespace Microsoft.AspNetCore.Blazor.Build
{
internal class Assert : Xunit.Assert
{
// Matches `{filename}: error {code}: {message} [{project}]
// See https://stackoverflow.com/questions/3441452/msbuild-and-ignorestandarderrorwarningformat/5180353#5180353
private static readonly Regex ErrorRegex = new Regex(@"^(?'location'.+): error (?'errorcode'[A-Z0-9]+): (?'message'.+) \[(?'project'.+)\]$");
private static readonly Regex WarningRegex = new Regex(@"^(?'location'.+): warning (?'errorcode'[A-Z0-9]+): (?'message'.+) \[(?'project'.+)\]$");
private static readonly string[] AllowedBuildWarnings = new[]
{
"MSB3491" , // The process cannot access the file. As long as the build succeeds, we're ok.
"NETSDK1071", // "A PackageReference to 'Microsoft.NETCore.App' specified a Version ..."
};
public static void BuildPassed(MSBuildResult result, bool allowWarnings = false)
{
if (result == null)
{
throw new ArgumentNullException(nameof(result));
}
if (result.ExitCode != 0)
{
throw new BuildFailedException(result);
}
var buildWarnings = GetBuildWarnings(result)
.Where(m => !AllowedBuildWarnings.Contains(m.match.Groups["errorcode"].Value))
.Select(m => m.line);
if (!allowWarnings && buildWarnings.Any())
{
throw new BuildWarningsException(result, buildWarnings);
}
}
public static void BuildError(MSBuildResult result, string errorCode, string location = null)
{
if (result == null)
{
throw new ArgumentNullException(nameof(result));
}
// We don't really need to search line by line, I'm doing this so that it's possible/easy to debug.
var lines = result.Output.Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
for (var i = 0; i < lines.Length; i++)
{
var line = lines[i];
var match = ErrorRegex.Match(line);
if (match.Success)
{
if (match.Groups["errorcode"].Value != errorCode)
{
continue;
}
if (location != null && match.Groups["location"].Value.Trim() != location)
{
continue;
}
// This is a match
return;
}
}
throw new BuildErrorMissingException(result, errorCode, location);
}
public static void BuildWarning(MSBuildResult result, string errorCode, string location = null)
{
if (result == null)
{
throw new ArgumentNullException(nameof(result));
}
// We don't really need to search line by line, I'm doing this so that it's possible/easy to debug.
foreach (var (_, match) in GetBuildWarnings(result))
{
if (match.Groups["errorcode"].Value != errorCode)
{
continue;
}
if (location != null && match.Groups["location"].Value.Trim() != location)
{
continue;
}
// This is a match
return;
}
throw new BuildErrorMissingException(result, errorCode, location);
}
private static IEnumerable<(string line, Match match)> GetBuildWarnings(MSBuildResult result)
{
var lines = result.Output.Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
for (var i = 0; i < lines.Length; i++)
{
var line = lines[i];
var match = WarningRegex.Match(line);
if (match.Success)
{
yield return (line, match);
}
}
}
public static void BuildFailed(MSBuildResult result)
{
if (result == null)
{
throw new ArgumentNullException(nameof(result));
};
if (result.ExitCode == 0)
{
throw new BuildPassedException(result);
}
}
public static void BuildOutputContainsLine(MSBuildResult result, string match)
{
if (result == null)
{
throw new ArgumentNullException(nameof(result));
}
if (match == null)
{
throw new ArgumentNullException(nameof(match));
}
// We don't really need to search line by line, I'm doing this so that it's possible/easy to debug.
var lines = result.Output.Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
for (var i = 0; i < lines.Length; i++)
{
var line = lines[i].Trim();
if (line == match)
{
return;
}
}
throw new BuildOutputMissingException(result, match);
}
public static void BuildOutputDoesNotContainLine(MSBuildResult result, string match)
{
if (result == null)
{
throw new ArgumentNullException(nameof(result));
}
if (match == null)
{
throw new ArgumentNullException(nameof(match));
}
// We don't really need to search line by line, I'm doing this so that it's possible/easy to debug.
var lines = result.Output.Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
for (var i = 0; i < lines.Length; i++)
{
var line = lines[i].Trim();
if (line == match)
{
throw new BuildOutputContainsLineException(result, match);
}
}
}
public static void FileContains(MSBuildResult result, string filePath, string match)
{
if (result == null)
{
throw new ArgumentNullException(nameof(result));
}
filePath = Path.Combine(result.Project.DirectoryPath, filePath);
FileExists(result, filePath);
var text = File.ReadAllText(filePath);
if (text.Contains(match))
{
return;
}
throw new FileContentMissingException(result, filePath, File.ReadAllText(filePath), match);
}
public static void FileDoesNotContain(MSBuildResult result, string filePath, string match)
{
if (result == null)
{
throw new ArgumentNullException(nameof(result));
}
filePath = Path.Combine(result.Project.DirectoryPath, filePath);
FileExists(result, filePath);
var text = File.ReadAllText(filePath);
if (text.Contains(match))
{
throw new FileContentFoundException(result, filePath, File.ReadAllText(filePath), match);
}
}
public static void FileContentEquals(MSBuildResult result, string filePath, string expected)
{
if (result == null)
{
throw new ArgumentNullException(nameof(result));
}
filePath = Path.Combine(result.Project.DirectoryPath, filePath);
FileExists(result, filePath);
var actual = File.ReadAllText(filePath);
if (!actual.Equals(expected, StringComparison.Ordinal))
{
throw new FileContentNotEqualException(result, filePath, expected, actual);
}
}
public static void FileEquals(MSBuildResult result, string expected, string actual)
{
if (result == null)
{
throw new ArgumentNullException(nameof(result));
}
expected = Path.Combine(result.Project.DirectoryPath, expected);
actual = Path.Combine(result.Project.DirectoryPath, actual);
FileExists(result, expected);
FileExists(result, actual);
if (!Enumerable.SequenceEqual(File.ReadAllBytes(expected), File.ReadAllBytes(actual)))
{
throw new FilesNotEqualException(result, expected, actual);
}
}
public static void FileContainsLine(MSBuildResult result, string filePath, string match)
{
if (result == null)
{
throw new ArgumentNullException(nameof(result));
}
filePath = Path.Combine(result.Project.DirectoryPath, filePath);
FileExists(result, filePath);
var lines = File.ReadAllLines(filePath);
for (var i = 0; i < lines.Length; i++)
{
var line = lines[i].Trim();
if (line == match)
{
return;
}
}
throw new FileContentMissingException(result, filePath, File.ReadAllText(filePath), match);
}
public static void FileDoesNotContainLine(MSBuildResult result, string filePath, string match)
{
if (result == null)
{
throw new ArgumentNullException(nameof(result));
}
filePath = Path.Combine(result.Project.DirectoryPath, filePath);
FileExists(result, filePath);
var lines = File.ReadAllLines(filePath);
for (var i = 0; i < lines.Length; i++)
{
var line = lines[i].Trim();
if (line == match)
{
throw new FileContentFoundException(result, filePath, File.ReadAllText(filePath), match);
}
}
}
public static string FileExists(MSBuildResult result, params string[] paths)
{
if (result == null)
{
throw new ArgumentNullException(nameof(result));
}
var filePath = Path.Combine(result.Project.DirectoryPath, Path.Combine(paths));
if (!File.Exists(filePath))
{
throw new FileMissingException(result, filePath);
}
return filePath;
}
public static void FileCountEquals(MSBuildResult result, int expected, string directoryPath, string searchPattern)
{
if (result == null)
{
throw new ArgumentNullException(nameof(result));
}
if (directoryPath == null)
{
throw new ArgumentNullException(nameof(directoryPath));
}
if (searchPattern == null)
{
throw new ArgumentNullException(nameof(searchPattern));
}
directoryPath = Path.Combine(result.Project.DirectoryPath, directoryPath);
if (Directory.Exists(directoryPath))
{
var files = Directory.GetFiles(directoryPath, searchPattern, SearchOption.AllDirectories);
if (files.Length != expected)
{
throw new FileCountException(result, expected, directoryPath, searchPattern, files);
}
}
else if (expected > 0)
{
// directory doesn't exist, that's OK if we expected to find nothing.
throw new FileCountException(result, expected, directoryPath, searchPattern, Array.Empty<string>());
}
}
public static void FileDoesNotExist(MSBuildResult result, params string[] paths)
{
if (result == null)
{
throw new ArgumentNullException(nameof(result));
}
var filePath = Path.Combine(result.Project.DirectoryPath, Path.Combine(paths));
if (File.Exists(filePath))
{
throw new FileFoundException(result, filePath);
}
}
public static void NuspecContains(MSBuildResult result, string nuspecPath, string expected)
{
if (result == null)
{
throw new ArgumentNullException(nameof(result));
}
if (nuspecPath == null)
{
throw new ArgumentNullException(nameof(nuspecPath));
}
if (expected == null)
{
throw new ArgumentNullException(nameof(expected));
}
nuspecPath = Path.Combine(result.Project.DirectoryPath, nuspecPath);
FileExists(result, nuspecPath);
var content = File.ReadAllText(nuspecPath);
if (!content.Contains(expected))
{
throw new NuspecException(result, nuspecPath, content, expected);
}
}
public static void NuspecDoesNotContain(MSBuildResult result, string nuspecPath, string expected)
{
if (result == null)
{
throw new ArgumentNullException(nameof(result));
}
if (nuspecPath == null)
{
throw new ArgumentNullException(nameof(nuspecPath));
}
if (expected == null)
{
throw new ArgumentNullException(nameof(expected));
}
nuspecPath = Path.Combine(result.Project.DirectoryPath, nuspecPath);
FileExists(result, nuspecPath);
var content = File.ReadAllText(nuspecPath);
if (content.Contains(expected))
{
throw new NuspecFoundException(result, nuspecPath, content, expected);
}
}
// This method extracts the nupkg to a fixed directory path. To avoid the extra work of
// cleaning up after each invocation, this method accepts multiple files.
public static void NupkgContains(MSBuildResult result, string nupkgPath, params string[] filePaths)
{
if (result == null)
{
throw new ArgumentNullException(nameof(result));
}
if (nupkgPath == null)
{
throw new ArgumentNullException(nameof(nupkgPath));
}
if (filePaths == null)
{
throw new ArgumentNullException(nameof(filePaths));
}
nupkgPath = Path.Combine(result.Project.DirectoryPath, nupkgPath);
FileExists(result, nupkgPath);
var unzipped = Path.Combine(result.Project.DirectoryPath, Path.GetFileNameWithoutExtension(nupkgPath));
ZipFile.ExtractToDirectory(nupkgPath, unzipped);
foreach (var filePath in filePaths)
{
if (!File.Exists(Path.Combine(unzipped, filePath)))
{
throw new NupkgFileMissingException(result, nupkgPath, filePath);
}
}
}
// This method extracts the nupkg to a fixed directory path. To avoid the extra work of
// cleaning up after each invocation, this method accepts multiple files.
public static void NupkgDoesNotContain(MSBuildResult result, string nupkgPath, params string[] filePaths)
{
if (result == null)
{
throw new ArgumentNullException(nameof(result));
}
if (nupkgPath == null)
{
throw new ArgumentNullException(nameof(nupkgPath));
}
if (filePaths == null)
{
throw new ArgumentNullException(nameof(filePaths));
}
nupkgPath = Path.Combine(result.Project.DirectoryPath, nupkgPath);
FileExists(result, nupkgPath);
var unzipped = Path.Combine(result.Project.DirectoryPath, Path.GetFileNameWithoutExtension(nupkgPath));
ZipFile.ExtractToDirectory(nupkgPath, unzipped);
foreach (var filePath in filePaths)
{
if (File.Exists(Path.Combine(unzipped, filePath)))
{
throw new NupkgFileFoundException(result, nupkgPath, filePath);
}
}
}
public static void AssemblyContainsType(MSBuildResult result, string assemblyPath, string fullTypeName)
{
if (result == null)
{
throw new ArgumentNullException(nameof(result));
}
assemblyPath = Path.Combine(result.Project.DirectoryPath, Path.Combine(assemblyPath));
var typeNames = GetDeclaredTypeNames(assemblyPath);
Assert.Contains(fullTypeName, typeNames);
}
public static void AssemblyDoesNotContainType(MSBuildResult result, string assemblyPath, string fullTypeName)
{
if (result == null)
{
throw new ArgumentNullException(nameof(result));
}
assemblyPath = Path.Combine(result.Project.DirectoryPath, Path.Combine(assemblyPath));
var typeNames = GetDeclaredTypeNames(assemblyPath);
Assert.DoesNotContain(fullTypeName, typeNames);
}
private static IEnumerable<string> GetDeclaredTypeNames(string assemblyPath)
{
using (var file = File.OpenRead(assemblyPath))
{
var peReader = new PEReader(file);
var metadataReader = peReader.GetMetadataReader();
return metadataReader.TypeDefinitions.Where(t => !t.IsNil).Select(t =>
{
var type = metadataReader.GetTypeDefinition(t);
return metadataReader.GetString(type.Namespace) + "." + metadataReader.GetString(type.Name);
}).ToArray();
}
}
public static void AssemblyHasAttribute(MSBuildResult result, string assemblyPath, string fullTypeName)
{
if (result == null)
{
throw new ArgumentNullException(nameof(result));
}
assemblyPath = Path.Combine(result.Project.DirectoryPath, Path.Combine(assemblyPath));
var typeNames = GetAssemblyAttributes(assemblyPath);
Assert.Contains(fullTypeName, typeNames);
}
private static IEnumerable<string> GetAssemblyAttributes(string assemblyPath)
{
using (var file = File.OpenRead(assemblyPath))
{
var peReader = new PEReader(file);
var metadataReader = peReader.GetMetadataReader();
return metadataReader.CustomAttributes.Where(t => !t.IsNil).Select(t =>
{
var attribute = metadataReader.GetCustomAttribute(t);
var constructor = metadataReader.GetMemberReference((MemberReferenceHandle)attribute.Constructor);
var type = metadataReader.GetTypeReference((TypeReferenceHandle)constructor.Parent);
return metadataReader.GetString(type.Namespace) + "." + metadataReader.GetString(type.Name);
}).ToArray();
}
}
private abstract class MSBuildXunitException : Xunit.Sdk.XunitException
{
protected MSBuildXunitException(MSBuildResult result)
{
Result = result;
}
protected abstract string Heading { get; }
public MSBuildResult Result { get; }
public override string Message
{
get
{
var message = new StringBuilder();
message.AppendLine(Heading);
message.Append(Result.FileName);
message.Append(" ");
message.Append(Result.Arguments);
message.AppendLine();
message.AppendLine();
message.Append(Result.Output);
message.AppendLine();
message.Append("Exit Code:");
message.Append(Result.ExitCode);
return message.ToString();
}
}
}
private class BuildErrorMissingException : MSBuildXunitException
{
public BuildErrorMissingException(MSBuildResult result, string errorCode, string location)
: base(result)
{
ErrorCode = errorCode;
Location = location;
}
public string ErrorCode { get; }
public string Location { get; }
protected override string Heading
{
get
{
return
$"Error code '{ErrorCode}' was not found." + Environment.NewLine +
$"Looking for '{Location ?? ".*"}: error {ErrorCode}: .*'";
}
}
}
private class BuildFailedException : MSBuildXunitException
{
public BuildFailedException(MSBuildResult result)
: base(result)
{
}
protected override string Heading => "Build failed.";
}
private class BuildWarningsException : MSBuildXunitException
{
public BuildWarningsException(MSBuildResult result, IEnumerable<string> warnings)
: base(result)
{
Warnings = warnings.ToList();
}
public List<string> Warnings { get; }
protected override string Heading => "Build contains unexpected warnings: " + string.Join(Environment.NewLine, Warnings);
}
private class BuildPassedException : MSBuildXunitException
{
public BuildPassedException(MSBuildResult result)
: base(result)
{
}
protected override string Heading => "Build should have failed, but it passed.";
}
private class BuildOutputMissingException : MSBuildXunitException
{
public BuildOutputMissingException(MSBuildResult result, string match)
: base(result)
{
Match = match;
}
public string Match { get; }
protected override string Heading => $"Build did not contain the line: '{Match}'.";
}
private class BuildOutputContainsLineException : MSBuildXunitException
{
public BuildOutputContainsLineException(MSBuildResult result, string match)
: base(result)
{
Match = match;
}
public string Match { get; }
protected override string Heading => $"Build output contains the line: '{Match}'.";
}
private class FileContentFoundException : MSBuildXunitException
{
public FileContentFoundException(MSBuildResult result, string filePath, string content, string match)
: base(result)
{
FilePath = filePath;
Content = content;
Match = match;
}
public string Content { get; }
public string FilePath { get; }
public string Match { get; }
protected override string Heading
{
get
{
var builder = new StringBuilder();
builder.AppendFormat("File content of '{0}' should not contain line: '{1}'.", FilePath, Match);
builder.AppendLine();
builder.AppendLine();
builder.AppendLine(Content);
return builder.ToString();
}
}
}
private class FileContentMissingException : MSBuildXunitException
{
public FileContentMissingException(MSBuildResult result, string filePath, string content, string match)
: base(result)
{
FilePath = filePath;
Content = content;
Match = match;
}
public string Content { get; }
public string FilePath { get; }
public string Match { get; }
protected override string Heading
{
get
{
var builder = new StringBuilder();
builder.AppendFormat("File content of '{0}' did not contain the line: '{1}'.", FilePath, Match);
builder.AppendLine();
builder.AppendLine();
builder.AppendLine(Content);
return builder.ToString();
}
}
}
private class FileContentNotEqualException : MSBuildXunitException
{
public FileContentNotEqualException(MSBuildResult result, string filePath, string expected, string actual)
: base(result)
{
FilePath = filePath;
Expected = expected;
Actual = actual;
}
public string Actual { get; }
public string FilePath { get; }
public string Expected { get; }
protected override string Heading
{
get
{
var builder = new StringBuilder();
builder.AppendFormat("File content of '{0}' did not match the expected content: '{1}'.", FilePath, Expected);
builder.AppendLine();
builder.AppendLine();
builder.AppendLine(Actual);
return builder.ToString();
}
}
}
private class FilesNotEqualException : MSBuildXunitException
{
public FilesNotEqualException(MSBuildResult result, string expected, string actual)
: base(result)
{
Expected = expected;
Actual = actual;
}
public string Actual { get; }
public string Expected { get; }
protected override string Heading
{
get
{
var builder = new StringBuilder();
builder.AppendFormat("File content of '{0}' did not match the contents of '{1}'.", Expected, Actual);
builder.AppendLine();
builder.AppendLine();
builder.AppendLine(Actual);
return builder.ToString();
}
}
}
private class FileMissingException : MSBuildXunitException
{
public FileMissingException(MSBuildResult result, string filePath)
: base(result)
{
FilePath = filePath;
}
public string FilePath { get; }
protected override string Heading => $"File: '{FilePath}' was not found.";
}
private class FileCountException : MSBuildXunitException
{
public FileCountException(MSBuildResult result, int expected, string directoryPath, string searchPattern, string[] files)
: base(result)
{
Expected = expected;
DirectoryPath = directoryPath;
SearchPattern = searchPattern;
Files = files;
}
public string DirectoryPath { get; }
public int Expected { get; }
public string[] Files { get; }
public string SearchPattern { get; }
protected override string Heading
{
get
{
var heading = new StringBuilder();
heading.AppendLine($"Expected {Expected} files matching {SearchPattern} in {DirectoryPath}, found {Files.Length}.");
if (Files.Length > 0)
{
heading.AppendLine("Files:");
foreach (var file in Files)
{
heading.Append("\t");
heading.Append(file);
}
heading.AppendLine();
}
return heading.ToString();
}
}
}
private class FileFoundException : MSBuildXunitException
{
public FileFoundException(MSBuildResult result, string filePath)
: base(result)
{
FilePath = filePath;
}
public string FilePath { get; }
protected override string Heading => $"File: '{FilePath}' was found, but should not exist.";
}
private class NuspecException : MSBuildXunitException
{
public NuspecException(MSBuildResult result, string filePath, string content, string expected)
: base(result)
{
FilePath = filePath;
Content = content;
Expected = expected;
}
public string Content { get; }
public string Expected { get; }
public string FilePath { get; }
protected override string Heading
{
get
{
return
$"nuspec: '{FilePath}' did not contain the expected content." + Environment.NewLine +
Environment.NewLine +
$"expected: {Expected}" + Environment.NewLine +
Environment.NewLine +
$"actual: {Content}";
}
}
}
private class NuspecFoundException : MSBuildXunitException
{
public NuspecFoundException(MSBuildResult result, string filePath, string content, string expected)
: base(result)
{
FilePath = filePath;
Content = content;
Expected = expected;
}
public string Content { get; }
public string Expected { get; }
public string FilePath { get; }
protected override string Heading
{
get
{
return
$"nuspec: '{FilePath}' should not contain the content {Expected}." +
Environment.NewLine +
$"actual content: {Content}";
}
}
}
private class NupkgFileMissingException : MSBuildXunitException
{
public NupkgFileMissingException(MSBuildResult result, string nupkgPath, string filePath)
: base(result)
{
NupkgPath = nupkgPath;
FilePath = filePath;
}
public string FilePath { get; }
public string NupkgPath { get; }
protected override string Heading => $"File: '{FilePath}' was not found was not found in {NupkgPath}.";
}
private class NupkgFileFoundException : MSBuildXunitException
{
public NupkgFileFoundException(MSBuildResult result, string nupkgPath, string filePath)
: base(result)
{
NupkgPath = nupkgPath;
FilePath = filePath;
}
public string FilePath { get; }
public string NupkgPath { get; }
protected override string Heading => $"File: '{FilePath}' was found in {NupkgPath}.";
}
}
}

View File

@ -0,0 +1,40 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Threading.Tasks;
using Xunit;
namespace Microsoft.AspNetCore.Blazor.Build
{
public class BuildIncrementalismTest
{
[Fact]
public async Task Build_WithLinker_IsIncremental()
{
// Arrange
using var project = ProjectDirectory.Create("standalone");
var result = await MSBuildProcessManager.DotnetMSBuild(project);
Assert.BuildPassed(result);
var buildOutputDirectory = project.BuildOutputDirectory;
// Act
var thumbPrint = FileThumbPrint.CreateFolderThumbprint(project, project.BuildOutputDirectory);
// Assert
for (var i = 0; i < 3; i++)
{
result = await MSBuildProcessManager.DotnetMSBuild(project);
Assert.BuildPassed(result);
var newThumbPrint = FileThumbPrint.CreateFolderThumbprint(project, project.BuildOutputDirectory);
Assert.Equal(thumbPrint.Count, newThumbPrint.Count);
for (var j = 0; j < thumbPrint.Count; j++)
{
Assert.Equal(thumbPrint[j], newThumbPrint[j]);
}
}
}
}
}

View File

@ -0,0 +1,74 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.IO;
using System.Threading.Tasks;
using Xunit;
namespace Microsoft.AspNetCore.Blazor.Build
{
public class BuildIntegrationTest
{
[Fact]
public async Task Build_WithDefaultSettings_Works()
{
// Arrange
using var project = ProjectDirectory.Create("standalone");
var result = await MSBuildProcessManager.DotnetMSBuild(project);
Assert.BuildPassed(result);
var buildOutputDirectory = project.BuildOutputDirectory;
Assert.FileExists(result, buildOutputDirectory, "dist", "_framework", "blazor.boot.json");
Assert.FileExists(result, buildOutputDirectory, "dist", "_framework", "blazor.webassembly.js");
Assert.FileExists(result, buildOutputDirectory, "dist", "_framework", "wasm", "mono.wasm");
Assert.FileExists(result, buildOutputDirectory, "dist", "_framework", "wasm", "mono.js");
Assert.FileExists(result, buildOutputDirectory, "dist", "_framework", "_bin", "standalone.dll");
Assert.FileExists(result, buildOutputDirectory, "dist", "_framework", "_bin", "Microsoft.Extensions.Logging.Abstractions.dll"); // Verify dependencies are part of the output.
}
[Fact]
public async Task Build_Hosted_Works()
{
// Arrange
using var project = ProjectDirectory.Create("blazorhosted", additionalProjects: new[] { "standalone", "razorclasslibrary", });
project.TargetFramework = "netcoreapp5.0";
var result = await MSBuildProcessManager.DotnetMSBuild(project);
Assert.BuildPassed(result);
var buildOutputDirectory = project.BuildOutputDirectory;
var blazorConfig = Path.Combine(buildOutputDirectory, "standalone.blazor.config");
Assert.FileExists(result, blazorConfig);
var path = Path.GetFullPath(Path.Combine(project.SolutionPath, "standalone", "bin", project.Configuration, "netstandard2.1", "standalone.dll"));
Assert.FileContains(result, blazorConfig, path);
Assert.FileDoesNotExist(result, buildOutputDirectory, "dist", "_framework", "_bin", "standalone.dll");
}
[Fact]
public async Task Build_WithLinkOnBuildDisabled_Works()
{
// Arrange
using var project = ProjectDirectory.Create("standalone");
project.AddProjectFileContent(
@"<PropertyGroup>
<BlazorLinkOnBuild>false</BlazorLinkOnBuild>
</PropertyGroup>");
var result = await MSBuildProcessManager.DotnetMSBuild(project);
Assert.BuildPassed(result);
var buildOutputDirectory = project.BuildOutputDirectory;
Assert.FileExists(result, buildOutputDirectory, "dist", "_framework", "blazor.boot.json");
Assert.FileExists(result, buildOutputDirectory, "dist", "_framework", "blazor.webassembly.js");
Assert.FileExists(result, buildOutputDirectory, "dist", "_framework", "wasm", "mono.wasm");
Assert.FileExists(result, buildOutputDirectory, "dist", "_framework", "wasm", "mono.js");
Assert.FileExists(result, buildOutputDirectory, "dist", "_framework", "_bin", "standalone.dll");
Assert.FileExists(result, buildOutputDirectory, "dist", "_framework", "_bin", "Microsoft.Extensions.Logging.Abstractions.dll"); // Verify dependencies are part of the output.
}
}
}

View File

@ -0,0 +1,74 @@
// 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.IO;
using System.Linq;
using System.Security.Cryptography;
namespace Microsoft.AspNetCore.Blazor.Build
{
internal class FileThumbPrint : IEquatable<FileThumbPrint>
{
private FileThumbPrint(string path, DateTime lastWriteTimeUtc, string hash)
{
FilePath = path;
LastWriteTimeUtc = lastWriteTimeUtc;
Hash = hash;
}
public string FilePath { get; }
public DateTime LastWriteTimeUtc { get; }
public string Hash { get; }
public override string ToString()
{
return $"{Path.GetFileName(FilePath)}, {LastWriteTimeUtc.ToString("u")}, {Hash}";
}
/// <summary>
/// Returns a list of thumbprints for all files (recursive) in the specified directory, sorted by file paths.
/// </summary>
public static List<FileThumbPrint> CreateFolderThumbprint(ProjectDirectory project, string directoryPath, params string[] filesToIgnore)
{
directoryPath = Path.Combine(project.DirectoryPath, directoryPath);
var files = Directory.GetFiles(directoryPath).Where(p => !filesToIgnore.Contains(p));
var thumbprintLookup = new List<FileThumbPrint>();
foreach (var file in files)
{
var thumbprint = Create(file);
thumbprintLookup.Add(thumbprint);
}
thumbprintLookup.Sort(Comparer<FileThumbPrint>.Create((a, b) => StringComparer.Ordinal.Compare(a.FilePath, b.FilePath)));
return thumbprintLookup;
}
public static FileThumbPrint Create(string path)
{
byte[] hashBytes;
using (var sha1 = SHA1.Create())
using (var fileStream = File.OpenRead(path))
{
hashBytes = sha1.ComputeHash(fileStream);
}
var hash = Convert.ToBase64String(hashBytes);
var lastWriteTimeUtc = File.GetLastWriteTimeUtc(path);
return new FileThumbPrint(path, lastWriteTimeUtc, hash);
}
public bool Equals(FileThumbPrint other)
{
return
string.Equals(FilePath, other.FilePath, StringComparison.Ordinal) &&
LastWriteTimeUtc == other.LastWriteTimeUtc &&
string.Equals(Hash, other.Hash, StringComparison.Ordinal);
}
public override int GetHashCode() => LastWriteTimeUtc.GetHashCode();
}
}

View File

@ -0,0 +1,282 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.CommandLineUtils;
namespace Microsoft.AspNetCore.Blazor.Build
{
internal static class MSBuildProcessManager
{
public static Task<MSBuildResult> DotnetMSBuild(
ProjectDirectory project,
string target = "Build",
string args = null)
{
var buildArgumentList = new List<string>
{
// Disable node-reuse. We don't want msbuild processes to stick around
// once the test is completed.
"/nr:false",
// Always generate a bin log for debugging purposes
"/bl",
};
buildArgumentList.Add($"/t:{target}");
buildArgumentList.Add($"/p:Configuration={project.Configuration}");
buildArgumentList.Add(args);
var buildArguments = string.Join(" ", buildArgumentList);
return MSBuildProcessManager.RunProcessAsync(project, buildArguments);
}
public static async Task<MSBuildResult> RunProcessAsync(
ProjectDirectory project,
string arguments,
TimeSpan? timeout = null)
{
var processStartInfo = new ProcessStartInfo()
{
WorkingDirectory = project.DirectoryPath,
UseShellExecute = false,
RedirectStandardError = true,
RedirectStandardOutput = true,
};
processStartInfo.FileName = DotNetMuxer.MuxerPathOrDefault();
processStartInfo.Arguments = $"msbuild {arguments}";
// Suppresses the 'Welcome to .NET Core!' output that times out tests and causes locked file issues.
// When using dotnet we're not guarunteed to run in an environment where the dotnet.exe has had its first run experience already invoked.
processStartInfo.EnvironmentVariables["DOTNET_SKIP_FIRST_TIME_EXPERIENCE"] = "true";
var processResult = await RunProcessCoreAsync(processStartInfo, timeout);
return new MSBuildResult(project, processResult.FileName, processResult.Arguments, processResult.ExitCode, processResult.Output);
}
internal static Task<ProcessResult> RunProcessCoreAsync(
ProcessStartInfo processStartInfo,
TimeSpan? timeout = null)
{
timeout = timeout ?? TimeSpan.FromSeconds(5 * 60);
var process = new Process()
{
StartInfo = processStartInfo,
EnableRaisingEvents = true,
};
var output = new StringBuilder();
var outputLock = new object();
var diagnostics = new StringBuilder();
diagnostics.AppendLine("Process execution diagnostics:");
process.ErrorDataReceived += Process_ErrorDataReceived;
process.OutputDataReceived += Process_OutputDataReceived;
process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();
var timeoutTask = GetTimeoutForProcess(process, timeout, diagnostics);
var waitTask = Task.Run(() =>
{
// We need to use two WaitForExit calls to ensure that all of the output/events are processed. Previously
// this code used Process.Exited, which could result in us missing some output due to the ordering of
// events.
//
// See the remarks here: https://msdn.microsoft.com/en-us/library/ty0d8k56(v=vs.110).aspx
if (!process.WaitForExit(Int32.MaxValue))
{
// unreachable - the timeoutTask will kill the process before this happens.
throw new TimeoutException();
}
process.WaitForExit();
string outputString;
lock (outputLock)
{
// This marks the end of the diagnostic info which we collect when something goes wrong.
diagnostics.AppendLine("Process output:");
// Expected output
// Process execution diagnostics:
// ...
// Process output:
outputString = diagnostics.ToString();
outputString += output.ToString();
}
var result = new ProcessResult(process.StartInfo.FileName, process.StartInfo.Arguments, process.ExitCode, outputString);
return result;
});
return Task.WhenAny<ProcessResult>(waitTask, timeoutTask).Unwrap();
void Process_ErrorDataReceived(object sender, DataReceivedEventArgs e)
{
lock (outputLock)
{
output.AppendLine(e.Data);
}
}
void Process_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
lock (outputLock)
{
output.AppendLine(e.Data);
}
}
async Task<ProcessResult> GetTimeoutForProcess(Process process, TimeSpan? timeout, StringBuilder diagnostics)
{
await Task.Delay(timeout.Value);
// Don't timeout during debug sessions
while (Debugger.IsAttached)
{
Thread.Sleep(TimeSpan.FromSeconds(1));
}
if (!process.HasExited)
{
await CollectDumps(process, timeout, diagnostics);
// This is a timeout.
process.Kill();
}
throw new TimeoutException($"command '${process.StartInfo.FileName} {process.StartInfo.Arguments}' timed out after {timeout}. Output: {output.ToString()}");
}
static async Task CollectDumps(Process process, TimeSpan? timeout, StringBuilder diagnostics)
{
var procDumpProcess = await CaptureDump(process, timeout, diagnostics);
var allDotNetProcesses = Process.GetProcessesByName("dotnet");
var allDotNetChildProcessCandidates = allDotNetProcesses
.Where(p => p.StartTime >= process.StartTime && p.Id != process.Id);
if (!allDotNetChildProcessCandidates.Any())
{
diagnostics.AppendLine("Couldn't find any candidate child process.");
foreach (var dotnetProcess in allDotNetProcesses)
{
diagnostics.AppendLine($"Found dotnet process with PID {dotnetProcess.Id} and start time {dotnetProcess.StartTime}.");
}
}
foreach (var childProcess in allDotNetChildProcessCandidates)
{
diagnostics.AppendLine($"Found child process candidate '{childProcess.Id}'.");
}
var childrenProcessDumpProcesses = await Task.WhenAll(allDotNetChildProcessCandidates.Select(d => CaptureDump(d, timeout, diagnostics)));
foreach (var childProcess in childrenProcessDumpProcesses)
{
if (childProcess != null && childProcess.HasExited)
{
diagnostics.AppendLine($"ProcDump failed to run for child dotnet process candidate '{process.Id}'.");
childProcess.Kill();
}
}
if (procDumpProcess != null && procDumpProcess.HasExited)
{
diagnostics.AppendLine($"ProcDump failed to run for '{process.Id}'.");
procDumpProcess.Kill();
}
}
static async Task<Process> CaptureDump(Process process, TimeSpan? timeout, StringBuilder diagnostics)
{
var metadataAttributes = Assembly.GetExecutingAssembly()
.GetCustomAttributes<AssemblyMetadataAttribute>();
var procDumpPath = metadataAttributes
.SingleOrDefault(ama => ama.Key == "ProcDumpToolPath")?.Value;
if (string.IsNullOrEmpty(procDumpPath))
{
diagnostics.AppendLine("ProcDumpPath not defined.");
return null;
}
var procDumpExePath = Path.Combine(procDumpPath, "procdump.exe");
if (!File.Exists(procDumpExePath))
{
diagnostics.AppendLine($"Can't find procdump.exe in '{procDumpPath}'.");
return null;
}
var dumpDirectory = metadataAttributes
.SingleOrDefault(ama => ama.Key == "ArtifactsLogDir")?.Value;
if (string.IsNullOrEmpty(dumpDirectory))
{
diagnostics.AppendLine("ArtifactsLogDir not defined.");
return null;
}
if (!Directory.Exists(dumpDirectory))
{
diagnostics.AppendLine($"'{dumpDirectory}' does not exist.");
return null;
}
var procDumpPattern = Path.Combine(dumpDirectory, "HangingProcess_PROCESSNAME_PID_YYMMDD_HHMMSS.dmp");
var procDumpStartInfo = new ProcessStartInfo(
procDumpExePath,
$"-accepteula -ma {process.Id} {procDumpPattern}")
{
CreateNoWindow = true,
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true
};
var procDumpProcess = Process.Start(procDumpStartInfo);
var tcs = new TaskCompletionSource<object>();
procDumpProcess.Exited += (s, a) => tcs.TrySetResult(null);
procDumpProcess.EnableRaisingEvents = true;
await Task.WhenAny(tcs.Task, Task.Delay(timeout ?? TimeSpan.FromSeconds(30)));
return procDumpProcess;
}
}
internal class ProcessResult
{
public ProcessResult(string fileName, string arguments, int exitCode, string output)
{
FileName = fileName;
Arguments = arguments;
ExitCode = exitCode;
Output = output;
}
public string Arguments { get; }
public string FileName { get; }
public int ExitCode { get; }
public string Output { get; }
}
}
}

View File

@ -0,0 +1,28 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace Microsoft.AspNetCore.Blazor.Build
{
internal class MSBuildResult
{
public MSBuildResult(ProjectDirectory project, string fileName, string arguments, int exitCode, string output)
{
Project = project;
FileName = fileName;
Arguments = arguments;
ExitCode = exitCode;
Output = output;
}
public ProjectDirectory Project { get; }
public string Arguments { get; }
public string FileName { get; }
public int ExitCode { get; }
public string Output { get; }
}
}

View File

@ -0,0 +1,211 @@
// 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.IO;
using System.Linq;
using System.Reflection;
using System.Threading;
namespace Microsoft.AspNetCore.Blazor.Build
{
internal class ProjectDirectory : IDisposable
{
public bool PreserveWorkingDirectory { get; set; } = false;
private static readonly string RepoRoot = GetTestAttribute("Testing.RepoRoot");
public static ProjectDirectory Create(string projectName, string baseDirectory = "", string[] additionalProjects = null)
{
var destinationPath = Path.Combine(Path.GetTempPath(), "BlazorBuild", baseDirectory, Path.GetRandomFileName());
Directory.CreateDirectory(destinationPath);
try
{
if (Directory.EnumerateFiles(destinationPath).Any())
{
throw new InvalidOperationException($"{destinationPath} should be empty");
}
if (string.IsNullOrEmpty(RepoRoot))
{
throw new InvalidOperationException("RepoRoot was not specified.");
}
var testAppsRoot = Path.Combine(RepoRoot, "src", "Components", "Blazor", "Build", "testassets");
foreach (var project in new string[] { projectName, }.Concat(additionalProjects ?? Array.Empty<string>()))
{
var projectRoot = Path.Combine(testAppsRoot, project);
if (!Directory.Exists(projectRoot))
{
throw new InvalidOperationException($"Could not find project at '{projectRoot}'");
}
var projectDestination = Path.Combine(destinationPath, project);
var projectDestinationDir = Directory.CreateDirectory(projectDestination);
CopyDirectory(new DirectoryInfo(projectRoot), projectDestinationDir);
SetupDirectoryBuildFiles(RepoRoot, testAppsRoot, projectDestination);
}
var directoryPath = Path.Combine(destinationPath, projectName);
var projectPath = Path.Combine(directoryPath, projectName + ".csproj");
CopyRepositoryAssets(destinationPath);
return new ProjectDirectory(
destinationPath,
directoryPath,
projectPath);
}
catch
{
CleanupDirectory(destinationPath);
throw;
}
static void CopyDirectory(DirectoryInfo source, DirectoryInfo destination, bool recursive = true)
{
foreach (var file in source.EnumerateFiles())
{
file.CopyTo(Path.Combine(destination.FullName, file.Name));
}
if (!recursive)
{
return;
}
foreach (var directory in source.EnumerateDirectories())
{
if (directory.Name == "bin")
{
// Just in case someone has opened the project in an IDE or built it. We don't want to copy
// these folders.
continue;
}
var created = destination.CreateSubdirectory(directory.Name);
if (directory.Name == "obj")
{
// Copy NuGet restore assets (viz all the files at the root of the obj directory, but stop there.)
CopyDirectory(directory, created, recursive: false);
}
else
{
CopyDirectory(directory, created);
}
}
}
static void SetupDirectoryBuildFiles(string repoRoot, string testAppsRoot, string projectDestination)
{
var beforeDirectoryPropsContent =
$@"<Project>
<PropertyGroup>
<RepoRoot>{repoRoot}</RepoRoot>
</PropertyGroup>
</Project>";
File.WriteAllText(Path.Combine(projectDestination, "Before.Directory.Build.props"), beforeDirectoryPropsContent);
new List<string> { "Directory.Build.props", "Directory.Build.targets", }
.ForEach(file =>
{
var source = Path.Combine(testAppsRoot, file);
var destination = Path.Combine(projectDestination, file);
File.Copy(source, destination);
});
}
static void CopyRepositoryAssets(string projectRoot)
{
const string GlobalJsonFileName = "global.json";
var globalJsonPath = Path.Combine(RepoRoot, GlobalJsonFileName);
var destinationFile = Path.Combine(projectRoot, GlobalJsonFileName);
File.Copy(globalJsonPath, destinationFile);
}
}
protected ProjectDirectory(string solutionPath, string directoryPath, string projectFilePath)
{
SolutionPath = solutionPath;
DirectoryPath = directoryPath;
ProjectFilePath = projectFilePath;
}
public string DirectoryPath { get; }
public string ProjectFilePath { get; }
public string SolutionPath { get; }
public string TargetFramework { get; set; } = "netstandard2.1";
#if DEBUG
public string Configuration => "Debug";
#elif RELEASE
public string Configuration => "Release";
#else
#error Configuration not supported
#endif
public string IntermediateOutputDirectory => Path.Combine("obj", Configuration, TargetFramework);
public string BuildOutputDirectory => Path.Combine("bin", Configuration, TargetFramework);
public string PublishOutputDirectory => Path.Combine(BuildOutputDirectory, "publish");
internal void AddProjectFileContent(string content)
{
if (content == null)
{
throw new ArgumentNullException(nameof(content));
}
var existing = File.ReadAllText(ProjectFilePath);
var updated = existing.Replace("<!-- Test Placeholder -->", content);
File.WriteAllText(ProjectFilePath, updated);
}
public void Dispose()
{
if (PreserveWorkingDirectory)
{
Console.WriteLine($"Skipping deletion of working directory {SolutionPath}");
}
else
{
CleanupDirectory(SolutionPath);
}
}
internal static void CleanupDirectory(string filePath)
{
var tries = 5;
var sleep = TimeSpan.FromSeconds(3);
for (var i = 0; i < tries; i++)
{
try
{
Directory.Delete(filePath, recursive: true);
return;
}
catch when (i < tries - 1)
{
Console.WriteLine($"Failed to delete directory {filePath}, trying again.");
Thread.Sleep(sleep);
}
}
}
private static string GetTestAttribute(string key)
{
return typeof(ProjectDirectory).Assembly
.GetCustomAttributes<AssemblyMetadataAttribute>()
.FirstOrDefault(f => f.Key == key)
?.Value;
}
}
}

View File

@ -0,0 +1,21 @@
// 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 Xunit;
namespace Microsoft.AspNetCore.Blazor.Build
{
public class ProjectDirectoryTest
{
[Fact]
public void ProjectDirectory_IsNotSetToBePreserved()
{
// Arrange
using var project = ProjectDirectory.Create("standalone");
// Act & Assert
// This flag is only meant for local debugging and should not be set when checking in.
Assert.False(project.PreserveWorkingDirectory);
}
}
}

View File

@ -0,0 +1,195 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.IO;
using System.Threading.Tasks;
using Xunit;
namespace Microsoft.AspNetCore.Blazor.Build
{
public class PublishIntegrationTest
{
[Fact]
public async Task Publish_WithDefaultSettings_Works()
{
// Arrange
using var project = ProjectDirectory.Create("standalone", additionalProjects: new [] { "razorclasslibrary" });
var result = await MSBuildProcessManager.DotnetMSBuild(project, "Publish");
Assert.BuildPassed(result);
var publishDirectory = project.PublishOutputDirectory;
var blazorPublishDirectory = Path.Combine(publishDirectory, Path.GetFileNameWithoutExtension(project.ProjectFilePath));
Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "blazor.boot.json");
Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "blazor.webassembly.js");
Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "wasm", "mono.wasm");
Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "wasm", "mono.js");
Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "_bin", "standalone.dll");
Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "_bin", "Microsoft.Extensions.Logging.Abstractions.dll"); // Verify dependencies are part of the output.
// Verify referenced static web assets
Assert.FileExists(result, blazorPublishDirectory, "dist", "_content", "RazorClassLibrary", "wwwroot", "exampleJsInterop.js");
Assert.FileExists(result, blazorPublishDirectory, "dist", "_content", "RazorClassLibrary", "styles.css");
// Verify static assets are in the publish directory
Assert.FileExists(result, blazorPublishDirectory, "dist", "index.html");
// Verify web.config
Assert.FileExists(result, publishDirectory, "web.config");
}
[Fact]
public async Task Publish_WithNoBuild_Works()
{
// Arrange
using var project = ProjectDirectory.Create("standalone", additionalProjects: new[] { "razorclasslibrary" });
var result = await MSBuildProcessManager.DotnetMSBuild(project, "Build");
Assert.BuildPassed(result);
result = await MSBuildProcessManager.DotnetMSBuild(project, "Publish", "/p:NoBuild=true");
Assert.BuildPassed(result);
var publishDirectory = project.PublishOutputDirectory;
var blazorPublishDirectory = Path.Combine(publishDirectory, Path.GetFileNameWithoutExtension(project.ProjectFilePath));
Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "blazor.boot.json");
Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "blazor.webassembly.js");
Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "wasm", "mono.wasm");
Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "wasm", "mono.js");
Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "_bin", "standalone.dll");
Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "_bin", "Microsoft.Extensions.Logging.Abstractions.dll"); // Verify dependencies are part of the output.
// Verify static assets are in the publish directory
Assert.FileExists(result, blazorPublishDirectory, "dist", "index.html");
// Verify static web assets from referenced projects are copied.
// Uncomment once https://github.com/aspnet/AspNetCore/issues/17426 is resolved.
// Assert.FileExists(result, blazorPublishDirectory, "dist", "_content", "RazorClassLibrary", "wwwroot", "exampleJsInterop.js");
// Assert.FileExists(result, blazorPublishDirectory, "dist", "_content", "RazorClassLibrary", "styles.css");
// Verify static assets are in the publish directory
Assert.FileExists(result, blazorPublishDirectory, "dist", "index.html");
// Verify web.config
Assert.FileExists(result, publishDirectory, "web.config");
}
[Fact]
public async Task Publish_WithLinkOnBuildDisabled_Works()
{
// Arrange
using var project = ProjectDirectory.Create("standalone", additionalProjects: new [] { "razorclasslibrary" });
project.AddProjectFileContent(
@"<PropertyGroup>
<BlazorLinkOnBuild>false</BlazorLinkOnBuild>
</PropertyGroup>");
var result = await MSBuildProcessManager.DotnetMSBuild(project, "Publish");
Assert.BuildPassed(result);
var publishDirectory = project.PublishOutputDirectory;
var blazorPublishDirectory = Path.Combine(publishDirectory, Path.GetFileNameWithoutExtension(project.ProjectFilePath));
Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "blazor.boot.json");
Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "blazor.webassembly.js");
Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "wasm", "mono.wasm");
Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "wasm", "mono.js");
Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "_bin", "standalone.dll");
Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "_bin", "Microsoft.Extensions.Logging.Abstractions.dll"); // Verify dependencies are part of the output.
// Verify static assets are in the publish directory
Assert.FileExists(result, blazorPublishDirectory, "dist", "index.html");
// Verify referenced static web assets
Assert.FileExists(result, blazorPublishDirectory, "dist", "_content", "RazorClassLibrary", "wwwroot", "exampleJsInterop.js");
Assert.FileExists(result, blazorPublishDirectory, "dist", "_content", "RazorClassLibrary", "styles.css");
// Verify web.config
Assert.FileExists(result, publishDirectory, "web.config");
}
[Fact]
public async Task Publish_HostedApp_Works()
{
// Arrange
using var project = ProjectDirectory.Create("blazorhosted", additionalProjects: new[] { "standalone", "razorclasslibrary", });
project.TargetFramework = "netcoreapp5.0";
var result = await MSBuildProcessManager.DotnetMSBuild(project, "Publish");
Assert.BuildPassed(result);
var publishDirectory = project.PublishOutputDirectory;
// Make sure the main project exists
Assert.FileExists(result, publishDirectory, "blazorhosted.dll");
var blazorPublishDirectory = Path.Combine(publishDirectory, "standalone");
Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "blazor.boot.json");
Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "blazor.webassembly.js");
Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "wasm", "mono.wasm");
Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "wasm", "mono.js");
Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "_bin", "standalone.dll");
Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "_bin", "Microsoft.Extensions.Logging.Abstractions.dll"); // Verify dependencies are part of the output.
// Verify static assets are in the publish directory
Assert.FileExists(result, blazorPublishDirectory, "dist", "index.html");
// Verify static web assets from referenced projects are copied.
Assert.FileExists(result, publishDirectory, "wwwroot", "_content", "RazorClassLibrary", "wwwroot", "exampleJsInterop.js");
Assert.FileExists(result, publishDirectory, "wwwroot", "_content", "RazorClassLibrary", "styles.css");
// Verify static assets are in the publish directory
Assert.FileExists(result, blazorPublishDirectory, "dist", "index.html");
// Verify web.config
Assert.FileExists(result, publishDirectory, "web.config");
var blazorConfig = Path.Combine(result.Project.DirectoryPath, publishDirectory, "standalone.blazor.config");
var blazorConfigLines = File.ReadAllLines(blazorConfig);
Assert.Equal(".", blazorConfigLines[0]);
Assert.Equal("standalone/", blazorConfigLines[1]);
}
[Fact]
public async Task Publish_HostedApp_WithNoBuild_Works()
{
// Arrange
using var project = ProjectDirectory.Create("blazorhosted", additionalProjects: new[] { "standalone", "razorclasslibrary", });
project.TargetFramework = "netcoreapp5.0";
var result = await MSBuildProcessManager.DotnetMSBuild(project, "Build");
Assert.BuildPassed(result);
result = await MSBuildProcessManager.DotnetMSBuild(project, "Publish", "/p:NoBuild=true");
var publishDirectory = project.PublishOutputDirectory;
// Make sure the main project exists
Assert.FileExists(result, publishDirectory, "blazorhosted.dll");
var blazorPublishDirectory = Path.Combine(publishDirectory, "standalone");
Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "blazor.boot.json");
Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "blazor.webassembly.js");
Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "wasm", "mono.wasm");
Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "wasm", "mono.js");
Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "_bin", "standalone.dll");
Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "_bin", "Microsoft.Extensions.Logging.Abstractions.dll"); // Verify dependencies are part of the output.
// Verify static assets are in the publish directory
Assert.FileExists(result, blazorPublishDirectory, "dist", "index.html");
// Verify static web assets from referenced projects are copied.
// Uncomment once https://github.com/aspnet/AspNetCore/issues/17426 is resolved.
// Assert.FileExists(result, publishDirectory, "wwwroot", "_content", "RazorClassLibrary", "wwwroot", "exampleJsInterop.js");
// Assert.FileExists(result, publishDirectory, "wwwroot", "_content", "RazorClassLibrary", "styles.css");
// Verify static assets are in the publish directory
Assert.FileExists(result, blazorPublishDirectory, "dist", "index.html");
// Verify web.config
Assert.FileExists(result, publishDirectory, "web.config");
}
}
}

View File

@ -5,6 +5,7 @@
<!-- Exclude the TestFiles directory from default wildcards -->
<DefaultItemExcludes>$(DefaultItemExcludes);TestFiles\**\*</DefaultItemExcludes>
<BuildHelixPayload>false</BuildHelixPayload>
</PropertyGroup>
<ItemGroup>
@ -25,16 +26,40 @@
<Reference Include="Microsoft.AspNetCore.Blazor.Mono" />
<Reference Include="Microsoft.AspNetCore.Mvc.Razor.Extensions" />
<Reference Include="Microsoft.AspNetCore.Razor.Language" />
<Reference Include="Microsoft.Build.Framework" />
<Reference Include="Microsoft.Build.Utilities.Core" />
<Reference Include="Microsoft.CodeAnalysis.Razor" />
<Reference Include="Microsoft.Extensions.CommandLineUtils.Sources" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\testassets\StandaloneApp\StandaloneApp.csproj" />
<Compile Include="$(SharedSourceRoot)test\SkipOnHelixAttribute.cs" />
<Compile Include="$(ComponentsSharedSourceRoot)test\**\*.cs" LinkBase="Helpers" />
</ItemGroup>
<ItemGroup>
<AssemblyAttribute Include="System.Reflection.AssemblyMetadataAttribute">
<_Parameter1>Testing.RepoRoot</_Parameter1>
<_Parameter2>$(RepoRoot)</_Parameter2>
</AssemblyAttribute>
</ItemGroup>
<Target Name="RestoreTestAssets" AfterTargets="Restore;Build" Condition="'$(DotNetBuildFromSource)' != 'true'">
<ItemGroup>
<_TestAsset Include="..\testassets\standalone\standalone.csproj" />
<_TestAsset Include="..\testassets\blazorhosted\blazorhosted.csproj" />
</ItemGroup>
<MSBuild
Projects="@(_TestAsset)"
Targets="Restore"
Properties="
RepoRoot=$(RepoRoot);
MicrosoftNetCompilersToolsetPackageVersion=$(MicrosoftNetCompilersToolsetPackageVersion);
MicrosoftNETSdkRazorPackageVersion=$(MicrosoftNETSdkRazorPackageVersion)" />
</Target>
<!-- A bit of msbuild magic to support reference resolver tests -->
<Target Name="CreateReferenceHintPathsList" AfterTargets="Build">
<ItemGroup>

View File

@ -9,7 +9,7 @@ using System.Text;
using Microsoft.AspNetCore.Testing;
using Xunit;
namespace Microsoft.AspNetCore.Blazor.Build.Test
namespace Microsoft.AspNetCore.Blazor.Build
{
public class RuntimeDependenciesResolverTest
{
@ -109,7 +109,7 @@ namespace Microsoft.AspNetCore.Blazor.Build.Test
// Act
var paths = RuntimeDependenciesResolver
var paths = ResolveBlazorRuntimeDependencies
.ResolveRuntimeDependenciesCore(
mainAssemblyLocation,
references,

View File

@ -0,0 +1,31 @@
<Project>
<Import Project="Before.Directory.Build.props" Condition="Exists('Before.Directory.Build.props')" />
<PropertyGroup>
<RepoRoot Condition="'$(RepoRoot)' ==''">$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), global.json))\</RepoRoot>
<ComponentsRoot>$(RepoRoot)src\Components\</ComponentsRoot>
<BlazorBuildRoot>$(ComponentsRoot)Blazor\Build\src\</BlazorBuildRoot>
<ReferenceBlazorBuildFromSourceProps>$(BlazorBuildRoot)ReferenceBlazorBuildFromSource.props</ReferenceBlazorBuildFromSourceProps>
<!-- Workaround for https://github.com/aspnet/AspNetCore/issues/17308 -->
<DefaultNetCoreTargetFramework>netcoreapp3.1</DefaultNetCoreTargetFramework>
<EnableSourceLink>false</EnableSourceLink>
<DeterministicSourcePaths>false</DeterministicSourcePaths>
</PropertyGroup>
<Import Project="$(RepoRoot)eng\Versions.props" />
<ItemGroup>
<!-- Use the sample compiler \ SDK that the rest of our build uses-->
<PackageReference Include="Microsoft.Net.Compilers.Toolset"
Version="$(MicrosoftNetCompilersToolsetPackageVersion)"
PrivateAssets="all"
IsImplicitlyDefined="true" />
<PackageReference Include="Microsoft.NET.Sdk.Razor"
Version="$(MicrosoftNETSdkRazorPackageVersion)"
PrivateAssets="All"
IsImplicitlyDefined="true" />
</ItemGroup>
</Project>

View File

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

View File

@ -0,0 +1,15 @@
using System;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
namespace blazorhosted.Server
{
public class Program
{
public static void Main(string[] args)
{
Console.WriteLine(typeof(IWebHost));
}
}
}

View File

@ -0,0 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp5.0</TargetFramework>
<DisableImplicitComponentsAnalyzers>true</DisableImplicitComponentsAnalyzers>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\standalone\standalone.csproj" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk.Razor">
<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
<RazorLangVersion>3.0</RazorLangVersion>
</PropertyGroup>
</Project>

View File

@ -0,0 +1,8 @@
<Router AppAssembly="@typeof(Program).Assembly">
<Found Context="routeData">
<RouteView RouteData="@routeData"/>
</Found>
<NotFound>
<p>Sorry, there's nothing at this address.</p>
</NotFound>
</Router>

View File

@ -0,0 +1,5 @@
@page "/"
<h1>Hello, world!</h1>
Welcome to your new app.

View File

@ -0,0 +1,10 @@

namespace standalone
{
public class Program
{
public static void Main(string[] args)
{
}
}
}

View File

@ -0,0 +1,2 @@
@using Microsoft.AspNetCore.Components.Routing
@using standalone

View File

@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<Import Project="$(ReferenceBlazorBuildFromSourceProps)" />
<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
<RazorLangVersion>3.0</RazorLangVersion>
</PropertyGroup>
<!-- Test Placeholder -->
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components" Version="3.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Blazor.Mono" Version="$(MicrosoftAspNetCoreBlazorMonoPackageVersion)" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\razorclasslibrary\RazorClassLibrary.csproj" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,24 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title>standalone</title>
<base href="/" />
<link href="css/bootstrap/bootstrap.min.css" rel="stylesheet" />
<link href="css/site.css" rel="stylesheet" />
</head>
<body>
<app>Loading...</app>
<div id="blazor-error-ui">
An unhandled error has occurred.
<a href="" class="reload">Reload</a>
<a class="dismiss">🗙</a>
</div>
<script src="_framework/blazor.webassembly.js"></script>
</body>
</html>

View File

@ -4,4 +4,5 @@
<PropertyGroup>
<ComponentsPackageVersion>$(PackageVersion)</ComponentsPackageVersion>
</PropertyGroup>
</Project>

View File

@ -1,10 +0,0 @@
<!-- This file is automatically generated. -->
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0</TargetFrameworks>
</PropertyGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
<Compile Include="Microsoft.AspNetCore.Blazor.HttpClient.netstandard2.0.cs" />
<Reference Include="System.Text.Json" />
</ItemGroup>
</Project>

View File

@ -1,18 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace Microsoft.AspNetCore.Components
{
public static partial class HttpClientJsonExtensions
{
[System.Diagnostics.DebuggerStepThroughAttribute]
public static System.Threading.Tasks.Task<T> GetJsonAsync<T>(this System.Net.Http.HttpClient httpClient, string requestUri) { throw null; }
public static System.Threading.Tasks.Task PostJsonAsync(this System.Net.Http.HttpClient httpClient, string requestUri, object content) { throw null; }
public static System.Threading.Tasks.Task<T> PostJsonAsync<T>(this System.Net.Http.HttpClient httpClient, string requestUri, object content) { throw null; }
public static System.Threading.Tasks.Task PutJsonAsync(this System.Net.Http.HttpClient httpClient, string requestUri, object content) { throw null; }
public static System.Threading.Tasks.Task<T> PutJsonAsync<T>(this System.Net.Http.HttpClient httpClient, string requestUri, object content) { throw null; }
public static System.Threading.Tasks.Task SendJsonAsync(this System.Net.Http.HttpClient httpClient, System.Net.Http.HttpMethod method, string requestUri, object content) { throw null; }
[System.Diagnostics.DebuggerStepThroughAttribute]
public static System.Threading.Tasks.Task<T> SendJsonAsync<T>(this System.Net.Http.HttpClient httpClient, System.Net.Http.HttpMethod method, string requestUri, object content) { throw null; }
}
}

View File

@ -4,6 +4,7 @@
<TargetFramework>netstandard2.0</TargetFramework>
<Description>Provides experimental support for using System.Text.Json with HttpClient. Intended for use with Blazor running under WebAssembly.</Description>
<IsShippingPackage>true</IsShippingPackage>
<HasReferenceAssembly>false</HasReferenceAssembly>
</PropertyGroup>
<ItemGroup>

View File

@ -0,0 +1,25 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Runtime.CompilerServices;
namespace WebAssembly.JSInterop
{
/// <summary>
/// Methods that map to the functions compiled into the Mono WebAssembly runtime,
/// as defined by 'mono_add_internal_call' calls in driver.c
/// </summary>
internal class InternalCalls
{
// The exact namespace, type, and method names must match the corresponding entries
// in driver.c in the Mono distribution
// We're passing asyncHandle by ref not because we want it to be writable, but so it gets
// passed as a pointer (4 bytes). We can pass 4-byte values, but not 8-byte ones.
[MethodImpl(MethodImplOptions.InternalCall)]
public static extern string InvokeJSMarshalled(out string exception, ref long asyncHandle, string functionIdentifier, string argsJson);
[MethodImpl(MethodImplOptions.InternalCall)]
public static extern TRes InvokeJSUnmarshalled<T0, T1, T2, TRes>(out string exception, string functionIdentifier, T0 arg0, T1 arg1, T2 arg2);
}
}

View File

@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
<Description>Abstractions and features for interop between Mono WebAssembly and JavaScript code.</Description>
<PackageTags>wasm;javascript;interop</PackageTags>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<IsPackable>true</IsPackable>
<IsShipping>true</IsShipping>
<HasReferenceAssembly>false</HasReferenceAssembly>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.JSInterop" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,157 @@
// 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.Text.Json;
using Microsoft.JSInterop;
using Microsoft.JSInterop.Infrastructure;
using WebAssembly.JSInterop;
namespace Mono.WebAssembly.Interop
{
/// <summary>
/// Provides methods for invoking JavaScript functions for applications running
/// on the Mono WebAssembly runtime.
/// </summary>
public class MonoWebAssemblyJSRuntime : JSInProcessRuntime
{
/// <summary>
/// Gets the <see cref="MonoWebAssemblyJSRuntime"/> used to perform operations using <see cref="DotNetDispatcher"/>.
/// </summary>
private static MonoWebAssemblyJSRuntime Instance { get; set; }
/// <summary>
/// Initializes the <see cref="MonoWebAssemblyJSRuntime"/> to be used to perform operations using <see cref="DotNetDispatcher"/>.
/// </summary>
/// <param name="jsRuntime">The <see cref="MonoWebAssemblyJSRuntime"/> instance.</param>
protected static void Initialize(MonoWebAssemblyJSRuntime jsRuntime)
{
if (Instance != null)
{
throw new InvalidOperationException("MonoWebAssemblyJSRuntime has already been initialized.");
}
Instance = jsRuntime ?? throw new ArgumentNullException(nameof(jsRuntime));
}
/// <inheritdoc />
protected override string InvokeJS(string identifier, string argsJson)
{
var noAsyncHandle = default(long);
var result = InternalCalls.InvokeJSMarshalled(out var exception, ref noAsyncHandle, identifier, argsJson);
return exception != null
? throw new JSException(exception)
: result;
}
/// <inheritdoc />
protected override void BeginInvokeJS(long asyncHandle, string identifier, string argsJson)
{
InternalCalls.InvokeJSMarshalled(out _, ref asyncHandle, identifier, argsJson);
}
// Invoked via Mono's JS interop mechanism (invoke_method)
private static string InvokeDotNet(string assemblyName, string methodIdentifier, string dotNetObjectId, string argsJson)
{
var callInfo = new DotNetInvocationInfo(assemblyName, methodIdentifier, dotNetObjectId == null ? default : long.Parse(dotNetObjectId), callId: null);
return DotNetDispatcher.Invoke(Instance, callInfo, argsJson);
}
// Invoked via Mono's JS interop mechanism (invoke_method)
private static void EndInvokeJS(string argsJson)
=> DotNetDispatcher.EndInvokeJS(Instance, argsJson);
// Invoked via Mono's JS interop mechanism (invoke_method)
private static void BeginInvokeDotNet(string callId, string assemblyNameOrDotNetObjectId, string methodIdentifier, string argsJson)
{
// Figure out whether 'assemblyNameOrDotNetObjectId' is the assembly name or the instance ID
// We only need one for any given call. This helps to work around the limitation that we can
// only pass a maximum of 4 args in a call from JS to Mono WebAssembly.
string assemblyName;
long dotNetObjectId;
if (char.IsDigit(assemblyNameOrDotNetObjectId[0]))
{
dotNetObjectId = long.Parse(assemblyNameOrDotNetObjectId);
assemblyName = null;
}
else
{
dotNetObjectId = default;
assemblyName = assemblyNameOrDotNetObjectId;
}
var callInfo = new DotNetInvocationInfo(assemblyName, methodIdentifier, dotNetObjectId, callId);
DotNetDispatcher.BeginInvokeDotNet(Instance, callInfo, argsJson);
}
protected override void EndInvokeDotNet(DotNetInvocationInfo callInfo, in DotNetInvocationResult dispatchResult)
{
// For failures, the common case is to call EndInvokeDotNet with the Exception object.
// For these we'll serialize as something that's useful to receive on the JS side.
// If the value is not an Exception, we'll just rely on it being directly JSON-serializable.
var resultOrError = dispatchResult.Success ? dispatchResult.Result : dispatchResult.Exception.ToString();
// We pass 0 as the async handle because we don't want the JS-side code to
// send back any notification (we're just providing a result for an existing async call)
var args = JsonSerializer.Serialize(new[] { callInfo.CallId, dispatchResult.Success, resultOrError }, JsonSerializerOptions);
BeginInvokeJS(0, "DotNet.jsCallDispatcher.endInvokeDotNetFromJS", args);
}
#region Custom MonoWebAssemblyJSRuntime methods
/// <summary>
/// Invokes the JavaScript function registered with the specified identifier.
/// </summary>
/// <typeparam name="TRes">The .NET type corresponding to the function's return value type.</typeparam>
/// <param name="identifier">The identifier used when registering the target function.</param>
/// <returns>The result of the function invocation.</returns>
public TRes InvokeUnmarshalled<TRes>(string identifier)
=> InvokeUnmarshalled<object, object, object, TRes>(identifier, null, null, null);
/// <summary>
/// Invokes the JavaScript function registered with the specified identifier.
/// </summary>
/// <typeparam name="T0">The type of the first argument.</typeparam>
/// <typeparam name="TRes">The .NET type corresponding to the function's return value type.</typeparam>
/// <param name="identifier">The identifier used when registering the target function.</param>
/// <param name="arg0">The first argument.</param>
/// <returns>The result of the function invocation.</returns>
public TRes InvokeUnmarshalled<T0, TRes>(string identifier, T0 arg0)
=> InvokeUnmarshalled<T0, object, object, TRes>(identifier, arg0, null, null);
/// <summary>
/// Invokes the JavaScript function registered with the specified identifier.
/// </summary>
/// <typeparam name="T0">The type of the first argument.</typeparam>
/// <typeparam name="T1">The type of the second argument.</typeparam>
/// <typeparam name="TRes">The .NET type corresponding to the function's return value type.</typeparam>
/// <param name="identifier">The identifier used when registering the target function.</param>
/// <param name="arg0">The first argument.</param>
/// <param name="arg1">The second argument.</param>
/// <returns>The result of the function invocation.</returns>
public TRes InvokeUnmarshalled<T0, T1, TRes>(string identifier, T0 arg0, T1 arg1)
=> InvokeUnmarshalled<T0, T1, object, TRes>(identifier, arg0, arg1, null);
/// <summary>
/// Invokes the JavaScript function registered with the specified identifier.
/// </summary>
/// <typeparam name="T0">The type of the first argument.</typeparam>
/// <typeparam name="T1">The type of the second argument.</typeparam>
/// <typeparam name="T2">The type of the third argument.</typeparam>
/// <typeparam name="TRes">The .NET type corresponding to the function's return value type.</typeparam>
/// <param name="identifier">The identifier used when registering the target function.</param>
/// <param name="arg0">The first argument.</param>
/// <param name="arg1">The second argument.</param>
/// <param name="arg2">The third argument.</param>
/// <returns>The result of the function invocation.</returns>
public TRes InvokeUnmarshalled<T0, T1, T2, TRes>(string identifier, T0 arg0, T1 arg1, T2 arg2)
{
var result = InternalCalls.InvokeJSUnmarshalled<T0, T1, T2, TRes>(out var exception, identifier, arg0, arg1, arg2);
return exception != null
? throw new JSException(exception)
: result;
}
#endregion
}
}

View File

@ -1,16 +0,0 @@
<!-- This file is automatically generated. -->
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>$(DefaultNetCoreTargetFramework)</TargetFrameworks>
</PropertyGroup>
<ItemGroup Condition="'$(TargetFramework)' == '$(DefaultNetCoreTargetFramework)'">
<Compile Include="Microsoft.AspNetCore.Blazor.Server.netcoreapp.cs" />
<Reference Include="Microsoft.AspNetCore.Hosting.Abstractions" />
<Reference Include="Microsoft.AspNetCore.SpaServices.Extensions" />
<Reference Include="Microsoft.AspNetCore.StaticFiles" />
<Reference Include="Microsoft.AspNetCore.WebSockets" />
<Reference Include="Microsoft.Extensions.FileProviders.Embedded" />
<Reference Include="Newtonsoft.Json" />
<Reference Include="Mono.Cecil" />
</ItemGroup>
</Project>

View File

@ -1,22 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace Microsoft.AspNetCore.Builder
{
public static partial class BlazorHostingApplicationBuilderExtensions
{
public static Microsoft.AspNetCore.Builder.IApplicationBuilder UseClientSideBlazorFiles(this Microsoft.AspNetCore.Builder.IApplicationBuilder app, string clientAssemblyFilePath) { throw null; }
public static Microsoft.AspNetCore.Builder.IApplicationBuilder UseClientSideBlazorFiles<TClientApp>(this Microsoft.AspNetCore.Builder.IApplicationBuilder app) { throw null; }
}
public static partial class BlazorHostingEndpointRouteBuilderExtensions
{
public static Microsoft.AspNetCore.Builder.IEndpointConventionBuilder MapFallbackToClientSideBlazor(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints, string clientAssemblyFilePath, string filePath) { throw null; }
public static Microsoft.AspNetCore.Builder.IEndpointConventionBuilder MapFallbackToClientSideBlazor(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints, string clientAssemblyFilePath, string pattern, string filePath) { throw null; }
public static Microsoft.AspNetCore.Builder.IEndpointConventionBuilder MapFallbackToClientSideBlazor<TClientApp>(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints, string filePath) { throw null; }
public static Microsoft.AspNetCore.Builder.IEndpointConventionBuilder MapFallbackToClientSideBlazor<TClientApp>(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints, string pattern, string filePath) { throw null; }
}
public static partial class BlazorMonoDebugProxyAppBuilderExtensions
{
public static void UseBlazorDebugging(this Microsoft.AspNetCore.Builder.IApplicationBuilder app) { }
}
}

View File

@ -4,13 +4,14 @@
<TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework>
<Description>Runtime server features for ASP.NET Core Blazor applications.</Description>
<IsShippingPackage>true</IsShippingPackage>
<HasReferenceAssembly>false</HasReferenceAssembly>
</PropertyGroup>
<ItemGroup>
<Compile Include="$(ComponentsSharedSourceRoot)\src\CacheHeaderSettings.cs" Link="Shared\CacheHeaderSettings.cs" />
</ItemGroup>
<ItemGroup>
<ItemGroup>
<Reference Include="Microsoft.AspNetCore.Hosting.Abstractions" />
<Reference Include="Microsoft.AspNetCore.SpaServices.Extensions" />
<Reference Include="Microsoft.AspNetCore.StaticFiles" />

View File

@ -9,9 +9,9 @@ using System.Linq;
using System.Net;
using System.Net.Http;
using System.Runtime.InteropServices;
using System.Text.Json;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Newtonsoft.Json;
using WsProxy;
namespace Microsoft.AspNetCore.Builder
@ -21,6 +21,15 @@ namespace Microsoft.AspNetCore.Builder
/// </summary>
public static class BlazorMonoDebugProxyAppBuilderExtensions
{
private static JsonSerializerOptions JsonOptions = new JsonSerializerOptions
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
PropertyNameCaseInsensitive = true,
IgnoreNullValues = true
};
private static string DefaultDebuggerHost = "http://localhost:9222";
/// <summary>
/// Adds middleware for needed for debugging Blazor applications
/// inside Chromium dev tools.
@ -29,6 +38,8 @@ namespace Microsoft.AspNetCore.Builder
{
app.UseWebSockets();
app.UseVisualStudioDebuggerConnectionRequestHandlers();
app.Use((context, next) =>
{
var requestPath = context.Request.Path;
@ -52,6 +63,85 @@ namespace Microsoft.AspNetCore.Builder
});
}
private static string GetDebuggerHost()
{
var envVar = Environment.GetEnvironmentVariable("ASPNETCORE_WEBASSEMBLYDEBUGHOST");
if (string.IsNullOrEmpty(envVar))
{
return DefaultDebuggerHost;
}
else
{
return envVar;
}
}
private static int GetDebuggerPort()
{
var host = GetDebuggerHost();
return new Uri(host).Port;
}
private static void UseVisualStudioDebuggerConnectionRequestHandlers(this IApplicationBuilder app)
{
// Unfortunately VS doesn't send any deliberately distinguishing information so we know it's
// not a regular browser or API client. The closest we can do is look for the *absence* of a
// User-Agent header. In the future, we should try to get VS to send a special header to indicate
// this is a debugger metadata request.
app.Use(async (context, next) =>
{
var request = context.Request;
var requestPath = request.Path;
if (requestPath.StartsWithSegments("/json")
&& !request.Headers.ContainsKey("User-Agent"))
{
if (requestPath.Equals("/json", StringComparison.OrdinalIgnoreCase) || requestPath.Equals("/json/list", StringComparison.OrdinalIgnoreCase))
{
var availableTabs = await GetOpenedBrowserTabs();
// Filter the list to only include tabs displaying the requested app,
// but only during the "choose application to debug" phase. We can't apply
// the same filter during the "connecting" phase (/json/list), nor do we need to.
if (requestPath.Equals("/json"))
{
availableTabs = availableTabs.Where(tab => tab.Url.StartsWith($"{request.Scheme}://{request.Host}{request.PathBase}/"));
}
var proxiedTabInfos = availableTabs.Select(tab =>
{
var underlyingV8Endpoint = tab.WebSocketDebuggerUrl;
var proxiedV8Endpoint = $"ws://{request.Host}{request.PathBase}/_framework/debug/ws-proxy?browser={WebUtility.UrlEncode(underlyingV8Endpoint)}";
return new
{
description = "",
devtoolsFrontendUrl = "",
id = tab.Id,
title = tab.Title,
type = tab.Type,
url = tab.Url,
webSocketDebuggerUrl = proxiedV8Endpoint
};
});
context.Response.ContentType = "application/json";
await context.Response.WriteAsync(JsonSerializer.Serialize(proxiedTabInfos));
}
else if (requestPath.Equals("/json/version", StringComparison.OrdinalIgnoreCase))
{
var browserVersionJson = await GetBrowserVersionInfoAsync();
context.Response.ContentType = "application/json";
await context.Response.WriteAsync(browserVersionJson);
}
}
else
{
await next();
}
});
}
private static async Task DebugWebSocketProxyRequest(HttpContext context)
{
if (!context.WebSockets.IsWebSocketRequest)
@ -81,13 +171,13 @@ namespace Microsoft.AspNetCore.Builder
// TODO: Allow overriding port (but not hostname, as we're connecting to the
// local browser, not to the webserver serving the app)
var debuggerHost = "http://localhost:9222";
var debuggerHost = GetDebuggerHost();
var debuggerTabsListUrl = $"{debuggerHost}/json";
IEnumerable<BrowserTab> availableTabs;
try
{
availableTabs = await GetOpenedBrowserTabs(debuggerHost);
availableTabs = await GetOpenedBrowserTabs();
}
catch (Exception ex)
{
@ -147,28 +237,30 @@ namespace Microsoft.AspNetCore.Builder
var underlyingV8Endpoint = tabToDebug.WebSocketDebuggerUrl;
var proxyEndpoint = $"{request.Host}{request.PathBase}/_framework/debug/ws-proxy?browser={WebUtility.UrlEncode(underlyingV8Endpoint)}";
var devToolsUrlAbsolute = new Uri(debuggerHost + tabToDebug.DevtoolsFrontendUrl);
var devToolsUrlWithProxy = $"{devToolsUrlAbsolute.Scheme}://{devToolsUrlAbsolute.Authority}{devToolsUrlAbsolute.AbsolutePath}?ws={proxyEndpoint}";
var wsParamName = request.IsHttps ? "wss" : "ws";
var devToolsUrlWithProxy = $"{devToolsUrlAbsolute.Scheme}://{devToolsUrlAbsolute.Authority}{devToolsUrlAbsolute.AbsolutePath}?{wsParamName}={proxyEndpoint}";
context.Response.Redirect(devToolsUrlWithProxy);
}
private static string GetLaunchChromeInstructions(string appRootUrl)
{
var profilePath = Path.Combine(Path.GetTempPath(), "blazor-edge-debug");
var profilePath = Path.Combine(Path.GetTempPath(), "blazor-chrome-debug");
var debuggerPort = GetDebuggerPort();
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
return $@"<p>Press Win+R and enter the following:</p>
<p><strong><code>chrome --remote-debugging-port=9222 --user-data-dir=""{profilePath}"" {appRootUrl}</code></strong></p>";
<p><strong><code>chrome --remote-debugging-port={debuggerPort} --user-data-dir=""{profilePath}"" {appRootUrl}</code></strong></p>";
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
return $@"<p>In a terminal window execute the following:</p>
<p><strong><code>google-chrome --remote-debugging-port=9222 --user-data-dir={profilePath} {appRootUrl}</code></strong></p>";
<p><strong><code>google-chrome --remote-debugging-port={debuggerPort} --user-data-dir={profilePath} {appRootUrl}</code></strong></p>";
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
return $@"<p>Execute the following:</p>
<p><strong><code>open /Applications/Google\ Chrome.app --args --remote-debugging-port=9222 --user-data-dir={profilePath} {appRootUrl}</code></strong></p>";
<p><strong><code>open /Applications/Google\ Chrome.app --args --remote-debugging-port={debuggerPort} --user-data-dir={profilePath} {appRootUrl}</code></strong></p>";
}
else
{
@ -178,17 +270,18 @@ namespace Microsoft.AspNetCore.Builder
private static string GetLaunchEdgeInstructions(string appRootUrl)
{
var profilePath = Path.Combine(Path.GetTempPath(), "blazor-chrome-debug");
var profilePath = Path.Combine(Path.GetTempPath(), "blazor-edge-debug");
var debugggerPort = GetDebuggerPort();
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
return $@"<p>Press Win+R and enter the following:</p>
<p><strong><code>msedge --remote-debugging-port=9222 --user-data-dir=""{profilePath}"" {appRootUrl}</code></strong></p>";
<p><strong><code>msedge --remote-debugging-port={debugggerPort} --user-data-dir=""{profilePath}"" --no-first-run {appRootUrl}</code></strong></p>";
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
return $@"<p>In a terminal window execute the following:</p>
<p><strong><code>open /Applications/Microsoft\ Edge\ Dev.app --args --remote-debugging-port=9222 --user-data-dir={profilePath} {appRootUrl}</code></strong></p>";
<p><strong><code>open /Applications/Microsoft\ Edge\ Dev.app --args --remote-debugging-port={debugggerPort} --user-data-dir={profilePath} {appRootUrl}</code></strong></p>";
}
else
{
@ -196,17 +289,24 @@ namespace Microsoft.AspNetCore.Builder
}
}
private static async Task<IEnumerable<BrowserTab>> GetOpenedBrowserTabs(string debuggerHost)
private static async Task<string> GetBrowserVersionInfoAsync()
{
using (var httpClient = new HttpClient { Timeout = TimeSpan.FromSeconds(5) })
{
var jsonResponse = await httpClient.GetStringAsync($"{debuggerHost}/json");
return JsonConvert.DeserializeObject<BrowserTab[]>(jsonResponse);
}
using var httpClient = new HttpClient { Timeout = TimeSpan.FromSeconds(5) };
var debuggerHost = GetDebuggerHost();
return await httpClient.GetStringAsync($"{debuggerHost}/json/version");
}
private static async Task<IEnumerable<BrowserTab>> GetOpenedBrowserTabs()
{
using var httpClient = new HttpClient { Timeout = TimeSpan.FromSeconds(5) };
var debuggerHost = GetDebuggerHost();
var jsonResponse = await httpClient.GetStringAsync($"{debuggerHost}/json");
return JsonSerializer.Deserialize<BrowserTab[]>(jsonResponse, JsonOptions);
}
class BrowserTab
{
public string Id { get; set; }
public string Type { get; set; }
public string Url { get; set; }
public string Title { get; set; }

View File

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<TargetFramework>netstandard2.1</TargetFramework>
<RazorLangVersion>3.0</RazorLangVersion>
</PropertyGroup>

View File

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<TargetFramework>netstandard2.1</TargetFramework>
<LangVersion>7.3</LangVersion>
</PropertyGroup>

View File

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<TargetFramework>netstandard2.1</TargetFramework>
<Description>Provides experimental support for validation using DataAnnotations.</Description>
<IsShippingPackage>true</IsShippingPackage>
<HasReferenceAssembly>false</HasReferenceAssembly>

View File

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<TargetFramework>netstandard2.1</TargetFramework>
<OutputType>Exe</OutputType>
<ReferenceBlazorBuildLocally>true</ReferenceBlazorBuildLocally>
<RazorLangVersion>3.0</RazorLangVersion>
@ -11,17 +11,4 @@
<Reference Include="Microsoft.AspNetCore.Blazor" />
</ItemGroup>
<PropertyGroup>
<GetCurrentProjectStaticWebAssetsDependsOn>
$(GetCurrentProjectStaticWebAssetsDependsOn);
_ClearCurrentStaticWebAssetsForReferenceDiscovery
</GetCurrentProjectStaticWebAssetsDependsOn>
</PropertyGroup>
<Target Name="_ClearCurrentStaticWebAssetsForReferenceDiscovery">
<ItemGroup>
<StaticWebAsset Remove="@(StaticWebAsset)" Condition="'%(SourceType)' == ''" />
</ItemGroup>
</Target>
</Project>

View File

@ -8,7 +8,7 @@
<ProjectReference Include="..\HostedInAspNet.Client\HostedInAspNet.Client.csproj" />
</ItemGroup>
<ItemGroup>
<ItemGroup>
<Reference Include="Microsoft.AspNetCore.Blazor.Server" />
<Reference Include="Microsoft.AspNetCore" />
<Reference Include="Microsoft.Extensions.Hosting" />

View File

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<TargetFramework>netstandard2.1</TargetFramework>
<ReferenceBlazorBuildLocally>true</ReferenceBlazorBuildLocally>
<RazorLangVersion>3.0</RazorLangVersion>
</PropertyGroup>

View File

@ -2,6 +2,7 @@
<PropertyGroup>
<TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework>
<!-- This is so that we add the FrameworkReference to Microsoft.AspNetCore.App -->
</PropertyGroup>
<ItemGroup>

View File

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.Razor" TreatAsLocalProperty="BlazorLinkOnBuild">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<TargetFramework>netstandard2.1</TargetFramework>
<IsPackable>false</IsPackable>
<BlazorLinkOnBuild>false</BlazorLinkOnBuild>
<OutputType>exe</OutputType>

View File

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<TargetFramework>netstandard2.1</TargetFramework>
<ReferenceBlazorBuildLocally>true</ReferenceBlazorBuildLocally>
<RazorLangVersion>3.0</RazorLangVersion>
</PropertyGroup>

View File

@ -246,6 +246,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Blazor
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Blazor.DataAnnotations.Validation.Tests", "Blazor\Validation\test\Microsoft.AspNetCore.Blazor.DataAnnotations.Validation.Tests.csproj", "{A5617A9D-C71E-44DE-936C-27611EB40A02}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Mono.WebAssembly.Interop", "Mono.WebAssembly.Interop", "{21BB9C13-20C1-4F2B-80E4-D7C64AA3BD05}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.WebAssembly.Interop", "Blazor\Mono.WebAssembly.Interop\src\Mono.WebAssembly.Interop.csproj", "{D141CFEE-D10A-406B-8963-F86FA13732E3}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -1516,6 +1520,18 @@ Global
{A5617A9D-C71E-44DE-936C-27611EB40A02}.Release|x64.Build.0 = Release|Any CPU
{A5617A9D-C71E-44DE-936C-27611EB40A02}.Release|x86.ActiveCfg = Release|Any CPU
{A5617A9D-C71E-44DE-936C-27611EB40A02}.Release|x86.Build.0 = Release|Any CPU
{D141CFEE-D10A-406B-8963-F86FA13732E3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D141CFEE-D10A-406B-8963-F86FA13732E3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D141CFEE-D10A-406B-8963-F86FA13732E3}.Debug|x64.ActiveCfg = Debug|Any CPU
{D141CFEE-D10A-406B-8963-F86FA13732E3}.Debug|x64.Build.0 = Debug|Any CPU
{D141CFEE-D10A-406B-8963-F86FA13732E3}.Debug|x86.ActiveCfg = Debug|Any CPU
{D141CFEE-D10A-406B-8963-F86FA13732E3}.Debug|x86.Build.0 = Debug|Any CPU
{D141CFEE-D10A-406B-8963-F86FA13732E3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D141CFEE-D10A-406B-8963-F86FA13732E3}.Release|Any CPU.Build.0 = Release|Any CPU
{D141CFEE-D10A-406B-8963-F86FA13732E3}.Release|x64.ActiveCfg = Release|Any CPU
{D141CFEE-D10A-406B-8963-F86FA13732E3}.Release|x64.Build.0 = Release|Any CPU
{D141CFEE-D10A-406B-8963-F86FA13732E3}.Release|x86.ActiveCfg = Release|Any CPU
{D141CFEE-D10A-406B-8963-F86FA13732E3}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -1629,6 +1645,8 @@ Global
{FD9BD646-9D50-42ED-A3E1-90558BA0C6B2} = {7260DED9-22A9-4E9D-92F4-5E8A4404DEAF}
{B70F90C7-2696-4050-B24E-BF0308F4E059} = {7260DED9-22A9-4E9D-92F4-5E8A4404DEAF}
{A5617A9D-C71E-44DE-936C-27611EB40A02} = {7260DED9-22A9-4E9D-92F4-5E8A4404DEAF}
{21BB9C13-20C1-4F2B-80E4-D7C64AA3BD05} = {7260DED9-22A9-4E9D-92F4-5E8A4404DEAF}
{D141CFEE-D10A-406B-8963-F86FA13732E3} = {21BB9C13-20C1-4F2B-80E4-D7C64AA3BD05}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {CC3C47E1-AD1A-4619-9CD3-E08A0148E5CE}

View File

@ -17,6 +17,7 @@
"Blazor\\Templates\\src\\Microsoft.AspNetCore.Blazor.Templates.csproj",
"Blazor\\Validation\\src\\Microsoft.AspNetCore.Blazor.DataAnnotations.Validation.csproj",
"Blazor\\Validation\\test\\Microsoft.AspNetCore.Blazor.DataAnnotations.Validation.Tests.csproj",
"Blazor\\Mono.WebAssembly.Interop\\src\\Mono.WebAssembly.Interop.csproj",
"Blazor\\testassets\\HostedInAspNet.Client\\HostedInAspNet.Client.csproj",
"Blazor\\testassets\\HostedInAspNet.Server\\HostedInAspNet.Server.csproj",
"Blazor\\testassets\\Microsoft.AspNetCore.Blazor.E2EPerformance\\Microsoft.AspNetCore.Blazor.E2EPerformance.csproj",

View File

@ -12,6 +12,10 @@
<PropertyGroup>
<PackageTags>aspnetcore;components</PackageTags>
<!-- This property points to the latest released Microsoft.AspNetCore.App version it needs to be updated to
target the latest patch before a preview release. -->
<LatestAspNetCoreReferenceVersion>3.1.0</LatestAspNetCoreReferenceVersion>
<ComponentsSharedSourceRoot>$(MSBuildThisFileDirectory)Shared\</ComponentsSharedSourceRoot>
<!-- So we can use the tool from source within the repo without having to pack -->

View File

@ -3,6 +3,26 @@
<GenerateDocumentationFile Condition="'$(GenerateDocumentationFile)' == ''">true</GenerateDocumentationFile>
</PropertyGroup>
<!-- We need to do this because our build config interferes with the FrameworkReference definition.
This is a way to add the framework defition to the projects that need it (like Blazor Server and
Blazor Dev Server) -->
<Target Name="_AddAspNetCoreFrameworkReference" BeforeTargets="ProcessFrameworkReferences" Condition="'$(UseLatestAspNetCoreReference)' == 'true' ">
<ItemGroup>
<FrameworkReference Include="Microsoft.AspNetCore.App" Version="$(LatestAspNetCoreReferenceVersion)" />
<KnownFrameworkReference Include="Microsoft.AspNetCore.App">
<TargetFramework>netcoreapp3.1</TargetFramework>
<RuntimeFrameworkName>Microsoft.AspNetCore.App</RuntimeFrameworkName>
<DefaultRuntimeFrameworkVersion>$(LatestAspNetCoreReferenceVersion)</DefaultRuntimeFrameworkVersion>
<LatestRuntimeFrameworkVersion>$(LatestAspNetCoreReferenceVersion)</LatestRuntimeFrameworkVersion>
<TargetingPackName>Microsoft.AspNetCore.App.Ref</TargetingPackName>
<TargetingPackVersion>$(LatestAspNetCoreReferenceVersion)</TargetingPackVersion>
<RuntimePackNamePatterns>Microsoft.AspNetCore.App.Runtime.**RID**</RuntimePackNamePatterns>
<RuntimePackRuntimeIdentifiers>linux-arm;linux-arm64;linux-musl-arm64;linux-musl-x64;linux-x64;osx-x64;rhel.6-x64;tizen.4.0.0-armel;tizen.5.0.0-armel;win-arm;win-arm64;win-x64;win-x86</RuntimePackRuntimeIdentifiers>
<IsTrimmable>true</IsTrimmable>
</KnownFrameworkReference>
</ItemGroup>
</Target>
<ItemGroup>
<None Include="$(MSBuildThisFileDirectory)THIRD-PARTY-NOTICES.txt" Pack="true" PackagePath="." />

View File

@ -26,6 +26,8 @@
Private="false" />
</ItemGroup>
<Target Name="GetTargetPath" />
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), Directory.Build.targets))\Directory.Build.targets" />
</Project>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -2,7 +2,6 @@ import '@dotnet/jsinterop';
import './GlobalExports';
import * as Environment from './Environment';
import { monoPlatform } from './Platform/Mono/MonoPlatform';
import { getAssemblyNameFromUrl } from './Platform/Url';
import { renderBatch } from './Rendering/Renderer';
import { SharedMemoryRenderBatch } from './Rendering/RenderBatch/SharedMemoryRenderBatch';
import { Pointer } from './Platform/Platform';
@ -39,15 +38,13 @@ async function boot(options?: any): Promise<void> {
// Fetch the boot JSON file
const bootConfig = await fetchBootConfigAsync();
const embeddedResourcesPromise = loadEmbeddedResourcesAsync(bootConfig);
if (!bootConfig.linkerEnabled) {
console.info('Blazor is running in dev mode without IL stripping. To make the bundle size significantly smaller, publish the application or see https://go.microsoft.com/fwlink/?linkid=870414');
}
// Determine the URLs of the assemblies we want to load, then begin fetching them all
const loadAssemblyUrls = [bootConfig.main]
.concat(bootConfig.assemblyReferences)
const loadAssemblyUrls = bootConfig.assemblies
.map(filename => `_framework/_bin/${filename}`);
try {
@ -56,12 +53,8 @@ async function boot(options?: any): Promise<void> {
throw new Error(`Failed to start platform. Reason: ${ex}`);
}
// Before we start running .NET code, be sure embedded content resources are all loaded
await embeddedResourcesPromise;
// Start up the application
const mainAssemblyName = getAssemblyNameFromUrl(bootConfig.main);
platform.callEntryPoint(mainAssemblyName, bootConfig.entryPoint, []);
platform.callEntryPoint(bootConfig.entryAssembly);
}
async function fetchBootConfigAsync() {
@ -71,36 +64,10 @@ async function fetchBootConfigAsync() {
return bootConfigResponse.json() as Promise<BootJsonData>;
}
function loadEmbeddedResourcesAsync(bootConfig: BootJsonData): Promise<any> {
const cssLoadingPromises = bootConfig.cssReferences.map(cssReference => {
const linkElement = document.createElement('link');
linkElement.rel = 'stylesheet';
linkElement.href = cssReference;
return loadResourceFromElement(linkElement);
});
const jsLoadingPromises = bootConfig.jsReferences.map(jsReference => {
const scriptElement = document.createElement('script');
scriptElement.src = jsReference;
return loadResourceFromElement(scriptElement);
});
return Promise.all(cssLoadingPromises.concat(jsLoadingPromises));
}
function loadResourceFromElement(element: HTMLElement) {
return new Promise((resolve, reject) => {
element.onload = resolve;
element.onerror = reject;
document.head!.appendChild(element);
});
}
// Keep in sync with BootJsonData in Microsoft.AspNetCore.Blazor.Build
interface BootJsonData {
main: string;
entryPoint: string;
assemblyReferences: string[];
cssReferences: string[];
jsReferences: string[];
entryAssembly: string;
assemblies: string[];
linkerEnabled: boolean;
}

View File

@ -11,6 +11,8 @@ let assembly_load: (assemblyName: string) => number;
let find_class: (assemblyHandle: number, namespace: string, className: string) => number;
let find_method: (typeHandle: number, methodName: string, unknownArg: number) => MethodHandle;
let invoke_method: (method: MethodHandle, target: System_Object, argsArrayPtr: number, exceptionFlagIntPtr: number) => System_Object;
let mono_call_assembly_entry_point: (assemblyName: string, args: System_Object[]) => System_Object;
let mono_obj_array_new: (length: number) => System_Object;
let mono_string_get_utf8: (managedString: System_String) => Mono.Utf8Ptr;
let mono_string: (jsString: string) => System_String;
const appBinDirName = 'appBinDir';
@ -39,21 +41,9 @@ export const monoPlatform: Platform = {
findMethod: findMethod,
callEntryPoint: function callEntryPoint(assemblyName: string, entrypointMethod: string, args: System_Object[]): void {
// Parse the entrypointMethod, which is of the form MyApp.MyNamespace.MyTypeName::MyMethodName
// Note that we don't support specifying a method overload, so it has to be unique
const entrypointSegments = entrypointMethod.split('::');
if (entrypointSegments.length != 2) {
throw new Error('Malformed entry point method name; could not resolve class name and method name.');
}
const typeFullName = entrypointSegments[0];
const methodName = entrypointSegments[1];
const lastDot = typeFullName.lastIndexOf('.');
const namespace = lastDot > -1 ? typeFullName.substring(0, lastDot) : '';
const typeShortName = lastDot > -1 ? typeFullName.substring(lastDot + 1) : typeFullName;
const entryPointMethodHandle = monoPlatform.findMethod(assemblyName, namespace, typeShortName, methodName);
monoPlatform.callMethod(entryPointMethodHandle, null, args);
callEntryPoint: function callEntryPoint(assemblyName: string): System_Object {
const empty_array = mono_obj_array_new(0);
return mono_call_assembly_entry_point(assemblyName, [empty_array]);
},
callMethod: function callMethod(method: MethodHandle, target: System_Object, args: System_Object[]): System_Object {
@ -272,8 +262,12 @@ function createEmscriptenModuleInstance(loadAssemblyUrls: string[], onReady: ()
'number',
'number',
]);
mono_call_assembly_entry_point = Module.mono_call_assembly_entry_point;
mono_string_get_utf8 = Module.cwrap('mono_wasm_string_get_utf8', 'number', ['number']);
mono_string = Module.cwrap('mono_wasm_string_from_js', 'number', ['string']);
mono_obj_array_new = Module.cwrap ('mono_wasm_obj_array_new', 'number', ['number']);
MONO.loaded_files = [];

View File

@ -9,6 +9,8 @@ declare namespace Module {
// These should probably be in @types/emscripten
function FS_createPath(parent, path, canRead, canWrite);
function FS_createDataFile(parent, name, data, canRead, canWrite, canOwn);
function mono_call_assembly_entry_point(assemblyName: string, args: any[]): any;
}
// Emscripten declares these globals

View File

@ -1,7 +1,7 @@
export interface Platform {
start(loadAssemblyUrls: string[]): Promise<void>;
callEntryPoint(assemblyName: string, entrypointMethod: string, args: (System_Object | null)[]);
callEntryPoint(assemblyName: string): System_Object;
findMethod(assemblyName: string, namespace: string, className: string, methodName: string): MethodHandle;
callMethod(method: MethodHandle, target: System_Object | null, args: (System_Object | null)[]): System_Object;

View File

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<TargetFramework>netstandard2.1</TargetFramework>
<RazorLangVersion>3.0</RazorLangVersion>
<ReferenceBlazorBuildLocally>true</ReferenceBlazorBuildLocally>

View File

@ -4,7 +4,7 @@
<TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework>
</PropertyGroup>
<ItemGroup>
<ItemGroup>
<Reference Include="Microsoft.AspNetCore" />
<Reference Include="Microsoft.AspNetCore.Authentication.Cookies" />
<Reference Include="Microsoft.AspNetCore.Blazor.Server" />

View File

@ -47,6 +47,7 @@ void HostFxr::Load(HMODULE moduleHandle)
m_corehost_set_error_writer_fn = ModuleHelpers::GetKnownProcAddress<corehost_set_error_writer_fn>(moduleHandle, "hostfxr_set_error_writer", /* optional */ true);
m_hostfxr_initialize_for_dotnet_commandline_fn = ModuleHelpers::GetKnownProcAddress<hostfxr_initialize_for_dotnet_runtime_fn>(moduleHandle, "hostfxr_initialize_for_dotnet_command_line", /* optional */ true);
m_hostfxr_set_runtime_property_value_fn = ModuleHelpers::GetKnownProcAddress<hostfxr_set_runtime_property_value_fn>(moduleHandle, "hostfxr_set_runtime_property_value", /* optional */ true);
m_hostfxr_get_runtime_property_value_fn = ModuleHelpers::GetKnownProcAddress<hostfxr_get_runtime_property_value_fn>(moduleHandle, "hostfxr_get_runtime_property_value", /* optional */ true);
m_hostfxr_run_app_fn = ModuleHelpers::GetKnownProcAddress<hostfxr_run_app_fn>(moduleHandle, "hostfxr_run_app", /* optional */ true);
m_hostfxr_close_fn = ModuleHelpers::GetKnownProcAddress<hostfxr_close_fn>(moduleHandle, "hostfxr_close", /* optional */ true);
}
@ -164,6 +165,15 @@ int HostFxr::SetRuntimePropertyValue(PCWSTR name, PCWSTR value) const noexcept
return 0;
}
int HostFxr::GetRuntimePropertyValue(PCWSTR name, PWSTR* value) const noexcept
{
if (m_host_context_handle != nullptr && m_hostfxr_get_runtime_property_value_fn != nullptr)
{
return m_hostfxr_get_runtime_property_value_fn(m_host_context_handle, name, value);
}
return 0;
}
void HostFxr::Close() const noexcept
{
if (m_host_context_handle != nullptr && m_hostfxr_close_fn != nullptr)

View File

@ -25,6 +25,7 @@ typedef void(*corehost_error_writer_fn) (const WCHAR* message);
typedef corehost_error_writer_fn(*corehost_set_error_writer_fn) (corehost_error_writer_fn error_writer);
typedef int(*hostfxr_initialize_for_dotnet_runtime_fn)(int argc, const PCWSTR* argv, hostfxr_initialize_parameters* parameters, void* const* host_context_handle);
typedef int(*hostfxr_set_runtime_property_value_fn)(void* host_context_handle, PCWSTR name, PCWSTR value);
typedef int(*hostfxr_get_runtime_property_value_fn)(void* host_context_handle, PCWSTR name, PWSTR* value);
typedef int(*hostfxr_run_app_fn)(void* host_context_handle);
typedef int(*hostfxr_close_fn)(void* hostfxr_context_handle);
@ -73,6 +74,7 @@ public:
HostFxrErrorRedirector RedirectOutput(RedirectionOutput* writer) const noexcept;
int SetRuntimePropertyValue(PCWSTR name, PCWSTR value) const noexcept;
int GetRuntimePropertyValue(PCWSTR name, PWSTR* value) const noexcept;
int InitializeForApp(int argc, PCWSTR* argv, const std::wstring& m_dotnetExeKnownLocation) const noexcept;
void Close() const noexcept;
@ -82,6 +84,7 @@ private:
hostfxr_get_native_search_directories_fn m_hostfxr_get_native_search_directories_fn;
hostfxr_initialize_for_dotnet_runtime_fn m_hostfxr_initialize_for_dotnet_commandline_fn;
hostfxr_set_runtime_property_value_fn m_hostfxr_set_runtime_property_value_fn;
hostfxr_get_runtime_property_value_fn m_hostfxr_get_runtime_property_value_fn;
hostfxr_run_app_fn m_hostfxr_run_app_fn;
corehost_set_error_writer_fn m_corehost_set_error_writer_fn;
hostfxr_close_fn m_hostfxr_close_fn;

View File

@ -14,6 +14,7 @@ class ConfigUtility
#define CS_ASPNETCORE_HANDLER_SETTINGS L"handlerSettings"
#define CS_ASPNETCORE_HANDLER_VERSION L"handlerVersion"
#define CS_ASPNETCORE_DEBUG_FILE L"debugFile"
#define CS_ASPNETCORE_ENABLE_OUT_OF_PROCESS_CONSOLE_REDIRECTION L"enableOutOfProcessConsoleRedirection"
#define CS_ASPNETCORE_FORWARD_RESPONSE_CONNECTION_HEADER L"forwardResponseConnectionHeader"
#define CS_ASPNETCORE_DEBUG_LEVEL L"debugLevel"
#define CS_ASPNETCORE_HANDLER_SETTINGS_NAME L"name"
@ -41,6 +42,13 @@ public:
return FindKeyValuePair(pElement, CS_ASPNETCORE_DEBUG_LEVEL, strDebugFile);
}
static
HRESULT
FindEnableOutOfProcessConsoleRedirection(IAppHostElement* pElement, STRU& strEnableOutOfProcessConsoleRedirection)
{
return FindKeyValuePair(pElement, CS_ASPNETCORE_ENABLE_OUT_OF_PROCESS_CONSOLE_REDIRECTION, strEnableOutOfProcessConsoleRedirection);
}
static
HRESULT
FindForwardResponseConnectionHeader(IAppHostElement* pElement, STRU& strForwardResponseConnectionHeader)

View File

@ -252,7 +252,20 @@ IN_PROCESS_APPLICATION::ExecuteApplication()
if (m_pConfig->QueryCallStartupHook())
{
RETURN_IF_NOT_ZERO(context->m_hostFxr.SetRuntimePropertyValue(DOTNETCORE_STARTUP_HOOK, ASPNETCORE_STARTUP_ASSEMBLY));
PWSTR startupHookValue = NULL;
// Will get property not found if the enviroment variable isn't set.
context->m_hostFxr.GetRuntimePropertyValue(DOTNETCORE_STARTUP_HOOK, &startupHookValue);
if (startupHookValue == NULL)
{
RETURN_IF_NOT_ZERO(context->m_hostFxr.SetRuntimePropertyValue(DOTNETCORE_STARTUP_HOOK, ASPNETCORE_STARTUP_ASSEMBLY));
}
else
{
std::wstring startupHook(startupHookValue);
startupHook.append(L";").append(ASPNETCORE_STARTUP_ASSEMBLY);
RETURN_IF_NOT_ZERO(context->m_hostFxr.SetRuntimePropertyValue(DOTNETCORE_STARTUP_HOOK, startupHook.c_str()));
}
}
RETURN_IF_NOT_ZERO(context->m_hostFxr.SetRuntimePropertyValue(DOTNETCORE_USE_ENTRYPOINT_FILTER, L"1"));

View File

@ -158,6 +158,7 @@ PROCESS_MANAGER::GetProcess(
pConfig->QueryAnonymousAuthEnabled(),
pConfig->QueryEnvironmentVariables(),
pConfig->QueryStdoutLogEnabled(),
pConfig->QueryEnableOutOfProcessConsoleRedirection(),
fWebsocketSupported,
pConfig->QueryStdoutLogFile(),
pConfig->QueryApplicationPhysicalPath(), // physical path

View File

@ -25,6 +25,7 @@ SERVER_PROCESS::Initialize(
BOOL fAnonymousAuthEnabled,
std::map<std::wstring, std::wstring, ignore_case_comparer>& pEnvironmentVariables,
BOOL fStdoutLogEnabled,
BOOL fEnableOutOfProcessConsoleRedirection,
BOOL fWebSocketSupported,
STRU *pstruStdoutLogFile,
STRU *pszAppPhysicalPath,
@ -43,6 +44,7 @@ SERVER_PROCESS::Initialize(
m_fWindowsAuthEnabled = fWindowsAuthEnabled;
m_fBasicAuthEnabled = fBasicAuthEnabled;
m_fAnonymousAuthEnabled = fAnonymousAuthEnabled;
m_fEnableOutOfProcessConsoleRedirection = fEnableOutOfProcessConsoleRedirection;
m_pProcessManager->ReferenceProcessManager();
m_fDebuggerAttached = FALSE;
@ -1030,6 +1032,15 @@ SERVER_PROCESS::SetupStdHandles(
saAttr.bInheritHandle = TRUE;
saAttr.lpSecurityDescriptor = NULL;
if (!m_fEnableOutOfProcessConsoleRedirection)
{
pStartupInfo->dwFlags = STARTF_USESTDHANDLES;
pStartupInfo->hStdInput = INVALID_HANDLE_VALUE;
pStartupInfo->hStdError = INVALID_HANDLE_VALUE;
pStartupInfo->hStdOutput = INVALID_HANDLE_VALUE;
return hr;
}
if (!m_fStdoutLogEnabled)
{
CreatePipe(&m_hStdoutHandle, &m_hStdErrWritePipe, &saAttr, 0 /*nSize*/);
@ -1770,6 +1781,8 @@ SERVER_PROCESS::SERVER_PROCESS() :
m_dwListeningProcessId(0),
m_hListeningProcessHandle(NULL),
m_hShutdownHandle(NULL),
m_hStdErrWritePipe(NULL),
m_hReadThread(nullptr),
m_randomGenerator(std::random_device()())
{
//InterlockedIncrement(&g_dwActiveServerProcesses);
@ -1866,13 +1879,15 @@ SERVER_PROCESS::~SERVER_PROCESS()
m_pProcessManager = NULL;
}
if (m_hStdoutHandle != NULL)
if (m_hStdErrWritePipe != NULL)
{
if (m_hStdoutHandle != INVALID_HANDLE_VALUE)
if (m_hStdErrWritePipe != INVALID_HANDLE_VALUE)
{
CloseHandle(m_hStdoutHandle);
FlushFileBuffers(m_hStdErrWritePipe);
CloseHandle(m_hStdErrWritePipe);
}
m_hStdoutHandle = NULL;
m_hStdErrWritePipe = NULL;
}
// Forces ReadFile to cancel, causing the read loop to complete.
@ -1907,6 +1922,15 @@ SERVER_PROCESS::~SERVER_PROCESS()
m_hReadThread = nullptr;
}
if (m_hStdoutHandle != NULL)
{
if (m_hStdoutHandle != INVALID_HANDLE_VALUE)
{
CloseHandle(m_hStdoutHandle);
}
m_hStdoutHandle = NULL;
}
if (m_fStdoutLogEnabled)
{
m_Timer.CancelTimer();

View File

@ -37,6 +37,7 @@ public:
_In_ BOOL fAnonymousAuthEnabled,
_In_ std::map<std::wstring, std::wstring, ignore_case_comparer>& pEnvironmentVariables,
_In_ BOOL fStdoutLogEnabled,
_In_ BOOL fDisableRedirection,
_In_ BOOL fWebSocketSupported,
_In_ STRU *pstruStdoutLogFile,
_In_ STRU *pszAppPhysicalPath,
@ -253,6 +254,7 @@ private:
BOOL m_fBasicAuthEnabled;
BOOL m_fAnonymousAuthEnabled;
BOOL m_fDebuggerAttached;
BOOL m_fEnableOutOfProcessConsoleRedirection;
STTIMER m_Timer;
SOCKET m_socket;

View File

@ -379,6 +379,12 @@ REQUESTHANDLER_CONFIG::Populate(
goto Finished;
}
hr = ConfigUtility::FindEnableOutOfProcessConsoleRedirection(pAspNetCoreElement, m_fEnableOutOfProcessConsoleRedirection);
if (FAILED(hr))
{
goto Finished;
}
hr = ConfigUtility::FindForwardResponseConnectionHeader(pAspNetCoreElement, m_struForwardResponseConnectionHeader);
if (FAILED(hr))
{

View File

@ -218,6 +218,12 @@ public:
return &m_struConfigPath;
}
BOOL
QueryEnableOutOfProcessConsoleRedirection()
{
return !m_fEnableOutOfProcessConsoleRedirection.Equals(L"false", 1);
}
STRU*
QueryForwardResponseConnectionHeader()
{
@ -262,6 +268,7 @@ protected:
BOOL m_fWindowsAuthEnabled;
BOOL m_fBasicAuthEnabled;
BOOL m_fAnonymousAuthEnabled;
STRU m_fEnableOutOfProcessConsoleRedirection;
APP_HOSTING_MODEL m_hostingModel;
std::map<std::wstring, std::wstring, ignore_case_comparer> m_pEnvironmentVariables;
STRU m_struHostFxrLocation;

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