Merge pull request #15084 from aspnet/merge/release/3.1-to-master

Merge/release/3.1 to master
This commit is contained in:
Pranav K 2019-10-23 16:15:33 -07:00 committed by GitHub
commit 602cb1dea5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
241 changed files with 3834 additions and 1961 deletions

View File

@ -46,7 +46,8 @@
<!-- Contact email address for NuGet packages and Linux installers. --> <!-- Contact email address for NuGet packages and Linux installers. -->
<MaintainerEmail>nugetaspnet@microsoft.com</MaintainerEmail> <MaintainerEmail>nugetaspnet@microsoft.com</MaintainerEmail>
<PackageIconUrl>https://go.microsoft.com/fwlink/?LinkID=288859</PackageIconUrl> <PackageIcon>packageIcon.png</PackageIcon>
<PackageIconFullPath>$(MSBuildThisFileDirectory)packageIcon.png</PackageIconFullPath>
<PackageProjectUrl>https://asp.net</PackageProjectUrl> <PackageProjectUrl>https://asp.net</PackageProjectUrl>
<NuspecBasePath>$(MSBuildProjectDirectory)</NuspecBasePath> <NuspecBasePath>$(MSBuildProjectDirectory)</NuspecBasePath>
@ -55,6 +56,10 @@
<DefaultNetCoreTargetFramework>netcoreapp5.0</DefaultNetCoreTargetFramework> <DefaultNetCoreTargetFramework>netcoreapp5.0</DefaultNetCoreTargetFramework>
</PropertyGroup> </PropertyGroup>
<ItemGroup>
<None Include="$(PackageIconFullPath)" Pack="true" PackagePath="\"/>
</ItemGroup>
<!-- Warnings and errors --> <!-- Warnings and errors -->
<PropertyGroup> <PropertyGroup>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors> <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
@ -90,7 +95,7 @@
<TargetingPackInstallerBaseName>aspnetcore-targeting-pack</TargetingPackInstallerBaseName> <TargetingPackInstallerBaseName>aspnetcore-targeting-pack</TargetingPackInstallerBaseName>
<!-- Used to only produce targeting pack installers/packages once per major.minor. --> <!-- Used to only produce targeting pack installers/packages once per major.minor. -->
<IsTargetingPackBuilding Condition="'$(IsServicingBuild)' == 'true' AND '$(DotNetBuildFromSource)' != 'true'">false</IsTargetingPackBuilding> <IsTargetingPackBuilding Condition="'$(AspNetCorePatchVersion)' != '0' OR '$(DotNetBuildFromSource)' == 'true'">false</IsTargetingPackBuilding>
<!-- <!--
Archives and installers using this prefix are intended for internal-use only. Archives and installers using this prefix are intended for internal-use only.

View File

@ -58,7 +58,8 @@
<Import Project="eng\Baseline.Designer.props" /> <Import Project="eng\Baseline.Designer.props" />
<PropertyGroup Condition=" '$(IsPackable)' != 'false' AND '$(AspNetCorePatchVersion)' != '0' "> <PropertyGroup
Condition=" '$(IsPackable)' != 'false' AND '$(AspNetCorePatchVersion)' != '0' AND '$(DisableServicingFeatures)' != 'true' ">
<IsPackageInThisPatch Condition="'$(IsPackageInThisPatch)' == ''">$(PackagesInPatch.Contains(' $(PackageId);'))</IsPackageInThisPatch> <IsPackageInThisPatch Condition="'$(IsPackageInThisPatch)' == ''">$(PackagesInPatch.Contains(' $(PackageId);'))</IsPackageInThisPatch>
</PropertyGroup> </PropertyGroup>
@ -104,6 +105,12 @@
<Compile Include="$(SharedSourceRoot)ReferenceAssemblyInfo.cs" LinkBase="Properties" /> <Compile Include="$(SharedSourceRoot)ReferenceAssemblyInfo.cs" LinkBase="Properties" />
</ItemGroup> </ItemGroup>
<PropertyGroup Condition="'$(Language)' == 'C#'">
<!-- Reference assemblies should always use Major.Minor.0.0 for assembly versions even during servicing. Only the package version should be updated. -->
<!-- Pinning the implementation assemblies at Major.Minor.0.0 as we figure out compiling against ref assemblies. -->
<AssemblyVersion>$(AspNetCoreMajorVersion).$(AspNetCoreMinorVersion).0.0</AssemblyVersion>
</PropertyGroup>
<ItemGroup> <ItemGroup>
<KnownFrameworkReference Update="Microsoft.NETCore.App"> <KnownFrameworkReference Update="Microsoft.NETCore.App">
<!-- Always update the 'latest version', whether the repo is servicing or not. --> <!-- Always update the 'latest version', whether the repo is servicing or not. -->

View File

@ -6,6 +6,7 @@
<add key="darc-pub-dotnet-corefx-4ac4c03" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/darc-pub-dotnet-corefx-4ac4c036/nuget/v3/index.json" /> <add key="darc-pub-dotnet-corefx-4ac4c03" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/darc-pub-dotnet-corefx-4ac4c036/nuget/v3/index.json" />
<!--End: Package sources managed by Dependency Flow automation. Do not edit the sources above.--> <!--End: Package sources managed by Dependency Flow automation. Do not edit the sources above.-->
<add key="dotnet-core" value="https://dotnetfeed.blob.core.windows.net/dotnet-core/index.json" /> <add key="dotnet-core" value="https://dotnetfeed.blob.core.windows.net/dotnet-core/index.json" />
<add key="dotnet-tools" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json" />
<add key="aspnet-blazor" value="https://dotnetfeed.blob.core.windows.net/aspnet-blazor/index.json" /> <add key="aspnet-blazor" value="https://dotnetfeed.blob.core.windows.net/aspnet-blazor/index.json" />
<add key="aspnet-extensions" value="https://dotnetfeed.blob.core.windows.net/aspnet-extensions/index.json" /> <add key="aspnet-extensions" value="https://dotnetfeed.blob.core.windows.net/aspnet-extensions/index.json" />
<add key="aspnet-entityframeworkcore" value="https://dotnetfeed.blob.core.windows.net/aspnet-entityframeworkcore/index.json" /> <add key="aspnet-entityframeworkcore" value="https://dotnetfeed.blob.core.windows.net/aspnet-entityframeworkcore/index.json" />

File diff suppressed because it is too large Load Diff

View File

@ -1,138 +1,91 @@
<!-- <!--
This file contains a list of all the packages and their versions which were released in the last servicing This file contains a list of all the packages and their versions which were released in ASP.NET Core 3.0.0.
build of ASP.NET Core 2.2.x. Update this list when preparing for a new patch. Update this list when preparing for a new patch.
--> -->
<Baseline Version="2.2.7">
<Package Id="dotnet-dev-certs" Version="2.2.0" /> <Baseline Version="3.0.0">
<Package Id="dotnet-sql-cache" Version="2.2.0" /> <Package Id="AspNetCoreRuntime.3.0.x64" Version="3.0.0" />
<Package Id="dotnet-user-secrets" Version="2.2.0" /> <Package Id="AspNetCoreRuntime.3.0.x86" Version="3.0.0" />
<Package Id="dotnet-watch" Version="2.2.0" /> <Package Id="dotnet-sql-cache" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Antiforgery" Version="2.2.0" /> <Package Id="Microsoft.AspNetCore.ApiAuthorization.IdentityServer" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.ApiAuthorization.IdentityServer" Version="2.2.0-preview-35687" /> <Package Id="Microsoft.AspNetCore.App.Runtime.win-x64" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.ApplicationInsights.HostingStartup" Version="2.2.0" /> <Package Id="Microsoft.AspNetCore.Authentication.AzureAD.UI" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.AspNetCoreModule" Version="2.2.7" /> <Package Id="Microsoft.AspNetCore.Authentication.AzureADB2C.UI" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.AspNetCoreModuleV2" Version="2.2.7" /> <Package Id="Microsoft.AspNetCore.Authentication.Certificate" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Authentication.Abstractions" Version="2.2.0" /> <Package Id="Microsoft.AspNetCore.Authentication.Facebook" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Authentication.AzureAD.UI" Version="2.2.0" /> <Package Id="Microsoft.AspNetCore.Authentication.Google" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Authentication.AzureADB2C.UI" Version="2.2.0" /> <Package Id="Microsoft.AspNetCore.Authentication.JwtBearer" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Authentication.Cookies" Version="2.2.0" /> <Package Id="Microsoft.AspNetCore.Authentication.MicrosoftAccount" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Authentication.Core" Version="2.2.0" /> <Package Id="Microsoft.AspNetCore.Authentication.Negotiate" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Authentication.Facebook" Version="2.2.0" /> <Package Id="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Authentication.Google" Version="2.2.2" /> <Package Id="Microsoft.AspNetCore.Authentication.Twitter" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Authentication.JwtBearer" Version="2.2.0" /> <Package Id="Microsoft.AspNetCore.Authentication.WsFederation" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Authentication.MicrosoftAccount" Version="2.2.0" /> <Package Id="Microsoft.AspNetCore.Authorization" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Authentication.OAuth" Version="2.2.0" /> <Package Id="Microsoft.AspNetCore.AzureAppServices.HostingStartup" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="2.2.0" /> <Package Id="Microsoft.AspNetCore.AzureAppServices.SiteExtension" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Authentication.Twitter" Version="2.2.0" /> <Package Id="Microsoft.AspNetCore.AzureAppServicesIntegration" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Authentication.WsFederation" Version="2.2.0" /> <Package Id="Microsoft.AspNetCore.Blazor" Version="3.0.0-preview9.19465.2" />
<Package Id="Microsoft.AspNetCore.Authentication" Version="2.2.0" /> <Package Id="Microsoft.AspNetCore.Blazor.Build" Version="3.0.0-preview9.19465.2" />
<Package Id="Microsoft.AspNetCore.Authorization.Policy" Version="2.2.0" /> <Package Id="Microsoft.AspNetCore.Blazor.DevServer" Version="3.0.0-preview9.19465.2" />
<Package Id="Microsoft.AspNetCore.Authorization" Version="2.2.0" /> <Package Id="Microsoft.AspNetCore.Blazor.HttpClient" Version="3.0.0-preview9.19465.2" />
<Package Id="Microsoft.AspNetCore.AzureAppServices.HostingStartup" Version="2.2.5" /> <Package Id="Microsoft.AspNetCore.Blazor.Server" Version="3.0.0-preview9.19465.2" />
<Package Id="Microsoft.AspNetCore.AzureAppServicesIntegration" Version="2.2.5" /> <Package Id="Microsoft.AspNetCore.Blazor.Templates" Version="3.0.0-preview9.19465.2" />
<Package Id="Microsoft.AspNetCore.Connections.Abstractions" Version="2.2.0" /> <Package Id="Microsoft.AspNetCore.Components" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.CookiePolicy" Version="2.2.0" /> <Package Id="Microsoft.AspNetCore.Components.Analyzers" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Cors" Version="2.2.0" /> <Package Id="Microsoft.AspNetCore.Components.Authorization" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Cryptography.Internal" Version="2.2.0" /> <Package Id="Microsoft.AspNetCore.Components.Forms" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="2.2.0" /> <Package Id="Microsoft.AspNetCore.Components.Web" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.DataProtection.Abstractions" Version="2.2.0" /> <Package Id="Microsoft.AspNetCore.ConcurrencyLimiter" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.DataProtection.AzureKeyVault" Version="2.2.0" /> <Package Id="Microsoft.AspNetCore.Connections.Abstractions" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.DataProtection.AzureStorage" Version="2.2.7" /> <Package Id="Microsoft.AspNetCore.Cryptography.Internal" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.DataProtection.EntityFrameworkCore" Version="2.2.0" /> <Package Id="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.DataProtection.Extensions" Version="2.2.0" /> <Package Id="Microsoft.AspNetCore.DataProtection" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" Version="2.2.5" /> <Package Id="Microsoft.AspNetCore.DataProtection.Abstractions" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.DataProtection.SystemWeb" Version="2.2.0" /> <Package Id="Microsoft.AspNetCore.DataProtection.AzureKeyVault" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.DataProtection" Version="2.2.0" /> <Package Id="Microsoft.AspNetCore.DataProtection.AzureStorage" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Diagnostics.Abstractions" Version="2.2.0" /> <Package Id="Microsoft.AspNetCore.DataProtection.EntityFrameworkCore" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="2.2.1" /> <Package Id="Microsoft.AspNetCore.DataProtection.Extensions" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Diagnostics.HealthChecks" Version="2.2.0" /> <Package Id="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Diagnostics" Version="2.2.0" /> <Package Id="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.HostFiltering" Version="2.2.0" /> <Package Id="Microsoft.AspNetCore.HeaderPropagation" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Hosting.Abstractions" Version="2.2.0" /> <Package Id="Microsoft.AspNetCore.Hosting.WindowsServices" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Hosting.Server.Abstractions" Version="2.2.0" /> <Package Id="Microsoft.AspNetCore.Http.Connections.Client" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Hosting.WindowsServices" Version="2.2.0" /> <Package Id="Microsoft.AspNetCore.Http.Connections.Common" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Hosting" Version="2.2.7" /> <Package Id="Microsoft.AspNetCore.Http.Features" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Html.Abstractions" Version="2.2.0" /> <Package Id="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Http.Abstractions" Version="2.2.0" /> <Package Id="Microsoft.AspNetCore.Identity.Specification.Tests" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Http.Connections.Client" Version="1.1.0" /> <Package Id="Microsoft.AspNetCore.Identity.UI" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Http.Connections.Common" Version="1.1.0" /> <Package Id="Microsoft.AspNetCore.JsonPatch" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Http.Connections" Version="1.1.0" /> <Package Id="Microsoft.AspNetCore.Metadata" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Http.Extensions" Version="2.2.0" /> <Package Id="Microsoft.AspNetCore.MiddlewareAnalysis" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Http.Features" Version="2.2.0" /> <Package Id="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Http" Version="2.2.2" /> <Package Id="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.HttpOverrides" Version="2.2.0" /> <Package Id="Microsoft.AspNetCore.Mvc.Testing" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.HttpsPolicy" Version="2.2.0" /> <Package Id="Microsoft.AspNetCore.NodeServices" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="2.2.0" /> <Package Id="Microsoft.AspNetCore.Owin" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Identity.Specification.Tests" Version="2.2.0" /> <Package Id="Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Identity.UI" Version="2.2.5" /> <Package Id="Microsoft.AspNetCore.SignalR.Client" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Identity" Version="2.2.0" /> <Package Id="Microsoft.AspNetCore.SignalR.Client.Core" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.JsonPatch" Version="2.2.0" /> <Package Id="Microsoft.AspNetCore.SignalR.Common" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Localization.Routing" Version="2.2.0" /> <Package Id="Microsoft.AspNetCore.SignalR.Protocols.Json" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Localization" Version="2.2.0" /> <Package Id="Microsoft.AspNetCore.SignalR.Protocols.MessagePack" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.MiddlewareAnalysis" Version="2.2.0" /> <Package Id="Microsoft.AspNetCore.SignalR.Protocols.NewtonsoftJson" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Mvc.Abstractions" Version="2.2.0" /> <Package Id="Microsoft.AspNetCore.SignalR.Specification.Tests" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Mvc.Analyzers" Version="2.2.0" /> <Package Id="Microsoft.AspNetCore.SignalR.StackExchangeRedis" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Mvc.Api.Analyzers" Version="2.2.6" /> <Package Id="Microsoft.AspNetCore.SpaServices" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Mvc.ApiExplorer" Version="2.2.0" /> <Package Id="Microsoft.AspNetCore.SpaServices.Extensions" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Mvc.Core" Version="2.2.5" /> <Package Id="Microsoft.AspNetCore.TestHost" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Mvc.Cors" Version="2.2.0" /> <Package Id="Microsoft.dotnet-openapi" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Mvc.DataAnnotations" Version="2.2.0" /> <Package Id="Microsoft.DotNet.Web.Client.ItemTemplates" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Mvc.Formatters.Json" Version="2.2.0" /> <Package Id="Microsoft.DotNet.Web.ItemTemplates" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Mvc.Formatters.Xml" Version="2.2.0" /> <Package Id="Microsoft.DotNet.Web.ProjectTemplates.3.0" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Mvc.Localization" Version="2.2.0" /> <Package Id="Microsoft.DotNet.Web.Spa.ProjectTemplates.3.0" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Mvc.Razor.Extensions" Version="2.2.0" /> <Package Id="Microsoft.Extensions.ApiDescription.Client" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Mvc.Razor" Version="2.2.0" /> <Package Id="Microsoft.Extensions.ApiDescription.Server" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Mvc.RazorPages" Version="2.2.5" /> <Package Id="Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Mvc.TagHelpers" Version="2.2.0" /> <Package Id="Microsoft.Extensions.Identity.Core" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Mvc.Testing" Version="2.2.0" /> <Package Id="Microsoft.Extensions.Identity.Stores" Version="3.0.0" />
<Package Id="Microsoft.AspNetCore.Mvc.ViewFeatures" Version="2.2.0" />
<Package Id="Microsoft.AspNetCore.Mvc" Version="2.2.0" />
<Package Id="Microsoft.AspNetCore.NodeServices" Version="2.2.0" />
<Package Id="Microsoft.AspNetCore.Owin" Version="2.2.0" />
<Package Id="Microsoft.AspNetCore.Razor.Design" Version="2.2.0" />
<Package Id="Microsoft.AspNetCore.Razor.Language" Version="2.2.0" />
<Package Id="Microsoft.AspNetCore.Razor.Runtime" Version="2.2.0" />
<Package Id="Microsoft.AspNetCore.Razor" Version="2.2.0" />
<Package Id="Microsoft.AspNetCore.ResponseCaching.Abstractions" Version="2.2.0" />
<Package Id="Microsoft.AspNetCore.ResponseCaching" Version="2.2.0" />
<Package Id="Microsoft.AspNetCore.ResponseCompression" Version="2.2.0" />
<Package Id="Microsoft.AspNetCore.Rewrite" Version="2.2.0" />
<Package Id="Microsoft.AspNetCore.Routing.Abstractions" Version="2.2.0" />
<Package Id="Microsoft.AspNetCore.Routing" Version="2.2.2" />
<Package Id="Microsoft.AspNetCore.Server.HttpSys" Version="2.2.6" />
<Package Id="Microsoft.AspNetCore.Server.IIS" Version="2.2.6" />
<Package Id="Microsoft.AspNetCore.Server.IISIntegration" Version="2.2.1" />
<Package Id="Microsoft.AspNetCore.Server.Kestrel.Core" Version="2.2.0" />
<Package Id="Microsoft.AspNetCore.Server.Kestrel.Https" Version="2.2.0" />
<Package Id="Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions" Version="2.2.0" />
<Package Id="Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv" Version="2.2.0" />
<Package Id="Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets" Version="2.2.1" />
<Package Id="Microsoft.AspNetCore.Server.Kestrel" Version="2.2.0" />
<Package Id="Microsoft.AspNetCore.Session" Version="2.2.0" />
<Package Id="Microsoft.AspNetCore.SignalR.Client.Core" Version="1.1.0" />
<Package Id="Microsoft.AspNetCore.SignalR.Client" Version="1.1.0" />
<Package Id="Microsoft.AspNetCore.SignalR.Common" Version="1.1.0" />
<Package Id="Microsoft.AspNetCore.SignalR.Core" Version="1.1.0" />
<Package Id="Microsoft.AspNetCore.SignalR.Protocols.Json" Version="1.1.0" />
<Package Id="Microsoft.AspNetCore.SignalR.Protocols.MessagePack" Version="1.1.5" />
<Package Id="Microsoft.AspNetCore.SignalR.Redis" Version="1.1.5" />
<Package Id="Microsoft.AspNetCore.SignalR.Specification.Tests" Version="1.1.0" />
<Package Id="Microsoft.AspNetCore.SignalR.StackExchangeRedis" Version="1.1.5" />
<Package Id="Microsoft.AspNetCore.SignalR" Version="1.1.0" />
<Package Id="Microsoft.AspNetCore.SpaServices.Extensions" Version="2.2.0" />
<Package Id="Microsoft.AspNetCore.SpaServices" Version="2.2.7" />
<Package Id="Microsoft.AspNetCore.StaticFiles" Version="2.2.0" />
<Package Id="Microsoft.AspNetCore.TestHost" Version="2.2.0" />
<Package Id="Microsoft.AspNetCore.WebSockets" Version="2.2.1" />
<Package Id="Microsoft.AspNetCore.WebUtilities" Version="2.2.0" />
<Package Id="Microsoft.AspNetCore" Version="2.2.0" />
<Package Id="Microsoft.CodeAnalysis.Razor" Version="2.2.0" />
<Package Id="Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore" Version="2.2.0" />
<Package Id="Microsoft.Extensions.Identity.Core" Version="2.2.0" />
<Package Id="Microsoft.Extensions.Identity.Stores" Version="2.2.0" />
<Package Id="Microsoft.Net.Http.Headers" Version="2.2.0" />
<Package Id="Microsoft.Net.Sdk.Razor" Version="2.2.0" />
<Package Id="Microsoft.Owin.Security.Interop" Version="2.2.0" />
</Baseline> </Baseline>

View File

@ -4,8 +4,8 @@ This file contains a list of the package IDs which are patching in a given relea
CAUTION: due to limitations in MSBuild, the format of the PackagesInPatch property is picky. CAUTION: due to limitations in MSBuild, the format of the PackagesInPatch property is picky.
When adding a new package, make sure the new line ends with a semicolon and starts with a space. When adding a new package, make sure the new line ends with a semicolon and starts with a space.
Later on, this will be checked using this condition:
Directory.Build.props checks this property using the following condition:
<IsPackageInThisPatch>$(PackagesInPatch.Contains(' $(PackageId);'))</IsPackageInThisPatch> <IsPackageInThisPatch>$(PackagesInPatch.Contains(' $(PackageId);'))</IsPackageInThisPatch>
--> -->
<Project> <Project>
@ -15,59 +15,14 @@ Later on, this will be checked using this condition:
<PropertyGroup Condition=" '$(VersionPrefix)' == '3.0.1' "> <PropertyGroup Condition=" '$(VersionPrefix)' == '3.0.1' ">
<PackagesInPatch> <PackagesInPatch>
</PackagesInPatch> Microsoft.Net.Http.Headers;
</PropertyGroup> Microsoft.AspNetCore.CookiePolicy;
<PropertyGroup Condition=" '$(VersionPrefix)' == '2.2.2' "> Microsoft.AspNetCore.DataProtection.EntityFrameworkCore;
<PackagesInPatch> @microsoft/signalr;
@aspnet/signalr; Microsoft.Net.Http.Headers;
Microsoft.AspNetCore.AspNetCoreModuleV2; Microsoft.AspNetCore.Http.Abstractions;
Microsoft.AspNetCore.Authentication.Google; Microsoft.AspNetCore.Http.Features;
Microsoft.AspNetCore.Http; Microsoft.AspNetCore.CookiePolicy;
Microsoft.AspNetCore.Mvc.Core;
Microsoft.AspNetCore.Routing;
Microsoft.AspNetCore.Server.IIS;
java:signalr;
</PackagesInPatch>
</PropertyGroup>
<PropertyGroup Condition=" '$(VersionPrefix)' == '2.2.4' ">
<PackagesInPatch>
@aspnet/signalr;
Microsoft.AspNetCore.AspNetCoreModuleV2;
</PackagesInPatch>
</PropertyGroup>
<PropertyGroup Condition=" '$(VersionPrefix)' == '2.2.5' ">
<PackagesInPatch>
Microsoft.AspNetCore.AspNetCoreModule;
Microsoft.AspNetCore.AspNetCoreModuleV2;
Microsoft.AspNetCore.Identity.UI;
java:signalr;
Microsoft.AspNetCore.SignalR.Protocols.MessagePack;
Microsoft.AspNetCore.SignalR.Redis;
Microsoft.AspNetCore.SignalR.StackExchangeRedis;
Microsoft.AspNetCore.DataProtection.StackExchangeRedis;
Microsoft.AspNetCore.Mvc.Core;
Microsoft.AspNetCore.Mvc.RazorPages;
Microsoft.AspNetCore.AzureAppServicesIntegration;
Microsoft.AspNetCore.AzureAppServices.HostingStartup;
Microsoft.AspNetCore.AzureAppServices.SiteExtension;
</PackagesInPatch>
</PropertyGroup>
<PropertyGroup Condition=" '$(VersionPrefix)' == '2.2.6' ">
<PackagesInPatch>
Microsoft.AspNetCore.Mvc.Api.Analyzers;
Microsoft.AspNetCore.Server.HttpSys;
Microsoft.AspNetCore.Server.IIS;
</PackagesInPatch>
</PropertyGroup>
<PropertyGroup Condition=" '$(VersionPrefix)' == '2.2.7' ">
<PackagesInPatch>
Microsoft.AspNetCore.DataProtection.AzureStorage;
Microsoft.AspNetCore.Hosting;
Microsoft.AspNetCore.SpaServices;
</PackagesInPatch>
</PropertyGroup>
<PropertyGroup Condition=" '$(VersionPrefix)' == '2.2.8' ">
<PackagesInPatch>
</PackagesInPatch> </PackagesInPatch>
</PropertyGroup> </PropertyGroup>
</Project> </Project>

View File

@ -412,17 +412,17 @@
<Uri>https://github.com/aspnet/Extensions</Uri> <Uri>https://github.com/aspnet/Extensions</Uri>
<Sha>f15f3278c73c72a6546d7cb2c1bd54a541ffc83e</Sha> <Sha>f15f3278c73c72a6546d7cb2c1bd54a541ffc83e</Sha>
</Dependency> </Dependency>
<Dependency Name="Microsoft.DotNet.GenAPI" Version="1.0.0-beta.19462.4"> <Dependency Name="Microsoft.DotNet.GenAPI" Version="1.0.0-beta.19510.3">
<Uri>https://github.com/dotnet/arcade</Uri> <Uri>https://github.com/dotnet/arcade</Uri>
<Sha>f8546fbab59a74a66c83b8cb76b3f6877ce1d374</Sha> <Sha>f70d1fca3d5d4045be75694006f1bee0e0aec572</Sha>
</Dependency> </Dependency>
<Dependency Name="Microsoft.DotNet.Arcade.Sdk" Version="1.0.0-beta.19462.4"> <Dependency Name="Microsoft.DotNet.Arcade.Sdk" Version="1.0.0-beta.19510.3">
<Uri>https://github.com/dotnet/arcade</Uri> <Uri>https://github.com/dotnet/arcade</Uri>
<Sha>f8546fbab59a74a66c83b8cb76b3f6877ce1d374</Sha> <Sha>f70d1fca3d5d4045be75694006f1bee0e0aec572</Sha>
</Dependency> </Dependency>
<Dependency Name="Microsoft.DotNet.Helix.Sdk" Version="2.0.0-beta.19462.4"> <Dependency Name="Microsoft.DotNet.Helix.Sdk" Version="2.0.0-beta.19510.3">
<Uri>https://github.com/dotnet/arcade</Uri> <Uri>https://github.com/dotnet/arcade</Uri>
<Sha>f8546fbab59a74a66c83b8cb76b3f6877ce1d374</Sha> <Sha>f70d1fca3d5d4045be75694006f1bee0e0aec572</Sha>
</Dependency> </Dependency>
<Dependency Name="Microsoft.AspNetCore.Testing" Version="5.0.0-alpha1.19517.7" CoherentParentDependency="Microsoft.EntityFrameworkCore"> <Dependency Name="Microsoft.AspNetCore.Testing" Version="5.0.0-alpha1.19517.7" CoherentParentDependency="Microsoft.EntityFrameworkCore">
<Uri>https://github.com/aspnet/Extensions</Uri> <Uri>https://github.com/aspnet/Extensions</Uri>

View File

@ -20,8 +20,15 @@
<AspNetCoreMajorMinorVersion>$(AspNetCoreMajorVersion).$(AspNetCoreMinorVersion)</AspNetCoreMajorMinorVersion> <AspNetCoreMajorMinorVersion>$(AspNetCoreMajorVersion).$(AspNetCoreMinorVersion)</AspNetCoreMajorMinorVersion>
<!-- Additional assembly attributes are already configured to include the source revision ID. --> <!-- Additional assembly attributes are already configured to include the source revision ID. -->
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion> <IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
<!--
Until package baselines are updated (see aspnet/AspNetCore#12702), ignore them and PatchConfig.props. This also
gives us time to build the entire repo and settle the infrastructure. Do _not_ do this when stabilizing versions.
-->
<DisableServicingFeatures
Condition=" '$(DisableServicingFeatures)' == '' AND '$(StabilizePackageVersion)' != 'true' ">true</DisableServicingFeatures>
<!-- Servicing builds have different characteristics for the way dependencies, baselines, and versions are handled. --> <!-- Servicing builds have different characteristics for the way dependencies, baselines, and versions are handled. -->
<IsServicingBuild Condition=" '$(PreReleaseVersionLabel)' == 'servicing' ">true</IsServicingBuild> <IsServicingBuild
Condition=" '$(DisableServicingFeatures)' != 'true' AND '$(PreReleaseVersionLabel)' == 'servicing' ">true</IsServicingBuild>
<VersionPrefix>$(AspNetCoreMajorVersion).$(AspNetCoreMinorVersion).$(AspNetCorePatchVersion)</VersionPrefix> <VersionPrefix>$(AspNetCoreMajorVersion).$(AspNetCoreMinorVersion).$(AspNetCorePatchVersion)</VersionPrefix>
<!-- TargetingPackVersionPrefix is used by projects, like .deb and .rpm, which use slightly different version formats. --> <!-- TargetingPackVersionPrefix is used by projects, like .deb and .rpm, which use slightly different version formats. -->
<TargetingPackVersionPrefix>$(VersionPrefix)</TargetingPackVersionPrefix> <TargetingPackVersionPrefix>$(VersionPrefix)</TargetingPackVersionPrefix>
@ -55,7 +62,7 @@
--> -->
<PropertyGroup Label="Automated"> <PropertyGroup Label="Automated">
<!-- Packages from dotnet/arcade --> <!-- Packages from dotnet/arcade -->
<MicrosoftDotNetGenAPIPackageVersion>1.0.0-beta.19462.4</MicrosoftDotNetGenAPIPackageVersion> <MicrosoftDotNetGenAPIPackageVersion>1.0.0-beta.19510.3</MicrosoftDotNetGenAPIPackageVersion>
<!-- Packages from dotnet/roslyn --> <!-- Packages from dotnet/roslyn -->
<MicrosoftNetCompilersToolsetPackageVersion>3.4.0-beta1-19456-03</MicrosoftNetCompilersToolsetPackageVersion> <MicrosoftNetCompilersToolsetPackageVersion>3.4.0-beta1-19456-03</MicrosoftNetCompilersToolsetPackageVersion>
<!-- Packages from dotnet/core-setup --> <!-- Packages from dotnet/core-setup -->
@ -229,7 +236,7 @@
<CastleCorePackageVersion>4.2.1</CastleCorePackageVersion> <CastleCorePackageVersion>4.2.1</CastleCorePackageVersion>
<FSharpCorePackageVersion>4.2.1</FSharpCorePackageVersion> <FSharpCorePackageVersion>4.2.1</FSharpCorePackageVersion>
<GoogleProtobufPackageVersion>3.8.0</GoogleProtobufPackageVersion> <GoogleProtobufPackageVersion>3.8.0</GoogleProtobufPackageVersion>
<GrpcAspNetCorePackageVersion>2.23.1</GrpcAspNetCorePackageVersion> <GrpcAspNetCorePackageVersion>2.23.2</GrpcAspNetCorePackageVersion>
<IdentityServer4AspNetIdentityPackageVersion>3.0.0</IdentityServer4AspNetIdentityPackageVersion> <IdentityServer4AspNetIdentityPackageVersion>3.0.0</IdentityServer4AspNetIdentityPackageVersion>
<IdentityServer4EntityFrameworkPackageVersion>3.0.0</IdentityServer4EntityFrameworkPackageVersion> <IdentityServer4EntityFrameworkPackageVersion>3.0.0</IdentityServer4EntityFrameworkPackageVersion>
<IdentityServer4PackageVersion>3.0.0</IdentityServer4PackageVersion> <IdentityServer4PackageVersion>3.0.0</IdentityServer4PackageVersion>

View File

@ -21,6 +21,8 @@
<PropertyGroup> <PropertyGroup>
<!-- Working around https://github.com/NuGet/Home/issues/8467 --> <!-- Working around https://github.com/NuGet/Home/issues/8467 -->
<NoWarn>$(NoWarn);NU5131</NoWarn> <NoWarn>$(NoWarn);NU5131</NoWarn>
<!-- Workaround until https://github.com/aspnet/AspNetCore-Internal/issues/3103 is resolved -->
<NoWarn>$(NoWarn);NU5048</NoWarn>
</PropertyGroup> </PropertyGroup>
<!-- Workaround https://github.com/dotnet/roslyn/issues/27975 --> <!-- Workaround https://github.com/dotnet/roslyn/issues/27975 -->

View File

@ -0,0 +1,6 @@
param(
[string] $token
)
Write-Host "##vso[task.setvariable variable=VSS_NUGET_ACCESSTOKEN]$token"
Write-Host "##vso[task.setvariable variable=VSS_NUGET_URI_PREFIXES]https://dnceng.pkgs.visualstudio.com/;https://pkgs.dev.azure.com/dnceng/;https://devdiv.pkgs.visualstudio.com/;https://pkgs.dev.azure.com/devdiv/"

View File

@ -5,6 +5,13 @@ param(
$ErrorActionPreference = "Stop" $ErrorActionPreference = "Stop"
Set-StrictMode -Version 2.0 Set-StrictMode -Version 2.0
# `tools.ps1` checks $ci to perform some actions. Since the post-build
# scripts don't necessarily execute in the same agent that run the
# build.ps1/sh script this variable isn't automatically set.
$ci = $true
. $PSScriptRoot\..\tools.ps1
$ExtractPackage = { $ExtractPackage = {
param( param(
[string] $PackagePath # Full path to a NuGet package [string] $PackagePath # Full path to a NuGet package

View File

@ -20,7 +20,7 @@ jobs:
enableTelemetry: ${{ parameters.enableTelemetry }} enableTelemetry: ${{ parameters.enableTelemetry }}
enablePublishBuildArtifacts: true enablePublishBuildArtifacts: true
continueOnError: ${{ parameters.continueOnError }} continueOnError: ${{ parameters.continueOnError }}
jobs: jobs:
- job: '${{ parameters.jobName }}' - job: '${{ parameters.jobName }}'
@ -51,7 +51,7 @@ jobs:
- ${{ if ne(parameters.osGroup, 'Windows_NT') }}: - ${{ if ne(parameters.osGroup, 'Windows_NT') }}:
- HelixPreCommand: 'export PERFLAB_UPLOAD_TOKEN="$(PerfCommandUploadTokenLinux)"' - HelixPreCommand: 'export PERFLAB_UPLOAD_TOKEN="$(PerfCommandUploadTokenLinux)"'
- IsInternal: --internal - IsInternal: --internal
- group: DotNet-HelixApi-Access - group: DotNet-HelixApi-Access
- group: dotnet-benchview - group: dotnet-benchview

View File

@ -0,0 +1,95 @@
parameters:
artifactsPublishingAdditionalParameters: ''
publishInstallersAndChecksums: false
stages:
- stage: NetCore_3_Tools_Validation_Publish
dependsOn: validate
variables:
- template: ../common-variables.yml
displayName: .NET 3 Tools - Validation Publishing
jobs:
- template: ../setup-maestro-vars.yml
- job: publish_assets
displayName: Publish Assets
dependsOn: setupMaestroVars
variables:
- group: DotNet-Blob-Feed
- group: AzureDevOps-Artifact-Feeds-Pats
- name: BARBuildId
value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.BARBuildId'] ]
- name: IsStableBuild
value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.IsStableBuild'] ]
condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', variables.NETCore_3_Tools_Validation_Channel_Id))
pool:
vmImage: 'windows-2019'
steps:
- task: DownloadBuildArtifacts@0
displayName: Download Package Artifacts
inputs:
buildType: current
artifactName: PackageArtifacts
- task: DownloadBuildArtifacts@0
displayName: Download Blob Artifacts
inputs:
buildType: current
artifactName: BlobArtifacts
- task: DownloadBuildArtifacts@0
displayName: Download Asset Manifests
inputs:
buildType: current
artifactName: AssetManifests
- task: NuGetToolInstaller@1
displayName: 'Install NuGet.exe'
# This is necessary whenever we want to publish/restore to an AzDO private feed
- task: NuGetAuthenticate@0
displayName: 'Authenticate to AzDO Feeds'
- task: PowerShell@2
displayName: Enable cross-org publishing
inputs:
filePath: eng\common\enable-cross-org-publishing.ps1
arguments: -token $(dn-bot-dnceng-artifact-feeds-rw)
- task: PowerShell@2
displayName: Publish Assets
inputs:
filePath: eng\common\sdk-task.ps1
arguments: -task PublishArtifactsInManifest -restore -msbuildEngine dotnet
/p:ArtifactsCategory=$(_DotNetValidationArtifactsCategory)
/p:IsStableBuild=$(IsStableBuild)
/p:IsInternalBuild=$(IsInternalBuild)
/p:RepositoryName=$(Build.Repository.Name)
/p:CommitSha=$(Build.SourceVersion)
/p:NugetPath=$(NuGetExeToolPath)
/p:AzdoTargetFeedPAT='$(dn-bot-dnceng-universal-packages-rw)'
/p:AzureStorageTargetFeedPAT='$(dotnetfeed-storage-access-key-1)'
/p:BARBuildId=$(BARBuildId)
/p:MaestroApiEndpoint='$(MaestroApiEndPoint)'
/p:BuildAssetRegistryToken='$(MaestroApiAccessToken)'
/p:ManifestsBasePath='$(Build.ArtifactStagingDirectory)/AssetManifests/'
/p:BlobBasePath='$(Build.ArtifactStagingDirectory)/BlobArtifacts/'
/p:PackageBasePath='$(Build.ArtifactStagingDirectory)/PackageArtifacts/'
/p:Configuration=Release
/p:PublishInstallersAndChecksums=${{ parameters.publishInstallersAndChecksums }}
/p:InstallersTargetStaticFeed=$(InstallersBlobFeedUrl)
/p:InstallersAzureAccountKey=$(dotnetcli-storage-key)
/p:ChecksumsTargetStaticFeed=$(ChecksumsBlobFeedUrl)
/p:ChecksumsAzureAccountKey=$(dotnetclichecksums-storage-key)
/p:PublishToAzureDevOpsNuGetFeeds=true
/p:AzureDevOpsStaticShippingFeed='https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json'
/p:AzureDevOpsStaticShippingFeedKey='$(dn-bot-dnceng-artifact-feeds-rw)'
/p:AzureDevOpsStaticTransportFeed='https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json'
/p:AzureDevOpsStaticTransportFeedKey='$(dn-bot-dnceng-artifact-feeds-rw)'
/p:AzureDevOpsStaticSymbolsFeed='https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools-symbols/nuget/v3/index.json'
/p:AzureDevOpsStaticSymbolsFeedKey='$(dn-bot-dnceng-artifact-feeds-rw)'
${{ parameters.artifactsPublishingAdditionalParameters }}
- template: ../../steps/promote-build.yml
parameters:
ChannelId: ${{ variables.NETCore_3_Tools_Validation_Channel_Id }}

View File

@ -4,18 +4,18 @@ parameters:
publishInstallersAndChecksums: false publishInstallersAndChecksums: false
stages: stages:
- stage: NetCore_Dev30_Publish - stage: NetCore_3_Tools_Publish
dependsOn: validate dependsOn: validate
variables: variables:
- template: ../common-variables.yml - template: ../common-variables.yml
displayName: .NET Core 3.0 Dev Publishing displayName: .NET 3 Tools Publishing
jobs: jobs:
- template: ../setup-maestro-vars.yml - template: ../setup-maestro-vars.yml
- job: - job:
displayName: Symbol Publishing displayName: Symbol Publishing
dependsOn: setupMaestroVars dependsOn: setupMaestroVars
condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', variables.PublicDevRelease_30_Channel_Id)) condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', variables.NetCore_3_Tools_Channel_Id))
variables: variables:
- group: DotNet-Symbol-Server-Pats - group: DotNet-Symbol-Server-Pats
pool: pool:
@ -56,7 +56,7 @@ stages:
value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.BARBuildId'] ] value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.BARBuildId'] ]
- name: IsStableBuild - name: IsStableBuild
value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.IsStableBuild'] ] value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.IsStableBuild'] ]
condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', variables.PublicDevRelease_30_Channel_Id)) condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', variables.NetCore_3_Tools_Channel_Id))
pool: pool:
vmImage: 'windows-2019' vmImage: 'windows-2019'
steps: steps:
@ -85,42 +85,46 @@ stages:
- task: NuGetAuthenticate@0 - task: NuGetAuthenticate@0
displayName: 'Authenticate to AzDO Feeds' displayName: 'Authenticate to AzDO Feeds'
- task: PowerShell@2
displayName: Enable cross-org publishing
inputs:
filePath: eng\common\enable-cross-org-publishing.ps1
arguments: -token $(dn-bot-dnceng-artifact-feeds-rw)
- task: PowerShell@2 - task: PowerShell@2
displayName: Publish Assets displayName: Publish Assets
env:
AZURE_DEVOPS_EXT_PAT: $(dn-bot-dnceng-universal-packages-rw)
inputs: inputs:
filePath: eng\common\sdk-task.ps1 filePath: eng\common\sdk-task.ps1
arguments: -task PublishArtifactsInManifest -restore -msbuildEngine dotnet arguments: -task PublishArtifactsInManifest -restore -msbuildEngine dotnet
/p:ArtifactsCategory=$(_DotNetArtifactsCategory) /p:ArtifactsCategory=$(_DotNetArtifactsCategory)
/p:IsStableBuild=$(IsStableBuild) /p:IsStableBuild=$(IsStableBuild)
/p:IsInternalBuild=$(IsInternalBuild) /p:IsInternalBuild=$(IsInternalBuild)
/p:RepositoryName=$(Build.Repository.Name) /p:RepositoryName=$(Build.Repository.Name)
/p:CommitSha=$(Build.SourceVersion) /p:CommitSha=$(Build.SourceVersion)
/p:NugetPath=$(NuGetExeToolPath) /p:NugetPath=$(NuGetExeToolPath)
/p:AzdoTargetFeedPAT='$(dn-bot-dnceng-universal-packages-rw)' /p:AzdoTargetFeedPAT='$(dn-bot-dnceng-universal-packages-rw)'
/p:AzureStorageTargetFeedPAT='$(dotnetfeed-storage-access-key-1)' /p:AzureStorageTargetFeedPAT='$(dotnetfeed-storage-access-key-1)'
/p:BARBuildId=$(BARBuildId) /p:BARBuildId=$(BARBuildId)
/p:MaestroApiEndpoint='$(MaestroApiEndPoint)' /p:MaestroApiEndpoint='$(MaestroApiEndPoint)'
/p:BuildAssetRegistryToken='$(MaestroApiAccessToken)' /p:BuildAssetRegistryToken='$(MaestroApiAccessToken)'
/p:ManifestsBasePath='$(Build.ArtifactStagingDirectory)/AssetManifests/' /p:ManifestsBasePath='$(Build.ArtifactStagingDirectory)/AssetManifests/'
/p:BlobBasePath='$(Build.ArtifactStagingDirectory)/BlobArtifacts/' /p:BlobBasePath='$(Build.ArtifactStagingDirectory)/BlobArtifacts/'
/p:PackageBasePath='$(Build.ArtifactStagingDirectory)/PackageArtifacts/' /p:PackageBasePath='$(Build.ArtifactStagingDirectory)/PackageArtifacts/'
/p:Configuration=Release /p:Configuration=Release
/p:PublishInstallersAndChecksums=${{ parameters.publishInstallersAndChecksums }} /p:PublishInstallersAndChecksums=${{ parameters.publishInstallersAndChecksums }}
/p:InstallersTargetStaticFeed=$(InstallersBlobFeedUrl) /p:InstallersTargetStaticFeed=$(InstallersBlobFeedUrl)
/p:InstallersAzureAccountKey=$(dotnetcli-storage-key) /p:InstallersAzureAccountKey=$(dotnetcli-storage-key)
/p:ChecksumsTargetStaticFeed=$(ChecksumsBlobFeedUrl) /p:ChecksumsTargetStaticFeed=$(ChecksumsBlobFeedUrl)
/p:ChecksumsAzureAccountKey=$(dotnetclichecksums-storage-key) /p:ChecksumsAzureAccountKey=$(dotnetclichecksums-storage-key)
/p:PublishToAzureDevOpsNuGetFeeds=true /p:PublishToAzureDevOpsNuGetFeeds=true
/p:AzureDevOpsStaticShippingFeed='https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3/nuget/v3/index.json' /p:AzureDevOpsStaticShippingFeed='https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json'
/p:AzureDevOpsStaticShippingFeedKey='$(dn-bot-dnceng-artifact-feeds-rw)' /p:AzureDevOpsStaticShippingFeedKey='$(dn-bot-dnceng-artifact-feeds-rw)'
/p:AzureDevOpsStaticTransportFeed='https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3-transport/nuget/v3/index.json' /p:AzureDevOpsStaticTransportFeed='https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json'
/p:AzureDevOpsStaticTransportFeedKey='$(dn-bot-dnceng-artifact-feeds-rw)' /p:AzureDevOpsStaticTransportFeedKey='$(dn-bot-dnceng-artifact-feeds-rw)'
/p:AzureDevOpsStaticSymbolsFeed='https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3-symbols/nuget/v3/index.json' /p:AzureDevOpsStaticSymbolsFeed='https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools-symbols/nuget/v3/index.json'
/p:AzureDevOpsStaticSymbolsFeedKey='$(dn-bot-dnceng-artifact-feeds-rw)' /p:AzureDevOpsStaticSymbolsFeedKey='$(dn-bot-dnceng-artifact-feeds-rw)'
${{ parameters.artifactsPublishingAdditionalParameters }} ${{ parameters.artifactsPublishingAdditionalParameters }}
- template: ../../steps/promote-build.yml - template: ../../steps/promote-build.yml
parameters: parameters:
ChannelId: ${{ variables.PublicDevRelease_30_Channel_Id }} ChannelId: ${{ variables.NetCore_3_Tools_Channel_Id }}

View File

@ -85,10 +85,14 @@ stages:
- task: NuGetAuthenticate@0 - task: NuGetAuthenticate@0
displayName: 'Authenticate to AzDO Feeds' displayName: 'Authenticate to AzDO Feeds'
- task: PowerShell@2
displayName: Enable cross-org publishing
inputs:
filePath: eng\common\enable-cross-org-publishing.ps1
arguments: -token $(dn-bot-dnceng-artifact-feeds-rw)
- task: PowerShell@2 - task: PowerShell@2
displayName: Publish Assets displayName: Publish Assets
env:
AZURE_DEVOPS_EXT_PAT: $(dn-bot-dnceng-universal-packages-rw)
inputs: inputs:
filePath: eng\common\sdk-task.ps1 filePath: eng\common\sdk-task.ps1
arguments: -task PublishArtifactsInManifest -restore -msbuildEngine dotnet arguments: -task PublishArtifactsInManifest -restore -msbuildEngine dotnet

View File

@ -85,10 +85,14 @@ stages:
- task: NuGetAuthenticate@0 - task: NuGetAuthenticate@0
displayName: 'Authenticate to AzDO Feeds' displayName: 'Authenticate to AzDO Feeds'
- task: PowerShell@2
displayName: Enable cross-org publishing
inputs:
filePath: eng\common\enable-cross-org-publishing.ps1
arguments: -token $(dn-bot-dnceng-artifact-feeds-rw)
- task: PowerShell@2 - task: PowerShell@2
displayName: Publish Assets displayName: Publish Assets
env:
AZURE_DEVOPS_EXT_PAT: $(dn-bot-dnceng-universal-packages-rw)
inputs: inputs:
filePath: eng\common\sdk-task.ps1 filePath: eng\common\sdk-task.ps1
arguments: -task PublishArtifactsInManifest -restore -msbuildEngine dotnet arguments: -task PublishArtifactsInManifest -restore -msbuildEngine dotnet

View File

@ -84,10 +84,14 @@ stages:
- task: NuGetAuthenticate@0 - task: NuGetAuthenticate@0
displayName: 'Authenticate to AzDO Feeds' displayName: 'Authenticate to AzDO Feeds'
- task: PowerShell@2
displayName: Enable cross-org publishing
inputs:
filePath: eng\common\enable-cross-org-publishing.ps1
arguments: -token $(dn-bot-dnceng-artifact-feeds-rw)
- task: PowerShell@2 - task: PowerShell@2
displayName: Publish Assets displayName: Publish Assets
env:
AZURE_DEVOPS_EXT_PAT: $(dn-bot-dnceng-universal-packages-rw)
inputs: inputs:
filePath: eng\common\sdk-task.ps1 filePath: eng\common\sdk-task.ps1
arguments: -task PublishArtifactsInManifest -restore -msbuildEngine dotnet arguments: -task PublishArtifactsInManifest -restore -msbuildEngine dotnet

View File

@ -85,10 +85,14 @@ stages:
- task: NuGetAuthenticate@0 - task: NuGetAuthenticate@0
displayName: 'Authenticate to AzDO Feeds' displayName: 'Authenticate to AzDO Feeds'
- task: PowerShell@2
displayName: Enable cross-org publishing
inputs:
filePath: eng\common\enable-cross-org-publishing.ps1
arguments: -token $(dn-bot-dnceng-artifact-feeds-rw)
- task: PowerShell@2 - task: PowerShell@2
displayName: Publish Assets displayName: Publish Assets
env:
AZURE_DEVOPS_EXT_PAT: $(dn-bot-dnceng-universal-packages-rw)
inputs: inputs:
filePath: eng\common\sdk-task.ps1 filePath: eng\common\sdk-task.ps1
arguments: -task PublishArtifactsInManifest -restore -msbuildEngine dotnet arguments: -task PublishArtifactsInManifest -restore -msbuildEngine dotnet

View File

@ -85,10 +85,14 @@ stages:
- task: NuGetAuthenticate@0 - task: NuGetAuthenticate@0
displayName: 'Authenticate to AzDO Feeds' displayName: 'Authenticate to AzDO Feeds'
- task: PowerShell@2
displayName: Enable cross-org publishing
inputs:
filePath: eng\common\enable-cross-org-publishing.ps1
arguments: -token $(dn-bot-dnceng-artifact-feeds-rw)
- task: PowerShell@2 - task: PowerShell@2
displayName: Publish Assets displayName: Publish Assets
env:
AZURE_DEVOPS_EXT_PAT: $(dn-bot-dnceng-universal-packages-rw)
inputs: inputs:
filePath: eng\common\sdk-task.ps1 filePath: eng\common\sdk-task.ps1
arguments: -task PublishArtifactsInManifest -restore -msbuildEngine dotnet arguments: -task PublishArtifactsInManifest -restore -msbuildEngine dotnet

View File

@ -85,10 +85,14 @@ stages:
- task: NuGetAuthenticate@0 - task: NuGetAuthenticate@0
displayName: 'Authenticate to AzDO Feeds' displayName: 'Authenticate to AzDO Feeds'
- task: PowerShell@2
displayName: Enable cross-org publishing
inputs:
filePath: eng\common\enable-cross-org-publishing.ps1
arguments: -token $(dn-bot-dnceng-artifact-feeds-rw)
- task: PowerShell@2 - task: PowerShell@2
displayName: Publish Assets displayName: Publish Assets
env:
AZURE_DEVOPS_EXT_PAT: $(dn-bot-dnceng-universal-packages-rw)
inputs: inputs:
filePath: eng\common\sdk-task.ps1 filePath: eng\common\sdk-task.ps1
arguments: -task PublishArtifactsInManifest -restore -msbuildEngine dotnet arguments: -task PublishArtifactsInManifest -restore -msbuildEngine dotnet

View File

@ -21,7 +21,7 @@ stages:
value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.BARBuildId'] ] value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.BARBuildId'] ]
- name: IsStableBuild - name: IsStableBuild
value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.IsStableBuild'] ] value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.IsStableBuild'] ]
condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', variables.PublicValidationRelease_30_Channel_Id)) condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', variables.NetCore_Tools_Validation_Channel_Id))
pool: pool:
vmImage: 'windows-2019' vmImage: 'windows-2019'
steps: steps:
@ -50,10 +50,14 @@ stages:
- task: NuGetAuthenticate@0 - task: NuGetAuthenticate@0
displayName: 'Authenticate to AzDO Feeds' displayName: 'Authenticate to AzDO Feeds'
- task: PowerShell@2
displayName: Enable cross-org publishing
inputs:
filePath: eng\common\enable-cross-org-publishing.ps1
arguments: -token $(dn-bot-dnceng-artifact-feeds-rw)
- task: PowerShell@2 - task: PowerShell@2
displayName: Publish Assets displayName: Publish Assets
env:
AZURE_DEVOPS_EXT_PAT: $(dn-bot-dnceng-universal-packages-rw)
inputs: inputs:
filePath: eng\common\sdk-task.ps1 filePath: eng\common\sdk-task.ps1
arguments: -task PublishArtifactsInManifest -restore -msbuildEngine dotnet arguments: -task PublishArtifactsInManifest -restore -msbuildEngine dotnet
@ -88,4 +92,4 @@ stages:
- template: ../../steps/promote-build.yml - template: ../../steps/promote-build.yml
parameters: parameters:
ChannelId: ${{ variables.PublicValidationRelease_30_Channel_Id }} ChannelId: ${{ variables.NetCore_Tools_Validation_Channel_Id }}

View File

@ -3,10 +3,6 @@ variables:
- group: DotNet-DotNetCli-Storage - group: DotNet-DotNetCli-Storage
- group: DotNet-MSRC-Storage - group: DotNet-MSRC-Storage
# .NET Core 3 Dev
- name: PublicDevRelease_30_Channel_Id
value: 3
# .NET Core 3.1 Dev # .NET Core 3.1 Dev
- name: PublicDevRelease_31_Channel_Id - name: PublicDevRelease_31_Channel_Id
value: 128 value: 128
@ -16,13 +12,21 @@ variables:
value: 131 value: 131
# .NET Tools - Validation # .NET Tools - Validation
- name: PublicValidationRelease_30_Channel_Id - name: NetCore_Tools_Validation_Channel_Id
value: 9 value: 9
# .NET Tools - Latest # .NET Tools - Latest
- name: NetCore_Tools_Latest_Channel_Id - name: NetCore_Tools_Latest_Channel_Id
value: 2 value: 2
# .NET 3 Tools - Validation
- name: NETCore_3_Tools_Validation_Channel_Id
value: 390
# .NET 3 Tools - Latest
- name: NetCore_3_Tools_Channel_Id
value: 344
# .NET Core 3.0 Internal Servicing # .NET Core 3.0 Internal Servicing
- name: InternalServicing_30_Channel_Id - name: InternalServicing_30_Channel_Id
value: 184 value: 184

View File

@ -101,12 +101,6 @@ stages:
artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
- template: \eng\common\templates\post-build\channels\netcore-dev-30.yml
parameters:
symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }}
artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
- template: \eng\common\templates\post-build\channels\netcore-dev-31.yml - template: \eng\common\templates\post-build\channels\netcore-dev-31.yml
parameters: parameters:
symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }}
@ -119,11 +113,22 @@ stages:
artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
- template: \eng\common\templates\post-build\channels\public-validation-release.yml - template: \eng\common\templates\post-build\channels\netcore-tools-validation.yml
parameters: parameters:
artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
- template: \eng\common\templates\post-build\channels\netcore-3-tools-validation.yml
parameters:
artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
- template: \eng\common\templates\post-build\channels\netcore-3-tools.yml
parameters:
symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }}
artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
- template: \eng\common\templates\post-build\channels\netcore-release-30.yml - template: \eng\common\templates\post-build\channels\netcore-release-30.yml
parameters: parameters:
symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }}

View File

@ -52,6 +52,7 @@
<_RefSourceOutputPath>$([System.IO.Directory]::GetParent('$(MSBuildProjectDirectory)'))/ref/</_RefSourceOutputPath> <_RefSourceOutputPath>$([System.IO.Directory]::GetParent('$(MSBuildProjectDirectory)'))/ref/</_RefSourceOutputPath>
<_RefSourceFileName>$(AssemblyName).$(_RefSourceFileTFM).cs</_RefSourceFileName> <_RefSourceFileName>$(AssemblyName).$(_RefSourceFileTFM).cs</_RefSourceFileName>
<_ManualRefSourceFileName>$(AssemblyName).Manual.cs</_ManualRefSourceFileName>
<_RefSourceFileOutputPath>$(_RefSourceOutputPath)$(_RefSourceFileName)</_RefSourceFileOutputPath> <_RefSourceFileOutputPath>$(_RefSourceOutputPath)$(_RefSourceFileName)</_RefSourceFileOutputPath>
</PropertyGroup> </PropertyGroup>
@ -87,10 +88,16 @@
</ItemGroup> </ItemGroup>
<PropertyGroup> <PropertyGroup>
<_ManualReferenceAssemblyContent />
<_ManualReferenceAssemblyContent Condition="Exists('$(_RefSourceOutputPath)$(_ManualRefSourceFileName)')">
<![CDATA[
<Compile Include="$(_ManualRefSourceFileName)" />]]>
</_ManualReferenceAssemblyContent>
<ReferencesContent> <ReferencesContent>
<![CDATA[ <![CDATA[
<ItemGroup Condition="'%24(TargetFramework)' == '$(_RefProjectFileTFM)'"> <ItemGroup Condition="'%24(TargetFramework)' == '$(_RefProjectFileTFM)'">
<Compile Include="$(_RefSourceFileName)" /> <Compile Include="$(_RefSourceFileName)" />]]>$(_ManualReferenceAssemblyContent)<![CDATA[
@(FilteredOriginalReferences->'<Reference Include="%(Identity)" />', '%0A ') @(FilteredOriginalReferences->'<Reference Include="%(Identity)" />', '%0A ')
</ItemGroup> </ItemGroup>
]]> ]]>

View File

@ -36,7 +36,8 @@
--> -->
<UseLatestPackageReferences Condition=" '$(UseLatestPackageReferences)' == '' AND '$(IsServicingBuild)' != 'true' ">true</UseLatestPackageReferences> <UseLatestPackageReferences Condition=" '$(UseLatestPackageReferences)' == '' AND '$(IsServicingBuild)' != 'true' ">true</UseLatestPackageReferences>
<UseLatestPackageReferences Condition=" '$(UseLatestPackageReferences)' == '' AND '$(IsImplementationProject)' != 'true' ">true</UseLatestPackageReferences> <UseLatestPackageReferences Condition=" '$(UseLatestPackageReferences)' == '' AND '$(IsImplementationProject)' != 'true' ">true</UseLatestPackageReferences>
<UseLatestPackageReferences Condition=" '$(UseLatestPackageReferences)' == '' AND '$(IsImplementationProject)' == 'true' AND ( '$(IsServicingBuild)' != 'true' OR '$(IsPackable)' == 'true' ) ">true</UseLatestPackageReferences> <UseLatestPackageReferences
Condition=" '$(UseLatestPackageReferences)' == '' AND '$(IsImplementationProject)' == 'true' AND '$(IsPackable)' == 'true' ">true</UseLatestPackageReferences>
<UseLatestPackageReferences Condition=" '$(UseLatestPackageReferences)' == '' ">false</UseLatestPackageReferences> <UseLatestPackageReferences Condition=" '$(UseLatestPackageReferences)' == '' ">false</UseLatestPackageReferences>
<!-- <!--
@ -45,7 +46,7 @@
* when a project is a test or sample project * when a project is a test or sample project
We don't use project references between components in servicing builds between compontents to preserve the baseline as much as possible. We don't use project references between components in servicing builds between compontents to preserve the baseline as much as possible.
--> -->
<UseProjectReferences Condition=" '$(UseProjectReferences)' == '' AND '$(IsServicingBuild)' != 'true' ">true</UseProjectReferences> <UseProjectReferences Condition=" '$(UseProjectReferences)' == '' AND '$(IsServicingBuild)' != 'true' ">true</UseProjectReferences>
<UseProjectReferences Condition=" '$(UseProjectReferences)' == '' AND '$(IsImplementationProject)' != 'true' ">true</UseProjectReferences> <UseProjectReferences Condition=" '$(UseProjectReferences)' == '' AND '$(IsImplementationProject)' != 'true' ">true</UseProjectReferences>
<UseProjectReferences Condition=" '$(UseProjectReferences)' == '' ">false</UseProjectReferences> <UseProjectReferences Condition=" '$(UseProjectReferences)' == '' ">false</UseProjectReferences>
@ -122,7 +123,7 @@
Text="Cannot reference &quot;%(_InvalidReferenceToNonSharedFxAssembly.Identity)&quot;. This dependency is not in the shared framework. See docs/SharedFramework.md for instructions on how to modify what is in the shared framework." /> Text="Cannot reference &quot;%(_InvalidReferenceToNonSharedFxAssembly.Identity)&quot;. This dependency is not in the shared framework. See docs/SharedFramework.md for instructions on how to modify what is in the shared framework." />
</Target> </Target>
<Target Name="_WarnAboutRedundantRef" AfterTargets="ResolveFrameworkReferences"> <Target Name="_WarnAboutRedundantRef" AfterTargets="ResolveFrameworkReferences;ProcessFrameworkReferences">
<Warning Condition="@(FrameworkReference->WithMetadataValue('Identity', 'Microsoft.AspNetCore.App')->Count()) &gt; 1" <Warning Condition="@(FrameworkReference->WithMetadataValue('Identity', 'Microsoft.AspNetCore.App')->Count()) &gt; 1"
Text="Redundant &lt;FrameworkReference&gt;. If you have an explicit item in the project file, you might be able to remove it. Some SDKs, like Microsoft.NET.Sdk.Web, add this implicitly." /> Text="Redundant &lt;FrameworkReference&gt;. If you have an explicit item in the project file, you might be able to remove it. Some SDKs, like Microsoft.NET.Sdk.Web, add this implicitly." />
</Target> </Target>

View File

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

View File

@ -12,14 +12,14 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="NuGet.Build.Tasks" Version="5.1.0-rtm.5921" /> <PackageReference Include="NuGet.Build.Tasks" Version="5.3.0-rtm.6192" />
<PackageReference Include="Microsoft.Extensions.DependencyModel" Version="2.1.0" /> <PackageReference Include="Microsoft.Extensions.DependencyModel" Version="2.1.0" />
</ItemGroup> </ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == '$(DefaultNetCoreTargetFramework)'"> <ItemGroup Condition="'$(TargetFramework)' == '$(DefaultNetCoreTargetFramework)'">
<PackageReference Include="Microsoft.Build.Framework" Version="15.8.166" /> <PackageReference Include="Microsoft.Build.Framework" Version="16.3.0" />
<PackageReference Include="Microsoft.Build.Tasks.Core" Version="15.8.166" /> <PackageReference Include="Microsoft.Build.Tasks.Core" Version="16.3.0" />
<PackageReference Include="Microsoft.Build.Utilities.Core" Version="15.8.166" /> <PackageReference Include="Microsoft.Build.Utilities.Core" Version="16.3.0" />
</ItemGroup> </ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net472'"> <ItemGroup Condition="'$(TargetFramework)' == 'net472'">

View File

@ -25,7 +25,7 @@
}, },
"msbuild-sdks": { "msbuild-sdks": {
"Yarn.MSBuild": "1.15.2", "Yarn.MSBuild": "1.15.2",
"Microsoft.DotNet.Arcade.Sdk": "1.0.0-beta.19462.4", "Microsoft.DotNet.Arcade.Sdk": "1.0.0-beta.19510.3",
"Microsoft.DotNet.Helix.Sdk": "2.0.0-beta.19462.4" "Microsoft.DotNet.Helix.Sdk": "2.0.0-beta.19510.3"
} }
} }

BIN
packageIcon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

View File

@ -25,6 +25,7 @@
<ItemGroup> <ItemGroup>
<NuspecProperty Include="OutputBinary=$(OutputPath)$(AssemblyName).dll" /> <NuspecProperty Include="OutputBinary=$(OutputPath)$(AssemblyName).dll" />
<NuspecProperty Include="OutputSymbol=$(OutputPath)$(AssemblyName).pdb" /> <NuspecProperty Include="OutputSymbol=$(OutputPath)$(AssemblyName).pdb" />
<NuspecProperty Include="PackageIcon=$(PackageIconFullPath)" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -2,10 +2,12 @@
<package xmlns="http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd"> <package xmlns="http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd">
<metadata> <metadata>
$CommonMetadataElements$ $CommonMetadataElements$
<icon>packageIcon.png</icon>
</metadata> </metadata>
<files> <files>
<file src="$OutputBinary$" target="analyzers\dotnet\cs\" /> <file src="$OutputBinary$" target="analyzers\dotnet\cs\" />
<file src="$OutputSymbol$" target="analyzers\dotnet\cs\" /> <file src="$OutputSymbol$" target="analyzers\dotnet\cs\" />
<file src="$PackageIcon$" target="" />
</files> </files>
</package> </package>

View File

@ -23,6 +23,7 @@
<NuspecProperty Include="componentsversion=$(ComponentsPackageVersion)" /> <NuspecProperty Include="componentsversion=$(ComponentsPackageVersion)" />
<NuspecProperty Include="razorversion=$(MicrosoftAspNetCoreRazorDesignPackageVersion)" /> <NuspecProperty Include="razorversion=$(MicrosoftAspNetCoreRazorDesignPackageVersion)" />
<NuspecProperty Include="blazormonoversion=$(MicrosoftAspNetCoreBlazorMonoPackageVersion)" /> <NuspecProperty Include="blazormonoversion=$(MicrosoftAspNetCoreBlazorMonoPackageVersion)" />
<NuspecProperty Include="PackageIcon=$(PackageIconFullPath)" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@ -5,6 +5,7 @@
<dependencies> <dependencies>
<dependency id="Microsoft.AspNetCore.Blazor.Mono" version="$blazormonoversion$" include="all" /> <dependency id="Microsoft.AspNetCore.Blazor.Mono" version="$blazormonoversion$" include="all" />
</dependencies> </dependencies>
<icon>packageIcon.png</icon>
</metadata> </metadata>
<files> <files>
<file src="..\..\..\THIRD-PARTY-NOTICES.txt" /> <file src="..\..\..\THIRD-PARTY-NOTICES.txt" />
@ -12,5 +13,6 @@
<file src="targets\**" target="targets" /> <file src="targets\**" target="targets" />
<file src="$publishdir$**\*" target="tools/" /> <file src="$publishdir$**\*" target="tools/" />
<file src="..\..\..\Web.JS\dist\$configuration$\blazor.*.js" target="tools/blazor" /> <file src="..\..\..\Web.JS\dist\$configuration$\blazor.*.js" target="tools/blazor" />
<file src="$PackageIcon$" target="" />
</files> </files>
</package> </package>

View File

@ -33,6 +33,7 @@
<NuspecProperty Include="publishDir=$(PublishDir)" /> <NuspecProperty Include="publishDir=$(PublishDir)" />
<NuspecProperty Include="componentsrootdir=..\..\..\" /> <NuspecProperty Include="componentsrootdir=..\..\..\" />
<NuspecProperty Include="blazorversion=$(PackageVersion)" /> <NuspecProperty Include="blazorversion=$(PackageVersion)" />
<NuspecProperty Include="PackageIcon=$(PackageIconFullPath)" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -2,10 +2,12 @@
<package xmlns="http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd"> <package xmlns="http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd">
<metadata> <metadata>
$CommonMetadataElements$ $CommonMetadataElements$
<icon>packageIcon.png</icon>
</metadata> </metadata>
<files> <files>
<file src="build\**" target="build" /> <file src="build\**" target="build" />
<file src="$publishDir$**\*" target="tools" /> <file src="$publishDir$**\*" target="tools" />
<file src="$componentsrootdir$THIRD-PARTY-NOTICES.txt" target=".\THIRD-PARTY-NOTICES.txt" /> <file src="$componentsrootdir$THIRD-PARTY-NOTICES.txt" target=".\THIRD-PARTY-NOTICES.txt" />
<file src="$PackageIcon$" target="" />
</files> </files>
</package> </package>

View File

@ -15,6 +15,10 @@
<IsProjectReferenceProvider>false</IsProjectReferenceProvider> <IsProjectReferenceProvider>false</IsProjectReferenceProvider>
</PropertyGroup> </PropertyGroup>
<ItemGroup>
<NuspecProperty Include="PackageIcon=$(PackageIconFullPath)" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<UpToDateCheckInput Include="content\**\.template.config.src\**\*.*" /> <UpToDateCheckInput Include="content\**\.template.config.src\**\*.*" />
</ItemGroup> </ItemGroup>

View File

@ -5,11 +5,13 @@
<packageTypes> <packageTypes>
<packageType name="Template" /> <packageType name="Template" />
</packageTypes> </packageTypes>
<icon>packageIcon.png</icon>
</metadata> </metadata>
<files> <files>
<file <file
src="content/**" src="content/**"
exclude="**/bin/**;**/obj/**;**/.template.config.src/**;content/Directory.Build.props;content/Directory.Build.targets;" exclude="**/bin/**;**/obj/**;**/.template.config.src/**;content/Directory.Build.props;content/Directory.Build.targets;"
target="Content" /> target="Content" />
<file src="$PackageIcon$" target="" />
</files> </files>
</package> </package>

View File

@ -96,6 +96,25 @@ app {
color: red; color: red;
} }
#blazor-error-ui {
background: lightyellow;
bottom: 0;
box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
display: none;
left: 0;
padding: 0.6rem 1.25rem 0.7rem 1.25rem;
position: fixed;
width: 100%;
z-index: 1000;
}
#blazor-error-ui .dismiss {
cursor: pointer;
position: absolute;
right: 0.75rem;
top: 0.5rem;
}
@media (max-width: 767.98px) { @media (max-width: 767.98px) {
.main .top-row { .main .top-row {
display: none; display: none;

View File

@ -1,5 +1,6 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width" /> <meta name="viewport" content="width=device-width" />
@ -8,9 +9,16 @@
<link href="css/bootstrap/bootstrap.min.css" rel="stylesheet" /> <link href="css/bootstrap/bootstrap.min.css" rel="stylesheet" />
<link href="css/site.css" rel="stylesheet" /> <link href="css/site.css" rel="stylesheet" />
</head> </head>
<body> <body>
<app>Loading...</app> <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> <script src="_framework/blazor.webassembly.js"></script>
</body> </body>
</html> </html>

View File

@ -23,6 +23,14 @@
<Reference Include="System.Buffers" /> <Reference Include="System.Buffers" />
</ItemGroup> </ItemGroup>
<!-- These references were removed in 3.0 -->
<ItemGroup>
<SuppressBaselineReference Include="Microsoft.AspNetCore.Components.Analyzers" />
<SuppressBaselineReference Include="Microsoft.AspNetCore.Authorization" />
<SuppressBaselineReference Include="Microsoft.JSInterop" />
<SuppressBaselineReference Include="System.ComponentModel.Annotations" />
</ItemGroup>
<Target Name="_GetNuspecDependencyPackageVersions"> <Target Name="_GetNuspecDependencyPackageVersions">
<MSBuild Targets="_GetPackageVersionInfo" <MSBuild Targets="_GetPackageVersionInfo"
BuildInParallel="$(BuildInParallel)" BuildInParallel="$(BuildInParallel)"
@ -47,6 +55,7 @@
<NuspecProperty Condition="'$(DotNetBuildFromSource)' != 'true'" Include="systemComponentModelAnnotationsPackageVersion=$(SystemComponentModelAnnotationsPackageVersion)" /> <NuspecProperty Condition="'$(DotNetBuildFromSource)' != 'true'" Include="systemComponentModelAnnotationsPackageVersion=$(SystemComponentModelAnnotationsPackageVersion)" />
<NuspecProperty Include="AssemblyName=$(AssemblyName)" /> <NuspecProperty Include="AssemblyName=$(AssemblyName)" />
<NuspecProperty Include="OutputPath=$(OutputPath)" /> <NuspecProperty Include="OutputPath=$(OutputPath)" />
<NuspecProperty Include="PackageIcon=$(PackageIconFullPath)" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -15,11 +15,13 @@
<dependency id="Microsoft.JSInterop" version="$jsInteropPackageVersion$" exclude="Build,Analyzers" /> <dependency id="Microsoft.JSInterop" version="$jsInteropPackageVersion$" exclude="Build,Analyzers" />
</group> </group>
</dependencies> </dependencies>
<icon>packageIcon.png</icon>
</metadata> </metadata>
<files> <files>
<file src="$OutputPath$**\$AssemblyName$.dll" target="lib\" /> <file src="$OutputPath$**\$AssemblyName$.dll" target="lib\" />
<file src="$OutputPath$**\$AssemblyName$.pdb" target="lib\" /> <file src="$OutputPath$**\$AssemblyName$.pdb" target="lib\" />
<file src="$OutputPath$**\$AssemblyName$.xml" target="lib\" /> <file src="$OutputPath$**\$AssemblyName$.xml" target="lib\" />
<file src="$PackageIcon$" target="" />
<file src="..\..\THIRD-PARTY-NOTICES.txt" target=".\THIRD-PARTY-NOTICES.txt" /> <file src="..\..\THIRD-PARTY-NOTICES.txt" target=".\THIRD-PARTY-NOTICES.txt" />
</files> </files>
</package> </package>

View File

@ -9,11 +9,13 @@
<dependency id="Microsoft.JSInterop" version="$jsInteropPackageVersion$" exclude="Build,Analyzers" /> <dependency id="Microsoft.JSInterop" version="$jsInteropPackageVersion$" exclude="Build,Analyzers" />
</group> </group>
</dependencies> </dependencies>
<icon>packageIcon.png</icon>
</metadata> </metadata>
<files> <files>
<file src="$OutputPath$**\$AssemblyName$.dll" target="lib\" /> <file src="$OutputPath$**\$AssemblyName$.dll" target="lib\" />
<file src="$OutputPath$**\$AssemblyName$.pdb" target="lib\" /> <file src="$OutputPath$**\$AssemblyName$.pdb" target="lib\" />
<file src="$OutputPath$**\$AssemblyName$.xml" target="lib\" /> <file src="$OutputPath$**\$AssemblyName$.xml" target="lib\" />
<file src="$PackageIcon$" target="" />
<file src="..\..\THIRD-PARTY-NOTICES.txt" target=".\THIRD-PARTY-NOTICES.txt" /> <file src="..\..\THIRD-PARTY-NOTICES.txt" target=".\THIRD-PARTY-NOTICES.txt" />
</files> </files>
</package> </package>

View File

@ -1,7 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework> <!-- Intentionally targeting netcoreapp3.0 because we do not want to update the Benchmark client to use 3.1 -->
<TargetFramework>netcoreapp3.0</TargetFramework>
<IsPackable>true</IsPackable> <IsPackable>true</IsPackable>
<IsShippingPackage>false</IsShippingPackage> <IsShippingPackage>false</IsShippingPackage>
<HasReferenceAssembly>false</HasReferenceAssembly> <HasReferenceAssembly>false</HasReferenceAssembly>

View File

@ -1,4 +1,4 @@
@page "/" @page "/"
<h1>Hello, world!</h1> <h1>Hello, world!</h1>

View File

@ -13,10 +13,16 @@
<link href="css/site.css" rel="stylesheet" /> <link href="css/site.css" rel="stylesheet" />
</head> </head>
<body> <body>
<app> <app><component type="typeof(App)" render-mode="ServerPrerendered" /></app>
@(await Html.RenderComponentAsync<App>(RenderMode.ServerPrerendered))
</app>
<script src="_framework/blazor.server.js"></script> <script src="_framework/blazor.server.js" autostart="false"></script>
<script>
(function start() {
Blazor.start({
logLevel: 1, // LogLevel.Debug
configureSignalR: builder => builder.configureLogging("debug") // LogLevel.Debug
});
})()
</script>
</body> </body>
</html> </html>

View File

@ -1,4 +1,4 @@
@inherits LayoutComponentBase @inherits LayoutComponentBase
<div class="sidebar"> <div class="sidebar">
<NavMenu /> <NavMenu />
@ -12,4 +12,10 @@
<div class="content px-4"> <div class="content px-4">
@Body @Body
</div> </div>
</div>
<div id="blazor-error-ui">
An unhandled error has occurred.
<a class="reload">Reload</a>
<a class="dismiss">X</a>
</div> </div>

View File

@ -1,4 +1,4 @@
<div class="top-row pl-4 navbar navbar-dark"> <div class="top-row pl-4 navbar navbar-dark">
<a class="navbar-brand" href="">BlazorServerApp</a> <a class="navbar-brand" href="">BlazorServerApp</a>
<button class="navbar-toggler" @onclick="ToggleNavMenu"> <button class="navbar-toggler" @onclick="ToggleNavMenu">
<span class="navbar-toggler-icon"></span> <span class="navbar-toggler-icon"></span>

View File

@ -1,9 +1,10 @@
{ {
"detailedErrors": true,
"Logging": { "Logging": {
"LogLevel": { "LogLevel": {
"Default": "Debug", "Default": "Debug",
"System": "Information", "System": "Information",
"Microsoft": "Information" "Microsoft": "Debug"
} }
} }
} }

View File

@ -9,9 +9,9 @@ a, .btn-link {
} }
.btn-primary { .btn-primary {
color: #fff; color: #fff;
background-color: #1b6ec2; background-color: #1b6ec2;
border-color: #1861ac; border-color: #1861ac;
} }
app { app {
@ -111,6 +111,25 @@ app {
color: red; color: red;
} }
#blazor-error-ui {
background: lightyellow;
bottom: 0;
box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
display: none;
left: 0;
padding: 0.6rem 1.25rem 0.7rem 1.25rem;
position: fixed;
width: 100%;
z-index: 1000;
}
#blazor-error-ui .dismiss {
cursor: pointer;
position: absolute;
right: 0.75rem;
top: 0.5rem;
}
@media (max-width: 767.98px) { @media (max-width: 767.98px) {
.main .top-row { .main .top-row {
display: none; display: none;

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,6 +2,7 @@ import '@dotnet/jsinterop';
import './GlobalExports'; import './GlobalExports';
import * as signalR from '@aspnet/signalr'; import * as signalR from '@aspnet/signalr';
import { MessagePackHubProtocol } from '@aspnet/signalr-protocol-msgpack'; import { MessagePackHubProtocol } from '@aspnet/signalr-protocol-msgpack';
import { showErrorNotification } from './BootErrors';
import { shouldAutoStart } from './BootCommon'; import { shouldAutoStart } from './BootCommon';
import { RenderQueue } from './Platform/Circuits/RenderQueue'; import { RenderQueue } from './Platform/Circuits/RenderQueue';
import { ConsoleLogger } from './Platform/Logging/Loggers'; import { ConsoleLogger } from './Platform/Logging/Loggers';
@ -106,6 +107,7 @@ async function initializeConnection(options: BlazorOptions, logger: Logger, circ
connection.on('JS.Error', error => { connection.on('JS.Error', error => {
renderingFailed = true; renderingFailed = true;
unhandledError(connection, error, logger); unhandledError(connection, error, logger);
showErrorNotification();
}); });
window['Blazor']._internal.forceCloseConnection = () => connection.stop(); window['Blazor']._internal.forceCloseConnection = () => connection.stop();

View File

@ -0,0 +1,30 @@
let hasFailed = false;
export async function showErrorNotification() {
let errorUi = document.querySelector('#blazor-error-ui') as HTMLElement;
if (errorUi) {
errorUi.style.display = 'block';
}
if (!hasFailed) {
hasFailed = true;
const errorUiReloads = document.querySelectorAll<HTMLElement>('#blazor-error-ui .reload');
errorUiReloads.forEach(reload => {
reload.onclick = function (e) {
location.reload();
e.preventDefault();
};
});
let errorUiDismiss = document.querySelectorAll<HTMLElement>('#blazor-error-ui .dismiss');
errorUiDismiss.forEach(dismiss => {
dismiss.onclick = function (e) {
const errorUi = document.querySelector<HTMLElement>('#blazor-error-ui');
if (errorUi) {
errorUi.style.display = 'none';
}
e.preventDefault();
};
});
}
}

View File

@ -101,7 +101,7 @@ export function discoverComponents(document: Document): ComponentDescriptor[] {
discoveredComponents.push(entry); discoveredComponents.push(entry);
} }
return discoveredComponents; return discoveredComponents.sort((a, b) => a.sequence - b.sequence);
} }

View File

@ -1,6 +1,7 @@
import { MethodHandle, System_Object, System_String, System_Array, Pointer, Platform } from '../Platform'; import { MethodHandle, System_Object, System_String, System_Array, Pointer, Platform } from '../Platform';
import { getFileNameFromUrl } from '../Url'; import { getFileNameFromUrl } from '../Url';
import { attachDebuggerHotkey, hasDebuggingEnabled } from './MonoDebugger'; import { attachDebuggerHotkey, hasDebuggingEnabled } from './MonoDebugger';
import { showErrorNotification } from '../../BootErrors';
const assemblyHandleCache: { [assemblyName: string]: number } = {}; const assemblyHandleCache: { [assemblyName: string]: number } = {};
const typeHandleCache: { [fullyQualifiedTypeName: string]: number } = {}; const typeHandleCache: { [fullyQualifiedTypeName: string]: number } = {};
@ -232,7 +233,11 @@ function createEmscriptenModuleInstance(loadAssemblyUrls: string[], onReady: ()
const suppressMessages = ['DEBUGGING ENABLED']; const suppressMessages = ['DEBUGGING ENABLED'];
module.print = line => (suppressMessages.indexOf(line) < 0 && console.log(`WASM: ${line}`)); module.print = line => (suppressMessages.indexOf(line) < 0 && console.log(`WASM: ${line}`));
module.printErr = line => console.error(`WASM: ${line}`);
module.printErr = line => {
console.error(`WASM: ${line}`);
showErrorNotification();
};
module.preRun = []; module.preRun = [];
module.postRun = []; module.postRun = [];
module.preloadPlugins = []; module.preloadPlugins = [];

View File

@ -341,9 +341,18 @@ export class BrowserRenderer {
} }
} }
private tryApplyValueProperty(batch: RenderBatch, element: Element, attributeFrame: RenderTreeFrame | null) { private tryApplyValueProperty(batch: RenderBatch, element: Element, attributeFrame: RenderTreeFrame | null): boolean {
// Certain elements have built-in behaviour for their 'value' property // Certain elements have built-in behaviour for their 'value' property
const frameReader = batch.frameReader; const frameReader = batch.frameReader;
if (element.tagName === 'INPUT' && element.getAttribute('type') === 'time' && !element.getAttribute('step')) {
const timeValue = attributeFrame ? frameReader.attributeValue(attributeFrame) : null;
if (timeValue) {
element['value'] = timeValue.substring(0, 5);
return true;
}
}
switch (element.tagName) { switch (element.tagName) {
case 'INPUT': case 'INPUT':
case 'SELECT': case 'SELECT':

View File

@ -1,13 +1,19 @@
export class EventForDotNet<TData extends UIEventArgs> { export class EventForDotNet<TData extends UIEventArgs> {
constructor(public readonly type: EventArgsType, public readonly data: TData) { public constructor(public readonly type: EventArgsType, public readonly data: TData) {
} }
static fromDOMEvent(event: Event): EventForDotNet<UIEventArgs> { public static fromDOMEvent(event: Event): EventForDotNet<UIEventArgs> {
const element = event.target as Element; const element = event.target as Element;
switch (event.type) { switch (event.type) {
case 'input': case 'input':
case 'change': { case 'change': {
if (isTimeBasedInput(element)) {
const normalizedValue = normalizeTimeBasedValue(element);
return new EventForDotNet<UIChangeEventArgs>('change', { type: event.type, value: normalizedValue });
}
const targetIsCheckbox = isCheckbox(element); const targetIsCheckbox = isCheckbox(element);
const newValue = targetIsCheckbox ? !!element['checked'] : element['value']; const newValue = targetIsCheckbox ? !!element['checked'] : element['value'];
return new EventForDotNet<UIChangeEventArgs>('change', { type: event.type, value: newValue }); return new EventForDotNet<UIChangeEventArgs>('change', { type: event.type, value: newValue });
@ -36,7 +42,7 @@ export class EventForDotNet<TData extends UIEventArgs> {
case 'keydown': case 'keydown':
case 'keyup': case 'keyup':
case 'keypress': case 'keypress':
return new EventForDotNet<UIKeyboardEventArgs>('keyboard', parseKeyboardEvent(<KeyboardEvent>event)); return new EventForDotNet<UIKeyboardEventArgs>('keyboard', parseKeyboardEvent(event as KeyboardEvent));
case 'contextmenu': case 'contextmenu':
case 'click': case 'click':
@ -46,10 +52,10 @@ export class EventForDotNet<TData extends UIEventArgs> {
case 'mousedown': case 'mousedown':
case 'mouseup': case 'mouseup':
case 'dblclick': case 'dblclick':
return new EventForDotNet<UIMouseEventArgs>('mouse', parseMouseEvent(<MouseEvent>event)); return new EventForDotNet<UIMouseEventArgs>('mouse', parseMouseEvent(event as MouseEvent));
case 'error': case 'error':
return new EventForDotNet<UIErrorEventArgs>('error', parseErrorEvent(<ErrorEvent>event)); return new EventForDotNet<UIErrorEventArgs>('error', parseErrorEvent(event as ErrorEvent));
case 'loadstart': case 'loadstart':
case 'timeout': case 'timeout':
@ -57,7 +63,7 @@ export class EventForDotNet<TData extends UIEventArgs> {
case 'load': case 'load':
case 'loadend': case 'loadend':
case 'progress': case 'progress':
return new EventForDotNet<UIProgressEventArgs>('progress', parseProgressEvent(<ProgressEvent>event)); return new EventForDotNet<UIProgressEventArgs>('progress', parseProgressEvent(event as ProgressEvent));
case 'touchcancel': case 'touchcancel':
case 'touchend': case 'touchend':
@ -65,7 +71,7 @@ export class EventForDotNet<TData extends UIEventArgs> {
case 'touchenter': case 'touchenter':
case 'touchleave': case 'touchleave':
case 'touchstart': case 'touchstart':
return new EventForDotNet<UITouchEventArgs>('touch', parseTouchEvent(<TouchEvent>event)); return new EventForDotNet<UITouchEventArgs>('touch', parseTouchEvent(event as TouchEvent));
case 'gotpointercapture': case 'gotpointercapture':
case 'lostpointercapture': case 'lostpointercapture':
@ -77,11 +83,11 @@ export class EventForDotNet<TData extends UIEventArgs> {
case 'pointerout': case 'pointerout':
case 'pointerover': case 'pointerover':
case 'pointerup': case 'pointerup':
return new EventForDotNet<UIPointerEventArgs>('pointer', parsePointerEvent(<PointerEvent>event)); return new EventForDotNet<UIPointerEventArgs>('pointer', parsePointerEvent(event as PointerEvent));
case 'wheel': case 'wheel':
case 'mousewheel': case 'mousewheel':
return new EventForDotNet<UIWheelEventArgs>('wheel', parseWheelEvent(<WheelEvent>event)); return new EventForDotNet<UIWheelEventArgs>('wheel', parseWheelEvent(event as WheelEvent));
default: default:
return new EventForDotNet<UIEventArgs>('unknown', { type: event.type }); return new EventForDotNet<UIEventArgs>('unknown', { type: event.type });
@ -204,8 +210,38 @@ function parseMouseEvent(event: MouseEvent) {
}; };
} }
function isCheckbox(element: Element | null) { function isCheckbox(element: Element | null): boolean {
return element && element.tagName === 'INPUT' && element.getAttribute('type') === 'checkbox'; return !!element && element.tagName === 'INPUT' && element.getAttribute('type') === 'checkbox';
}
const timeBasedInputs = [
'date',
'datetime-local',
'month',
'time',
'week',
];
function isTimeBasedInput(element: Element): element is HTMLInputElement {
return timeBasedInputs.indexOf(element.getAttribute('type')!) !== -1;
}
function normalizeTimeBasedValue(element: HTMLInputElement): string {
const value = element.value;
const type = element.type;
switch (type) {
case 'date':
case 'datetime-local':
case 'month':
return value;
case 'time':
return value.length === 5 ? value + ':00' : value; // Convert hh:mm to hh:mm:00
case 'week':
// For now we are not going to normalize input type week as it is not trivial
return value;
}
throw new Error(`Invalid element type '${type}'.`);
} }
// The following interfaces must be kept in sync with the UIEventArgs C# classes // The following interfaces must be kept in sync with the UIEventArgs C# classes

View File

@ -42,7 +42,7 @@ namespace Microsoft.AspNetCore.Components.Forms
protected override void BuildRenderTree(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder builder) { } protected override void BuildRenderTree(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder builder) { }
protected override void OnParametersSet() { } protected override void OnParametersSet() { }
} }
public abstract partial class InputBase<TValue> : Microsoft.AspNetCore.Components.ComponentBase public abstract partial class InputBase<TValue> : Microsoft.AspNetCore.Components.ComponentBase, System.IDisposable
{ {
protected InputBase() { } protected InputBase() { }
[Microsoft.AspNetCore.Components.ParameterAttribute(CaptureUnmatchedValues=true)] [Microsoft.AspNetCore.Components.ParameterAttribute(CaptureUnmatchedValues=true)]
@ -58,8 +58,10 @@ namespace Microsoft.AspNetCore.Components.Forms
public Microsoft.AspNetCore.Components.EventCallback<TValue> ValueChanged { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } public Microsoft.AspNetCore.Components.EventCallback<TValue> ValueChanged { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
[Microsoft.AspNetCore.Components.ParameterAttribute] [Microsoft.AspNetCore.Components.ParameterAttribute]
public System.Linq.Expressions.Expression<System.Func<TValue>> ValueExpression { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } public System.Linq.Expressions.Expression<System.Func<TValue>> ValueExpression { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
protected virtual void Dispose(bool disposing) { }
protected virtual string FormatValueAsString(TValue value) { throw null; } protected virtual string FormatValueAsString(TValue value) { throw null; }
public override System.Threading.Tasks.Task SetParametersAsync(Microsoft.AspNetCore.Components.ParameterView parameters) { throw null; } public override System.Threading.Tasks.Task SetParametersAsync(Microsoft.AspNetCore.Components.ParameterView parameters) { throw null; }
void System.IDisposable.Dispose() { }
protected abstract bool TryParseValueFromString(string value, out TValue result, out string validationErrorMessage); protected abstract bool TryParseValueFromString(string value, out TValue result, out string validationErrorMessage);
} }
public partial class InputCheckbox : Microsoft.AspNetCore.Components.Forms.InputBase<bool> public partial class InputCheckbox : Microsoft.AspNetCore.Components.Forms.InputBase<bool>
@ -172,9 +174,15 @@ namespace Microsoft.AspNetCore.Components.Web
[Microsoft.AspNetCore.Components.BindInputElementAttribute("checkbox", null, "checked", "onchange", false, null)] [Microsoft.AspNetCore.Components.BindInputElementAttribute("checkbox", null, "checked", "onchange", false, null)]
[Microsoft.AspNetCore.Components.BindInputElementAttribute("date", "value", "value", "onchange", true, "yyyy-MM-dd")] [Microsoft.AspNetCore.Components.BindInputElementAttribute("date", "value", "value", "onchange", true, "yyyy-MM-dd")]
[Microsoft.AspNetCore.Components.BindInputElementAttribute("date", null, "value", "onchange", true, "yyyy-MM-dd")] [Microsoft.AspNetCore.Components.BindInputElementAttribute("date", null, "value", "onchange", true, "yyyy-MM-dd")]
[Microsoft.AspNetCore.Components.BindInputElementAttribute("datetime-local", "value", "value", "onchange", true, "yyyy-MM-ddTHH:mm:ss")]
[Microsoft.AspNetCore.Components.BindInputElementAttribute("datetime-local", null, "value", "onchange", true, "yyyy-MM-ddTHH:mm:ss")]
[Microsoft.AspNetCore.Components.BindInputElementAttribute("month", "value", "value", "onchange", true, "yyyy-MM")]
[Microsoft.AspNetCore.Components.BindInputElementAttribute("month", null, "value", "onchange", true, "yyyy-MM")]
[Microsoft.AspNetCore.Components.BindInputElementAttribute("number", "value", "value", "onchange", true, null)] [Microsoft.AspNetCore.Components.BindInputElementAttribute("number", "value", "value", "onchange", true, null)]
[Microsoft.AspNetCore.Components.BindInputElementAttribute("number", null, "value", "onchange", true, null)] [Microsoft.AspNetCore.Components.BindInputElementAttribute("number", null, "value", "onchange", true, null)]
[Microsoft.AspNetCore.Components.BindInputElementAttribute("text", null, "value", "onchange", false, null)] [Microsoft.AspNetCore.Components.BindInputElementAttribute("text", null, "value", "onchange", false, null)]
[Microsoft.AspNetCore.Components.BindInputElementAttribute("time", "value", "value", "onchange", true, "HH:mm:ss")]
[Microsoft.AspNetCore.Components.BindInputElementAttribute("time", null, "value", "onchange", true, "HH:mm:ss")]
[Microsoft.AspNetCore.Components.BindInputElementAttribute(null, "value", "value", "onchange", false, null)] [Microsoft.AspNetCore.Components.BindInputElementAttribute(null, "value", "value", "onchange", false, null)]
[Microsoft.AspNetCore.Components.BindInputElementAttribute(null, null, "value", "onchange", false, null)] [Microsoft.AspNetCore.Components.BindInputElementAttribute(null, null, "value", "onchange", false, null)]
public static partial class BindAttributes public static partial class BindAttributes

View File

@ -42,7 +42,7 @@ namespace Microsoft.AspNetCore.Components.Forms
protected override void BuildRenderTree(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder builder) { } protected override void BuildRenderTree(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder builder) { }
protected override void OnParametersSet() { } protected override void OnParametersSet() { }
} }
public abstract partial class InputBase<TValue> : Microsoft.AspNetCore.Components.ComponentBase public abstract partial class InputBase<TValue> : Microsoft.AspNetCore.Components.ComponentBase, System.IDisposable
{ {
protected InputBase() { } protected InputBase() { }
[Microsoft.AspNetCore.Components.ParameterAttribute(CaptureUnmatchedValues=true)] [Microsoft.AspNetCore.Components.ParameterAttribute(CaptureUnmatchedValues=true)]
@ -58,8 +58,10 @@ namespace Microsoft.AspNetCore.Components.Forms
public Microsoft.AspNetCore.Components.EventCallback<TValue> ValueChanged { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } public Microsoft.AspNetCore.Components.EventCallback<TValue> ValueChanged { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
[Microsoft.AspNetCore.Components.ParameterAttribute] [Microsoft.AspNetCore.Components.ParameterAttribute]
public System.Linq.Expressions.Expression<System.Func<TValue>> ValueExpression { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } public System.Linq.Expressions.Expression<System.Func<TValue>> ValueExpression { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
protected virtual void Dispose(bool disposing) { }
protected virtual string FormatValueAsString(TValue value) { throw null; } protected virtual string FormatValueAsString(TValue value) { throw null; }
public override System.Threading.Tasks.Task SetParametersAsync(Microsoft.AspNetCore.Components.ParameterView parameters) { throw null; } public override System.Threading.Tasks.Task SetParametersAsync(Microsoft.AspNetCore.Components.ParameterView parameters) { throw null; }
void System.IDisposable.Dispose() { }
protected abstract bool TryParseValueFromString(string value, out TValue result, out string validationErrorMessage); protected abstract bool TryParseValueFromString(string value, out TValue result, out string validationErrorMessage);
} }
public partial class InputCheckbox : Microsoft.AspNetCore.Components.Forms.InputBase<bool> public partial class InputCheckbox : Microsoft.AspNetCore.Components.Forms.InputBase<bool>
@ -172,9 +174,15 @@ namespace Microsoft.AspNetCore.Components.Web
[Microsoft.AspNetCore.Components.BindInputElementAttribute("checkbox", null, "checked", "onchange", false, null)] [Microsoft.AspNetCore.Components.BindInputElementAttribute("checkbox", null, "checked", "onchange", false, null)]
[Microsoft.AspNetCore.Components.BindInputElementAttribute("date", "value", "value", "onchange", true, "yyyy-MM-dd")] [Microsoft.AspNetCore.Components.BindInputElementAttribute("date", "value", "value", "onchange", true, "yyyy-MM-dd")]
[Microsoft.AspNetCore.Components.BindInputElementAttribute("date", null, "value", "onchange", true, "yyyy-MM-dd")] [Microsoft.AspNetCore.Components.BindInputElementAttribute("date", null, "value", "onchange", true, "yyyy-MM-dd")]
[Microsoft.AspNetCore.Components.BindInputElementAttribute("datetime-local", "value", "value", "onchange", true, "yyyy-MM-ddTHH:mm:ss")]
[Microsoft.AspNetCore.Components.BindInputElementAttribute("datetime-local", null, "value", "onchange", true, "yyyy-MM-ddTHH:mm:ss")]
[Microsoft.AspNetCore.Components.BindInputElementAttribute("month", "value", "value", "onchange", true, "yyyy-MM")]
[Microsoft.AspNetCore.Components.BindInputElementAttribute("month", null, "value", "onchange", true, "yyyy-MM")]
[Microsoft.AspNetCore.Components.BindInputElementAttribute("number", "value", "value", "onchange", true, null)] [Microsoft.AspNetCore.Components.BindInputElementAttribute("number", "value", "value", "onchange", true, null)]
[Microsoft.AspNetCore.Components.BindInputElementAttribute("number", null, "value", "onchange", true, null)] [Microsoft.AspNetCore.Components.BindInputElementAttribute("number", null, "value", "onchange", true, null)]
[Microsoft.AspNetCore.Components.BindInputElementAttribute("text", null, "value", "onchange", false, null)] [Microsoft.AspNetCore.Components.BindInputElementAttribute("text", null, "value", "onchange", false, null)]
[Microsoft.AspNetCore.Components.BindInputElementAttribute("time", "value", "value", "onchange", true, "HH:mm:ss")]
[Microsoft.AspNetCore.Components.BindInputElementAttribute("time", null, "value", "onchange", true, "HH:mm:ss")]
[Microsoft.AspNetCore.Components.BindInputElementAttribute(null, "value", "value", "onchange", false, null)] [Microsoft.AspNetCore.Components.BindInputElementAttribute(null, "value", "value", "onchange", false, null)]
[Microsoft.AspNetCore.Components.BindInputElementAttribute(null, null, "value", "onchange", false, null)] [Microsoft.AspNetCore.Components.BindInputElementAttribute(null, null, "value", "onchange", false, null)]
public static partial class BindAttributes public static partial class BindAttributes

View File

@ -13,8 +13,9 @@ namespace Microsoft.AspNetCore.Components.Forms
/// integrates with an <see cref="Forms.EditContext"/>, which must be supplied /// integrates with an <see cref="Forms.EditContext"/>, which must be supplied
/// as a cascading parameter. /// as a cascading parameter.
/// </summary> /// </summary>
public abstract class InputBase<TValue> : ComponentBase public abstract class InputBase<TValue> : ComponentBase, IDisposable
{ {
private readonly EventHandler<ValidationStateChangedEventArgs> _validationStateChangedHandler;
private bool _previousParsingAttemptFailed; private bool _previousParsingAttemptFailed;
private ValidationMessageStore _parsingValidationMessages; private ValidationMessageStore _parsingValidationMessages;
private Type _nullableUnderlyingType; private Type _nullableUnderlyingType;
@ -122,7 +123,15 @@ namespace Microsoft.AspNetCore.Components.Forms
} }
/// <summary> /// <summary>
/// Formats the value as a string. Derived classes can override this to determine the formatting used for <see cref="CurrentValueAsString"/>. /// Constructs an instance of <see cref="InputBase{TValue}"/>.
/// </summary>
protected InputBase()
{
_validationStateChangedHandler = (sender, eventArgs) => StateHasChanged();
}
/// <summary>
/// Formats the value as a string. Derived classes can override this to determine the formating used for <see cref="CurrentValueAsString"/>.
/// </summary> /// </summary>
/// <param name="value">The value to format.</param> /// <param name="value">The value to format.</param>
/// <returns>A string representation of the value.</returns> /// <returns>A string representation of the value.</returns>
@ -193,6 +202,8 @@ namespace Microsoft.AspNetCore.Components.Forms
EditContext = CascadedEditContext; EditContext = CascadedEditContext;
FieldIdentifier = FieldIdentifier.Create(ValueExpression); FieldIdentifier = FieldIdentifier.Create(ValueExpression);
_nullableUnderlyingType = Nullable.GetUnderlyingType(typeof(TValue)); _nullableUnderlyingType = Nullable.GetUnderlyingType(typeof(TValue));
EditContext.OnValidationStateChanged += _validationStateChangedHandler;
} }
else if (CascadedEditContext != EditContext) else if (CascadedEditContext != EditContext)
{ {
@ -208,5 +219,19 @@ namespace Microsoft.AspNetCore.Components.Forms
// For derived components, retain the usual lifecycle with OnInit/OnParametersSet/etc. // For derived components, retain the usual lifecycle with OnInit/OnParametersSet/etc.
return base.SetParametersAsync(ParameterView.Empty); return base.SetParametersAsync(ParameterView.Empty);
} }
protected virtual void Dispose(bool disposing)
{
}
void IDisposable.Dispose()
{
if (EditContext != null)
{
EditContext.OnValidationStateChanged -= _validationStateChangedHandler;
}
Dispose(disposing: true);
}
} }
} }

View File

@ -21,6 +21,7 @@ namespace Microsoft.AspNetCore.Components.Forms
// of it for us. We will only get asked to parse the T for nonempty inputs. // of it for us. We will only get asked to parse the T for nonempty inputs.
var targetType = Nullable.GetUnderlyingType(typeof(TValue)) ?? typeof(TValue); var targetType = Nullable.GetUnderlyingType(typeof(TValue)) ?? typeof(TValue);
if (targetType == typeof(int) || if (targetType == typeof(int) ||
targetType == typeof(long) ||
targetType == typeof(float) || targetType == typeof(float) ||
targetType == typeof(double) || targetType == typeof(double) ||
targetType == typeof(decimal)) targetType == typeof(decimal))

View File

@ -175,7 +175,7 @@ namespace Microsoft.AspNetCore.Components.Routing
var prefixLength = prefix.Length; var prefixLength = prefix.Length;
if (value.Length > prefixLength) if (value.Length > prefixLength)
{ {
return value.StartsWith(prefix, StringComparison.Ordinal) return value.StartsWith(prefix, StringComparison.OrdinalIgnoreCase)
&& ( && (
// Only match when there's a separator character either at the end of the // Only match when there's a separator character either at the end of the
// prefix or right after it. // prefix or right after it.

View File

@ -30,6 +30,20 @@ namespace Microsoft.AspNetCore.Components.Web
[BindInputElement("date", null, "value", "onchange", isInvariantCulture: true, format: "yyyy-MM-dd")] [BindInputElement("date", null, "value", "onchange", isInvariantCulture: true, format: "yyyy-MM-dd")]
[BindInputElement("date", "value", "value", "onchange", isInvariantCulture: true, format: "yyyy-MM-dd")] [BindInputElement("date", "value", "value", "onchange", isInvariantCulture: true, format: "yyyy-MM-dd")]
// type="datetime-local" is invariant culture with a specific format.
// See https://docs.microsoft.com/en-us/dotnet/standard/base-types/standard-date-and-time-format-strings for details.
[BindInputElement("datetime-local", null, "value", "onchange", isInvariantCulture: true, format: "yyyy-MM-ddTHH:mm:ss")]
[BindInputElement("datetime-local", "value", "value", "onchange", isInvariantCulture: true, format: "yyyy-MM-ddTHH:mm:ss")]
// type="month" is invariant culture with a specific format.
// See https://docs.microsoft.com/en-us/dotnet/standard/base-types/standard-date-and-time-format-strings for details.
[BindInputElement("month", null, "value", "onchange", isInvariantCulture: true, format: "yyyy-MM")]
[BindInputElement("month", "value", "value", "onchange", isInvariantCulture: true, format: "yyyy-MM")]
// type="time" is invariant culture with a specific format.
[BindInputElement("time", null, "value", "onchange", isInvariantCulture: true, format: "HH:mm:ss")]
[BindInputElement("time", "value", "value", "onchange", isInvariantCulture: true, format: "HH:mm:ss")]
[BindElement("select", null, "value", "onchange")] [BindElement("select", null, "value", "onchange")]
[BindElement("textarea", null, "value", "onchange")] [BindElement("textarea", null, "value", "onchange")]
public static class BindAttributes public static class BindAttributes

View File

@ -294,7 +294,7 @@ namespace Microsoft.AspNetCore.Components.Forms
rootComponent.EditContext.OnValidationStateChanged += (sender, eventArgs) => { numValidationStateChanges++; }; rootComponent.EditContext.OnValidationStateChanged += (sender, eventArgs) => { numValidationStateChanges++; };
// Act // Act
inputComponent.CurrentValueAsString = "1991/11/20"; await inputComponent.SetCurrentValueAsStringAsync("1991/11/20");
// Assert // Assert
var receivedParsedValue = valueChangedArgs.Single(); var receivedParsedValue = valueChangedArgs.Single();
@ -324,14 +324,14 @@ namespace Microsoft.AspNetCore.Components.Forms
rootComponent.EditContext.OnValidationStateChanged += (sender, eventArgs) => { numValidationStateChanges++; }; rootComponent.EditContext.OnValidationStateChanged += (sender, eventArgs) => { numValidationStateChanges++; };
// Act/Assert 1: Transition to invalid // Act/Assert 1: Transition to invalid
inputComponent.CurrentValueAsString = "1991/11/40"; await inputComponent.SetCurrentValueAsStringAsync("1991/11/40");
Assert.Empty(valueChangedArgs); Assert.Empty(valueChangedArgs);
Assert.True(rootComponent.EditContext.IsModified(fieldIdentifier)); Assert.True(rootComponent.EditContext.IsModified(fieldIdentifier));
Assert.Equal(new[] { "Bad date value" }, rootComponent.EditContext.GetValidationMessages(fieldIdentifier)); Assert.Equal(new[] { "Bad date value" }, rootComponent.EditContext.GetValidationMessages(fieldIdentifier));
Assert.Equal(1, numValidationStateChanges); Assert.Equal(1, numValidationStateChanges);
// Act/Assert 2: Transition to valid // Act/Assert 2: Transition to valid
inputComponent.CurrentValueAsString = "1991/11/20"; await inputComponent.SetCurrentValueAsStringAsync("1991/11/20");
var receivedParsedValue = valueChangedArgs.Single(); var receivedParsedValue = valueChangedArgs.Single();
Assert.Equal(1991, receivedParsedValue.Year); Assert.Equal(1991, receivedParsedValue.Year);
Assert.Equal(11, receivedParsedValue.Month); Assert.Equal(11, receivedParsedValue.Month);
@ -341,6 +341,65 @@ namespace Microsoft.AspNetCore.Components.Forms
Assert.Equal(2, numValidationStateChanges); Assert.Equal(2, numValidationStateChanges);
} }
[Fact]
public async Task RespondsToValidationStateChangeNotifications()
{
// Arrange
var model = new TestModel();
var rootComponent = new TestInputHostComponent<string, TestInputComponent<string>>
{
EditContext = new EditContext(model),
ValueExpression = () => model.StringProperty
};
var fieldIdentifier = FieldIdentifier.Create(() => model.StringProperty);
var renderer = new TestRenderer();
var rootComponentId = renderer.AssignRootComponentId(rootComponent);
await renderer.RenderRootComponentAsync(rootComponentId);
// Initally, it rendered one batch and is valid
var batch1 = renderer.Batches.Single();
var componentFrame1 = batch1.GetComponentFrames<TestInputComponent<string>>().Single();
var inputComponentId = componentFrame1.ComponentId;
var component = (TestInputComponent<string>)componentFrame1.Component;
Assert.Equal("valid", component.CssClass);
// Act: update the field state in the EditContext and notify
var messageStore = new ValidationMessageStore(rootComponent.EditContext);
messageStore.Add(fieldIdentifier, "Some message");
await renderer.Dispatcher.InvokeAsync(rootComponent.EditContext.NotifyValidationStateChanged);
// Assert: The input component rendered itself again and now has the new class
var batch2 = renderer.Batches.Skip(1).Single();
Assert.Equal(inputComponentId, batch2.DiffsByComponentId.Keys.Single());
Assert.Equal("invalid", component.CssClass);
}
[Fact]
public async Task UnsubscribesFromValidationStateChangeNotifications()
{
// Arrange
var model = new TestModel();
var rootComponent = new TestInputHostComponent<string, TestInputComponent<string>>
{
EditContext = new EditContext(model),
ValueExpression = () => model.StringProperty
};
var fieldIdentifier = FieldIdentifier.Create(() => model.StringProperty);
var renderer = new TestRenderer();
var rootComponentId = renderer.AssignRootComponentId(rootComponent);
await renderer.RenderRootComponentAsync(rootComponentId);
var component = renderer.Batches.Single().GetComponentFrames<TestInputComponent<string>>().Single().Component;
// Act: dispose, then update the field state in the EditContext and notify
((IDisposable)component).Dispose();
var messageStore = new ValidationMessageStore(rootComponent.EditContext);
messageStore.Add(fieldIdentifier, "Some message");
await renderer.Dispatcher.InvokeAsync(rootComponent.EditContext.NotifyValidationStateChanged);
// Assert: No additional render
Assert.Empty(renderer.Batches.Skip(1));
}
private static TComponent FindComponent<TComponent>(CapturedBatch batch) private static TComponent FindComponent<TComponent>(CapturedBatch batch)
=> batch.ReferenceFrames => batch.ReferenceFrames
.Where(f => f.FrameType == RenderTreeFrameType.Component) .Where(f => f.FrameType == RenderTreeFrameType.Component)
@ -376,7 +435,6 @@ namespace Microsoft.AspNetCore.Components.Forms
public new string CurrentValueAsString public new string CurrentValueAsString
{ {
get => base.CurrentValueAsString; get => base.CurrentValueAsString;
set { base.CurrentValueAsString = value; }
} }
public new IReadOnlyDictionary<string, object> AdditionalAttributes => base.AdditionalAttributes; public new IReadOnlyDictionary<string, object> AdditionalAttributes => base.AdditionalAttributes;
@ -391,6 +449,15 @@ namespace Microsoft.AspNetCore.Components.Forms
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
public async Task SetCurrentValueAsStringAsync(string value)
{
// This is equivalent to the subclass writing to CurrentValueAsString
// (e.g., from @bind), except to simplify the test code there's an InvokeAsync
// here. In production code it wouldn't normally be required because @bind
// calls run on the sync context anyway.
await InvokeAsync(() => { base.CurrentValueAsString = value; });
}
} }
class TestDateInputComponent : TestInputComponent<DateTime> class TestDateInputComponent : TestInputComponent<DateTime>

View File

@ -0,0 +1,60 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Linq;
using System.Text.Json;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components.E2ETest.Infrastructure;
using Microsoft.AspNetCore.Components.E2ETest.Infrastructure.ServerFixtures;
using Microsoft.AspNetCore.E2ETesting;
using OpenQA.Selenium;
using TestServer;
using Xunit;
using Xunit.Abstractions;
namespace Microsoft.AspNetCore.Components.E2ETest.ServerExecutionTests
{
public class ComponentWithParametersTest : ServerTestBase<BasicTestAppServerSiteFixture<PrerenderedStartup>>
{
public ComponentWithParametersTest(
BrowserFixture browserFixture,
BasicTestAppServerSiteFixture<PrerenderedStartup> serverFixture,
ITestOutputHelper output)
: base(browserFixture, serverFixture, output)
{
}
[Fact]
public void PassingParametersToComponentsFromThePageWorks()
{
Navigate("/prerendered/componentwithparameters?QueryValue=testQueryValue");
BeginInteractivity();
Browser.Exists(By.CssSelector(".interactive"));
var parameter1 = Browser.FindElement(By.CssSelector(".Param1"));
Assert.Equal(100, parameter1.FindElements(By.CssSelector("li")).Count);
Assert.Equal("99 99", parameter1.FindElement(By.CssSelector("li:last-child")).Text);
// The assigned value is of a more derived type than the declared model type. This check
// verifies we use the actual model type during round tripping.
var parameter2 = Browser.FindElement(By.CssSelector(".Param2"));
Assert.Equal("Value Derived-Value", parameter2.Text);
// This check verifies CaptureUnmatchedValues works
var parameter3 = Browser.FindElements(By.CssSelector(".Param3 li"));
Assert.Collection(
parameter3,
p => Assert.Equal("key1 testQueryValue", p.Text),
p => Assert.Equal("key2 43", p.Text));
}
private void BeginInteractivity()
{
Browser.FindElement(By.Id("load-boot-script")).Click();
}
}
}

View File

@ -174,6 +174,18 @@ namespace Microsoft.AspNetCore.Components.E2ETest.ServerExecutionTests
Browser.Equal(9000.ToString(cultureInfo), () => display.Text); Browser.Equal(9000.ToString(cultureInfo), () => display.Text);
Browser.Equal(9000.ToString(CultureInfo.InvariantCulture), () => input.GetAttribute("value")); Browser.Equal(9000.ToString(CultureInfo.InvariantCulture), () => input.GetAttribute("value"));
// long
input = Browser.FindElement(By.Id("inputnumber_long"));
display = Browser.FindElement(By.Id("inputnumber_long_value"));
Browser.Equal(4200.ToString(cultureInfo), () => display.Text);
Browser.Equal(4200.ToString(CultureInfo.InvariantCulture), () => input.GetAttribute("value"));
input.Clear();
input.SendKeys(90000000000.ToString(CultureInfo.InvariantCulture));
input.SendKeys("\t");
Browser.Equal(90000000000.ToString(cultureInfo), () => display.Text);
Browser.Equal(90000000000.ToString(CultureInfo.InvariantCulture), () => input.GetAttribute("value"));
// decimal // decimal
input = Browser.FindElement(By.Id("inputnumber_decimal")); input = Browser.FindElement(By.Id("inputnumber_decimal"));
display = Browser.FindElement(By.Id("inputnumber_decimal_value")); display = Browser.FindElement(By.Id("inputnumber_decimal_value"));

View File

@ -16,13 +16,13 @@ using Xunit.Abstractions;
namespace Microsoft.AspNetCore.Components.E2ETest.ServerExecutionTests namespace Microsoft.AspNetCore.Components.E2ETest.ServerExecutionTests
{ {
public class MultipleComponentsTest : ServerTestBase<BasicTestAppServerSiteFixture<PrerenderedStartup>> public class MultipleComponentsTest : ServerTestBase<BasicTestAppServerSiteFixture<MultipleComponents>>
{ {
private const string MarkerPattern = ".*?<!--Blazor:(.*?)-->.*?"; private const string MarkerPattern = ".*?<!--Blazor:(.*?)-->.*?";
public MultipleComponentsTest( public MultipleComponentsTest(
BrowserFixture browserFixture, BrowserFixture browserFixture,
BasicTestAppServerSiteFixture<PrerenderedStartup> serverFixture, BasicTestAppServerSiteFixture<MultipleComponents> serverFixture,
ITestOutputHelper output) ITestOutputHelper output)
: base(browserFixture, serverFixture, output) : base(browserFixture, serverFixture, output)
{ {
@ -46,7 +46,7 @@ namespace Microsoft.AspNetCore.Components.E2ETest.ServerExecutionTests
[Fact] [Fact]
public void DoesNotStartMultipleConnections() public void DoesNotStartMultipleConnections()
{ {
Navigate("/prerendered/multiple-components"); Navigate("/multiple-components");
BeginInteractivity(); BeginInteractivity();
Browser.Exists(By.CssSelector("h3.interactive")); Browser.Exists(By.CssSelector("h3.interactive"));
@ -60,17 +60,18 @@ namespace Microsoft.AspNetCore.Components.E2ETest.ServerExecutionTests
}); });
} }
[Fact] [Fact]
public void CanRenderMultipleRootComponents() public void CanRenderMultipleRootComponents()
{ {
Navigate("/prerendered/multiple-components"); Navigate("/multiple-components");
var greets = Browser.FindElements(By.CssSelector(".greet-wrapper .greet")).Select(e => e.Text).ToArray(); var greets = Browser.FindElements(By.CssSelector(".greet-wrapper .greet")).Select(e => e.Text).ToArray();
Assert.Equal(5, greets.Length); // 1 statically rendered + 3 prerendered + 1 server prerendered Assert.Equal(7, greets.Length); // 1 statically rendered + 5 prerendered + 1 server prerendered
Assert.DoesNotContain("Hello Red fish", greets);
Assert.Single(greets, "Hello John"); Assert.Single(greets, "Hello John");
Assert.Single(greets, "Hello Abraham"); Assert.Single(greets, "Hello Abraham");
Assert.Equal(2, greets.Where(g => g == "Hello Blue fish").Count());
Assert.Equal(3, greets.Where(g => string.Equals("Hello", g)).Count()); // 3 server prerendered without parameters Assert.Equal(3, greets.Where(g => string.Equals("Hello", g)).Count()); // 3 server prerendered without parameters
var content = Browser.FindElement(By.Id("test-container")).GetAttribute("innerHTML"); var content = Browser.FindElement(By.Id("test-container")).GetAttribute("innerHTML");
var markers = ReadMarkers(content); var markers = ReadMarkers(content);
@ -86,7 +87,11 @@ namespace Microsoft.AspNetCore.Components.E2ETest.ServerExecutionTests
false, false,
true, true,
false, false,
true true,
false,
true,
false,
true,
}; };
Assert.Equal(expectedComponentSequence, componentSequence); Assert.Equal(expectedComponentSequence, componentSequence);
@ -96,6 +101,8 @@ namespace Microsoft.AspNetCore.Components.E2ETest.ServerExecutionTests
Browser.Exists(By.CssSelector("h3.interactive")); Browser.Exists(By.CssSelector("h3.interactive"));
var updatedGreets = Browser.FindElements(By.CssSelector(".greet-wrapper .greet")).Select(e => e.Text).ToArray(); var updatedGreets = Browser.FindElements(By.CssSelector(".greet-wrapper .greet")).Select(e => e.Text).ToArray();
Assert.Equal(7, updatedGreets.Where(g => string.Equals("Hello Alfred", g)).Count()); Assert.Equal(7, updatedGreets.Where(g => string.Equals("Hello Alfred", g)).Count());
Assert.Equal(2, updatedGreets.Where(g => g == "Hello Red fish").Count());
Assert.Equal(2, updatedGreets.Where(g => g == "Hello Blue fish").Count());
Assert.Single(updatedGreets.Where(g => string.Equals("Hello Albert", g))); Assert.Single(updatedGreets.Where(g => string.Equals("Hello Albert", g)));
Assert.Single(updatedGreets.Where(g => string.Equals("Hello Abraham", g))); Assert.Single(updatedGreets.Where(g => string.Equals("Hello Abraham", g)));
} }

View File

@ -2,10 +2,12 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System; using System;
using System.Text.Json;
using BasicTestApp; using BasicTestApp;
using Microsoft.AspNetCore.Components.E2ETest.Infrastructure; using Microsoft.AspNetCore.Components.E2ETest.Infrastructure;
using Microsoft.AspNetCore.Components.E2ETest.Infrastructure.ServerFixtures; using Microsoft.AspNetCore.Components.E2ETest.Infrastructure.ServerFixtures;
using Microsoft.AspNetCore.E2ETesting; using Microsoft.AspNetCore.E2ETesting;
using Moq;
using OpenQA.Selenium; using OpenQA.Selenium;
using OpenQA.Selenium.Support.UI; using OpenQA.Selenium.Support.UI;
using Xunit; using Xunit;
@ -1018,5 +1020,263 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Tests
Browser.Equal(expected.DateTime, () => DateTimeOffset.Parse(boundValue.Text).DateTime); Browser.Equal(expected.DateTime, () => DateTimeOffset.Parse(boundValue.Text).DateTime);
Assert.Equal(expected.DateTime, DateTimeOffset.Parse(mirrorValue.GetAttribute("value")).DateTime); Assert.Equal(expected.DateTime, DateTimeOffset.Parse(mirrorValue.GetAttribute("value")).DateTime);
} }
// For date comparisons, we parse (non-formatted) values to compare them. Client-side and server-side
// Blazor have different formatting behaviour by default.
[Fact]
public void CanBindDateTimeLocalTextboxDateTime()
{
var target = Browser.FindElement(By.Id("datetime-local-textbox-datetime"));
var boundValue = Browser.FindElement(By.Id("datetime-local-textbox-datetime-value"));
var mirrorValue = Browser.FindElement(By.Id("datetime-local-textbox-datetime-mirror"));
var expected = new DateTime(1985, 3, 4);
Assert.Equal(expected, DateTime.Parse(target.GetAttribute("value")));
Assert.Equal(expected, DateTime.Parse(boundValue.Text));
Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value")));
// Clear textbox; value updates to 01/01/0001 because that's the default
target.Clear();
expected = default;
Browser.Equal(expected, () => DateTime.Parse(target.GetAttribute("value")));
Assert.Equal(expected, DateTime.Parse(boundValue.Text));
Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value")));
// We have to do it this way because the browser gets in the way when sending keys to the input
// element directly.
ApplyInputValue("#datetime-local-textbox-datetime", "2000-01-02T04:05:06");
expected = new DateTime(2000, 1, 2, 04, 05, 06);
Browser.Equal(expected, () => DateTime.Parse(boundValue.Text));
Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value")));
}
// For date comparisons, we parse (non-formatted) values to compare them. Client-side and server-side
// Blazor have different formatting behaviour by default.
[Fact]
public void CanBindDateTimeLocalTextboxNullableDateTime()
{
var target = Browser.FindElement(By.Id("datetime-local-textbox-nullable-datetime"));
var boundValue = Browser.FindElement(By.Id("datetime-local-textbox-nullable-datetime-value"));
var mirrorValue = Browser.FindElement(By.Id("datetime-local-textbox-nullable-datetime-mirror"));
Assert.Equal(string.Empty, target.GetAttribute("value"));
Assert.Equal(string.Empty, boundValue.Text);
Assert.Equal(string.Empty, mirrorValue.GetAttribute("value"));
// Modify target; verify value is updated and that textboxes linked to the same data are updated
target.Clear();
Browser.Equal("", () => boundValue.Text);
Assert.Equal("", mirrorValue.GetAttribute("value"));
// Modify target; verify value is updated and that textboxes linked to the same data are updated
// We have to do it this way because the browser gets in the way when sending keys to the input
// element directly.
ApplyInputValue("#datetime-local-textbox-nullable-datetime", "2000-01-02T04:05:06");
var expected = new DateTime(2000, 1, 2, 04, 05, 06);
Browser.Equal(expected, () => DateTime.Parse(boundValue.Text));
Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value")));
// Modify target; verify value is updated and that textboxes linked to the same data are updated
target.Clear();
target.SendKeys("\t");
Browser.Equal(string.Empty, () => boundValue.Text);
Assert.Equal(string.Empty, mirrorValue.GetAttribute("value"));
}
// For date comparisons, we parse (non-formatted) values to compare them. Client-side and server-side
// Blazor have different formatting behaviour by default.
[Fact]
public void CanBindMonthTextboxDateTime()
{
var target = Browser.FindElement(By.Id("month-textbox-datetime"));
var boundValue = Browser.FindElement(By.Id("month-textbox-datetime-value"));
var mirrorValue = Browser.FindElement(By.Id("month-textbox-datetime-mirror"));
var expected = new DateTime(1985, 3, 1);
Assert.Equal(expected, DateTime.Parse(target.GetAttribute("value")));
// When the value gets displayed the first time it gets truncated to the 1st day,
// until there is no change the bound value doesn't get updated.
Assert.Equal(expected.AddDays(3), DateTime.Parse(boundValue.Text));
Assert.Equal(expected.AddDays(3), DateTime.Parse(mirrorValue.GetAttribute("value")));
// Clear textbox; value updates to 01/01/0001 because that's the default
target.Clear();
expected = default;
Browser.Equal(expected, () => DateTime.Parse(target.GetAttribute("value")));
Assert.Equal(expected, DateTime.Parse(boundValue.Text));
Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value")));
// We have to do it this way because the browser gets in the way when sending keys to the input
// element directly.
ApplyInputValue("#month-textbox-datetime", "2000-02");
expected = new DateTime(2000, 2, 1);
Browser.Equal(expected, () => DateTime.Parse(boundValue.Text));
Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value")));
}
// For date comparisons, we parse (non-formatted) values to compare them. Client-side and server-side
// Blazor have different formatting behaviour by default.
[Fact]
public void CanBindMonthTextboxNullableDateTime()
{
var target = Browser.FindElement(By.Id("month-textbox-nullable-datetime"));
var boundValue = Browser.FindElement(By.Id("month-textbox-nullable-datetime-value"));
var mirrorValue = Browser.FindElement(By.Id("month-textbox-nullable-datetime-mirror"));
Assert.Equal(string.Empty, target.GetAttribute("value"));
Assert.Equal(string.Empty, boundValue.Text);
Assert.Equal(string.Empty, mirrorValue.GetAttribute("value"));
// Modify target; verify value is updated and that textboxes linked to the same data are updated
target.Clear();
Browser.Equal("", () => boundValue.Text);
Assert.Equal("", mirrorValue.GetAttribute("value"));
// Modify target; verify value is updated and that textboxes linked to the same data are updated
// We have to do it this way because the browser gets in the way when sending keys to the input
// element directly.
ApplyInputValue("#month-textbox-nullable-datetime", "2000-02");
var expected = new DateTime(2000, 2, 1);
Browser.Equal(expected, () => DateTime.Parse(boundValue.Text));
Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value")));
// Modify target; verify value is updated and that textboxes linked to the same data are updated
target.Clear();
target.SendKeys("\t");
Browser.Equal(string.Empty, () => boundValue.Text);
Assert.Equal(string.Empty, mirrorValue.GetAttribute("value"));
}
// For date comparisons, we parse (non-formatted) values to compare them. Client-side and server-side
// Blazor have different formatting behaviour by default.
[Fact]
public void CanBindTimeTextboxDateTime()
{
var target = Browser.FindElement(By.Id("time-textbox-datetime"));
var boundValue = Browser.FindElement(By.Id("time-textbox-datetime-value"));
var mirrorValue = Browser.FindElement(By.Id("time-textbox-datetime-mirror"));
var expected = DateTime.Now.Date.AddHours(8).AddMinutes(5);
Assert.Equal(expected, DateTime.Parse(target.GetAttribute("value")));
Assert.Equal(expected, DateTime.Parse(boundValue.Text));
Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value")));
// Clear textbox; value updates to 00:00 because that's the default
target.Clear();
expected = default;
Browser.Equal(DateTime.Now.Date, () => DateTime.Parse(target.GetAttribute("value")));
Assert.Equal(default, DateTime.Parse(boundValue.Text));
Assert.Equal(default, DateTime.Parse(mirrorValue.GetAttribute("value")));
// We have to do it this way because the browser gets in the way when sending keys to the input
// element directly.
ApplyInputValue("#time-textbox-datetime", "04:05");
expected = DateTime.Now.Date.Add(new TimeSpan(4, 5, 0));
Browser.Equal(expected, () => DateTime.Parse(boundValue.Text));
Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value")));
}
// For date comparisons, we parse (non-formatted) values to compare them. Client-side and server-side
// Blazor have different formatting behaviour by default.
[Fact]
public void CanBindTimeTextboxNullableDateTime()
{
var target = Browser.FindElement(By.Id("time-textbox-nullable-datetime"));
var boundValue = Browser.FindElement(By.Id("time-textbox-nullable-datetime-value"));
var mirrorValue = Browser.FindElement(By.Id("time-textbox-nullable-datetime-mirror"));
Assert.Equal(string.Empty, target.GetAttribute("value"));
Assert.Equal(string.Empty, boundValue.Text);
Assert.Equal(string.Empty, mirrorValue.GetAttribute("value"));
// Modify target; verify value is updated and that textboxes linked to the same data are updated
target.Clear();
Browser.Equal("", () => boundValue.Text);
Assert.Equal("", mirrorValue.GetAttribute("value"));
// Modify target; verify value is updated and that textboxes linked to the same data are updated
// We have to do it this way because the browser gets in the way when sending keys to the input
// element directly.
ApplyInputValue("#time-textbox-nullable-datetime", "05:06");
var expected = DateTime.Now.Date.Add(new TimeSpan(05, 06, 0));
Browser.Equal(expected, () => DateTime.Parse(boundValue.Text));
Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value")));
// Modify target; verify value is updated and that textboxes linked to the same data are updated
target.Clear();
target.SendKeys("\t");
Browser.Equal(string.Empty, () => boundValue.Text);
Assert.Equal(string.Empty, mirrorValue.GetAttribute("value"));
}
// For date comparisons, we parse (non-formatted) values to compare them. Client-side and server-side
// Blazor have different formatting behaviour by default.
[Fact]
public void CanBindTimeStepTextboxDateTime()
{
var target = Browser.FindElement(By.Id("time-step-textbox-datetime"));
var boundValue = Browser.FindElement(By.Id("time-step-textbox-datetime-value"));
var mirrorValue = Browser.FindElement(By.Id("time-step-textbox-datetime-mirror"));
var expected = DateTime.Now.Date.Add(new TimeSpan(8, 5, 30));
Assert.Equal(expected, DateTime.Parse(target.GetAttribute("value")));
Assert.Equal(expected, DateTime.Parse(boundValue.Text));
Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value")));
// Clear textbox; value updates to 00:00 because that's the default
target.Clear();
expected = default;
Browser.Equal(DateTime.Now.Date, () => DateTime.Parse(target.GetAttribute("value")));
Assert.Equal(default, DateTime.Parse(boundValue.Text));
Assert.Equal(default, DateTime.Parse(mirrorValue.GetAttribute("value")));
// We have to do it this way because the browser gets in the way when sending keys to the input
// element directly.
ApplyInputValue("#time-step-textbox-datetime", "04:05:06");
expected = DateTime.Now.Date.Add(new TimeSpan(4, 5, 6));
Browser.Equal(expected, () => DateTime.Parse(boundValue.Text));
Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value")));
}
// For date comparisons, we parse (non-formatted) values to compare them. Client-side and server-side
// Blazor have different formatting behaviour by default.
[Fact]
public void CanBindTimeStepTextboxNullableDateTime()
{
var target = Browser.FindElement(By.Id("time-step-textbox-nullable-datetime"));
var boundValue = Browser.FindElement(By.Id("time-step-textbox-nullable-datetime-value"));
var mirrorValue = Browser.FindElement(By.Id("time-step-textbox-nullable-datetime-mirror"));
Assert.Equal(string.Empty, target.GetAttribute("value"));
Assert.Equal(string.Empty, boundValue.Text);
Assert.Equal(string.Empty, mirrorValue.GetAttribute("value"));
// Modify target; verify value is updated and that textboxes linked to the same data are updated
target.Clear();
Browser.Equal("", () => boundValue.Text);
Assert.Equal("", mirrorValue.GetAttribute("value"));
// Modify target; verify value is updated and that textboxes linked to the same data are updated
// We have to do it this way because the browser gets in the way when sending keys to the input
// element directly.
ApplyInputValue("#time-step-textbox-nullable-datetime", "05:06");
var expected = DateTime.Now.Date.Add(new TimeSpan(05, 06, 0));
Browser.Equal(expected, () => DateTime.Parse(boundValue.Text));
Assert.Equal(expected, DateTime.Parse(mirrorValue.GetAttribute("value")));
// Modify target; verify value is updated and that textboxes linked to the same data are updated
target.Clear();
target.SendKeys("\t");
Browser.Equal(string.Empty, () => boundValue.Text);
Assert.Equal(string.Empty, mirrorValue.GetAttribute("value"));
}
// Applies an input through javascript to datetime-local/month/time controls.
private void ApplyInputValue(string cssSelector, string value)
{
// It's very difficult to enter an invalid value into an <input type=date>, because
// most combinations of keystrokes get normalized to something valid. Additionally,
// using Selenium's SendKeys interacts unpredictably with this normalization logic,
// most likely based on timings. As a workaround, use JS to apply the values. This
// should only be used when strictly necessary, as it doesn't represent actual user
// interaction as authentically as SendKeys in other cases.
var javascript = (IJavaScriptExecutor)Browser;
javascript.ExecuteScript(
$"var elem = document.querySelector('{cssSelector}');"
+ $"elem.value = '{value}';"
+ "elem.dispatchEvent(new KeyboardEvent('change'));");
}
} }
} }

View File

@ -0,0 +1,67 @@
// 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 BasicTestApp;
using Microsoft.AspNetCore.Components.E2ETest.Infrastructure;
using Microsoft.AspNetCore.Components.E2ETest.Infrastructure.ServerFixtures;
using Microsoft.AspNetCore.E2ETesting;
using OpenQA.Selenium;
using Xunit;
using Xunit.Abstractions;
namespace Microsoft.AspNetCore.Components.E2ETest.Tests
{
[Collection("ErrorNotification")] // When the clientside and serverside tests run together it seems to cause failures, possibly due to connection lose on exception.
public class ErrorNotificationClientSideTest : ServerTestBase<ToggleExecutionModeServerFixture<Program>>
{
public ErrorNotificationClientSideTest(
BrowserFixture browserFixture,
ToggleExecutionModeServerFixture<Program> serverFixture,
ITestOutputHelper output)
: base(browserFixture, serverFixture, output)
{
}
protected override void InitializeAsyncCore()
{
// On WebAssembly, page reloads are expensive so skip if possible
Navigate(ServerPathBase, noReload: _serverFixture.ExecutionMode == ExecutionMode.Client);
Browser.MountTestComponent<ErrorComponent>();
Browser.Exists(By.Id("blazor-error-ui"));
Browser.Exists(By.TagName("button"));
}
[Fact]
public void ShowsErrorNotification_OnError_Dismiss()
{
var errorUi = Browser.FindElement(By.Id("blazor-error-ui"));
Assert.Equal("none", errorUi.GetCssValue("display"));
var causeErrorButton = Browser.FindElement(By.TagName("button"));
causeErrorButton.Click();
Browser.Exists(By.CssSelector("#blazor-error-ui[style='display: block;']"), TimeSpan.FromSeconds(10));
var reload = Browser.FindElement(By.ClassName("reload"));
reload.Click();
Browser.DoesNotExist(By.TagName("button"));
}
[Fact]
public void ShowsErrorNotification_OnError_Reload()
{
var causeErrorButton = Browser.Exists(By.TagName("button"));
var errorUi = Browser.FindElement(By.Id("blazor-error-ui"));
Assert.Equal("none", errorUi.GetCssValue("display"));
causeErrorButton.Click();
Browser.Exists(By.CssSelector("#blazor-error-ui[style='display: block;']"));
var dismiss = Browser.FindElement(By.ClassName("dismiss"));
dismiss.Click();
Browser.Exists(By.CssSelector("#blazor-error-ui[style='display: none;']"));
}
}
}

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 BasicTestApp;
using Microsoft.AspNetCore.Components.E2ETest.Infrastructure.ServerFixtures;
using Microsoft.AspNetCore.Components.E2ETest.ServerExecutionTests;
using Microsoft.AspNetCore.E2ETesting;
using OpenQA.Selenium;
using Xunit;
using Xunit.Abstractions;
namespace Microsoft.AspNetCore.Components.E2ETest.Tests
{
[Collection("ErrorNotification")] // When the clientside and serverside tests run together it seems to cause failures, possibly due to connection lose on exception.
public class ErrorNotificationServerSideTest : ErrorNotificationClientSideTest
{
public ErrorNotificationServerSideTest(
BrowserFixture browserFixture,
ToggleExecutionModeServerFixture<Program> serverFixture,
ITestOutputHelper output)
: base(browserFixture, serverFixture.WithServerExecution(), output)
{
}
}
}

View File

@ -376,6 +376,24 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Tests
Browser.Equal("Premium", () => selectedTicketClassDisplay.Text); Browser.Equal("Premium", () => selectedTicketClassDisplay.Text);
} }
[Fact]
public void InputComponentsRespondToAsynchronouslyAddedMessages()
{
var appElement = Browser.MountTestComponent<TypicalValidationComponent>();
var input = appElement.FindElement(By.CssSelector(".username input"));
var triggerAsyncErrorButton = appElement.FindElement(By.CssSelector(".username button"));
var messagesAccessor = CreateValidationMessagesAccessor(appElement);
// Initially shows no error
Browser.Empty(() => messagesAccessor());
Browser.Equal("valid", () => input.GetAttribute("class"));
// Can trigger async error
triggerAsyncErrorButton.Click();
Browser.Equal(new[] { "This is invalid, asynchronously" }, messagesAccessor);
Browser.Equal("invalid", () => input.GetAttribute("class"));
}
private Func<string[]> CreateValidationMessagesAccessor(IWebElement appElement) private Func<string[]> CreateValidationMessagesAccessor(IWebElement appElement)
{ {
return () => appElement.FindElements(By.ClassName("validation-message")) return () => appElement.FindElements(By.ClassName("validation-message"))

View File

@ -11,6 +11,7 @@ using OpenQA.Selenium;
using OpenQA.Selenium.Support.UI; using OpenQA.Selenium.Support.UI;
using Xunit; using Xunit;
using Xunit.Abstractions; using Xunit.Abstractions;
using Xunit.Sdk;
namespace Microsoft.AspNetCore.Components.E2ETest.Tests namespace Microsoft.AspNetCore.Components.E2ETest.Tests
{ {
@ -68,6 +69,8 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Tests
["testDtoAsync"] = "Same", ["testDtoAsync"] = "Same",
["returnPrimitiveAsync"] = "123", ["returnPrimitiveAsync"] = "123",
["returnArrayAsync"] = "first,second", ["returnArrayAsync"] = "first,second",
["syncGenericInstanceMethod"] = @"""Initial value""",
["asyncGenericInstanceMethod"] = @"""Updated value 1""",
}; };
var expectedSyncValues = new Dictionary<string, string> var expectedSyncValues = new Dictionary<string, string>
@ -102,6 +105,7 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Tests
["testDtoSync"] = "Same", ["testDtoSync"] = "Same",
["returnPrimitive"] = "123", ["returnPrimitive"] = "123",
["returnArray"] = "first,second", ["returnArray"] = "first,second",
["genericInstanceMethod"] = @"""Updated value 2""",
}; };
// Include the sync assertions only when running under WebAssembly // Include the sync assertions only when running under WebAssembly
@ -132,13 +136,17 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Tests
// Assert // Assert
foreach (var expectedValue in expectedValues) foreach (var expectedValue in expectedValues)
{ {
var actualValue = actualValues[expectedValue.Key];
if (expectedValue.Key.Contains("Exception")) if (expectedValue.Key.Contains("Exception"))
{ {
Assert.StartsWith(expectedValue.Value, actualValues[expectedValue.Key]); Assert.StartsWith(expectedValue.Value, actualValue);
} }
else else
{ {
Assert.Equal(expectedValue.Value, actualValues[expectedValue.Key]); if (expectedValue.Value != actualValue)
{
throw new AssertActualExpectedException(expectedValue.Value, actualValue, $"Scenario '{expectedValue.Key}' failed. Expected '{expectedValue.Value}, Actual {actualValue}");
}
} }
} }
} }

View File

@ -254,6 +254,63 @@
<span id="select-markup-box-value">@selectMarkupValue</span> <span id="select-markup-box-value">@selectMarkupValue</span>
</p> </p>
<h2>Time related inputs (datetime-local, month, time)</h2>
<h3>datetime-local</h3>
<p>
DateTime:
<input id="datetime-local-textbox-datetime" @bind="dateTimeLocalTextboxDateTimeValue" type="datetime-local" />
<span id="datetime-local-textbox-datetime-value">@dateTimeLocalTextboxDateTimeValue</span>
<input id="datetime-local-textbox-datetime-mirror" @bind="dateTimeLocalTextboxDateTimeValue" readonly />
</p>
<p>
Nullable DateTime:
<input id="datetime-local-textbox-nullable-datetime" @bind-value="dateTimeLocalTextboxNullableDateTimeValue" type="datetime-local" />
<span id="datetime-local-textbox-nullable-datetime-value">@dateTimeLocalTextboxNullableDateTimeValue</span>
<input id="datetime-local-textbox-nullable-datetime-mirror" @bind="dateTimeLocalTextboxNullableDateTimeValue" readonly />
</p>
<h3>month</h3>
<p>
DateTime:
<input id="month-textbox-datetime" @bind="monthTextboxDateTimeValue" type="month" />
<span id="month-textbox-datetime-value">@monthTextboxDateTimeValue</span>
<input id="month-textbox-datetime-mirror" @bind="monthTextboxDateTimeValue" readonly />
</p>
<p>
Nullable DateTime:
<input id="month-textbox-nullable-datetime" @bind-value="monthTextboxNullableDateTimeValue" type="month" />
<span id="month-textbox-nullable-datetime-value">@monthTextboxNullableDateTimeValue</span>
<input id="month-textbox-nullable-datetime-mirror" @bind="monthTextboxNullableDateTimeValue" readonly />
</p>
<h3>time</h3>
<p>
DateTime:
<input id="time-textbox-datetime" @bind="timeTextboxDateTimeValue" type="time" />
<span id="time-textbox-datetime-value">@timeTextboxDateTimeValue</span>
<input id="time-textbox-datetime-mirror" @bind="timeTextboxDateTimeValue" readonly />
</p>
<p>
Nullable DateTime:
<input id="time-textbox-nullable-datetime" @bind-value="timeTextboxNullableDateTimeValue" type="time" />
<span id="time-textbox-nullable-datetime-value">@timeTextboxNullableDateTimeValue</span>
<input id="time-textbox-nullable-datetime-mirror" @bind="timeTextboxNullableDateTimeValue" readonly />
</p>
<h3>time with step (supports seconds)</h3>
<p>
DateTime:
<input id="time-step-textbox-datetime" @bind="timeStepTextboxDateTimeValue" type="time" step="1" />
<span id="time-step-textbox-datetime-value">@timeStepTextboxDateTimeValue</span>
<input id="time-step-textbox-datetime-mirror" @bind="timeStepTextboxDateTimeValue" readonly />
</p>
<p>
Nullable DateTime:
<input id="time-step-textbox-nullable-datetime" @bind-value="timeStepTextboxNullableDateTimeValue" type="time" step="1" />
<span id="time-step-textbox-nullable-datetime-value">@timeStepTextboxNullableDateTimeValue</span>
<input id="time-step-textbox-nullable-datetime-mirror" @bind="timeStepTextboxNullableDateTimeValue" readonly />
</p>
@code { @code {
string textboxInitiallyBlankValue = null; string textboxInitiallyBlankValue = null;
string textboxInitiallyPopulatedValue = "Hello"; string textboxInitiallyPopulatedValue = "Hello";
@ -297,6 +354,18 @@
DateTime textboxDateTimeFormatInvalidValue = new DateTime(1985, 3, 4); DateTime textboxDateTimeFormatInvalidValue = new DateTime(1985, 3, 4);
DateTimeOffset? textboxNullableDateTimeOffsetFormatInvalidValue = null; DateTimeOffset? textboxNullableDateTimeOffsetFormatInvalidValue = null;
DateTime dateTimeLocalTextboxDateTimeValue = new DateTime(1985, 3, 4);
DateTime? dateTimeLocalTextboxNullableDateTimeValue = null;
DateTime monthTextboxDateTimeValue = new DateTime(1985, 3, 4);
DateTime? monthTextboxNullableDateTimeValue = null;
DateTime timeTextboxDateTimeValue = DateTime.Now.Date.Add(new TimeSpan(8, 5, 0));
DateTime? timeTextboxNullableDateTimeValue = null;
DateTime timeStepTextboxDateTimeValue = DateTime.Now.Date.Add(new TimeSpan(8, 5, 30));
DateTime? timeStepTextboxNullableDateTimeValue = null;
bool includeFourthOption = false; bool includeFourthOption = false;
enum SelectableValue { First, Second, Third, Fourth } enum SelectableValue { First, Second, Third, Fourth }
SelectableValue selectValue = SelectableValue.Second; SelectableValue selectValue = SelectableValue.Second;

View File

@ -0,0 +1,48 @@
<h3 class="interactive">Component With Parameters</h3>
<ul class="Param1">
@foreach (var value in Param1)
{
<li>@value.StringProperty @value.IntProperty</li>
}
</ul>
@* Making sure polymorphism works *@
<div class="Param2">@DerivedParam2.StringProperty @DerivedParam2.DerivedProperty</div>
@* Making sure CaptureUnmatchedValues works *@
<ul class="Param3">
@foreach (var value in Param3.OrderBy(kvp => kvp.Key))
{
<li>@value.Key @value.Value</li>
}
</ul>
@code
{
[Parameter] public List<TestModel> Param1 { get; set; }
[Parameter] public TestModel Param2 { get; set; }
[Parameter(CaptureUnmatchedValues = true)] public IDictionary<string, object> Param3 { get; set; }
private DerivedModel DerivedParam2 => (DerivedModel)Param2;
public static List<TestModel> TestModelValues => Enumerable.Range(0, 100).Select(c => new TestModel { StringProperty = c.ToString(), IntProperty = c }).ToList();
public static DerivedModel DerivedModelValue = new DerivedModel { StringProperty = "Value", DerivedProperty = "Derived-Value" };
public class TestModel
{
public string StringProperty { get; set; }
public int IntProperty { get; set; }
}
public class DerivedModel : TestModel
{
public string DerivedProperty { get; set; }
}
}

View File

@ -0,0 +1,16 @@
<div>
<h2>Error throwing button</h2>
<p>
<button @onclick="@(IncrementCount)">Click me</button>
</p>
</div>
@code {
int currentCount = 0;
void IncrementCount()
{
currentCount++;
throw new NotImplementedException("Doing crazy things!");
}
}

View File

@ -1,7 +1,7 @@
@using System.ComponentModel.DataAnnotations @using System.ComponentModel.DataAnnotations
@using Microsoft.AspNetCore.Components.Forms @using Microsoft.AspNetCore.Components.Forms
<EditForm Model="@person" OnValidSubmit="@HandleValidSubmit"> <EditForm EditContext="@editContext" OnValidSubmit="@HandleValidSubmit">
<DataAnnotationsValidator /> <DataAnnotationsValidator />
<p class="name"> <p class="name">
@ -42,6 +42,10 @@
<p class="is-evil"> <p class="is-evil">
Is evil: <InputCheckbox @bind-Value="person.IsEvil" /> Is evil: <InputCheckbox @bind-Value="person.IsEvil" />
</p> </p>
<p class="username">
Username (optional): <InputText @bind-Value="person.Username" />
<button type="button" @onclick="@TriggerAsyncValidationError">Trigger async error</button>
</p>
<button type="submit">Submit</button> <button type="submit">Submit</button>
@ -52,6 +56,14 @@
@code { @code {
Person person = new Person(); Person person = new Person();
EditContext editContext;
ValidationMessageStore customValidationMessageStore;
protected override void OnInitialized()
{
editContext = new EditContext(person);
customValidationMessageStore = new ValidationMessageStore(editContext);
}
// Usually this would be in a different file // Usually this would be in a different file
class Person class Person
@ -83,6 +95,8 @@
[Required, EnumDataType(typeof(TicketClass))] [Required, EnumDataType(typeof(TicketClass))]
public TicketClass TicketClass { get; set; } public TicketClass TicketClass { get; set; }
public string Username { get; set; }
} }
enum TicketClass { Economy, Premium, First } enum TicketClass { Economy, Premium, First }
@ -93,4 +107,22 @@
{ {
submissionLog.Add("OnValidSubmit"); submissionLog.Add("OnValidSubmit");
} }
void TriggerAsyncValidationError()
{
customValidationMessageStore.Clear();
// Note that this method returns void, so the renderer doesn't react to
// its async flow by default. This is to simulate some external system
// implementing async validation.
Task.Run(async () =>
{
// The duration of the delay doesn't matter to the test, as long as it's not
// so long that we time out. Picking a value that's long enough for humans
// to observe the asynchrony too.
await Task.Delay(500);
customValidationMessageStore.Add(editContext.Field(nameof(Person.Username)), "This is invalid, asynchronously");
_ = InvokeAsync(editContext.NotifyValidationStateChanged);
});
}
} }

View File

@ -62,6 +62,10 @@
int: <InputNumber id="inputnumber_int" @bind-Value="inputNumberInt" /> int: <InputNumber id="inputnumber_int" @bind-Value="inputNumberInt" />
<span id="inputnumber_int_value">@inputNumberInt</span> <span id="inputnumber_int_value">@inputNumberInt</span>
</div> </div>
<div>
long: <InputNumber id="inputnumber_long" @bind-Value="inputNumberLong" />
<span id="inputnumber_long_value">@inputNumberLong</span>
</div>
<div> <div>
decimal: <InputNumber id="inputnumber_decimal" @bind-Value="inputNumberDecimal" /> decimal: <InputNumber id="inputnumber_decimal" @bind-Value="inputNumberDecimal" />
<span id="inputnumber_decimal_value">@inputNumberDecimal</span> <span id="inputnumber_decimal_value">@inputNumberDecimal</span>
@ -99,8 +103,18 @@
DateTimeOffset inputTypeDateDateTimeOffset = new DateTimeOffset(new DateTime(1985, 3, 4)); DateTimeOffset inputTypeDateDateTimeOffset = new DateTimeOffset(new DateTime(1985, 3, 4));
int inputNumberInt = 42; int inputNumberInt = 42;
long inputNumberLong = 4200;
decimal inputNumberDecimal = 4.2m; decimal inputNumberDecimal = 4.2m;
DateTime inputDateDateTime = new DateTime(1985, 3, 4); DateTime inputDateDateTime = new DateTime(1985, 3, 4);
DateTimeOffset inputDateDateTimeOffset = new DateTimeOffset(new DateTime(1985, 3, 4)); DateTimeOffset inputDateDateTimeOffset = new DateTimeOffset(new DateTime(1985, 3, 4));
DateTime inputTypeDateTimeLocalDateTime = new DateTime(1985, 3, 4);
DateTimeOffset inputTypeDateTimeLocalDateTimeOffset = new DateTimeOffset(new DateTime(1985, 3, 4));
DateTime inputTypeMonthDateTime = new DateTime(1985, 3, 4);
DateTimeOffset inputTypeMonthDateTimeOffset = new DateTimeOffset(new DateTime(1985, 3, 4));
DateTime inputTypeTimeDateTime = new DateTime(1985, 3, 4);
DateTimeOffset inputTypeTimeDateTimeOffset = new DateTimeOffset(new DateTime(1985, 3, 4));
} }

View File

@ -1,6 +1,6 @@
@using Microsoft.AspNetCore.Components.Rendering @using Microsoft.AspNetCore.Components.Rendering
<div id="test-selector"> <div id="test-selector">
Select test: Select test:
<select id="test-selector-select" @bind=SelectedComponentTypeName> <select id="test-selector-select" @bind=SelectedComponentTypeName>
<option value="none">Choose...</option> <option value="none">Choose...</option>
<option value="BasicTestApp.AddRemoveChildComponents">Add/remove child components</option> <option value="BasicTestApp.AddRemoveChildComponents">Add/remove child components</option>
@ -20,6 +20,7 @@
<option value="BasicTestApp.DispatchingComponent">Dispatching to sync context</option> <option value="BasicTestApp.DispatchingComponent">Dispatching to sync context</option>
<option value="BasicTestApp.DuplicateAttributesComponent">Duplicate attributes</option> <option value="BasicTestApp.DuplicateAttributesComponent">Duplicate attributes</option>
<option value="BasicTestApp.ElementRefComponent">Element ref component</option> <option value="BasicTestApp.ElementRefComponent">Element ref component</option>
<option value="BasicTestApp.ErrorComponent">Error throwing</option>
<option value="BasicTestApp.EventBubblingComponent">Event bubbling</option> <option value="BasicTestApp.EventBubblingComponent">Event bubbling</option>
<option value="BasicTestApp.EventCallbackTest.EventCallbackCases">EventCallback</option> <option value="BasicTestApp.EventCallbackTest.EventCallbackCases">EventCallback</option>
<option value="BasicTestApp.EventCasesComponent">Event cases</option> <option value="BasicTestApp.EventCasesComponent">Event cases</option>
@ -82,6 +83,12 @@
@((RenderFragment)RenderSelectedComponent) @((RenderFragment)RenderSelectedComponent)
</app> </app>
<div id="blazor-error-ui">
An unhandled error has occurred.
<a href class='reload'>Reload</a>
<a class='dismiss' style="cursor: pointer;">🗙</a>
</div>
@code { @code {
string SelectedComponentTypeName { get; set; } = "none"; string SelectedComponentTypeName { get; set; } = "none";

View File

@ -70,13 +70,15 @@
var shouldSupportSyncInterop = RuntimeInformation.IsOSPlatform(OSPlatform.Create("WEBASSEMBLY")); var shouldSupportSyncInterop = RuntimeInformation.IsOSPlatform(OSPlatform.Create("WEBASSEMBLY"));
var testDTOTOPassByRef = new TestDTO(nonSerializedValue: 123); var testDTOTOPassByRef = new TestDTO(nonSerializedValue: 123);
var instanceMethodsTarget = new JavaScriptInterop(); var instanceMethodsTarget = new JavaScriptInterop();
var genericType = new JavaScriptInterop.GenericType<string> { Value = "Initial value" };
Console.WriteLine("Starting interop invocations."); Console.WriteLine("Starting interop invocations.");
await JSRuntime.InvokeVoidAsync( await JSRuntime.InvokeVoidAsync(
"jsInteropTests.invokeDotNetInteropMethodsAsync", "jsInteropTests.invokeDotNetInteropMethodsAsync",
shouldSupportSyncInterop, shouldSupportSyncInterop,
DotNetObjectReference.Create(testDTOTOPassByRef), DotNetObjectReference.Create(testDTOTOPassByRef),
DotNetObjectReference.Create(instanceMethodsTarget)); DotNetObjectReference.Create(instanceMethodsTarget),
DotNetObjectReference.Create(genericType));
if (shouldSupportSyncInterop) if (shouldSupportSyncInterop)
{ {

View File

@ -462,5 +462,25 @@ namespace BasicTestApp.InteropTest
public DotNetObjectReference<TestDTO> OutgoingByRef { get; set; } public DotNetObjectReference<TestDTO> OutgoingByRef { get; set; }
} }
public class GenericType<TValue>
{
public TValue Value { get; set; }
[JSInvokable]
public TValue Update(TValue newValue)
{
var oldValue = Value;
Value = newValue;
return oldValue;
}
[JSInvokable]
public async Task<TValue> UpdateAsync(TValue newValue)
{
await Task.Yield();
return Update(newValue);
}
}
} }
} }

View File

@ -14,7 +14,7 @@
<li><NavLink href="/subdir/Default.html">With extension</NavLink></li> <li><NavLink href="/subdir/Default.html">With extension</NavLink></li>
<li><NavLink href="/subdir/Other">Other</NavLink></li> <li><NavLink href="/subdir/Other">Other</NavLink></li>
<li><NavLink href="Other" Match=NavLinkMatch.All>Other with base-relative URL (matches all)</NavLink></li> <li><NavLink href="Other" Match=NavLinkMatch.All>Other with base-relative URL (matches all)</NavLink></li>
<li><NavLink href="/subdir/Other?abc=123">Other with query</NavLink></li> <li><NavLink href="/subdir/other?abc=123">Other with query</NavLink></li>
<li><NavLink href="/subdir/Other#blah">Other with hash</NavLink></li> <li><NavLink href="/subdir/Other#blah">Other with hash</NavLink></li>
<li><NavLink href="/subdir/WithParameters/Name/Abc">With parameters</NavLink></li> <li><NavLink href="/subdir/WithParameters/Name/Abc">With parameters</NavLink></li>
<li><NavLink href="/subdir/WithParameters/Name/Abc/LastName/McDef">With more parameters</NavLink></li> <li><NavLink href="/subdir/WithParameters/Name/Abc/LastName/McDef">With more parameters</NavLink></li>

View File

@ -1,5 +1,6 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<title>Basic test app</title> <title>Basic test app</title>
@ -9,6 +10,7 @@
<!-- Used by ExternalContentPackage --> <!-- Used by ExternalContentPackage -->
<link href="_content/TestContentPackage/styles.css" rel="stylesheet" /> <link href="_content/TestContentPackage/styles.css" rel="stylesheet" />
</head> </head>
<body> <body>
<root>Loading...</root> <root>Loading...</root>
@ -31,4 +33,5 @@
<!-- Used by ExternalContentPackage --> <!-- Used by ExternalContentPackage -->
<script src="_content/TestContentPackage/prompt.js"></script> <script src="_content/TestContentPackage/prompt.js"></script>
</body> </body>
</html> </html>

View File

@ -2,7 +2,7 @@
var results = {}; var results = {};
var assemblyName = 'BasicTestApp'; var assemblyName = 'BasicTestApp';
function invokeDotNetInteropMethodsAsync(shouldSupportSyncInterop, dotNetObjectByRef, instanceMethodsTarget) { async function invokeDotNetInteropMethodsAsync(shouldSupportSyncInterop, dotNetObjectByRef, instanceMethodsTarget, genericDotNetObjectByRef) {
if (shouldSupportSyncInterop) { if (shouldSupportSyncInterop) {
console.log('Invoking void sync methods.'); console.log('Invoking void sync methods.');
DotNet.invokeMethod(assemblyName, 'VoidParameterless'); DotNet.invokeMethod(assemblyName, 'VoidParameterless');
@ -15,6 +15,7 @@ function invokeDotNetInteropMethodsAsync(shouldSupportSyncInterop, dotNetObjectB
DotNet.invokeMethod(assemblyName, 'VoidWithSevenParameters', ...createArgumentList(7, dotNetObjectByRef)); DotNet.invokeMethod(assemblyName, 'VoidWithSevenParameters', ...createArgumentList(7, dotNetObjectByRef));
DotNet.invokeMethod(assemblyName, 'VoidWithEightParameters', ...createArgumentList(8, dotNetObjectByRef)); DotNet.invokeMethod(assemblyName, 'VoidWithEightParameters', ...createArgumentList(8, dotNetObjectByRef));
console.log('Invoking returning sync methods.'); console.log('Invoking returning sync methods.');
results['result1'] = DotNet.invokeMethod(assemblyName, 'ReturnArray'); results['result1'] = DotNet.invokeMethod(assemblyName, 'ReturnArray');
results['result2'] = DotNet.invokeMethod(assemblyName, 'EchoOneParameter', ...createArgumentList(1, dotNetObjectByRef)); results['result2'] = DotNet.invokeMethod(assemblyName, 'EchoOneParameter', ...createArgumentList(1, dotNetObjectByRef));
@ -40,75 +41,73 @@ function invokeDotNetInteropMethodsAsync(shouldSupportSyncInterop, dotNetObjectB
} }
console.log('Invoking void async methods.'); console.log('Invoking void async methods.');
return DotNet.invokeMethodAsync(assemblyName, 'VoidParameterlessAsync')
.then(() => DotNet.invokeMethodAsync(assemblyName, 'VoidWithOneParameterAsync', ...createArgumentList(1, dotNetObjectByRef)))
.then(() => DotNet.invokeMethodAsync(assemblyName, 'VoidWithTwoParametersAsync', ...createArgumentList(2, dotNetObjectByRef)))
.then(() => DotNet.invokeMethodAsync(assemblyName, 'VoidWithThreeParametersAsync', ...createArgumentList(3, dotNetObjectByRef)))
.then(() => DotNet.invokeMethodAsync(assemblyName, 'VoidWithFourParametersAsync', ...createArgumentList(4, dotNetObjectByRef)))
.then(() => DotNet.invokeMethodAsync(assemblyName, 'VoidWithFiveParametersAsync', ...createArgumentList(5, dotNetObjectByRef)))
.then(() => DotNet.invokeMethodAsync(assemblyName, 'VoidWithSixParametersAsync', ...createArgumentList(6, dotNetObjectByRef)))
.then(() => DotNet.invokeMethodAsync(assemblyName, 'VoidWithSevenParametersAsync', ...createArgumentList(7, dotNetObjectByRef)))
.then(() => DotNet.invokeMethodAsync(assemblyName, 'VoidWithEightParametersAsync', ...createArgumentList(8, dotNetObjectByRef)))
.then(() => {
console.log('Invoking returning async methods.');
return DotNet.invokeMethodAsync(assemblyName, 'ReturnArrayAsync')
.then(r => results['result1Async'] = r)
.then(() => DotNet.invokeMethodAsync(assemblyName, 'EchoOneParameterAsync', ...createArgumentList(1, dotNetObjectByRef)))
.then(r => results['result2Async'] = r)
.then(() => DotNet.invokeMethodAsync(assemblyName, 'EchoTwoParametersAsync', ...createArgumentList(2, dotNetObjectByRef)))
.then(r => results['result3Async'] = r)
.then(() => DotNet.invokeMethodAsync(assemblyName, 'EchoThreeParametersAsync', ...createArgumentList(3, dotNetObjectByRef)))
.then(r => results['result4Async'] = r)
.then(() => DotNet.invokeMethodAsync(assemblyName, 'EchoFourParametersAsync', ...createArgumentList(4, dotNetObjectByRef)))
.then(r => results['result5Async'] = r)
.then(() => DotNet.invokeMethodAsync(assemblyName, 'EchoFiveParametersAsync', ...createArgumentList(5, dotNetObjectByRef)))
.then(r => results['result6Async'] = r)
.then(() => DotNet.invokeMethodAsync(assemblyName, 'EchoSixParametersAsync', ...createArgumentList(6, dotNetObjectByRef)))
.then(r => results['result7Async'] = r)
.then(() => DotNet.invokeMethodAsync(assemblyName, 'EchoSevenParametersAsync', ...createArgumentList(7, dotNetObjectByRef)))
.then(r => results['result8Async'] = r)
.then(() => DotNet.invokeMethodAsync(assemblyName, 'EchoEightParametersAsync', ...createArgumentList(8, dotNetObjectByRef)))
.then(r => results['result9Async'] = r)
.then(() => DotNet.invokeMethodAsync(assemblyName, 'ReturnDotNetObjectByRefAsync'))
.then(r => DotNet.invokeMethodAsync(assemblyName, 'ExtractNonSerializedValue', r['Some async instance']))
.then(r => {
results['resultReturnDotNetObjectByRefAsync'] = r;
})
.then(() => instanceMethodsTarget.invokeMethodAsync('InstanceMethodAsync', {
stringValue: 'My string',
dtoByRef: dotNetObjectByRef
}))
.then(r => {
results['instanceMethodThisTypeNameAsync'] = r.thisTypeName;
results['instanceMethodStringValueUpperAsync'] = r.stringValueUpper;
results['instanceMethodIncomingByRefAsync'] = r.incomingByRef;
return DotNet.invokeMethodAsync(assemblyName, 'ExtractNonSerializedValue', r.outgoingByRef);
}).then(r => {
results['instanceMethodOutgoingByRefAsync'] = r;
})
})
.then(() => {
console.log('Invoking methods that throw exceptions');
try {
shouldSupportSyncInterop && DotNet.invokeMethod(assemblyName, 'ThrowException');
} catch (e) {
results['ThrowException'] = e.message;
}
return DotNet.invokeMethodAsync(assemblyName, 'AsyncThrowSyncException') await DotNet.invokeMethodAsync(assemblyName, 'VoidParameterlessAsync');
.catch(e => { await DotNet.invokeMethodAsync(assemblyName, 'VoidWithOneParameterAsync', ...createArgumentList(1, dotNetObjectByRef));
results['AsyncThrowSyncException'] = e.message; await DotNet.invokeMethodAsync(assemblyName, 'VoidWithTwoParametersAsync', ...createArgumentList(2, dotNetObjectByRef));
await DotNet.invokeMethodAsync(assemblyName, 'VoidWithThreeParametersAsync', ...createArgumentList(3, dotNetObjectByRef));
await DotNet.invokeMethodAsync(assemblyName, 'VoidWithFourParametersAsync', ...createArgumentList(4, dotNetObjectByRef));
await DotNet.invokeMethodAsync(assemblyName, 'VoidWithFiveParametersAsync', ...createArgumentList(5, dotNetObjectByRef));
await DotNet.invokeMethodAsync(assemblyName, 'VoidWithSixParametersAsync', ...createArgumentList(6, dotNetObjectByRef));
await DotNet.invokeMethodAsync(assemblyName, 'VoidWithSevenParametersAsync', ...createArgumentList(7, dotNetObjectByRef));
await DotNet.invokeMethodAsync(assemblyName, 'VoidWithEightParametersAsync', ...createArgumentList(8, dotNetObjectByRef));
return DotNet.invokeMethodAsync(assemblyName, 'AsyncThrowAsyncException'); console.log('Invoking returning async methods.');
}).catch(e => { results['result1Async'] = await DotNet.invokeMethodAsync(assemblyName, 'ReturnArrayAsync');
results['AsyncThrowAsyncException'] = e.message; results['result2Async'] = await DotNet.invokeMethodAsync(assemblyName, 'EchoOneParameterAsync', ...createArgumentList(1, dotNetObjectByRef));
results['result3Async'] = await DotNet.invokeMethodAsync(assemblyName, 'EchoTwoParametersAsync', ...createArgumentList(2, dotNetObjectByRef));
results['result4Async'] = await DotNet.invokeMethodAsync(assemblyName, 'EchoThreeParametersAsync', ...createArgumentList(3, dotNetObjectByRef));
results['result5Async'] = await DotNet.invokeMethodAsync(assemblyName, 'EchoFourParametersAsync', ...createArgumentList(4, dotNetObjectByRef));
results['result6Async'] = await DotNet.invokeMethodAsync(assemblyName, 'EchoFiveParametersAsync', ...createArgumentList(5, dotNetObjectByRef));
results['result7Async'] = await DotNet.invokeMethodAsync(assemblyName, 'EchoSixParametersAsync', ...createArgumentList(6, dotNetObjectByRef));
results['result8Async'] = await DotNet.invokeMethodAsync(assemblyName, 'EchoSevenParametersAsync', ...createArgumentList(7, dotNetObjectByRef));
results['result9Async'] = await DotNet.invokeMethodAsync(assemblyName, 'EchoEightParametersAsync', ...createArgumentList(8, dotNetObjectByRef));
console.log('Done invoking interop methods'); const returnDotNetObjectByRefAsync = await DotNet.invokeMethodAsync(assemblyName, 'ReturnDotNetObjectByRefAsync');
}); results['resultReturnDotNetObjectByRefAsync'] = await DotNet.invokeMethodAsync(assemblyName, 'ExtractNonSerializedValue', returnDotNetObjectByRefAsync['Some async instance']);
});
const instanceMethodAsync = await instanceMethodsTarget.invokeMethodAsync('InstanceMethodAsync', {
stringValue: 'My string',
dtoByRef: dotNetObjectByRef
});
results['instanceMethodThisTypeNameAsync'] = instanceMethodAsync.thisTypeName;
results['instanceMethodStringValueUpperAsync'] = instanceMethodAsync.stringValueUpper;
results['instanceMethodIncomingByRefAsync'] = instanceMethodAsync.incomingByRef;
results['instanceMethodOutgoingByRefAsync'] = await DotNet.invokeMethodAsync(assemblyName, 'ExtractNonSerializedValue', instanceMethodAsync.outgoingByRef);
console.log('Invoking generic type instance methods.');
results['syncGenericInstanceMethod'] = await genericDotNetObjectByRef.invokeMethodAsync('Update', 'Updated value 1');
results['asyncGenericInstanceMethod'] = await genericDotNetObjectByRef.invokeMethodAsync('UpdateAsync', 'Updated value 2');
if (shouldSupportSyncInterop) {
results['genericInstanceMethod'] = genericDotNetObjectByRef.invokeMethod('Update', 'Updated Value 3');
}
console.log('Invoking methods that throw exceptions');
try {
shouldSupportSyncInterop && DotNet.invokeMethod(assemblyName, 'ThrowException');
} catch (e) {
results['ThrowException'] = e.message;
}
try {
await DotNet.invokeMethodAsync(assemblyName, 'AsyncThrowSyncException');
} catch (e) {
results['AsyncThrowSyncException'] = e.message;
}
try {
await DotNet.invokeMethodAsync(assemblyName, 'AsyncThrowAsyncException');
} catch (e) {
results['AsyncThrowAsyncException'] = e.message;
}
console.log('Done invoking interop methods');
} }
function createArgumentList(argumentNumber, dotNetObjectByRef){ function createArgumentList(argumentNumber, dotNetObjectByRef) {
const array = new Array(argumentNumber); const array = new Array(argumentNumber);
if (argumentNumber === 0) { if (argumentNumber === 0) {
return []; return [];
@ -149,7 +148,7 @@ function createArgumentList(argumentNumber, dotNetObjectByRef){
source: `Some random text with at least ${i} characters`, source: `Some random text with at least ${i} characters`,
start: argumentNumber + 1, start: argumentNumber + 1,
length: argumentNumber + 1 length: argumentNumber + 1
} };
break; break;
default: default:
console.log(i); console.log(i);
@ -169,7 +168,7 @@ window.jsInteropTests = {
returnPrimitive: returnPrimitive, returnPrimitive: returnPrimitive,
returnPrimitiveAsync: returnPrimitiveAsync, returnPrimitiveAsync: returnPrimitiveAsync,
receiveDotNetObjectByRef: receiveDotNetObjectByRef, receiveDotNetObjectByRef: receiveDotNetObjectByRef,
receiveDotNetObjectByRefAsync: receiveDotNetObjectByRefAsync, receiveDotNetObjectByRefAsync: receiveDotNetObjectByRefAsync
}; };
function returnPrimitive() { function returnPrimitive() {
@ -211,9 +210,9 @@ function asyncFunctionThrowsAsyncException() {
} }
function asyncFunctionTakesLongerThanDefaultTimeoutToResolve() { function asyncFunctionTakesLongerThanDefaultTimeoutToResolve() {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
setTimeout(() => resolve(undefined), 5000); setTimeout(() => resolve(undefined), 5000);
}); });
} }
function collectInteropResults() { function collectInteropResults() {

View File

@ -6,6 +6,14 @@
outline: 1px solid red; outline: 1px solid red;
} }
#blazor-error-ui {
display: none;
}
#blazor-error-ui dismiss {
cursor: pointer;
}
.validation-message { .validation-message {
color: red; color: red;
} }

View File

@ -12,7 +12,7 @@
<link href="css/site.css" rel="stylesheet" /> <link href="css/site.css" rel="stylesheet" />
</head> </head>
<body> <body>
<app>@(await Html.RenderComponentAsync<App>(RenderMode.Server))</app> <component type="typeof(App)" render-mode="Server" />
<script src="_framework/blazor.server.js" autostart="false"></script> <script src="_framework/blazor.server.js" autostart="false"></script>
<script> <script>
Blazor.start({ Blazor.start({

View File

@ -0,0 +1,51 @@
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
namespace TestServer
{
public class MultipleComponents
{
public MultipleComponents(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddServerSideBlazor();
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.Map("/multiple-components", app =>
{
app.UseStaticFiles();
app.UseAuthentication();
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
endpoints.MapFallbackToPage("/MultipleComponents");
endpoints.MapBlazorHub();
});
});
}
}
}

View File

@ -0,0 +1,37 @@
@page
<component type="typeof(ComponentWithParameters)"
render-mode="ServerPrerendered"
param-Param1="ComponentWithParameters.TestModelValues"
param-Param2="ComponentWithParameters.DerivedModelValue"
param-key1="QueryValue"
param-key2="43" />
@*
So that E2E tests can make assertions about both the prerendered and
interactive states, we only load the .js file when told to.
*@
<hr />
<button id="load-boot-script" onclick="start()">Load boot script</button>
<script src="_framework/blazor.server.js" autostart="false"></script>
<script>
// Used by InteropOnInitializationComponent
function setElementValue(element, newValue) {
element.value = newValue;
return element.value;
}
function start() {
Blazor.start({
logLevel: 1 // LogLevel.Debug
});
}
</script>
@functions
{
[BindProperty(SupportsGet = true)]
public string QueryValue { get; set; }
}

View File

@ -1,59 +1,29 @@
@page "/multiple-components" @page "/multiple-components"
@using BasicTestApp.MultipleComponents; @using BasicTestApp.MultipleComponents;
<!DOCTYPE html>
<html> @{
<head> Layout = "./MultipleComponentsLayout.cshtml";
<title>Multiple component entry points</title> }
<base href="~/" />
@* This page is used to validate the ability to render multiple root components in a blazor server-side application.
*@ @(await Html.RenderComponentAsync<GreeterComponent>(RenderMode.ServerPrerendered))
</head> @(await Html.RenderComponentAsync<GreeterComponent>(RenderMode.Server))
<body> <component type="typeof(GreeterComponent)" render-mode="Static" param-name='"John"' />
<div id="test-container"> <component type="typeof(GreeterComponent)" render-mode="Server" />
@(await Html.RenderComponentAsync<GreeterComponent>(RenderMode.ServerPrerendered)) <div id="container">
@(await Html.RenderComponentAsync<GreeterComponent>(RenderMode.Server)) <p>Some content before</p>
@(await Html.RenderComponentAsync<GreeterComponent>(RenderMode.Static, new { Name = "John" })) <component type="typeof(GreeterComponent)" render-mode="Server" />
@(await Html.RenderComponentAsync<GreeterComponent>(RenderMode.Server)) <p>Some content between</p>
<div id="container"> <component type="typeof(GreeterComponent)" render-mode="ServerPrerendered" />
<p>Some content before</p> <p>Some content after</p>
@(await Html.RenderComponentAsync<GreeterComponent>(RenderMode.Server)) <div id="nested-an-extra-level">
<p>Some content between</p> <p>Some content before</p>
@(await Html.RenderComponentAsync<GreeterComponent>(RenderMode.ServerPrerendered)) <component type="typeof(GreeterComponent)" render-mode="Server" />
<p>Some content after</p> <component type="typeof(GreeterComponent)" render-mode="ServerPrerendered" />
<div id="nested-an-extra-level"> <p>Some content after</p>
<p>Some content before</p>
@(await Html.RenderComponentAsync<GreeterComponent>(RenderMode.Server))
@(await Html.RenderComponentAsync<GreeterComponent>(RenderMode.ServerPrerendered))
<p>Some content after</p>
</div>
</div>
<div id="container">
@(await Html.RenderComponentAsync<GreeterComponent>(RenderMode.Server, new { Name = "Albert" }))
@(await Html.RenderComponentAsync<GreeterComponent>(RenderMode.ServerPrerendered, new { Name = "Abraham" }))
</div>
</div> </div>
</div>
@* <div id="container">
So that E2E tests can make assertions about both the prerendered and <component type="typeof(GreeterComponent)" render-mode="Server" param-name='"Albert"' />
interactive states, we only load the .js file when told to. <component type="typeof(GreeterComponent)" render-mode="ServerPrerendered" param-name='"Abraham"' />
*@ </div>
<hr />
<button id="load-boot-script" onclick="start()">Load boot script</button>
<script src="_framework/blazor.server.js" autostart="false"></script>
<script>
// Used by InteropOnInitializationComponent
function setElementValue(element, newValue) {
element.value = newValue;
return element.value;
}
function start() {
Blazor.start({
logLevel: 1 // LogLevel.Debug
});
}
</script>
</body>
</html>

View File

@ -0,0 +1,43 @@
@using BasicTestApp.MultipleComponents;
<!DOCTYPE html>
<html>
<head>
<title>Multiple component entry points</title>
<base href="~/" />
@* This page is used to validate the ability to render multiple root components in a blazor server-side application.
*@
</head>
<body>
<div id="test-container">
<component type="typeof(GreeterComponent)" render-mode="Server" param-name='"Red fish"' />
<component type="typeof(GreeterComponent)" render-mode="ServerPrerendered" param-name='"Blue fish"' />
@RenderBody()
<component type="typeof(GreeterComponent)" render-mode="Server" param-name='"Red fish"' />
<component type="typeof(GreeterComponent)" render-mode="ServerPrerendered" param-name='"Blue fish"' />
</div>
@*
So that E2E tests can make assertions about both the prerendered and
interactive states, we only load the .js file when told to.
*@
<hr />
<button id="load-boot-script" onclick="start()">Load boot script</button>
<script src="_framework/blazor.server.js" autostart="false"></script>
<script>
// Used by InteropOnInitializationComponent
function setElementValue(element, newValue) {
element.value = newValue;
return element.value;
}
function start() {
Blazor.start({
logLevel: 1 // LogLevel.Debug
});
}
</script>
</body>
</html>

View File

@ -1,5 +1,6 @@
@page @page
@using BasicTestApp.RouterTest @using BasicTestApp.RouterTest
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
@ -7,7 +8,7 @@
<base href="~/" /> <base href="~/" />
</head> </head>
<body> <body>
<app>@(await Html.RenderComponentAsync<TestRouter>(RenderMode.ServerPrerendered))</app> <app><component type="typeof(TestRouter)" render-mode="ServerPrerendered" /></app>
@* @*
So that E2E tests can make assertions about both the prerendered and So that E2E tests can make assertions about both the prerendered and

View File

@ -1,4 +1,5 @@
@page "" @page ""
@addTagHelper "*, Microsoft.AspNetCore.Mvc.TagHelpers"
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
@ -11,7 +12,7 @@
<link href="_content/TestContentPackage/styles.css" rel="stylesheet" /> <link href="_content/TestContentPackage/styles.css" rel="stylesheet" />
</head> </head>
<body> <body>
<root>@(await Html.RenderComponentAsync<BasicTestApp.Index>(RenderMode.Server))</root> <root><component type="typeof(BasicTestApp.Index)" render-mode="Server" /></root>
<!-- Used for testing interop scenarios between JS and .NET --> <!-- Used for testing interop scenarios between JS and .NET -->
<script src="js/jsinteroptests.js"></script> <script src="js/jsinteroptests.js"></script>

View File

@ -0,0 +1,3 @@
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@using BasicTestApp

View File

@ -1,15 +1,10 @@
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Hosting.Server; using Microsoft.AspNetCore.Hosting.Server;
using Microsoft.AspNetCore.Hosting.Server.Features; using Microsoft.AspNetCore.Hosting.Server.Features;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
@ -28,6 +23,7 @@ namespace TestServer
["Server authentication"] = (BuildWebHost<ServerAuthenticationStartup>(CreateAdditionalArgs(args)), "/subdir"), ["Server authentication"] = (BuildWebHost<ServerAuthenticationStartup>(CreateAdditionalArgs(args)), "/subdir"),
["CORS (WASM)"] = (BuildWebHost<CorsStartup>(CreateAdditionalArgs(args)), "/subdir"), ["CORS (WASM)"] = (BuildWebHost<CorsStartup>(CreateAdditionalArgs(args)), "/subdir"),
["Prerendering (Server-side)"] = (BuildWebHost<PrerenderedStartup>(CreateAdditionalArgs(args)), "/prerendered"), ["Prerendering (Server-side)"] = (BuildWebHost<PrerenderedStartup>(CreateAdditionalArgs(args)), "/prerendered"),
["Multiple components (Server-side)"] = (BuildWebHost<MultipleComponents>(CreateAdditionalArgs(args)), "/multiple-components"),
["Globalization + Localization (Server-side)"] = (BuildWebHost<InternationalizationStartup>(CreateAdditionalArgs(args)), "/subdir"), ["Globalization + Localization (Server-side)"] = (BuildWebHost<InternationalizationStartup>(CreateAdditionalArgs(args)), "/subdir"),
["Server-side blazor"] = (BuildWebHost<ServerStartup>(CreateAdditionalArgs(args)), "/subdir"), ["Server-side blazor"] = (BuildWebHost<ServerStartup>(CreateAdditionalArgs(args)), "/subdir"),
["Hosted client-side blazor"] = (BuildWebHost<ClientStartup>(CreateAdditionalArgs(args)), "/subdir"), ["Hosted client-side blazor"] = (BuildWebHost<ClientStartup>(CreateAdditionalArgs(args)), "/subdir"),

View File

@ -38,10 +38,17 @@ This package is an internal implementation of the .NET Core SDK and is not meant
<!-- Reference implementation assemblies in addition to ref assemblies to get xml docs --> <!-- Reference implementation assemblies in addition to ref assemblies to get xml docs -->
<ReferenceImplementationAssemblies>true</ReferenceImplementationAssemblies> <ReferenceImplementationAssemblies>true</ReferenceImplementationAssemblies>
<!-- We are ignoring MSB3243 warnings since implemenation and reference assemblies are versioned differently. We need both to compose the targeting pack with reference assemblies and xml docs. -->
<MSBuildWarningsAsMessages>MSB3243</MSBuildWarningsAsMessages >
<!-- Platform manifest data --> <!-- Platform manifest data -->
<FrameworkListFileName>FrameworkList.xml</FrameworkListFileName> <FrameworkListFileName>FrameworkList.xml</FrameworkListFileName>
<FrameworkListOutputPath>$(ArtifactsObjDir)$(FrameworkListFileName)</FrameworkListOutputPath> <FrameworkListOutputPath>$(ArtifactsObjDir)$(FrameworkListFileName)</FrameworkListOutputPath>
<!-- Platform manifest and package override metatdata -->
<ReferencePackSharedFxVersion>$(AspNetCoreMajorVersion).$(AspNetCoreMinorVersion).0</ReferencePackSharedFxVersion>
<ReferencePackSharedFxVersion Condition="'$(VersionSuffix)' != ''">$(ReferencePackSharedFxVersion)-$(VersionSuffix)</ReferencePackSharedFxVersion>
<ReferencePlatformManifestOutputPath>$(ArtifactsObjDir)ref\PlatformManifest.txt</ReferencePlatformManifestOutputPath>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
@ -80,7 +87,7 @@ This package is an internal implementation of the .NET Core SDK and is not meant
</BuildDependsOn> </BuildDependsOn>
<!-- No-op when in source build --> <!-- No-op when in source build -->
<BuildDependsOn Condition="'$(IsTargetingPackBuilding)' != 'false' and '$(DotNetBuildFromSource)' == 'true'"/> <BuildDependsOn Condition="'$(IsTargetingPackBuilding)' == 'false'"/>
</PropertyGroup> </PropertyGroup>
<!-- Override the default MSBuild targets so that nothing is returned from the project since it represents a collection of assemblies. --> <!-- Override the default MSBuild targets so that nothing is returned from the project since it represents a collection of assemblies. -->
@ -95,6 +102,7 @@ This package is an internal implementation of the .NET Core SDK and is not meant
<!-- This target finds the reference assemblies. --> <!-- This target finds the reference assemblies. -->
<Target Name="_ResolveTargetingPackContent" <Target Name="_ResolveTargetingPackContent"
Returns="@(AspNetCoreReferenceAssemblyPath)"
BeforeTargets="_GetPackageFiles" BeforeTargets="_GetPackageFiles"
DependsOnTargets="ResolveReferences;FindReferenceAssembliesForReferences"> DependsOnTargets="ResolveReferences;FindReferenceAssembliesForReferences">
<ItemGroup> <ItemGroup>
@ -111,6 +119,7 @@ This package is an internal implementation of the .NET Core SDK and is not meant
Exclude=" Exclude="
@(_SelectedExtensionsRefAssemblies); @(_SelectedExtensionsRefAssemblies);
@(ReferencePathWithRefAssemblies->WithMetadataValue('NuGetPackageId', 'Microsoft.NETCore.App.Ref')); @(ReferencePathWithRefAssemblies->WithMetadataValue('NuGetPackageId', 'Microsoft.NETCore.App.Ref'));
@(ReferencePathWithRefAssemblies->WithMetadataValue('IsReferenceAssembly', 'false'));
@(ReferencePathWithRefAssemblies->WithMetadataValue('ReferenceGrouping', 'Microsoft.NETCore.App'));" /> @(ReferencePathWithRefAssemblies->WithMetadataValue('ReferenceGrouping', 'Microsoft.NETCore.App'));" />
<AspNetCoreReferenceAssemblyPath <AspNetCoreReferenceAssemblyPath
@ -118,11 +127,23 @@ This package is an internal implementation of the .NET Core SDK and is not meant
<AspNetCoreReferenceDocXml Include="@(_ResolvedProjectReferencePaths->WithMetadataValue('IsReferenceAssembly', 'false')->'%(RootDir)%(Directory)%(FileName).xml')" /> <AspNetCoreReferenceDocXml Include="@(_ResolvedProjectReferencePaths->WithMetadataValue('IsReferenceAssembly', 'false')->'%(RootDir)%(Directory)%(FileName).xml')" />
<AspNetCoreReferenceDocXml Include="@(_SelectedExtensionsRefAssemblies->'$(MicrosoftInternalExtensionsRefsPath)%(FileName).xml')" /> <AspNetCoreReferenceDocXml Include="@(_SelectedExtensionsRefAssemblies->'$(MicrosoftInternalExtensionsRefsPath)%(FileName).xml')" />
</ItemGroup>
<RepoTasks.GenerateSharedFrameworkDepsFile
DepsFilePath="$(ProjectDepsFilePath)"
TargetFramework="$(TargetFramework)"
FrameworkName="$(TargetingPackName)"
FrameworkVersion="$(ReferencePackSharedFxVersion)"
References="@(AspNetCoreReferenceAssemblyPath)"
RuntimeIdentifier="$(TargetRuntimeIdentifier)"
RuntimePackageName="$(PackageId)"
PlatformManifestOutputPath="$(ReferencePlatformManifestOutputPath)" />
<ItemGroup>
<RefPackContent Include="@(AspNetCoreReferenceAssemblyPath)" PackagePath="$(RefAssemblyPackagePath)" /> <RefPackContent Include="@(AspNetCoreReferenceAssemblyPath)" PackagePath="$(RefAssemblyPackagePath)" />
<RefPackContent Include="@(AspNetCoreReferenceDocXml)" PackagePath="$(RefAssemblyPackagePath)" /> <RefPackContent Include="@(AspNetCoreReferenceDocXml)" PackagePath="$(RefAssemblyPackagePath)" />
<RefPackContent Include="$(TargetDir)$(PackageConflictManifestFileName)" PackagePath="$(ManifestsPackagePath)" /> <RefPackContent Include="$(TargetDir)$(PackageConflictManifestFileName)" PackagePath="$(ManifestsPackagePath)" />
<RefPackContent Include="$(PlatformManifestOutputPath)" PackagePath="$(ManifestsPackagePath)" /> <RefPackContent Include="$(ReferencePlatformManifestOutputPath)" PackagePath="$(ManifestsPackagePath)" />
</ItemGroup> </ItemGroup>
</Target> </Target>
@ -130,9 +151,10 @@ This package is an internal implementation of the .NET Core SDK and is not meant
DependsOnTargets="ResolveReferences" DependsOnTargets="ResolveReferences"
Inputs="$(MSBuildAllProjects)" Inputs="$(MSBuildAllProjects)"
Outputs="$(TargetDir)$(PackageConflictManifestFileName)"> Outputs="$(TargetDir)$(PackageConflictManifestFileName)">
<ItemGroup> <ItemGroup>
<_AspNetCoreAppPackageOverrides Include="@(ReferencePath->'%(NuGetPackageId)|%(NuGetPackageVersion)')" Condition=" '%(ReferencePath.NuGetPackageId)' != 'Microsoft.NETCore.App' AND '%(ReferencePath.NuGetSourceType)' == 'Package' " /> <_AspNetCoreAppPackageOverrides Include="@(ReferencePath->'%(NuGetPackageId)|%(NuGetPackageVersion)')" Condition=" '%(ReferencePath.NuGetPackageId)' != 'Microsoft.NETCore.App' AND '%(ReferencePath.NuGetSourceType)' == 'Package' " />
<_AspNetCoreAppPackageOverrides Include="@(ReferencePath->'%(FileName)|$(SharedFxVersion)')" Condition=" '%(ReferencePath.ReferenceSourceTarget)' == 'ProjectReference' " /> <_AspNetCoreAppPackageOverrides Include="@(ReferencePath->'%(FileName)|$(ReferencePackSharedFxVersion)')" Condition=" '%(ReferencePath.ReferenceSourceTarget)' == 'ProjectReference' AND '%(ReferencePath.IsReferenceAssembly)' == 'true' " />
</ItemGroup> </ItemGroup>
<WriteLinesToFile <WriteLinesToFile

View File

@ -53,6 +53,13 @@
</ItemGroup> </ItemGroup>
<Target Name="GenerateTestData" BeforeTargets="GetAssemblyAttributes" DependsOnTargets="InitializeSourceControlInformation"> <Target Name="GenerateTestData" BeforeTargets="GetAssemblyAttributes" DependsOnTargets="InitializeSourceControlInformation">
<!-- Use the ref pack logic to compute the list of expected targeting pack content -->
<MSBuild Projects="$(RepoRoot)src\Framework\ref\Microsoft.AspNetCore.App.Ref.csproj"
Targets="_ResolveTargetingPackContent"
SkipNonexistentProjects="false">
<Output TaskParameter="TargetOutputs" ItemName="_TargetingPackDependencies" />
</MSBuild>
<!-- This target is defined in eng/targets/Packaging.targets and included in every C# and F# project. --> <!-- This target is defined in eng/targets/Packaging.targets and included in every C# and F# project. -->
<MSBuild Projects="$(RepoRoot)src\Framework\src\Microsoft.AspNetCore.App.Runtime.csproj" <MSBuild Projects="$(RepoRoot)src\Framework\src\Microsoft.AspNetCore.App.Runtime.csproj"
Targets="_GetPackageVersionInfo" Targets="_GetPackageVersionInfo"
@ -68,6 +75,11 @@
</MSBuild> </MSBuild>
<ItemGroup> <ItemGroup>
<AssemblyAttribute Include="Microsoft.AspNetCore.TestData">
<_Parameter1>TargetingPackDependencies</_Parameter1>
<_Parameter2>@(_TargetingPackDependencies)</_Parameter2>
</AssemblyAttribute>
<AssemblyAttribute Include="Microsoft.AspNetCore.TestData"> <AssemblyAttribute Include="Microsoft.AspNetCore.TestData">
<_Parameter1>RepositoryCommit</_Parameter1> <_Parameter1>RepositoryCommit</_Parameter1>
<_Parameter2>$(SourceRevisionId)</_Parameter2> <_Parameter2>$(SourceRevisionId)</_Parameter2>

View File

@ -59,8 +59,15 @@ namespace Microsoft.AspNetCore
public void PlatformManifestListsAllFiles() public void PlatformManifestListsAllFiles()
{ {
var platformManifestPath = Path.Combine(_targetingPackRoot, "data", "PlatformManifest.txt"); var platformManifestPath = Path.Combine(_targetingPackRoot, "data", "PlatformManifest.txt");
var expectedAssemblies = TestData.GetSharedFxDependencies() var expectedAssemblies = TestData.GetTargetingPackDependencies()
.Split(';', StringSplitOptions.RemoveEmptyEntries) .Split(';', StringSplitOptions.RemoveEmptyEntries)
.Select(i =>
{
var fileName = Path.GetFileName(i);
return fileName.EndsWith(".dll", StringComparison.Ordinal)
? fileName.Substring(0, fileName.Length - 4)
: fileName;
})
.ToHashSet(); .ToHashSet();
_output.WriteLine("==== file contents ===="); _output.WriteLine("==== file contents ====");

View File

@ -18,6 +18,8 @@ namespace Microsoft.AspNetCore
public static string GetSharedFxDependencies() => GetTestDataValue("SharedFxDependencies"); public static string GetSharedFxDependencies() => GetTestDataValue("SharedFxDependencies");
public static string GetTargetingPackDependencies() => GetTestDataValue("TargetingPackDependencies");
public static string GetTestDataValue(string key) public static string GetTestDataValue(string key)
=> typeof(TestData).Assembly.GetCustomAttributes<TestDataAttribute>().Single(d => d.Key == key).Value; => typeof(TestData).Assembly.GetCustomAttributes<TestDataAttribute>().Single(d => d.Key == key).Value;
} }

View File

@ -46,7 +46,7 @@ namespace Microsoft.AspNetCore.Hosting.StaticWebAssets
} }
else else
{ {
return InnerProvider.GetDirectoryContents(physicalPath); return InnerProvider.GetDirectoryContents(physicalPath.Value);
} }
} }
@ -59,7 +59,7 @@ namespace Microsoft.AspNetCore.Hosting.StaticWebAssets
} }
else else
{ {
return InnerProvider.GetFileInfo(physicalPath); return InnerProvider.GetFileInfo(physicalPath.Value);
} }
} }

View File

@ -9,6 +9,7 @@
<Compile Include="$(SharedSourceRoot)EventSource.Testing\TestEventListener.cs" /> <Compile Include="$(SharedSourceRoot)EventSource.Testing\TestEventListener.cs" />
<Compile Include="$(SharedSourceRoot)EventSource.Testing\TestCounterListener.cs" /> <Compile Include="$(SharedSourceRoot)EventSource.Testing\TestCounterListener.cs" />
<Content Include="testroot\**\*" CopyToOutputDirectory="PreserveNewest" CopyToPublishDirectory="PreserveNewest" /> <Content Include="testroot\**\*" CopyToOutputDirectory="PreserveNewest" CopyToPublishDirectory="PreserveNewest" />
<None Remove="testroot\wwwroot\Static Web Assets.txt" />
<Content Include="Microsoft.AspNetCore.Hosting.StaticWebAssets.xml" CopyToOutputDirectory="PreserveNewest" /> <Content Include="Microsoft.AspNetCore.Hosting.StaticWebAssets.xml" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup> </ItemGroup>

View File

@ -37,6 +37,17 @@ namespace Microsoft.AspNetCore.Hosting.StaticWebAssets
Assert.Equal("/_content", provider.BasePath); Assert.Equal("/_content", provider.BasePath);
} }
[Fact]
public void StaticWebAssetsFileProvider_FindsFileWithSpaces()
{
// Arrange & Act
var provider = new StaticWebAssetsFileProvider("/_content",
Path.Combine(AppContext.BaseDirectory, "testroot", "wwwroot"));
// Assert
Assert.True(provider.GetFileInfo("/_content/Static Web Assets.txt").Exists);
}
[Fact] [Fact]
public void GetFileInfo_DoesNotMatch_IncompletePrefixSegments() public void GetFileInfo_DoesNotMatch_IncompletePrefixSegments()
{ {

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