Merge branch 'release/5.0' into prkrishn/nullability-feedback
This commit is contained in:
commit
87a51a358a
|
|
@ -28,7 +28,7 @@ jobs:
|
|||
# Test this script using changes in a fork
|
||||
repository: 'dotnet/runtime'
|
||||
path: runtime
|
||||
ref: release/5.0-rc1
|
||||
ref: release/5.0
|
||||
- name: Copy
|
||||
shell: cmd
|
||||
working-directory: .\runtime\src\libraries\Common\src\System\Net\Http\aspnetcore\
|
||||
|
|
|
|||
257
AspNetCore.sln
257
AspNetCore.sln
|
|
@ -1397,14 +1397,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sockets.BindTests", "src\Se
|
|||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "http2cat", "src\Servers\Kestrel\samples\http2cat\http2cat.csproj", "{8BDEC645-73BD-453B-8A5C-D616BC4EA08D}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "QuicSampleApp", "src\Servers\Kestrel\samples\QuicSampleApp\QuicSampleApp.csproj", "{CBCD6AC2-72D3-4E82-9E78-12E3A9C68E1D}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Transport.Quic", "Transport.Quic", "{EE9D0952-6060-4723-B329-94A2950A6762}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Server.Kestrel.Transport.Experimental.Quic", "src\Servers\Kestrel\Transport.Quic\src\Microsoft.AspNetCore.Server.Kestrel.Transport.Experimental.Quic.csproj", "{132D43A2-067A-4E24-A520-45B9F14DCB8E}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "QuicSampleClient", "src\Servers\Kestrel\samples\QuicSampleClient\QuicSampleClient.csproj", "{FA8D7CA4-C33B-4409-865F-54192BAC59A4}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Http3SampleApp", "src\Servers\Kestrel\samples\Http3SampleApp\Http3SampleApp.csproj", "{2EC4E939-513F-44CD-A956-498966EAC929}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HttpStress", "src\Servers\Kestrel\stress\HttpStress.csproj", "{987E1C29-F124-40C8-8E6F-1B2B6A4CB62A}"
|
||||
|
|
@ -1423,13 +1419,13 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Compon
|
|||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Sdk", "Sdk", "{FED4267E-E5E4-49C5-98DB-8B3F203596EE}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.NET.Sdk.BlazorWebAssembly", "src\Components\WebAssembly\Sdk\src\Microsoft.NET.Sdk.BlazorWebAssembly.csproj", "{6B2734BF-C61D-4889-ABBF-456A4075D59B}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.NET.Sdk.BlazorWebAssembly", "src\Components\WebAssembly\Sdk\src\Microsoft.NET.Sdk.BlazorWebAssembly.csproj", "{6B2734BF-C61D-4889-ABBF-456A4075D59B}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.NET.Sdk.BlazorWebAssembly.Tests", "src\Components\WebAssembly\Sdk\test\Microsoft.NET.Sdk.BlazorWebAssembly.Tests.csproj", "{83371889-9A3E-4D16-AE77-EB4F83BC6374}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.NET.Sdk.BlazorWebAssembly.Tests", "src\Components\WebAssembly\Sdk\test\Microsoft.NET.Sdk.BlazorWebAssembly.Tests.csproj", "{83371889-9A3E-4D16-AE77-EB4F83BC6374}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.NET.Sdk.BlazorWebAssembly.IntegrationTests", "src\Components\WebAssembly\Sdk\integrationtests\Microsoft.NET.Sdk.BlazorWebAssembly.IntegrationTests.csproj", "{525EBCB4-A870-470B-BC90-845306C337D1}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.NET.Sdk.BlazorWebAssembly.IntegrationTests", "src\Components\WebAssembly\Sdk\integrationtests\Microsoft.NET.Sdk.BlazorWebAssembly.IntegrationTests.csproj", "{525EBCB4-A870-470B-BC90-845306C337D1}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.NET.Sdk.BlazorWebAssembly.Tools", "src\Components\WebAssembly\Sdk\tools\Microsoft.NET.Sdk.BlazorWebAssembly.Tools.csproj", "{175E5CD8-92D4-46BB-882E-3A930D3302D4}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.NET.Sdk.BlazorWebAssembly.Tools", "src\Components\WebAssembly\Sdk\tools\Microsoft.NET.Sdk.BlazorWebAssembly.Tools.csproj", "{175E5CD8-92D4-46BB-882E-3A930D3302D4}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "testassets", "testassets", "{6126DCE4-9692-4EE2-B240-C65743572995}"
|
||||
EndProject
|
||||
|
|
@ -1455,7 +1451,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "InteropClient", "src\Grpc\t
|
|||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "InteropWebsite", "src\Grpc\test\testassets\InteropWebsite\InteropWebsite.csproj", "{19189670-E206-471D-94F8-7D3D545E5020}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wasm.Performance.ConsoleHost", "src\Components\benchmarkapps\Wasm.Performance\ConsoleHost\Wasm.Performance.ConsoleHost.csproj", "{E9408723-E6A9-4715-B906-3B25B0238ABA}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Wasm.Performance.ConsoleHost", "src\Components\benchmarkapps\Wasm.Performance\ConsoleHost\Wasm.Performance.ConsoleHost.csproj", "{E9408723-E6A9-4715-B906-3B25B0238ABA}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "InProcessWebSite", "src\Servers\IIS\IIS\test\testassets\InProcessWebSite\InProcessWebSite.csproj", "{8DA61885-B95E-4BA1-A752-C79B6597FC44}"
|
||||
EndProject
|
||||
|
|
@ -1483,6 +1479,36 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Watch.
|
|||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Watch.BrowserRefresh.Tests", "src\Tools\dotnet-watch\BrowserRefresh\test\Microsoft.AspNetCore.Watch.BrowserRefresh.Tests.csproj", "{E6A23627-8D63-4DF1-A4F2-8881172C1FE6}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "testassets", "testassets", "{7D2B0799-A634-42AC-AE77-5D167BA51389}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HostedInAspNet.Client", "src\Components\WebAssembly\testassets\HostedInAspNet.Client\HostedInAspNet.Client.csproj", "{9788C76F-658B-4441-88F8-22C6B86FAD27}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HostedInAspNet.Server", "src\Components\WebAssembly\testassets\HostedInAspNet.Server\HostedInAspNet.Server.csproj", "{1970D5CD-D9A4-4673-A297-179BB04199F4}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "StandaloneApp", "src\Components\WebAssembly\testassets\StandaloneApp\StandaloneApp.csproj", "{A40350FE-4334-4007-B1C3-6BEB1B070309}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Wasm.Authentication.Client", "src\Components\WebAssembly\testassets\Wasm.Authentication.Client\Wasm.Authentication.Client.csproj", "{C26965A9-EAC6-4E5A-B8C1-D161260EFE4F}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Wasm.Authentication.Server", "src\Components\WebAssembly\testassets\Wasm.Authentication.Server\Wasm.Authentication.Server.csproj", "{FE5290C7-45DA-46F8-BD74-698E7A161DD6}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Wasm.Authentication.Shared", "src\Components\WebAssembly\testassets\Wasm.Authentication.Shared\Wasm.Authentication.Shared.csproj", "{ED66DC0E-FD6A-477A-BA8A-5273AA64F580}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "HealthChecks", "HealthChecks", "{C1E7F837-6988-43E2-9E1C-7302DB484F99}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{2A91479A-4ABE-4BB7-9A5E-CA3B9CCFC69E}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{7CB09412-C9B0-47E8-A8C3-311AA4CFDE04}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Abstractions", "Abstractions", "{22D7D74B-565D-4047-97B4-F149B1A13350}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions", "src\HealthChecks\Abstractions\src\Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions.csproj", "{B06040BC-DA28-4923-8CAC-20EB517D471B}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Diagnostics.HealthChecks", "src\HealthChecks\HealthChecks\src\Microsoft.Extensions.Diagnostics.HealthChecks.csproj", "{55CACC1F-FE96-47C8-8073-91F4CAA55C75}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Diagnostics.HealthChecks.Tests", "src\HealthChecks\HealthChecks\test\Microsoft.Extensions.Diagnostics.HealthChecks.Tests.csproj", "{7509AA1E-3093-4BEE-984F-E11579E98A11}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.JSInterop.Tests", "src\JSInterop\Microsoft.JSInterop\test\Microsoft.JSInterop.Tests.csproj", "{DAAB6B35-CBD2-4573-B633-CDD42F583A0E}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
|
|
@ -6653,18 +6679,6 @@ Global
|
|||
{8BDEC645-73BD-453B-8A5C-D616BC4EA08D}.Release|x64.Build.0 = Release|Any CPU
|
||||
{8BDEC645-73BD-453B-8A5C-D616BC4EA08D}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{8BDEC645-73BD-453B-8A5C-D616BC4EA08D}.Release|x86.Build.0 = Release|Any CPU
|
||||
{CBCD6AC2-72D3-4E82-9E78-12E3A9C68E1D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{CBCD6AC2-72D3-4E82-9E78-12E3A9C68E1D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{CBCD6AC2-72D3-4E82-9E78-12E3A9C68E1D}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{CBCD6AC2-72D3-4E82-9E78-12E3A9C68E1D}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{CBCD6AC2-72D3-4E82-9E78-12E3A9C68E1D}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{CBCD6AC2-72D3-4E82-9E78-12E3A9C68E1D}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{CBCD6AC2-72D3-4E82-9E78-12E3A9C68E1D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{CBCD6AC2-72D3-4E82-9E78-12E3A9C68E1D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{CBCD6AC2-72D3-4E82-9E78-12E3A9C68E1D}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{CBCD6AC2-72D3-4E82-9E78-12E3A9C68E1D}.Release|x64.Build.0 = Release|Any CPU
|
||||
{CBCD6AC2-72D3-4E82-9E78-12E3A9C68E1D}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{CBCD6AC2-72D3-4E82-9E78-12E3A9C68E1D}.Release|x86.Build.0 = Release|Any CPU
|
||||
{132D43A2-067A-4E24-A520-45B9F14DCB8E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{132D43A2-067A-4E24-A520-45B9F14DCB8E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{132D43A2-067A-4E24-A520-45B9F14DCB8E}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
|
|
@ -6677,18 +6691,6 @@ Global
|
|||
{132D43A2-067A-4E24-A520-45B9F14DCB8E}.Release|x64.Build.0 = Release|Any CPU
|
||||
{132D43A2-067A-4E24-A520-45B9F14DCB8E}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{132D43A2-067A-4E24-A520-45B9F14DCB8E}.Release|x86.Build.0 = Release|Any CPU
|
||||
{FA8D7CA4-C33B-4409-865F-54192BAC59A4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{FA8D7CA4-C33B-4409-865F-54192BAC59A4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{FA8D7CA4-C33B-4409-865F-54192BAC59A4}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{FA8D7CA4-C33B-4409-865F-54192BAC59A4}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{FA8D7CA4-C33B-4409-865F-54192BAC59A4}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{FA8D7CA4-C33B-4409-865F-54192BAC59A4}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{FA8D7CA4-C33B-4409-865F-54192BAC59A4}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{FA8D7CA4-C33B-4409-865F-54192BAC59A4}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{FA8D7CA4-C33B-4409-865F-54192BAC59A4}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{FA8D7CA4-C33B-4409-865F-54192BAC59A4}.Release|x64.Build.0 = Release|Any CPU
|
||||
{FA8D7CA4-C33B-4409-865F-54192BAC59A4}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{FA8D7CA4-C33B-4409-865F-54192BAC59A4}.Release|x86.Build.0 = Release|Any CPU
|
||||
{2EC4E939-513F-44CD-A956-498966EAC929}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{2EC4E939-513F-44CD-A956-498966EAC929}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2EC4E939-513F-44CD-A956-498966EAC929}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
|
|
@ -6809,30 +6811,6 @@ Global
|
|||
{175E5CD8-92D4-46BB-882E-3A930D3302D4}.Release|x64.Build.0 = Release|Any CPU
|
||||
{175E5CD8-92D4-46BB-882E-3A930D3302D4}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{175E5CD8-92D4-46BB-882E-3A930D3302D4}.Release|x86.Build.0 = Release|Any CPU
|
||||
{A5CE25E9-89E1-4F2C-9B89-0C161707E700}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{A5CE25E9-89E1-4F2C-9B89-0C161707E700}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A5CE25E9-89E1-4F2C-9B89-0C161707E700}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{A5CE25E9-89E1-4F2C-9B89-0C161707E700}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{A5CE25E9-89E1-4F2C-9B89-0C161707E700}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{A5CE25E9-89E1-4F2C-9B89-0C161707E700}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{A5CE25E9-89E1-4F2C-9B89-0C161707E700}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A5CE25E9-89E1-4F2C-9B89-0C161707E700}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{A5CE25E9-89E1-4F2C-9B89-0C161707E700}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{A5CE25E9-89E1-4F2C-9B89-0C161707E700}.Release|x64.Build.0 = Release|Any CPU
|
||||
{A5CE25E9-89E1-4F2C-9B89-0C161707E700}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{A5CE25E9-89E1-4F2C-9B89-0C161707E700}.Release|x86.Build.0 = Release|Any CPU
|
||||
{E6A23627-8D63-4DF1-A4F2-8881172C1FE6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E6A23627-8D63-4DF1-A4F2-8881172C1FE6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E6A23627-8D63-4DF1-A4F2-8881172C1FE6}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{E6A23627-8D63-4DF1-A4F2-8881172C1FE6}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{E6A23627-8D63-4DF1-A4F2-8881172C1FE6}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{E6A23627-8D63-4DF1-A4F2-8881172C1FE6}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{E6A23627-8D63-4DF1-A4F2-8881172C1FE6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E6A23627-8D63-4DF1-A4F2-8881172C1FE6}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{E6A23627-8D63-4DF1-A4F2-8881172C1FE6}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{E6A23627-8D63-4DF1-A4F2-8881172C1FE6}.Release|x64.Build.0 = Release|Any CPU
|
||||
{E6A23627-8D63-4DF1-A4F2-8881172C1FE6}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{E6A23627-8D63-4DF1-A4F2-8881172C1FE6}.Release|x86.Build.0 = Release|Any CPU
|
||||
{46FB7E93-1294-4068-B80A-D4864F78277A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{46FB7E93-1294-4068-B80A-D4864F78277A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{46FB7E93-1294-4068-B80A-D4864F78277A}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
|
|
@ -7071,6 +7049,150 @@ Global
|
|||
{7E268085-1046-4362-80CB-2977FF826DCA}.Release|x64.Build.0 = Release|Any CPU
|
||||
{7E268085-1046-4362-80CB-2977FF826DCA}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{7E268085-1046-4362-80CB-2977FF826DCA}.Release|x86.Build.0 = Release|Any CPU
|
||||
{A5CE25E9-89E1-4F2C-9B89-0C161707E700}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{A5CE25E9-89E1-4F2C-9B89-0C161707E700}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A5CE25E9-89E1-4F2C-9B89-0C161707E700}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{A5CE25E9-89E1-4F2C-9B89-0C161707E700}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{A5CE25E9-89E1-4F2C-9B89-0C161707E700}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{A5CE25E9-89E1-4F2C-9B89-0C161707E700}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{A5CE25E9-89E1-4F2C-9B89-0C161707E700}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A5CE25E9-89E1-4F2C-9B89-0C161707E700}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{A5CE25E9-89E1-4F2C-9B89-0C161707E700}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{A5CE25E9-89E1-4F2C-9B89-0C161707E700}.Release|x64.Build.0 = Release|Any CPU
|
||||
{A5CE25E9-89E1-4F2C-9B89-0C161707E700}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{A5CE25E9-89E1-4F2C-9B89-0C161707E700}.Release|x86.Build.0 = Release|Any CPU
|
||||
{E6A23627-8D63-4DF1-A4F2-8881172C1FE6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E6A23627-8D63-4DF1-A4F2-8881172C1FE6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E6A23627-8D63-4DF1-A4F2-8881172C1FE6}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{E6A23627-8D63-4DF1-A4F2-8881172C1FE6}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{E6A23627-8D63-4DF1-A4F2-8881172C1FE6}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{E6A23627-8D63-4DF1-A4F2-8881172C1FE6}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{E6A23627-8D63-4DF1-A4F2-8881172C1FE6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E6A23627-8D63-4DF1-A4F2-8881172C1FE6}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{E6A23627-8D63-4DF1-A4F2-8881172C1FE6}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{E6A23627-8D63-4DF1-A4F2-8881172C1FE6}.Release|x64.Build.0 = Release|Any CPU
|
||||
{E6A23627-8D63-4DF1-A4F2-8881172C1FE6}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{E6A23627-8D63-4DF1-A4F2-8881172C1FE6}.Release|x86.Build.0 = Release|Any CPU
|
||||
{9788C76F-658B-4441-88F8-22C6B86FAD27}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{9788C76F-658B-4441-88F8-22C6B86FAD27}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{9788C76F-658B-4441-88F8-22C6B86FAD27}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{9788C76F-658B-4441-88F8-22C6B86FAD27}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{9788C76F-658B-4441-88F8-22C6B86FAD27}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{9788C76F-658B-4441-88F8-22C6B86FAD27}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{9788C76F-658B-4441-88F8-22C6B86FAD27}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{9788C76F-658B-4441-88F8-22C6B86FAD27}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{9788C76F-658B-4441-88F8-22C6B86FAD27}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{9788C76F-658B-4441-88F8-22C6B86FAD27}.Release|x64.Build.0 = Release|Any CPU
|
||||
{9788C76F-658B-4441-88F8-22C6B86FAD27}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{9788C76F-658B-4441-88F8-22C6B86FAD27}.Release|x86.Build.0 = Release|Any CPU
|
||||
{1970D5CD-D9A4-4673-A297-179BB04199F4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{1970D5CD-D9A4-4673-A297-179BB04199F4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{1970D5CD-D9A4-4673-A297-179BB04199F4}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{1970D5CD-D9A4-4673-A297-179BB04199F4}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{1970D5CD-D9A4-4673-A297-179BB04199F4}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{1970D5CD-D9A4-4673-A297-179BB04199F4}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{1970D5CD-D9A4-4673-A297-179BB04199F4}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{1970D5CD-D9A4-4673-A297-179BB04199F4}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{1970D5CD-D9A4-4673-A297-179BB04199F4}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{1970D5CD-D9A4-4673-A297-179BB04199F4}.Release|x64.Build.0 = Release|Any CPU
|
||||
{1970D5CD-D9A4-4673-A297-179BB04199F4}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{1970D5CD-D9A4-4673-A297-179BB04199F4}.Release|x86.Build.0 = Release|Any CPU
|
||||
{A40350FE-4334-4007-B1C3-6BEB1B070309}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{A40350FE-4334-4007-B1C3-6BEB1B070309}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A40350FE-4334-4007-B1C3-6BEB1B070309}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{A40350FE-4334-4007-B1C3-6BEB1B070309}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{A40350FE-4334-4007-B1C3-6BEB1B070309}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{A40350FE-4334-4007-B1C3-6BEB1B070309}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{A40350FE-4334-4007-B1C3-6BEB1B070309}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A40350FE-4334-4007-B1C3-6BEB1B070309}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{A40350FE-4334-4007-B1C3-6BEB1B070309}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{A40350FE-4334-4007-B1C3-6BEB1B070309}.Release|x64.Build.0 = Release|Any CPU
|
||||
{A40350FE-4334-4007-B1C3-6BEB1B070309}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{A40350FE-4334-4007-B1C3-6BEB1B070309}.Release|x86.Build.0 = Release|Any CPU
|
||||
{C26965A9-EAC6-4E5A-B8C1-D161260EFE4F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C26965A9-EAC6-4E5A-B8C1-D161260EFE4F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C26965A9-EAC6-4E5A-B8C1-D161260EFE4F}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{C26965A9-EAC6-4E5A-B8C1-D161260EFE4F}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{C26965A9-EAC6-4E5A-B8C1-D161260EFE4F}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{C26965A9-EAC6-4E5A-B8C1-D161260EFE4F}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{C26965A9-EAC6-4E5A-B8C1-D161260EFE4F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C26965A9-EAC6-4E5A-B8C1-D161260EFE4F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{C26965A9-EAC6-4E5A-B8C1-D161260EFE4F}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{C26965A9-EAC6-4E5A-B8C1-D161260EFE4F}.Release|x64.Build.0 = Release|Any CPU
|
||||
{C26965A9-EAC6-4E5A-B8C1-D161260EFE4F}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{C26965A9-EAC6-4E5A-B8C1-D161260EFE4F}.Release|x86.Build.0 = Release|Any CPU
|
||||
{FE5290C7-45DA-46F8-BD74-698E7A161DD6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{FE5290C7-45DA-46F8-BD74-698E7A161DD6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{FE5290C7-45DA-46F8-BD74-698E7A161DD6}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{FE5290C7-45DA-46F8-BD74-698E7A161DD6}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{FE5290C7-45DA-46F8-BD74-698E7A161DD6}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{FE5290C7-45DA-46F8-BD74-698E7A161DD6}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{FE5290C7-45DA-46F8-BD74-698E7A161DD6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{FE5290C7-45DA-46F8-BD74-698E7A161DD6}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{FE5290C7-45DA-46F8-BD74-698E7A161DD6}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{FE5290C7-45DA-46F8-BD74-698E7A161DD6}.Release|x64.Build.0 = Release|Any CPU
|
||||
{FE5290C7-45DA-46F8-BD74-698E7A161DD6}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{FE5290C7-45DA-46F8-BD74-698E7A161DD6}.Release|x86.Build.0 = Release|Any CPU
|
||||
{ED66DC0E-FD6A-477A-BA8A-5273AA64F580}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{ED66DC0E-FD6A-477A-BA8A-5273AA64F580}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{ED66DC0E-FD6A-477A-BA8A-5273AA64F580}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{ED66DC0E-FD6A-477A-BA8A-5273AA64F580}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{ED66DC0E-FD6A-477A-BA8A-5273AA64F580}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{ED66DC0E-FD6A-477A-BA8A-5273AA64F580}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{ED66DC0E-FD6A-477A-BA8A-5273AA64F580}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{ED66DC0E-FD6A-477A-BA8A-5273AA64F580}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{ED66DC0E-FD6A-477A-BA8A-5273AA64F580}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{ED66DC0E-FD6A-477A-BA8A-5273AA64F580}.Release|x64.Build.0 = Release|Any CPU
|
||||
{ED66DC0E-FD6A-477A-BA8A-5273AA64F580}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{ED66DC0E-FD6A-477A-BA8A-5273AA64F580}.Release|x86.Build.0 = Release|Any CPU
|
||||
{B06040BC-DA28-4923-8CAC-20EB517D471B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B06040BC-DA28-4923-8CAC-20EB517D471B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B06040BC-DA28-4923-8CAC-20EB517D471B}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{B06040BC-DA28-4923-8CAC-20EB517D471B}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{B06040BC-DA28-4923-8CAC-20EB517D471B}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{B06040BC-DA28-4923-8CAC-20EB517D471B}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{B06040BC-DA28-4923-8CAC-20EB517D471B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B06040BC-DA28-4923-8CAC-20EB517D471B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{B06040BC-DA28-4923-8CAC-20EB517D471B}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{B06040BC-DA28-4923-8CAC-20EB517D471B}.Release|x64.Build.0 = Release|Any CPU
|
||||
{B06040BC-DA28-4923-8CAC-20EB517D471B}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{B06040BC-DA28-4923-8CAC-20EB517D471B}.Release|x86.Build.0 = Release|Any CPU
|
||||
{55CACC1F-FE96-47C8-8073-91F4CAA55C75}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{55CACC1F-FE96-47C8-8073-91F4CAA55C75}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{55CACC1F-FE96-47C8-8073-91F4CAA55C75}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{55CACC1F-FE96-47C8-8073-91F4CAA55C75}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{55CACC1F-FE96-47C8-8073-91F4CAA55C75}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{55CACC1F-FE96-47C8-8073-91F4CAA55C75}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{55CACC1F-FE96-47C8-8073-91F4CAA55C75}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{55CACC1F-FE96-47C8-8073-91F4CAA55C75}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{55CACC1F-FE96-47C8-8073-91F4CAA55C75}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{55CACC1F-FE96-47C8-8073-91F4CAA55C75}.Release|x64.Build.0 = Release|Any CPU
|
||||
{55CACC1F-FE96-47C8-8073-91F4CAA55C75}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{55CACC1F-FE96-47C8-8073-91F4CAA55C75}.Release|x86.Build.0 = Release|Any CPU
|
||||
{7509AA1E-3093-4BEE-984F-E11579E98A11}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{7509AA1E-3093-4BEE-984F-E11579E98A11}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{7509AA1E-3093-4BEE-984F-E11579E98A11}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{7509AA1E-3093-4BEE-984F-E11579E98A11}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{7509AA1E-3093-4BEE-984F-E11579E98A11}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{7509AA1E-3093-4BEE-984F-E11579E98A11}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{7509AA1E-3093-4BEE-984F-E11579E98A11}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{7509AA1E-3093-4BEE-984F-E11579E98A11}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{7509AA1E-3093-4BEE-984F-E11579E98A11}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{7509AA1E-3093-4BEE-984F-E11579E98A11}.Release|x64.Build.0 = Release|Any CPU
|
||||
{7509AA1E-3093-4BEE-984F-E11579E98A11}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{7509AA1E-3093-4BEE-984F-E11579E98A11}.Release|x86.Build.0 = Release|Any CPU
|
||||
{DAAB6B35-CBD2-4573-B633-CDD42F583A0E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{DAAB6B35-CBD2-4573-B633-CDD42F583A0E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{DAAB6B35-CBD2-4573-B633-CDD42F583A0E}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{DAAB6B35-CBD2-4573-B633-CDD42F583A0E}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{DAAB6B35-CBD2-4573-B633-CDD42F583A0E}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{DAAB6B35-CBD2-4573-B633-CDD42F583A0E}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{DAAB6B35-CBD2-4573-B633-CDD42F583A0E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{DAAB6B35-CBD2-4573-B633-CDD42F583A0E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{DAAB6B35-CBD2-4573-B633-CDD42F583A0E}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{DAAB6B35-CBD2-4573-B633-CDD42F583A0E}.Release|x64.Build.0 = Release|Any CPU
|
||||
{DAAB6B35-CBD2-4573-B633-CDD42F583A0E}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{DAAB6B35-CBD2-4573-B633-CDD42F583A0E}.Release|x86.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
|
@ -7771,10 +7893,8 @@ Global
|
|||
{8550A02D-BA13-411A-AAD3-6124D33D669F} = {47EF1A9F-89DB-4EBA-9BC1-1D4E0E12DE44}
|
||||
{EDE77D0C-321A-49FD-95D7-56ED41242A93} = {47EF1A9F-89DB-4EBA-9BC1-1D4E0E12DE44}
|
||||
{8BDEC645-73BD-453B-8A5C-D616BC4EA08D} = {7B976D8F-EA31-4C0B-97BD-DFD9B3CC86FB}
|
||||
{CBCD6AC2-72D3-4E82-9E78-12E3A9C68E1D} = {7B976D8F-EA31-4C0B-97BD-DFD9B3CC86FB}
|
||||
{EE9D0952-6060-4723-B329-94A2950A6762} = {4FDDC525-4E60-4CAF-83A3-261C5B43721F}
|
||||
{132D43A2-067A-4E24-A520-45B9F14DCB8E} = {EE9D0952-6060-4723-B329-94A2950A6762}
|
||||
{FA8D7CA4-C33B-4409-865F-54192BAC59A4} = {7B976D8F-EA31-4C0B-97BD-DFD9B3CC86FB}
|
||||
{2EC4E939-513F-44CD-A956-498966EAC929} = {7B976D8F-EA31-4C0B-97BD-DFD9B3CC86FB}
|
||||
{987E1C29-F124-40C8-8E6F-1B2B6A4CB62A} = {4FDDC525-4E60-4CAF-83A3-261C5B43721F}
|
||||
{3CBC4802-E9B8-48B7-BC8C-B0AFB9EEC643} = {0ACCEDA7-339C-4B4D-8DD4-1AC271F31C04}
|
||||
|
|
@ -7788,8 +7908,6 @@ Global
|
|||
{83371889-9A3E-4D16-AE77-EB4F83BC6374} = {FED4267E-E5E4-49C5-98DB-8B3F203596EE}
|
||||
{525EBCB4-A870-470B-BC90-845306C337D1} = {FED4267E-E5E4-49C5-98DB-8B3F203596EE}
|
||||
{175E5CD8-92D4-46BB-882E-3A930D3302D4} = {FED4267E-E5E4-49C5-98DB-8B3F203596EE}
|
||||
{A5CE25E9-89E1-4F2C-9B89-0C161707E700} = {B6118E15-C37A-4B05-B4DF-97FE99790417}
|
||||
{E6A23627-8D63-4DF1-A4F2-8881172C1FE6} = {B6118E15-C37A-4B05-B4DF-97FE99790417}
|
||||
{6126DCE4-9692-4EE2-B240-C65743572995} = {0508E463-0269-40C9-B5C2-3B600FB2A28B}
|
||||
{46FB7E93-1294-4068-B80A-D4864F78277A} = {6126DCE4-9692-4EE2-B240-C65743572995}
|
||||
{25FA84DB-EEA7-4068-8E2D-F3D48B281C16} = {6126DCE4-9692-4EE2-B240-C65743572995}
|
||||
|
|
@ -7814,6 +7932,23 @@ Global
|
|||
{7F87406C-A3C8-4139-A68D-E4C344294A67} = {D62AF49B-F9FE-4794-AC39-A473FF13CA81}
|
||||
{1533E271-F61B-441B-8B74-59FB61DF0552} = {D62AF49B-F9FE-4794-AC39-A473FF13CA81}
|
||||
{7E268085-1046-4362-80CB-2977FF826DCA} = {D62AF49B-F9FE-4794-AC39-A473FF13CA81}
|
||||
{A5CE25E9-89E1-4F2C-9B89-0C161707E700} = {B6118E15-C37A-4B05-B4DF-97FE99790417}
|
||||
{E6A23627-8D63-4DF1-A4F2-8881172C1FE6} = {B6118E15-C37A-4B05-B4DF-97FE99790417}
|
||||
{7D2B0799-A634-42AC-AE77-5D167BA51389} = {562D5067-8CD8-4F19-BCBB-873204932C61}
|
||||
{9788C76F-658B-4441-88F8-22C6B86FAD27} = {7D2B0799-A634-42AC-AE77-5D167BA51389}
|
||||
{1970D5CD-D9A4-4673-A297-179BB04199F4} = {7D2B0799-A634-42AC-AE77-5D167BA51389}
|
||||
{A40350FE-4334-4007-B1C3-6BEB1B070309} = {7D2B0799-A634-42AC-AE77-5D167BA51389}
|
||||
{C26965A9-EAC6-4E5A-B8C1-D161260EFE4F} = {7D2B0799-A634-42AC-AE77-5D167BA51389}
|
||||
{FE5290C7-45DA-46F8-BD74-698E7A161DD6} = {7D2B0799-A634-42AC-AE77-5D167BA51389}
|
||||
{ED66DC0E-FD6A-477A-BA8A-5273AA64F580} = {7D2B0799-A634-42AC-AE77-5D167BA51389}
|
||||
{C1E7F837-6988-43E2-9E1C-7302DB484F99} = {017429CC-C5FB-48B4-9C46-034E29EE2F06}
|
||||
{2A91479A-4ABE-4BB7-9A5E-CA3B9CCFC69E} = {C1E7F837-6988-43E2-9E1C-7302DB484F99}
|
||||
{7CB09412-C9B0-47E8-A8C3-311AA4CFDE04} = {C1E7F837-6988-43E2-9E1C-7302DB484F99}
|
||||
{22D7D74B-565D-4047-97B4-F149B1A13350} = {2A91479A-4ABE-4BB7-9A5E-CA3B9CCFC69E}
|
||||
{B06040BC-DA28-4923-8CAC-20EB517D471B} = {22D7D74B-565D-4047-97B4-F149B1A13350}
|
||||
{55CACC1F-FE96-47C8-8073-91F4CAA55C75} = {2A91479A-4ABE-4BB7-9A5E-CA3B9CCFC69E}
|
||||
{7509AA1E-3093-4BEE-984F-E11579E98A11} = {7CB09412-C9B0-47E8-A8C3-311AA4CFDE04}
|
||||
{DAAB6B35-CBD2-4573-B633-CDD42F583A0E} = {16898702-3E33-41C1-B8D8-4CE3F1D46BD9}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {3E8720B3-DBDD-498C-B383-2CC32A054E8F}
|
||||
|
|
|
|||
|
|
@ -267,4 +267,29 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
SOFTWARE.
|
||||
|
||||
License notice for BedrockFramework
|
||||
===================================
|
||||
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 David Fowler
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
|
|
|||
|
|
@ -64,6 +64,7 @@ and are generated based on the last package release.
|
|||
<LatestPackageReference Include="System.ComponentModel.Annotations" />
|
||||
<LatestPackageReference Include="System.Diagnostics.DiagnosticSource" />
|
||||
<LatestPackageReference Include="System.Diagnostics.EventLog" />
|
||||
<LatestPackageReference Include="System.DirectoryServices.Protocols" />
|
||||
<LatestPackageReference Include="System.Drawing.Common" />
|
||||
<LatestPackageReference Include="System.IO.Pipelines" />
|
||||
<LatestPackageReference Include="System.Net.Http" />
|
||||
|
|
@ -107,6 +108,7 @@ and are generated based on the last package release.
|
|||
<LatestPackageReference Include="Microsoft.Bcl.AsyncInterfaces" />
|
||||
<LatestPackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" />
|
||||
<LatestPackageReference Include="Microsoft.CodeAnalysis.PublicApiAnalyzers" />
|
||||
<LatestPackageReference Include="Microsoft.EntityFrameworkCore.Design" />
|
||||
<LatestPackageReference Include="Microsoft.EntityFrameworkCore.InMemory" />
|
||||
<LatestPackageReference Include="Microsoft.EntityFrameworkCore.Relational" />
|
||||
<LatestPackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" />
|
||||
|
|
|
|||
|
|
@ -13,305 +13,313 @@
|
|||
<Uri>https://github.com/dotnet/blazor</Uri>
|
||||
<Sha>cc449601d638ffaab58ae9487f0fd010bb178a12</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="dotnet-ef" Version="5.0.0-rc.1.20417.2">
|
||||
<Dependency Name="dotnet-ef" Version="5.0.0-rc.1.20425.4">
|
||||
<Uri>https://github.com/dotnet/efcore</Uri>
|
||||
<Sha>5099d918192f5df031e1ff5e3beea9cb361c605a</Sha>
|
||||
<Sha>9638c0cda4bfb2eb8b70a047baefc982ffa7dade</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.EntityFrameworkCore.InMemory" Version="5.0.0-rc.1.20417.2">
|
||||
<Dependency Name="Microsoft.EntityFrameworkCore.InMemory" Version="5.0.0-rc.1.20425.4">
|
||||
<Uri>https://github.com/dotnet/efcore</Uri>
|
||||
<Sha>5099d918192f5df031e1ff5e3beea9cb361c605a</Sha>
|
||||
<Sha>9638c0cda4bfb2eb8b70a047baefc982ffa7dade</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.EntityFrameworkCore.Relational" Version="5.0.0-rc.1.20417.2">
|
||||
<Dependency Name="Microsoft.EntityFrameworkCore.Relational" Version="5.0.0-rc.1.20425.4">
|
||||
<Uri>https://github.com/dotnet/efcore</Uri>
|
||||
<Sha>5099d918192f5df031e1ff5e3beea9cb361c605a</Sha>
|
||||
<Sha>9638c0cda4bfb2eb8b70a047baefc982ffa7dade</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.EntityFrameworkCore.Sqlite" Version="5.0.0-rc.1.20417.2">
|
||||
<Dependency Name="Microsoft.EntityFrameworkCore.Sqlite" Version="5.0.0-rc.1.20425.4">
|
||||
<Uri>https://github.com/dotnet/efcore</Uri>
|
||||
<Sha>5099d918192f5df031e1ff5e3beea9cb361c605a</Sha>
|
||||
<Sha>9638c0cda4bfb2eb8b70a047baefc982ffa7dade</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.EntityFrameworkCore.SqlServer" Version="5.0.0-rc.1.20417.2">
|
||||
<Dependency Name="Microsoft.EntityFrameworkCore.SqlServer" Version="5.0.0-rc.1.20425.4">
|
||||
<Uri>https://github.com/dotnet/efcore</Uri>
|
||||
<Sha>5099d918192f5df031e1ff5e3beea9cb361c605a</Sha>
|
||||
<Sha>9638c0cda4bfb2eb8b70a047baefc982ffa7dade</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.EntityFrameworkCore.Tools" Version="5.0.0-rc.1.20417.2">
|
||||
<Dependency Name="Microsoft.EntityFrameworkCore.Tools" Version="5.0.0-rc.1.20425.4">
|
||||
<Uri>https://github.com/dotnet/efcore</Uri>
|
||||
<Sha>5099d918192f5df031e1ff5e3beea9cb361c605a</Sha>
|
||||
<Sha>9638c0cda4bfb2eb8b70a047baefc982ffa7dade</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.EntityFrameworkCore" Version="5.0.0-rc.1.20417.2">
|
||||
<Dependency Name="Microsoft.EntityFrameworkCore" Version="5.0.0-rc.1.20425.4">
|
||||
<Uri>https://github.com/dotnet/efcore</Uri>
|
||||
<Sha>5099d918192f5df031e1ff5e3beea9cb361c605a</Sha>
|
||||
<Sha>9638c0cda4bfb2eb8b70a047baefc982ffa7dade</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Caching.Abstractions" Version="5.0.0-rc.1.20416.7">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
||||
<Dependency Name="Microsoft.EntityFrameworkCore.Design" Version="5.0.0-rc.1.20425.4">
|
||||
<Uri>https://github.com/dotnet/efcore</Uri>
|
||||
<Sha>9638c0cda4bfb2eb8b70a047baefc982ffa7dade</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Caching.Memory" Version="5.0.0-rc.1.20416.7">
|
||||
<Dependency Name="Microsoft.Extensions.Caching.Abstractions" Version="5.0.0-rc.1.20425.1">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
||||
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Configuration.Abstractions" Version="5.0.0-rc.1.20416.7">
|
||||
<Dependency Name="Microsoft.Extensions.Caching.Memory" Version="5.0.0-rc.1.20425.1">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
||||
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Configuration.Binder" Version="5.0.0-rc.1.20416.7">
|
||||
<Dependency Name="Microsoft.Extensions.Configuration.Abstractions" Version="5.0.0-rc.1.20425.1">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
||||
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Configuration.CommandLine" Version="5.0.0-rc.1.20416.7">
|
||||
<Dependency Name="Microsoft.Extensions.Configuration.Binder" Version="5.0.0-rc.1.20425.1">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
||||
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="5.0.0-rc.1.20416.7">
|
||||
<Dependency Name="Microsoft.Extensions.Configuration.CommandLine" Version="5.0.0-rc.1.20425.1">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
||||
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Configuration.FileExtensions" Version="5.0.0-rc.1.20416.7">
|
||||
<Dependency Name="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="5.0.0-rc.1.20425.1">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
||||
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Configuration.Ini" Version="5.0.0-rc.1.20416.7">
|
||||
<Dependency Name="Microsoft.Extensions.Configuration.FileExtensions" Version="5.0.0-rc.1.20425.1">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
||||
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Configuration.Json" Version="5.0.0-rc.1.20416.7">
|
||||
<Dependency Name="Microsoft.Extensions.Configuration.Ini" Version="5.0.0-rc.1.20425.1">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
||||
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Configuration.UserSecrets" Version="5.0.0-rc.1.20416.7">
|
||||
<Dependency Name="Microsoft.Extensions.Configuration.Json" Version="5.0.0-rc.1.20425.1">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
||||
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Configuration.Xml" Version="5.0.0-rc.1.20416.7">
|
||||
<Dependency Name="Microsoft.Extensions.Configuration.UserSecrets" Version="5.0.0-rc.1.20425.1">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
||||
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Configuration" Version="5.0.0-rc.1.20416.7">
|
||||
<Dependency Name="Microsoft.Extensions.Configuration.Xml" Version="5.0.0-rc.1.20425.1">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
||||
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.DependencyInjection.Abstractions" Version="5.0.0-rc.1.20416.7">
|
||||
<Dependency Name="Microsoft.Extensions.Configuration" Version="5.0.0-rc.1.20425.1">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
||||
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.DependencyInjection" Version="5.0.0-rc.1.20416.7">
|
||||
<Dependency Name="Microsoft.Extensions.DependencyInjection.Abstractions" Version="5.0.0-rc.1.20425.1">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
||||
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.FileProviders.Abstractions" Version="5.0.0-rc.1.20416.7">
|
||||
<Dependency Name="Microsoft.Extensions.DependencyInjection" Version="5.0.0-rc.1.20425.1">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
||||
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.FileProviders.Composite" Version="5.0.0-rc.1.20416.7">
|
||||
<Dependency Name="Microsoft.Extensions.FileProviders.Abstractions" Version="5.0.0-rc.1.20425.1">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
||||
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.FileProviders.Physical" Version="5.0.0-rc.1.20416.7">
|
||||
<Dependency Name="Microsoft.Extensions.FileProviders.Composite" Version="5.0.0-rc.1.20425.1">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
||||
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.FileSystemGlobbing" Version="5.0.0-rc.1.20416.7">
|
||||
<Dependency Name="Microsoft.Extensions.FileProviders.Physical" Version="5.0.0-rc.1.20425.1">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
||||
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.HostFactoryResolver.Sources" Version="5.0.0-rc.1.20416.7">
|
||||
<Dependency Name="Microsoft.Extensions.FileSystemGlobbing" Version="5.0.0-rc.1.20425.1">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
||||
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Hosting.Abstractions" Version="5.0.0-rc.1.20416.7">
|
||||
<Dependency Name="Microsoft.Extensions.HostFactoryResolver.Sources" Version="5.0.0-rc.1.20425.1">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
||||
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Hosting" Version="5.0.0-rc.1.20416.7">
|
||||
<Dependency Name="Microsoft.Extensions.Hosting.Abstractions" Version="5.0.0-rc.1.20425.1">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
||||
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Http" Version="5.0.0-rc.1.20416.7">
|
||||
<Dependency Name="Microsoft.Extensions.Hosting" Version="5.0.0-rc.1.20425.1">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
||||
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Logging.Abstractions" Version="5.0.0-rc.1.20416.7">
|
||||
<Dependency Name="Microsoft.Extensions.Http" Version="5.0.0-rc.1.20425.1">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
||||
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Logging.Configuration" Version="5.0.0-rc.1.20416.7">
|
||||
<Dependency Name="Microsoft.Extensions.Logging.Abstractions" Version="5.0.0-rc.1.20425.1">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
||||
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Logging.Console" Version="5.0.0-rc.1.20416.7">
|
||||
<Dependency Name="Microsoft.Extensions.Logging.Configuration" Version="5.0.0-rc.1.20425.1">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
||||
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Logging.Debug" Version="5.0.0-rc.1.20416.7">
|
||||
<Dependency Name="Microsoft.Extensions.Logging.Console" Version="5.0.0-rc.1.20425.1">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
||||
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Logging.EventSource" Version="5.0.0-rc.1.20416.7">
|
||||
<Dependency Name="Microsoft.Extensions.Logging.Debug" Version="5.0.0-rc.1.20425.1">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
||||
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Logging.EventLog" Version="5.0.0-rc.1.20416.7">
|
||||
<Dependency Name="Microsoft.Extensions.Logging.EventSource" Version="5.0.0-rc.1.20425.1">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
||||
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Logging.TraceSource" Version="5.0.0-rc.1.20416.7">
|
||||
<Dependency Name="Microsoft.Extensions.Logging.EventLog" Version="5.0.0-rc.1.20425.1">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
||||
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Logging" Version="5.0.0-rc.1.20416.7">
|
||||
<Dependency Name="Microsoft.Extensions.Logging.TraceSource" Version="5.0.0-rc.1.20425.1">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
||||
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Options.ConfigurationExtensions" Version="5.0.0-rc.1.20416.7">
|
||||
<Dependency Name="Microsoft.Extensions.Logging" Version="5.0.0-rc.1.20425.1">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
||||
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Options.DataAnnotations" Version="5.0.0-rc.1.20416.7">
|
||||
<Dependency Name="Microsoft.Extensions.Options.ConfigurationExtensions" Version="5.0.0-rc.1.20425.1">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
||||
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Options" Version="5.0.0-rc.1.20416.7">
|
||||
<Dependency Name="Microsoft.Extensions.Options.DataAnnotations" Version="5.0.0-rc.1.20425.1">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
||||
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Primitives" Version="5.0.0-rc.1.20416.7">
|
||||
<Dependency Name="Microsoft.Extensions.Options" Version="5.0.0-rc.1.20425.1">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
||||
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.Internal.Transport" Version="5.0.0-rc.1.20416.7">
|
||||
<Dependency Name="Microsoft.Extensions.Primitives" Version="5.0.0-rc.1.20425.1">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
||||
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Win32.Registry" Version="5.0.0-rc.1.20416.7">
|
||||
<Dependency Name="Microsoft.Extensions.Internal.Transport" Version="5.0.0-rc.1.20425.1">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
||||
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Win32.SystemEvents" Version="5.0.0-rc.1.20416.7">
|
||||
<Dependency Name="Microsoft.Win32.Registry" Version="5.0.0-rc.1.20425.1">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
||||
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="System.ComponentModel.Annotations" Version="5.0.0-rc.1.20416.7">
|
||||
<Dependency Name="Microsoft.Win32.SystemEvents" Version="5.0.0-rc.1.20425.1">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
||||
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="System.Diagnostics.DiagnosticSource" Version="5.0.0-rc.1.20416.7">
|
||||
<Dependency Name="System.ComponentModel.Annotations" Version="5.0.0-rc.1.20425.1">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
||||
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="System.Diagnostics.EventLog" Version="5.0.0-rc.1.20416.7">
|
||||
<Dependency Name="System.Diagnostics.DiagnosticSource" Version="5.0.0-rc.1.20425.1">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
||||
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="System.Drawing.Common" Version="5.0.0-rc.1.20416.7">
|
||||
<Dependency Name="System.Diagnostics.EventLog" Version="5.0.0-rc.1.20425.1">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
||||
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="System.IO.Pipelines" Version="5.0.0-rc.1.20416.7">
|
||||
<Dependency Name="System.DirectoryServices.Protocols" Version="5.0.0-rc.1.20425.1">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
||||
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="System.Net.Http.Json" Version="5.0.0-rc.1.20416.7">
|
||||
<Dependency Name="System.Drawing.Common" Version="5.0.0-rc.1.20425.1">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
||||
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="System.Net.Http.WinHttpHandler" Version="5.0.0-rc.1.20416.7">
|
||||
<Dependency Name="System.IO.Pipelines" Version="5.0.0-rc.1.20425.1">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
||||
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="System.Net.WebSockets.WebSocketProtocol" Version="5.0.0-rc.1.20416.7">
|
||||
<Dependency Name="System.Net.Http.Json" Version="5.0.0-rc.1.20425.1">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
||||
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="System.Reflection.Metadata" Version="5.0.0-rc.1.20416.7">
|
||||
<Dependency Name="System.Net.Http.WinHttpHandler" Version="5.0.0-rc.1.20425.1">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
||||
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="System.Resources.Extensions" Version="5.0.0-rc.1.20416.7">
|
||||
<Dependency Name="System.Net.WebSockets.WebSocketProtocol" Version="5.0.0-rc.1.20425.1">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
||||
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="System.Runtime.CompilerServices.Unsafe" Version="5.0.0-rc.1.20416.7">
|
||||
<Dependency Name="System.Reflection.Metadata" Version="5.0.0-rc.1.20425.1">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
||||
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="System.Resources.Extensions" Version="5.0.0-rc.1.20425.1">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="System.Runtime.CompilerServices.Unsafe" Version="5.0.0-rc.1.20425.1">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||
</Dependency>
|
||||
<!-- System.Security.AccessControl should only be referenced in Dependencies.props and RTMVersions.csproj. -->
|
||||
<Dependency Name="System.Security.AccessControl" Version="5.0.0-rc.1.20416.7">
|
||||
<Dependency Name="System.Security.AccessControl" Version="5.0.0-rc.1.20425.1">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
||||
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="System.Security.Cryptography.Cng" Version="5.0.0-rc.1.20416.7">
|
||||
<Dependency Name="System.Security.Cryptography.Cng" Version="5.0.0-rc.1.20425.1">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
||||
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="System.Security.Cryptography.Pkcs" Version="5.0.0-rc.1.20416.7">
|
||||
<Dependency Name="System.Security.Cryptography.Pkcs" Version="5.0.0-rc.1.20425.1">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
||||
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="System.Security.Cryptography.Xml" Version="5.0.0-rc.1.20416.7">
|
||||
<Dependency Name="System.Security.Cryptography.Xml" Version="5.0.0-rc.1.20425.1">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
||||
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="System.Security.Permissions" Version="5.0.0-rc.1.20416.7">
|
||||
<Dependency Name="System.Security.Permissions" Version="5.0.0-rc.1.20425.1">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
||||
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="System.Security.Principal.Windows" Version="5.0.0-rc.1.20416.7">
|
||||
<Dependency Name="System.Security.Principal.Windows" Version="5.0.0-rc.1.20425.1">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
||||
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="System.ServiceProcess.ServiceController" Version="5.0.0-rc.1.20416.7">
|
||||
<Dependency Name="System.ServiceProcess.ServiceController" Version="5.0.0-rc.1.20425.1">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
||||
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="System.Text.Encodings.Web" Version="5.0.0-rc.1.20416.7">
|
||||
<Dependency Name="System.Text.Encodings.Web" Version="5.0.0-rc.1.20425.1">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
||||
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="System.Text.Json" Version="5.0.0-rc.1.20416.7">
|
||||
<Dependency Name="System.Text.Json" Version="5.0.0-rc.1.20425.1">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
||||
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="System.Threading.Channels" Version="5.0.0-rc.1.20416.7">
|
||||
<Dependency Name="System.Threading.Channels" Version="5.0.0-rc.1.20425.1">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
||||
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="System.Windows.Extensions" Version="5.0.0-rc.1.20416.7">
|
||||
<Dependency Name="System.Windows.Extensions" Version="5.0.0-rc.1.20425.1">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
||||
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Extensions.DependencyModel" Version="5.0.0-rc.1.20416.7">
|
||||
<Dependency Name="Microsoft.Extensions.DependencyModel" Version="5.0.0-rc.1.20425.1">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
||||
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.NETCore.App.Ref" Version="5.0.0-rc.1.20416.7">
|
||||
<Dependency Name="Microsoft.NETCore.App.Ref" Version="5.0.0-rc.1.20425.1">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
||||
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||
</Dependency>
|
||||
<!--
|
||||
Win-x64 is used here because we have picked an arbitrary runtime identifier to flow the version of the latest NETCore.App runtime.
|
||||
All Runtime.$rid packages should have the same version.
|
||||
-->
|
||||
<Dependency Name="Microsoft.NETCore.App.Runtime.win-x64" Version="5.0.0-rc.1.20416.7">
|
||||
<Dependency Name="Microsoft.NETCore.App.Runtime.win-x64" Version="5.0.0-rc.1.20425.1">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
||||
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.NETCore.App.Internal" Version="5.0.0-rc.1.20416.7">
|
||||
<Dependency Name="Microsoft.NETCore.App.Internal" Version="5.0.0-rc.1.20425.1">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
||||
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||
</Dependency>
|
||||
</ProductDependencies>
|
||||
<ToolsetDependencies>
|
||||
<!-- Listed explicitly to workaround https://github.com/dotnet/cli/issues/10528 -->
|
||||
<Dependency Name="Microsoft.NETCore.Platforms" Version="5.0.0-rc.1.20416.7">
|
||||
<Dependency Name="Microsoft.NETCore.Platforms" Version="5.0.0-rc.1.20425.1">
|
||||
<Uri>https://github.com/dotnet/runtime</Uri>
|
||||
<Sha>0862d48a9c9fbda879206b194a16d8e607deac42</Sha>
|
||||
<Sha>f4e99f4afa445b519abcd7c5c87cbf54771614db</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.DotNet.Arcade.Sdk" Version="5.0.0-beta.20411.8">
|
||||
<Dependency Name="Microsoft.DotNet.Arcade.Sdk" Version="5.0.0-beta.20419.21">
|
||||
<Uri>https://github.com/dotnet/arcade</Uri>
|
||||
<Sha>ecec08a0eebbd92bb9538e351d475582551d9092</Sha>
|
||||
<Sha>56a95cc477558c1ccdf16d7abe962849ea970ba4</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.DotNet.Helix.Sdk" Version="5.0.0-beta.20411.8">
|
||||
<Dependency Name="Microsoft.DotNet.Helix.Sdk" Version="5.0.0-beta.20419.21">
|
||||
<Uri>https://github.com/dotnet/arcade</Uri>
|
||||
<Sha>ecec08a0eebbd92bb9538e351d475582551d9092</Sha>
|
||||
<Sha>56a95cc477558c1ccdf16d7abe962849ea970ba4</Sha>
|
||||
</Dependency>
|
||||
<Dependency Name="Microsoft.Net.Compilers.Toolset" Version="3.8.0-2.20407.3">
|
||||
<Uri>https://github.com/dotnet/roslyn</Uri>
|
||||
|
|
|
|||
|
|
@ -64,82 +64,84 @@
|
|||
<!-- Packages from dotnet/roslyn -->
|
||||
<MicrosoftNetCompilersToolsetPackageVersion>3.8.0-2.20407.3</MicrosoftNetCompilersToolsetPackageVersion>
|
||||
<!-- Packages from dotnet/runtime -->
|
||||
<MicrosoftExtensionsDependencyModelPackageVersion>5.0.0-rc.1.20416.7</MicrosoftExtensionsDependencyModelPackageVersion>
|
||||
<MicrosoftNETCoreAppInternalPackageVersion>5.0.0-rc.1.20416.7</MicrosoftNETCoreAppInternalPackageVersion>
|
||||
<MicrosoftNETCoreAppRefPackageVersion>5.0.0-rc.1.20416.7</MicrosoftNETCoreAppRefPackageVersion>
|
||||
<MicrosoftNETCoreAppRuntimewinx64PackageVersion>5.0.0-rc.1.20416.7</MicrosoftNETCoreAppRuntimewinx64PackageVersion>
|
||||
<MicrosoftWin32RegistryPackageVersion>5.0.0-rc.1.20416.7</MicrosoftWin32RegistryPackageVersion>
|
||||
<MicrosoftWin32SystemEventsPackageVersion>5.0.0-rc.1.20416.7</MicrosoftWin32SystemEventsPackageVersion>
|
||||
<MicrosoftExtensionsCachingAbstractionsPackageVersion>5.0.0-rc.1.20416.7</MicrosoftExtensionsCachingAbstractionsPackageVersion>
|
||||
<MicrosoftExtensionsCachingMemoryPackageVersion>5.0.0-rc.1.20416.7</MicrosoftExtensionsCachingMemoryPackageVersion>
|
||||
<MicrosoftExtensionsConfigurationAbstractionsPackageVersion>5.0.0-rc.1.20416.7</MicrosoftExtensionsConfigurationAbstractionsPackageVersion>
|
||||
<MicrosoftExtensionsConfigurationBinderPackageVersion>5.0.0-rc.1.20416.7</MicrosoftExtensionsConfigurationBinderPackageVersion>
|
||||
<MicrosoftExtensionsConfigurationCommandLinePackageVersion>5.0.0-rc.1.20416.7</MicrosoftExtensionsConfigurationCommandLinePackageVersion>
|
||||
<MicrosoftExtensionsConfigurationEnvironmentVariablesPackageVersion>5.0.0-rc.1.20416.7</MicrosoftExtensionsConfigurationEnvironmentVariablesPackageVersion>
|
||||
<MicrosoftExtensionsConfigurationFileExtensionsPackageVersion>5.0.0-rc.1.20416.7</MicrosoftExtensionsConfigurationFileExtensionsPackageVersion>
|
||||
<MicrosoftExtensionsConfigurationIniPackageVersion>5.0.0-rc.1.20416.7</MicrosoftExtensionsConfigurationIniPackageVersion>
|
||||
<MicrosoftExtensionsConfigurationJsonPackageVersion>5.0.0-rc.1.20416.7</MicrosoftExtensionsConfigurationJsonPackageVersion>
|
||||
<MicrosoftExtensionsConfigurationPackageVersion>5.0.0-rc.1.20416.7</MicrosoftExtensionsConfigurationPackageVersion>
|
||||
<MicrosoftExtensionsConfigurationUserSecretsPackageVersion>5.0.0-rc.1.20416.7</MicrosoftExtensionsConfigurationUserSecretsPackageVersion>
|
||||
<MicrosoftExtensionsConfigurationXmlPackageVersion>5.0.0-rc.1.20416.7</MicrosoftExtensionsConfigurationXmlPackageVersion>
|
||||
<MicrosoftExtensionsDependencyInjectionAbstractionsPackageVersion>5.0.0-rc.1.20416.7</MicrosoftExtensionsDependencyInjectionAbstractionsPackageVersion>
|
||||
<MicrosoftExtensionsDependencyInjectionPackageVersion>5.0.0-rc.1.20416.7</MicrosoftExtensionsDependencyInjectionPackageVersion>
|
||||
<MicrosoftExtensionsFileProvidersAbstractionsPackageVersion>5.0.0-rc.1.20416.7</MicrosoftExtensionsFileProvidersAbstractionsPackageVersion>
|
||||
<MicrosoftExtensionsFileProvidersCompositePackageVersion>5.0.0-rc.1.20416.7</MicrosoftExtensionsFileProvidersCompositePackageVersion>
|
||||
<MicrosoftExtensionsFileProvidersPhysicalPackageVersion>5.0.0-rc.1.20416.7</MicrosoftExtensionsFileProvidersPhysicalPackageVersion>
|
||||
<MicrosoftExtensionsFileSystemGlobbingPackageVersion>5.0.0-rc.1.20416.7</MicrosoftExtensionsFileSystemGlobbingPackageVersion>
|
||||
<MicrosoftExtensionsHostFactoryResolverSourcesPackageVersion>5.0.0-rc.1.20416.7</MicrosoftExtensionsHostFactoryResolverSourcesPackageVersion>
|
||||
<MicrosoftExtensionsHostingAbstractionsPackageVersion>5.0.0-rc.1.20416.7</MicrosoftExtensionsHostingAbstractionsPackageVersion>
|
||||
<MicrosoftExtensionsHostingPackageVersion>5.0.0-rc.1.20416.7</MicrosoftExtensionsHostingPackageVersion>
|
||||
<MicrosoftExtensionsHttpPackageVersion>5.0.0-rc.1.20416.7</MicrosoftExtensionsHttpPackageVersion>
|
||||
<MicrosoftExtensionsLoggingAbstractionsPackageVersion>5.0.0-rc.1.20416.7</MicrosoftExtensionsLoggingAbstractionsPackageVersion>
|
||||
<MicrosoftExtensionsLoggingConfigurationPackageVersion>5.0.0-rc.1.20416.7</MicrosoftExtensionsLoggingConfigurationPackageVersion>
|
||||
<MicrosoftExtensionsLoggingConsolePackageVersion>5.0.0-rc.1.20416.7</MicrosoftExtensionsLoggingConsolePackageVersion>
|
||||
<MicrosoftExtensionsLoggingDebugPackageVersion>5.0.0-rc.1.20416.7</MicrosoftExtensionsLoggingDebugPackageVersion>
|
||||
<MicrosoftExtensionsLoggingEventSourcePackageVersion>5.0.0-rc.1.20416.7</MicrosoftExtensionsLoggingEventSourcePackageVersion>
|
||||
<MicrosoftExtensionsLoggingEventLogPackageVersion>5.0.0-rc.1.20416.7</MicrosoftExtensionsLoggingEventLogPackageVersion>
|
||||
<MicrosoftExtensionsLoggingPackageVersion>5.0.0-rc.1.20416.7</MicrosoftExtensionsLoggingPackageVersion>
|
||||
<MicrosoftExtensionsLoggingTraceSourcePackageVersion>5.0.0-rc.1.20416.7</MicrosoftExtensionsLoggingTraceSourcePackageVersion>
|
||||
<MicrosoftExtensionsOptionsConfigurationExtensionsPackageVersion>5.0.0-rc.1.20416.7</MicrosoftExtensionsOptionsConfigurationExtensionsPackageVersion>
|
||||
<MicrosoftExtensionsOptionsDataAnnotationsPackageVersion>5.0.0-rc.1.20416.7</MicrosoftExtensionsOptionsDataAnnotationsPackageVersion>
|
||||
<MicrosoftExtensionsOptionsPackageVersion>5.0.0-rc.1.20416.7</MicrosoftExtensionsOptionsPackageVersion>
|
||||
<MicrosoftExtensionsPrimitivesPackageVersion>5.0.0-rc.1.20416.7</MicrosoftExtensionsPrimitivesPackageVersion>
|
||||
<MicrosoftExtensionsInternalTransportPackageVersion>5.0.0-rc.1.20416.7</MicrosoftExtensionsInternalTransportPackageVersion>
|
||||
<SystemComponentModelAnnotationsPackageVersion>5.0.0-rc.1.20416.7</SystemComponentModelAnnotationsPackageVersion>
|
||||
<SystemDiagnosticsDiagnosticSourcePackageVersion>5.0.0-rc.1.20416.7</SystemDiagnosticsDiagnosticSourcePackageVersion>
|
||||
<SystemDiagnosticsEventLogPackageVersion>5.0.0-rc.1.20416.7</SystemDiagnosticsEventLogPackageVersion>
|
||||
<SystemDrawingCommonPackageVersion>5.0.0-rc.1.20416.7</SystemDrawingCommonPackageVersion>
|
||||
<SystemIOPipelinesPackageVersion>5.0.0-rc.1.20416.7</SystemIOPipelinesPackageVersion>
|
||||
<SystemNetHttpJsonPackageVersion>5.0.0-rc.1.20416.7</SystemNetHttpJsonPackageVersion>
|
||||
<SystemNetHttpWinHttpHandlerPackageVersion>5.0.0-rc.1.20416.7</SystemNetHttpWinHttpHandlerPackageVersion>
|
||||
<SystemNetWebSocketsWebSocketProtocolPackageVersion>5.0.0-rc.1.20416.7</SystemNetWebSocketsWebSocketProtocolPackageVersion>
|
||||
<SystemReflectionMetadataPackageVersion>5.0.0-rc.1.20416.7</SystemReflectionMetadataPackageVersion>
|
||||
<SystemResourcesExtensionsPackageVersion>5.0.0-rc.1.20416.7</SystemResourcesExtensionsPackageVersion>
|
||||
<SystemRuntimeCompilerServicesUnsafePackageVersion>5.0.0-rc.1.20416.7</SystemRuntimeCompilerServicesUnsafePackageVersion>
|
||||
<MicrosoftExtensionsDependencyModelPackageVersion>5.0.0-rc.1.20425.1</MicrosoftExtensionsDependencyModelPackageVersion>
|
||||
<MicrosoftNETCoreAppInternalPackageVersion>5.0.0-rc.1.20425.1</MicrosoftNETCoreAppInternalPackageVersion>
|
||||
<MicrosoftNETCoreAppRefPackageVersion>5.0.0-rc.1.20425.1</MicrosoftNETCoreAppRefPackageVersion>
|
||||
<MicrosoftNETCoreAppRuntimewinx64PackageVersion>5.0.0-rc.1.20425.1</MicrosoftNETCoreAppRuntimewinx64PackageVersion>
|
||||
<MicrosoftWin32RegistryPackageVersion>5.0.0-rc.1.20425.1</MicrosoftWin32RegistryPackageVersion>
|
||||
<MicrosoftWin32SystemEventsPackageVersion>5.0.0-rc.1.20425.1</MicrosoftWin32SystemEventsPackageVersion>
|
||||
<MicrosoftExtensionsCachingAbstractionsPackageVersion>5.0.0-rc.1.20425.1</MicrosoftExtensionsCachingAbstractionsPackageVersion>
|
||||
<MicrosoftExtensionsCachingMemoryPackageVersion>5.0.0-rc.1.20425.1</MicrosoftExtensionsCachingMemoryPackageVersion>
|
||||
<MicrosoftExtensionsConfigurationAbstractionsPackageVersion>5.0.0-rc.1.20425.1</MicrosoftExtensionsConfigurationAbstractionsPackageVersion>
|
||||
<MicrosoftExtensionsConfigurationBinderPackageVersion>5.0.0-rc.1.20425.1</MicrosoftExtensionsConfigurationBinderPackageVersion>
|
||||
<MicrosoftExtensionsConfigurationCommandLinePackageVersion>5.0.0-rc.1.20425.1</MicrosoftExtensionsConfigurationCommandLinePackageVersion>
|
||||
<MicrosoftExtensionsConfigurationEnvironmentVariablesPackageVersion>5.0.0-rc.1.20425.1</MicrosoftExtensionsConfigurationEnvironmentVariablesPackageVersion>
|
||||
<MicrosoftExtensionsConfigurationFileExtensionsPackageVersion>5.0.0-rc.1.20425.1</MicrosoftExtensionsConfigurationFileExtensionsPackageVersion>
|
||||
<MicrosoftExtensionsConfigurationIniPackageVersion>5.0.0-rc.1.20425.1</MicrosoftExtensionsConfigurationIniPackageVersion>
|
||||
<MicrosoftExtensionsConfigurationJsonPackageVersion>5.0.0-rc.1.20425.1</MicrosoftExtensionsConfigurationJsonPackageVersion>
|
||||
<MicrosoftExtensionsConfigurationPackageVersion>5.0.0-rc.1.20425.1</MicrosoftExtensionsConfigurationPackageVersion>
|
||||
<MicrosoftExtensionsConfigurationUserSecretsPackageVersion>5.0.0-rc.1.20425.1</MicrosoftExtensionsConfigurationUserSecretsPackageVersion>
|
||||
<MicrosoftExtensionsConfigurationXmlPackageVersion>5.0.0-rc.1.20425.1</MicrosoftExtensionsConfigurationXmlPackageVersion>
|
||||
<MicrosoftExtensionsDependencyInjectionAbstractionsPackageVersion>5.0.0-rc.1.20425.1</MicrosoftExtensionsDependencyInjectionAbstractionsPackageVersion>
|
||||
<MicrosoftExtensionsDependencyInjectionPackageVersion>5.0.0-rc.1.20425.1</MicrosoftExtensionsDependencyInjectionPackageVersion>
|
||||
<MicrosoftExtensionsFileProvidersAbstractionsPackageVersion>5.0.0-rc.1.20425.1</MicrosoftExtensionsFileProvidersAbstractionsPackageVersion>
|
||||
<MicrosoftExtensionsFileProvidersCompositePackageVersion>5.0.0-rc.1.20425.1</MicrosoftExtensionsFileProvidersCompositePackageVersion>
|
||||
<MicrosoftExtensionsFileProvidersPhysicalPackageVersion>5.0.0-rc.1.20425.1</MicrosoftExtensionsFileProvidersPhysicalPackageVersion>
|
||||
<MicrosoftExtensionsFileSystemGlobbingPackageVersion>5.0.0-rc.1.20425.1</MicrosoftExtensionsFileSystemGlobbingPackageVersion>
|
||||
<MicrosoftExtensionsHostFactoryResolverSourcesPackageVersion>5.0.0-rc.1.20425.1</MicrosoftExtensionsHostFactoryResolverSourcesPackageVersion>
|
||||
<MicrosoftExtensionsHostingAbstractionsPackageVersion>5.0.0-rc.1.20425.1</MicrosoftExtensionsHostingAbstractionsPackageVersion>
|
||||
<MicrosoftExtensionsHostingPackageVersion>5.0.0-rc.1.20425.1</MicrosoftExtensionsHostingPackageVersion>
|
||||
<MicrosoftExtensionsHttpPackageVersion>5.0.0-rc.1.20425.1</MicrosoftExtensionsHttpPackageVersion>
|
||||
<MicrosoftExtensionsLoggingAbstractionsPackageVersion>5.0.0-rc.1.20425.1</MicrosoftExtensionsLoggingAbstractionsPackageVersion>
|
||||
<MicrosoftExtensionsLoggingConfigurationPackageVersion>5.0.0-rc.1.20425.1</MicrosoftExtensionsLoggingConfigurationPackageVersion>
|
||||
<MicrosoftExtensionsLoggingConsolePackageVersion>5.0.0-rc.1.20425.1</MicrosoftExtensionsLoggingConsolePackageVersion>
|
||||
<MicrosoftExtensionsLoggingDebugPackageVersion>5.0.0-rc.1.20425.1</MicrosoftExtensionsLoggingDebugPackageVersion>
|
||||
<MicrosoftExtensionsLoggingEventSourcePackageVersion>5.0.0-rc.1.20425.1</MicrosoftExtensionsLoggingEventSourcePackageVersion>
|
||||
<MicrosoftExtensionsLoggingEventLogPackageVersion>5.0.0-rc.1.20425.1</MicrosoftExtensionsLoggingEventLogPackageVersion>
|
||||
<MicrosoftExtensionsLoggingPackageVersion>5.0.0-rc.1.20425.1</MicrosoftExtensionsLoggingPackageVersion>
|
||||
<MicrosoftExtensionsLoggingTraceSourcePackageVersion>5.0.0-rc.1.20425.1</MicrosoftExtensionsLoggingTraceSourcePackageVersion>
|
||||
<MicrosoftExtensionsOptionsConfigurationExtensionsPackageVersion>5.0.0-rc.1.20425.1</MicrosoftExtensionsOptionsConfigurationExtensionsPackageVersion>
|
||||
<MicrosoftExtensionsOptionsDataAnnotationsPackageVersion>5.0.0-rc.1.20425.1</MicrosoftExtensionsOptionsDataAnnotationsPackageVersion>
|
||||
<MicrosoftExtensionsOptionsPackageVersion>5.0.0-rc.1.20425.1</MicrosoftExtensionsOptionsPackageVersion>
|
||||
<MicrosoftExtensionsPrimitivesPackageVersion>5.0.0-rc.1.20425.1</MicrosoftExtensionsPrimitivesPackageVersion>
|
||||
<MicrosoftExtensionsInternalTransportPackageVersion>5.0.0-rc.1.20425.1</MicrosoftExtensionsInternalTransportPackageVersion>
|
||||
<SystemComponentModelAnnotationsPackageVersion>5.0.0-rc.1.20425.1</SystemComponentModelAnnotationsPackageVersion>
|
||||
<SystemDiagnosticsDiagnosticSourcePackageVersion>5.0.0-rc.1.20425.1</SystemDiagnosticsDiagnosticSourcePackageVersion>
|
||||
<SystemDiagnosticsEventLogPackageVersion>5.0.0-rc.1.20425.1</SystemDiagnosticsEventLogPackageVersion>
|
||||
<SystemDirectoryServicesProtocolsPackageVersion>5.0.0-rc.1.20425.1</SystemDirectoryServicesProtocolsPackageVersion>
|
||||
<SystemDrawingCommonPackageVersion>5.0.0-rc.1.20425.1</SystemDrawingCommonPackageVersion>
|
||||
<SystemIOPipelinesPackageVersion>5.0.0-rc.1.20425.1</SystemIOPipelinesPackageVersion>
|
||||
<SystemNetHttpJsonPackageVersion>5.0.0-rc.1.20425.1</SystemNetHttpJsonPackageVersion>
|
||||
<SystemNetHttpWinHttpHandlerPackageVersion>5.0.0-rc.1.20425.1</SystemNetHttpWinHttpHandlerPackageVersion>
|
||||
<SystemNetWebSocketsWebSocketProtocolPackageVersion>5.0.0-rc.1.20425.1</SystemNetWebSocketsWebSocketProtocolPackageVersion>
|
||||
<SystemReflectionMetadataPackageVersion>5.0.0-rc.1.20425.1</SystemReflectionMetadataPackageVersion>
|
||||
<SystemResourcesExtensionsPackageVersion>5.0.0-rc.1.20425.1</SystemResourcesExtensionsPackageVersion>
|
||||
<SystemRuntimeCompilerServicesUnsafePackageVersion>5.0.0-rc.1.20425.1</SystemRuntimeCompilerServicesUnsafePackageVersion>
|
||||
<!-- System.Security.AccessControl should only be referenced in Dependencies.props and RTMVersions.csproj. -->
|
||||
<SystemSecurityAccessControlPackageVersion>5.0.0-rc.1.20416.7</SystemSecurityAccessControlPackageVersion>
|
||||
<SystemSecurityCryptographyCngPackageVersion>5.0.0-rc.1.20416.7</SystemSecurityCryptographyCngPackageVersion>
|
||||
<SystemSecurityCryptographyPkcsPackageVersion>5.0.0-rc.1.20416.7</SystemSecurityCryptographyPkcsPackageVersion>
|
||||
<SystemSecurityCryptographyXmlPackageVersion>5.0.0-rc.1.20416.7</SystemSecurityCryptographyXmlPackageVersion>
|
||||
<SystemSecurityPermissionsPackageVersion>5.0.0-rc.1.20416.7</SystemSecurityPermissionsPackageVersion>
|
||||
<SystemSecurityPrincipalWindowsPackageVersion>5.0.0-rc.1.20416.7</SystemSecurityPrincipalWindowsPackageVersion>
|
||||
<SystemServiceProcessServiceControllerPackageVersion>5.0.0-rc.1.20416.7</SystemServiceProcessServiceControllerPackageVersion>
|
||||
<SystemTextEncodingsWebPackageVersion>5.0.0-rc.1.20416.7</SystemTextEncodingsWebPackageVersion>
|
||||
<SystemTextJsonPackageVersion>5.0.0-rc.1.20416.7</SystemTextJsonPackageVersion>
|
||||
<SystemThreadingChannelsPackageVersion>5.0.0-rc.1.20416.7</SystemThreadingChannelsPackageVersion>
|
||||
<SystemWindowsExtensionsPackageVersion>5.0.0-rc.1.20416.7</SystemWindowsExtensionsPackageVersion>
|
||||
<SystemSecurityAccessControlPackageVersion>5.0.0-rc.1.20425.1</SystemSecurityAccessControlPackageVersion>
|
||||
<SystemSecurityCryptographyCngPackageVersion>5.0.0-rc.1.20425.1</SystemSecurityCryptographyCngPackageVersion>
|
||||
<SystemSecurityCryptographyPkcsPackageVersion>5.0.0-rc.1.20425.1</SystemSecurityCryptographyPkcsPackageVersion>
|
||||
<SystemSecurityCryptographyXmlPackageVersion>5.0.0-rc.1.20425.1</SystemSecurityCryptographyXmlPackageVersion>
|
||||
<SystemSecurityPermissionsPackageVersion>5.0.0-rc.1.20425.1</SystemSecurityPermissionsPackageVersion>
|
||||
<SystemSecurityPrincipalWindowsPackageVersion>5.0.0-rc.1.20425.1</SystemSecurityPrincipalWindowsPackageVersion>
|
||||
<SystemServiceProcessServiceControllerPackageVersion>5.0.0-rc.1.20425.1</SystemServiceProcessServiceControllerPackageVersion>
|
||||
<SystemTextEncodingsWebPackageVersion>5.0.0-rc.1.20425.1</SystemTextEncodingsWebPackageVersion>
|
||||
<SystemTextJsonPackageVersion>5.0.0-rc.1.20425.1</SystemTextJsonPackageVersion>
|
||||
<SystemThreadingChannelsPackageVersion>5.0.0-rc.1.20425.1</SystemThreadingChannelsPackageVersion>
|
||||
<SystemWindowsExtensionsPackageVersion>5.0.0-rc.1.20425.1</SystemWindowsExtensionsPackageVersion>
|
||||
<!-- Only listed explicitly to workaround https://github.com/dotnet/cli/issues/10528 -->
|
||||
<MicrosoftNETCorePlatformsPackageVersion>5.0.0-rc.1.20416.7</MicrosoftNETCorePlatformsPackageVersion>
|
||||
<MicrosoftNETCorePlatformsPackageVersion>5.0.0-rc.1.20425.1</MicrosoftNETCorePlatformsPackageVersion>
|
||||
<!-- Packages from dotnet/blazor -->
|
||||
<MicrosoftAspNetCoreComponentsWebAssemblyRuntimePackageVersion>3.2.0</MicrosoftAspNetCoreComponentsWebAssemblyRuntimePackageVersion>
|
||||
<!-- Packages from dotnet/efcore -->
|
||||
<dotnetefPackageVersion>5.0.0-rc.1.20417.2</dotnetefPackageVersion>
|
||||
<MicrosoftEntityFrameworkCoreInMemoryPackageVersion>5.0.0-rc.1.20417.2</MicrosoftEntityFrameworkCoreInMemoryPackageVersion>
|
||||
<MicrosoftEntityFrameworkCoreRelationalPackageVersion>5.0.0-rc.1.20417.2</MicrosoftEntityFrameworkCoreRelationalPackageVersion>
|
||||
<MicrosoftEntityFrameworkCoreSqlitePackageVersion>5.0.0-rc.1.20417.2</MicrosoftEntityFrameworkCoreSqlitePackageVersion>
|
||||
<MicrosoftEntityFrameworkCoreSqlServerPackageVersion>5.0.0-rc.1.20417.2</MicrosoftEntityFrameworkCoreSqlServerPackageVersion>
|
||||
<MicrosoftEntityFrameworkCoreToolsPackageVersion>5.0.0-rc.1.20417.2</MicrosoftEntityFrameworkCoreToolsPackageVersion>
|
||||
<MicrosoftEntityFrameworkCorePackageVersion>5.0.0-rc.1.20417.2</MicrosoftEntityFrameworkCorePackageVersion>
|
||||
<dotnetefPackageVersion>5.0.0-rc.1.20425.4</dotnetefPackageVersion>
|
||||
<MicrosoftEntityFrameworkCoreInMemoryPackageVersion>5.0.0-rc.1.20425.4</MicrosoftEntityFrameworkCoreInMemoryPackageVersion>
|
||||
<MicrosoftEntityFrameworkCoreRelationalPackageVersion>5.0.0-rc.1.20425.4</MicrosoftEntityFrameworkCoreRelationalPackageVersion>
|
||||
<MicrosoftEntityFrameworkCoreSqlitePackageVersion>5.0.0-rc.1.20425.4</MicrosoftEntityFrameworkCoreSqlitePackageVersion>
|
||||
<MicrosoftEntityFrameworkCoreSqlServerPackageVersion>5.0.0-rc.1.20425.4</MicrosoftEntityFrameworkCoreSqlServerPackageVersion>
|
||||
<MicrosoftEntityFrameworkCoreToolsPackageVersion>5.0.0-rc.1.20425.4</MicrosoftEntityFrameworkCoreToolsPackageVersion>
|
||||
<MicrosoftEntityFrameworkCorePackageVersion>5.0.0-rc.1.20425.4</MicrosoftEntityFrameworkCorePackageVersion>
|
||||
<MicrosoftEntityFrameworkCoreDesignPackageVersion>5.0.0-rc.1.20425.4</MicrosoftEntityFrameworkCoreDesignPackageVersion>
|
||||
</PropertyGroup>
|
||||
<!--
|
||||
|
||||
|
|
@ -250,11 +252,11 @@
|
|||
<GrpcAuthPackageVersion>2.27.0</GrpcAuthPackageVersion>
|
||||
<GrpcNetClientPackageVersion>2.27.0</GrpcNetClientPackageVersion>
|
||||
<GrpcToolsPackageVersion>2.27.0</GrpcToolsPackageVersion>
|
||||
<IdentityServer4AspNetIdentityPackageVersion>3.0.0</IdentityServer4AspNetIdentityPackageVersion>
|
||||
<IdentityServer4EntityFrameworkPackageVersion>3.0.0</IdentityServer4EntityFrameworkPackageVersion>
|
||||
<IdentityServer4PackageVersion>3.0.0</IdentityServer4PackageVersion>
|
||||
<IdentityServer4StoragePackageVersion>3.0.0</IdentityServer4StoragePackageVersion>
|
||||
<IdentityServer4EntityFrameworkStoragePackageVersion>3.0.0</IdentityServer4EntityFrameworkStoragePackageVersion>
|
||||
<IdentityServer4AspNetIdentityPackageVersion>4.0.4</IdentityServer4AspNetIdentityPackageVersion>
|
||||
<IdentityServer4EntityFrameworkPackageVersion>4.0.4</IdentityServer4EntityFrameworkPackageVersion>
|
||||
<IdentityServer4PackageVersion>4.0.4</IdentityServer4PackageVersion>
|
||||
<IdentityServer4StoragePackageVersion>4.0.4</IdentityServer4StoragePackageVersion>
|
||||
<IdentityServer4EntityFrameworkStoragePackageVersion>4.0.4</IdentityServer4EntityFrameworkStoragePackageVersion>
|
||||
<MessagePackPackageVersion>2.1.90</MessagePackPackageVersion>
|
||||
<MicrosoftIdentityWebPackageVersion>0.2.1-preview</MicrosoftIdentityWebPackageVersion>
|
||||
<MicrosoftIdentityWebUIPackageVersion>0.2.1-preview</MicrosoftIdentityWebUIPackageVersion>
|
||||
|
|
@ -273,6 +275,7 @@
|
|||
<SerilogSinksFilePackageVersion>4.0.0</SerilogSinksFilePackageVersion>
|
||||
<StackExchangeRedisPackageVersion>2.0.593</StackExchangeRedisPackageVersion>
|
||||
<SystemReactiveLinqPackageVersion>3.1.1</SystemReactiveLinqPackageVersion>
|
||||
<SwashbuckleAspNetCorePackageVersion>5.5.1</SwashbuckleAspNetCorePackageVersion>
|
||||
<XunitAbstractionsPackageVersion>2.0.3</XunitAbstractionsPackageVersion>
|
||||
<XunitAnalyzersPackageVersion>0.10.0</XunitAnalyzersPackageVersion>
|
||||
<XunitVersion>2.4.1</XunitVersion>
|
||||
|
|
|
|||
|
|
@ -19,7 +19,9 @@ if(TARGET_ARCH_NAME STREQUAL "armel")
|
|||
endif()
|
||||
elseif(TARGET_ARCH_NAME STREQUAL "arm")
|
||||
set(CMAKE_SYSTEM_PROCESSOR armv7l)
|
||||
if(EXISTS ${CROSS_ROOTFS}/usr/lib/gcc/armv6-alpine-linux-musleabihf)
|
||||
if(EXISTS ${CROSS_ROOTFS}/usr/lib/gcc/armv7-alpine-linux-musleabihf)
|
||||
set(TOOLCHAIN "armv7-alpine-linux-musleabihf")
|
||||
elseif(EXISTS ${CROSS_ROOTFS}/usr/lib/gcc/armv6-alpine-linux-musleabihf)
|
||||
set(TOOLCHAIN "armv6-alpine-linux-musleabihf")
|
||||
else()
|
||||
set(TOOLCHAIN "arm-linux-gnueabihf")
|
||||
|
|
|
|||
|
|
@ -199,14 +199,15 @@ if [[ "$mono_dotnet" != "" ]]; then
|
|||
fi
|
||||
|
||||
if [[ "$wasm_runtime_loc" != "" ]]; then
|
||||
configurations="CompilationMode=wasm;RunKind=micro"
|
||||
configurations="CompilationMode=wasm RunKind=micro"
|
||||
extra_benchmark_dotnet_arguments="$extra_benchmark_dotnet_arguments --category-exclusion-filter NoInterpreter NoWASM"
|
||||
fi
|
||||
|
||||
if [[ "$monointerpreter" == "true" ]]; then
|
||||
extra_benchmark_dotnet_arguments="$extra_benchmark_dotnet_arguments --category-exclusion-filter NoInterpreter"
|
||||
fi
|
||||
|
||||
common_setup_arguments="--channel master --queue $queue --build-number $build_number --build-configs \"$configurations\" --architecture $architecture"
|
||||
common_setup_arguments="--channel master --queue $queue --build-number $build_number --build-configs $configurations --architecture $architecture"
|
||||
setup_arguments="--repository https://github.com/$repository --branch $branch --get-perf-hash --commit-sha $commit_sha $common_setup_arguments"
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,12 +1,13 @@
|
|||
param(
|
||||
[Parameter(Mandatory=$true)][int] $BuildId,
|
||||
[Parameter(Mandatory=$true)][int] $PublishingInfraVersion,
|
||||
[Parameter(Mandatory=$true)][string] $AzdoToken,
|
||||
[Parameter(Mandatory=$true)][string] $MaestroToken,
|
||||
[Parameter(Mandatory=$false)][string] $MaestroApiEndPoint = 'https://maestro-prod.westus2.cloudapp.azure.com',
|
||||
[Parameter(Mandatory=$true)][string] $WaitPublishingFinish,
|
||||
[Parameter(Mandatory=$true)][string] $EnableSourceLinkValidation,
|
||||
[Parameter(Mandatory=$true)][string] $EnableSigningValidation,
|
||||
[Parameter(Mandatory=$true)][string] $EnableNugetValidation,
|
||||
[Parameter(Mandatory=$false)][string] $EnableSourceLinkValidation,
|
||||
[Parameter(Mandatory=$false)][string] $EnableSigningValidation,
|
||||
[Parameter(Mandatory=$false)][string] $EnableNugetValidation,
|
||||
[Parameter(Mandatory=$true)][string] $PublishInstallersAndChecksums,
|
||||
[Parameter(Mandatory=$false)][string] $ArtifactsPublishingAdditionalParameters,
|
||||
[Parameter(Mandatory=$false)][string] $SigningValidationAdditionalParameters
|
||||
|
|
@ -14,7 +15,8 @@ param(
|
|||
|
||||
try {
|
||||
. $PSScriptRoot\post-build-utils.ps1
|
||||
. $PSScriptRoot\..\darc-init.ps1
|
||||
# Hard coding darc version till the next arcade-services roll out, cos this version has required API changes for darc add-build-to-channel
|
||||
. $PSScriptRoot\..\darc-init.ps1 -darcVersion "1.1.0-beta.20418.1"
|
||||
|
||||
$optionalParams = [System.Collections.ArrayList]::new()
|
||||
|
||||
|
|
@ -49,12 +51,13 @@ try {
|
|||
}
|
||||
|
||||
& darc add-build-to-channel `
|
||||
--id $buildId `
|
||||
--default-channels `
|
||||
--source-branch master `
|
||||
--azdev-pat $AzdoToken `
|
||||
--bar-uri $MaestroApiEndPoint `
|
||||
--password $MaestroToken `
|
||||
--id $buildId `
|
||||
--publishing-infra-version $PublishingInfraVersion `
|
||||
--default-channels `
|
||||
--source-branch master `
|
||||
--azdev-pat $AzdoToken `
|
||||
--bar-uri $MaestroApiEndPoint `
|
||||
--password $MaestroToken `
|
||||
@optionalParams
|
||||
|
||||
if ($LastExitCode -ne 0) {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
parameters:
|
||||
BARBuildId: ''
|
||||
PromoteToChannelIds: ''
|
||||
artifactsPublishingAdditionalParameters: ''
|
||||
dependsOn:
|
||||
- Validate
|
||||
|
|
@ -19,6 +21,9 @@ stages:
|
|||
displayName: ${{ parameters.channelName }} Publishing
|
||||
jobs:
|
||||
- template: ../setup-maestro-vars.yml
|
||||
parameters:
|
||||
BARBuildId: ${{ parameters.BARBuildId }}
|
||||
PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }}
|
||||
|
||||
- job: publish_symbols
|
||||
displayName: Symbol Publishing
|
||||
|
|
@ -138,6 +143,7 @@ stages:
|
|||
inputs:
|
||||
filePath: eng\common\sdk-task.ps1
|
||||
arguments: -task PublishArtifactsInManifest -restore -msbuildEngine dotnet
|
||||
/p:PublishingInfraVersion=2
|
||||
/p:IsStableBuild=$(IsStableBuild)
|
||||
/p:IsInternalBuild=$(IsInternalBuild)
|
||||
/p:RepositoryName=$(Build.Repository.Name)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
parameters:
|
||||
BARBuildId: ''
|
||||
PromoteToChannelIds: ''
|
||||
artifactsPublishingAdditionalParameters: ''
|
||||
dependsOn:
|
||||
- Validate
|
||||
|
|
@ -21,6 +23,9 @@ stages:
|
|||
displayName: ${{ parameters.channelName }} Publishing
|
||||
jobs:
|
||||
- template: ../setup-maestro-vars.yml
|
||||
parameters:
|
||||
BARBuildId: ${{ parameters.BARBuildId }}
|
||||
PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }}
|
||||
|
||||
- job: publish_symbols
|
||||
displayName: Symbol Publishing
|
||||
|
|
@ -137,6 +142,7 @@ stages:
|
|||
inputs:
|
||||
filePath: eng\common\sdk-task.ps1
|
||||
arguments: -task PublishArtifactsInManifest -restore -msbuildEngine dotnet
|
||||
/p:PublishingInfraVersion=2
|
||||
/p:ArtifactsCategory=$(ArtifactsCategory)
|
||||
/p:IsStableBuild=$(IsStableBuild)
|
||||
/p:IsInternalBuild=$(IsInternalBuild)
|
||||
|
|
|
|||
|
|
@ -1,13 +1,20 @@
|
|||
parameters:
|
||||
# Which publishing infra should be used. THIS SHOULD MATCH THE VERSION ON THE BUILD MANIFEST.
|
||||
# Publishing V2 accepts optionally outlining the publishing stages - default is inline.
|
||||
# Publishing V3 DOES NOT accept inlining the publishing stages.
|
||||
publishingInfraVersion: 2
|
||||
# When set to true the publishing templates from the repo will be used
|
||||
# otherwise Darc add-build-to-channel will be used to trigger the promotion pipeline
|
||||
inline: true
|
||||
|
||||
# Only used if inline==false. When set to true will stall the current build until
|
||||
# the Promotion Pipeline build finishes. Otherwise, the current build continue
|
||||
# the Promotion Pipeline build finishes. Otherwise, the current build will continue
|
||||
# execution concurrently with the promotion build.
|
||||
waitPublishingFinish: true
|
||||
|
||||
BARBuildId: ''
|
||||
PromoteToChannelIds: ''
|
||||
|
||||
enableSourceLinkValidation: false
|
||||
enableSigningValidation: true
|
||||
enableSymbolValidation: false
|
||||
|
|
@ -39,6 +46,7 @@ parameters:
|
|||
NetEngLatestChannelId: 2
|
||||
NetEngValidationChannelId: 9
|
||||
NetDev5ChannelId: 131
|
||||
NetDev6ChannelId: 1296
|
||||
GeneralTestingChannelId: 529
|
||||
NETCoreToolingDevChannelId: 548
|
||||
NETCoreToolingReleaseChannelId: 549
|
||||
|
|
@ -46,7 +54,6 @@ parameters:
|
|||
NETCoreExperimentalChannelId: 562
|
||||
NetEngServicesIntChannelId: 678
|
||||
NetEngServicesProdChannelId: 679
|
||||
Net5Preview7ChannelId: 1065
|
||||
Net5Preview8ChannelId: 1155
|
||||
Net5RC1ChannelId: 1157
|
||||
NetCoreSDK313xxChannelId: 759
|
||||
|
|
@ -59,14 +66,183 @@ parameters:
|
|||
VSMasterChannelId: 1012
|
||||
|
||||
stages:
|
||||
- ${{ if ne(parameters.inline, 'true') }}:
|
||||
- stage: Validate
|
||||
dependsOn: ${{ parameters.validateDependsOn }}
|
||||
displayName: Validate Build Assets
|
||||
variables:
|
||||
- template: common-variables.yml
|
||||
jobs:
|
||||
- template: setup-maestro-vars.yml
|
||||
parameters:
|
||||
BARBuildId: ${{ parameters.BARBuildId }}
|
||||
PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }}
|
||||
|
||||
- job:
|
||||
displayName: Post-build Checks
|
||||
dependsOn: setupMaestroVars
|
||||
variables:
|
||||
- name: TargetChannels
|
||||
value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.TargetChannels'] ]
|
||||
pool:
|
||||
vmImage: 'windows-2019'
|
||||
steps:
|
||||
- task: PowerShell@2
|
||||
displayName: Maestro Channels Consistency
|
||||
inputs:
|
||||
filePath: $(Build.SourcesDirectory)/eng/common/post-build/check-channel-consistency.ps1
|
||||
arguments: -PromoteToChannels "$(TargetChannels)"
|
||||
-AvailableChannelIds ${{parameters.NetEngLatestChannelId}},${{parameters.NetEngValidationChannelId}},${{parameters.NetDev5ChannelId}},${{parameters.NetDev6ChannelId}},${{parameters.GeneralTestingChannelId}},${{parameters.NETCoreToolingDevChannelId}},${{parameters.NETCoreToolingReleaseChannelId}},${{parameters.NETInternalToolingChannelId}},${{parameters.NETCoreExperimentalChannelId}},${{parameters.NetEngServicesIntChannelId}},${{parameters.NetEngServicesProdChannelId}},${{parameters.Net5Preview8ChannelId}},${{parameters.Net5RC1ChannelId}},${{parameters.NetCoreSDK313xxChannelId}},${{parameters.NetCoreSDK313xxInternalChannelId}},${{parameters.NetCoreSDK314xxChannelId}},${{parameters.NetCoreSDK314xxInternalChannelId}},${{parameters.VS166ChannelId}},${{parameters.VS167ChannelId}},${{parameters.VS168ChannelId}},${{parameters.VSMasterChannelId}}
|
||||
|
||||
- job:
|
||||
displayName: NuGet Validation
|
||||
dependsOn: setupMaestroVars
|
||||
condition: eq( ${{ parameters.enableNugetValidation }}, 'true')
|
||||
pool:
|
||||
vmImage: 'windows-2019'
|
||||
variables:
|
||||
- name: AzDOProjectName
|
||||
value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOProjectName'] ]
|
||||
- name: AzDOPipelineId
|
||||
value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOPipelineId'] ]
|
||||
- name: AzDOBuildId
|
||||
value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOBuildId'] ]
|
||||
steps:
|
||||
- task: DownloadBuildArtifacts@0
|
||||
displayName: Download Package Artifacts
|
||||
inputs:
|
||||
buildType: specific
|
||||
buildVersionToDownload: specific
|
||||
project: $(AzDOProjectName)
|
||||
pipeline: $(AzDOPipelineId)
|
||||
buildId: $(AzDOBuildId)
|
||||
artifactName: PackageArtifacts
|
||||
|
||||
- task: PowerShell@2
|
||||
displayName: Validate
|
||||
inputs:
|
||||
filePath: $(Build.SourcesDirectory)/eng/common/post-build/nuget-validation.ps1
|
||||
arguments: -PackagesPath $(Build.ArtifactStagingDirectory)/PackageArtifacts/
|
||||
-ToolDestinationPath $(Agent.BuildDirectory)/Extract/
|
||||
|
||||
- job:
|
||||
displayName: Signing Validation
|
||||
dependsOn: setupMaestroVars
|
||||
condition: eq( ${{ parameters.enableSigningValidation }}, 'true')
|
||||
variables:
|
||||
- template: common-variables.yml
|
||||
- name: AzDOProjectName
|
||||
value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOProjectName'] ]
|
||||
- name: AzDOPipelineId
|
||||
value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOPipelineId'] ]
|
||||
- name: AzDOBuildId
|
||||
value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOBuildId'] ]
|
||||
pool:
|
||||
vmImage: 'windows-2019'
|
||||
steps:
|
||||
- ${{ if eq(parameters.useBuildManifest, true) }}:
|
||||
- task: DownloadBuildArtifacts@0
|
||||
displayName: Download build manifest
|
||||
inputs:
|
||||
buildType: specific
|
||||
buildVersionToDownload: specific
|
||||
project: $(AzDOProjectName)
|
||||
pipeline: $(AzDOPipelineId)
|
||||
buildId: $(AzDOBuildId)
|
||||
artifactName: BuildManifests
|
||||
- task: DownloadBuildArtifacts@0
|
||||
displayName: Download Package Artifacts
|
||||
inputs:
|
||||
buildType: specific
|
||||
buildVersionToDownload: specific
|
||||
project: $(AzDOProjectName)
|
||||
pipeline: $(AzDOPipelineId)
|
||||
buildId: $(AzDOBuildId)
|
||||
artifactName: PackageArtifacts
|
||||
|
||||
# This is necessary whenever we want to publish/restore to an AzDO private feed
|
||||
# Since sdk-task.ps1 tries to restore packages we need to do this authentication here
|
||||
# otherwise it'll complain about accessing a 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)
|
||||
|
||||
# Signing validation will optionally work with the buildmanifest file which is downloaded from
|
||||
# Azure DevOps above.
|
||||
- task: PowerShell@2
|
||||
displayName: Validate
|
||||
inputs:
|
||||
filePath: eng\common\sdk-task.ps1
|
||||
arguments: -task SigningValidation -restore -msbuildEngine vs
|
||||
/p:PackageBasePath='$(Build.ArtifactStagingDirectory)/PackageArtifacts'
|
||||
/p:SignCheckExclusionsFile='$(Build.SourcesDirectory)/eng/SignCheckExclusionsFile.txt'
|
||||
${{ parameters.signingValidationAdditionalParameters }}
|
||||
|
||||
- template: ../steps/publish-logs.yml
|
||||
parameters:
|
||||
StageLabel: 'Validation'
|
||||
JobLabel: 'Signing'
|
||||
|
||||
- job:
|
||||
displayName: SourceLink Validation
|
||||
dependsOn: setupMaestroVars
|
||||
condition: eq( ${{ parameters.enableSourceLinkValidation }}, 'true')
|
||||
variables:
|
||||
- template: common-variables.yml
|
||||
- name: AzDOProjectName
|
||||
value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOProjectName'] ]
|
||||
- name: AzDOPipelineId
|
||||
value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOPipelineId'] ]
|
||||
- name: AzDOBuildId
|
||||
value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOBuildId'] ]
|
||||
pool:
|
||||
vmImage: 'windows-2019'
|
||||
steps:
|
||||
- task: DownloadBuildArtifacts@0
|
||||
displayName: Download Blob Artifacts
|
||||
inputs:
|
||||
buildType: specific
|
||||
buildVersionToDownload: specific
|
||||
project: $(AzDOProjectName)
|
||||
pipeline: $(AzDOPipelineId)
|
||||
buildId: $(AzDOBuildId)
|
||||
artifactName: BlobArtifacts
|
||||
|
||||
- task: PowerShell@2
|
||||
displayName: Validate
|
||||
inputs:
|
||||
filePath: $(Build.SourcesDirectory)/eng/common/post-build/sourcelink-validation.ps1
|
||||
arguments: -InputPath $(Build.ArtifactStagingDirectory)/BlobArtifacts/
|
||||
-ExtractPath $(Agent.BuildDirectory)/Extract/
|
||||
-GHRepoName $(Build.Repository.Name)
|
||||
-GHCommit $(Build.SourceVersion)
|
||||
-SourcelinkCliVersion $(SourceLinkCLIVersion)
|
||||
continueOnError: true
|
||||
|
||||
- template: /eng/common/templates/job/execute-sdl.yml
|
||||
parameters:
|
||||
enable: ${{ parameters.SDLValidationParameters.enable }}
|
||||
dependsOn: setupMaestroVars
|
||||
additionalParameters: ${{ parameters.SDLValidationParameters.params }}
|
||||
continueOnError: ${{ parameters.SDLValidationParameters.continueOnError }}
|
||||
artifactNames: ${{ parameters.SDLValidationParameters.artifactNames }}
|
||||
downloadArtifacts: ${{ parameters.SDLValidationParameters.downloadArtifacts }}
|
||||
|
||||
- ${{ if or(ge(parameters.publishingInfraVersion, 3), eq(parameters.inline, 'false')) }}:
|
||||
- stage: publish_using_darc
|
||||
dependsOn: ${{ parameters.validateDependsOn }}
|
||||
dependsOn: Validate
|
||||
displayName: Publish using Darc
|
||||
variables:
|
||||
- template: common-variables.yml
|
||||
jobs:
|
||||
- template: setup-maestro-vars.yml
|
||||
parameters:
|
||||
BARBuildId: ${{ parameters.BARBuildId }}
|
||||
PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }}
|
||||
|
||||
- job:
|
||||
displayName: Publish Using Darc
|
||||
|
|
@ -82,182 +258,17 @@ stages:
|
|||
inputs:
|
||||
filePath: $(Build.SourcesDirectory)/eng/common/post-build/publish-using-darc.ps1
|
||||
arguments: -BuildId $(BARBuildId)
|
||||
-PublishingInfraVersion ${{ parameters.PublishingInfraVersion }}
|
||||
-AzdoToken '$(publishing-dnceng-devdiv-code-r-build-re)'
|
||||
-MaestroToken '$(MaestroApiAccessToken)'
|
||||
-WaitPublishingFinish ${{ parameters.waitPublishingFinish }}
|
||||
-EnableSourceLinkValidation ${{ parameters.enableSourceLinkValidation }}
|
||||
-EnableSigningValidation ${{ parameters.enableSourceLinkValidation }}
|
||||
-EnableNugetValidation ${{ parameters.enableSourceLinkValidation }}
|
||||
-PublishInstallersAndChecksums ${{ parameters.publishInstallersAndChecksums }}
|
||||
-ArtifactsPublishingAdditionalParameters '${{ parameters.artifactsPublishingAdditionalParameters }}'
|
||||
-SigningValidationAdditionalParameters '${{ parameters.signingValidationAdditionalParameters }}'
|
||||
|
||||
- ${{ if eq(parameters.inline, 'true') }}:
|
||||
- stage: Validate
|
||||
dependsOn: ${{ parameters.validateDependsOn }}
|
||||
displayName: Validate Build Assets
|
||||
variables:
|
||||
- template: common-variables.yml
|
||||
jobs:
|
||||
- template: setup-maestro-vars.yml
|
||||
|
||||
- job:
|
||||
displayName: Post-build Checks
|
||||
dependsOn: setupMaestroVars
|
||||
variables:
|
||||
- name: TargetChannels
|
||||
value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.TargetChannels'] ]
|
||||
pool:
|
||||
vmImage: 'windows-2019'
|
||||
steps:
|
||||
- task: PowerShell@2
|
||||
displayName: Maestro Channels Consistency
|
||||
inputs:
|
||||
filePath: $(Build.SourcesDirectory)/eng/common/post-build/check-channel-consistency.ps1
|
||||
arguments: -PromoteToChannels "$(TargetChannels)"
|
||||
-AvailableChannelIds ${{parameters.NetEngLatestChannelId}},${{parameters.NetEngValidationChannelId}},${{parameters.NetDev5ChannelId}},${{parameters.GeneralTestingChannelId}},${{parameters.NETCoreToolingDevChannelId}},${{parameters.NETCoreToolingReleaseChannelId}},${{parameters.NETInternalToolingChannelId}},${{parameters.NETCoreExperimentalChannelId}},${{parameters.NetEngServicesIntChannelId}},${{parameters.NetEngServicesProdChannelId}},${{parameters.Net5Preview7ChannelId}},${{parameters.Net5Preview8ChannelId}},${{parameters.Net5RC1ChannelId}},${{parameters.NetCoreSDK313xxChannelId}},${{parameters.NetCoreSDK313xxInternalChannelId}},${{parameters.NetCoreSDK314xxChannelId}},${{parameters.NetCoreSDK314xxInternalChannelId}},${{parameters.VS166ChannelId}},${{parameters.VS167ChannelId}},${{parameters.VS168ChannelId}},${{parameters.VSMasterChannelId}}
|
||||
|
||||
- job:
|
||||
displayName: NuGet Validation
|
||||
dependsOn: setupMaestroVars
|
||||
condition: eq( ${{ parameters.enableNugetValidation }}, 'true')
|
||||
pool:
|
||||
vmImage: 'windows-2019'
|
||||
variables:
|
||||
- name: AzDOProjectName
|
||||
value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOProjectName'] ]
|
||||
- name: AzDOPipelineId
|
||||
value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOPipelineId'] ]
|
||||
- name: AzDOBuildId
|
||||
value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOBuildId'] ]
|
||||
steps:
|
||||
- task: DownloadBuildArtifacts@0
|
||||
displayName: Download Package Artifacts
|
||||
inputs:
|
||||
buildType: specific
|
||||
buildVersionToDownload: specific
|
||||
project: $(AzDOProjectName)
|
||||
pipeline: $(AzDOPipelineId)
|
||||
buildId: $(AzDOBuildId)
|
||||
artifactName: PackageArtifacts
|
||||
|
||||
- task: PowerShell@2
|
||||
displayName: Validate
|
||||
inputs:
|
||||
filePath: $(Build.SourcesDirectory)/eng/common/post-build/nuget-validation.ps1
|
||||
arguments: -PackagesPath $(Build.ArtifactStagingDirectory)/PackageArtifacts/
|
||||
-ToolDestinationPath $(Agent.BuildDirectory)/Extract/
|
||||
|
||||
- job:
|
||||
displayName: Signing Validation
|
||||
dependsOn: setupMaestroVars
|
||||
condition: eq( ${{ parameters.enableSigningValidation }}, 'true')
|
||||
variables:
|
||||
- template: common-variables.yml
|
||||
- name: AzDOProjectName
|
||||
value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOProjectName'] ]
|
||||
- name: AzDOPipelineId
|
||||
value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOPipelineId'] ]
|
||||
- name: AzDOBuildId
|
||||
value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOBuildId'] ]
|
||||
pool:
|
||||
vmImage: 'windows-2019'
|
||||
steps:
|
||||
- ${{ if eq(parameters.useBuildManifest, true) }}:
|
||||
- task: DownloadBuildArtifacts@0
|
||||
displayName: Download build manifest
|
||||
inputs:
|
||||
buildType: specific
|
||||
buildVersionToDownload: specific
|
||||
project: $(AzDOProjectName)
|
||||
pipeline: $(AzDOPipelineId)
|
||||
buildId: $(AzDOBuildId)
|
||||
artifactName: BuildManifests
|
||||
- task: DownloadBuildArtifacts@0
|
||||
displayName: Download Package Artifacts
|
||||
inputs:
|
||||
buildType: specific
|
||||
buildVersionToDownload: specific
|
||||
project: $(AzDOProjectName)
|
||||
pipeline: $(AzDOPipelineId)
|
||||
buildId: $(AzDOBuildId)
|
||||
artifactName: PackageArtifacts
|
||||
|
||||
# This is necessary whenever we want to publish/restore to an AzDO private feed
|
||||
# Since sdk-task.ps1 tries to restore packages we need to do this authentication here
|
||||
# otherwise it'll complain about accessing a 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)
|
||||
|
||||
# Signing validation will optionally work with the buildmanifest file which is downloaded from
|
||||
# Azure DevOps above.
|
||||
- task: PowerShell@2
|
||||
displayName: Validate
|
||||
inputs:
|
||||
filePath: eng\common\sdk-task.ps1
|
||||
arguments: -task SigningValidation -restore -msbuildEngine vs
|
||||
/p:PackageBasePath='$(Build.ArtifactStagingDirectory)/PackageArtifacts'
|
||||
/p:SignCheckExclusionsFile='$(Build.SourcesDirectory)/eng/SignCheckExclusionsFile.txt'
|
||||
${{ parameters.signingValidationAdditionalParameters }}
|
||||
|
||||
- template: ../steps/publish-logs.yml
|
||||
parameters:
|
||||
StageLabel: 'Validation'
|
||||
JobLabel: 'Signing'
|
||||
|
||||
- job:
|
||||
displayName: SourceLink Validation
|
||||
dependsOn: setupMaestroVars
|
||||
condition: eq( ${{ parameters.enableSourceLinkValidation }}, 'true')
|
||||
variables:
|
||||
- template: common-variables.yml
|
||||
- name: AzDOProjectName
|
||||
value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOProjectName'] ]
|
||||
- name: AzDOPipelineId
|
||||
value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOPipelineId'] ]
|
||||
- name: AzDOBuildId
|
||||
value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOBuildId'] ]
|
||||
pool:
|
||||
vmImage: 'windows-2019'
|
||||
steps:
|
||||
- task: DownloadBuildArtifacts@0
|
||||
displayName: Download Blob Artifacts
|
||||
inputs:
|
||||
buildType: specific
|
||||
buildVersionToDownload: specific
|
||||
project: $(AzDOProjectName)
|
||||
pipeline: $(AzDOPipelineId)
|
||||
buildId: $(AzDOBuildId)
|
||||
artifactName: BlobArtifacts
|
||||
|
||||
- task: PowerShell@2
|
||||
displayName: Validate
|
||||
inputs:
|
||||
filePath: $(Build.SourcesDirectory)/eng/common/post-build/sourcelink-validation.ps1
|
||||
arguments: -InputPath $(Build.ArtifactStagingDirectory)/BlobArtifacts/
|
||||
-ExtractPath $(Agent.BuildDirectory)/Extract/
|
||||
-GHRepoName $(Build.Repository.Name)
|
||||
-GHCommit $(Build.SourceVersion)
|
||||
-SourcelinkCliVersion $(SourceLinkCLIVersion)
|
||||
continueOnError: true
|
||||
|
||||
- template: /eng/common/templates/job/execute-sdl.yml
|
||||
parameters:
|
||||
enable: ${{ parameters.SDLValidationParameters.enable }}
|
||||
dependsOn: setupMaestroVars
|
||||
additionalParameters: ${{ parameters.SDLValidationParameters.params }}
|
||||
continueOnError: ${{ parameters.SDLValidationParameters.continueOnError }}
|
||||
artifactNames: ${{ parameters.SDLValidationParameters.artifactNames }}
|
||||
downloadArtifacts: ${{ parameters.SDLValidationParameters.downloadArtifacts }}
|
||||
|
||||
- ${{ if and(le(parameters.publishingInfraVersion, 2), eq(parameters.inline, 'true')) }}:
|
||||
- template: \eng\common\templates\post-build\channels\generic-public-channel.yml
|
||||
parameters:
|
||||
BARBuildId: ${{ parameters.BARBuildId }}
|
||||
PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }}
|
||||
artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
|
||||
dependsOn: ${{ parameters.publishDependsOn }}
|
||||
publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
|
||||
|
|
@ -272,20 +283,24 @@ stages:
|
|||
|
||||
- template: \eng\common\templates\post-build\channels\generic-public-channel.yml
|
||||
parameters:
|
||||
BARBuildId: ${{ parameters.BARBuildId }}
|
||||
PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }}
|
||||
artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
|
||||
dependsOn: ${{ parameters.publishDependsOn }}
|
||||
publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
|
||||
symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }}
|
||||
stageName: 'Net5_Preview7_Publish'
|
||||
channelName: '.NET 5 Preview 7'
|
||||
akaMSChannelName: 'net5/preview7'
|
||||
channelId: ${{ parameters.Net5Preview7ChannelId }}
|
||||
transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet5-transport/nuget/v3/index.json'
|
||||
shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet5/nuget/v3/index.json'
|
||||
symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet5-symbols/nuget/v3/index.json'
|
||||
stageName: 'NetCore_Dev6_Publish'
|
||||
channelName: '.NET 6 Dev'
|
||||
akaMSChannelName: 'net6/dev'
|
||||
channelId: ${{ parameters.NetDev6ChannelId }}
|
||||
transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet6-transport/nuget/v3/index.json'
|
||||
shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet6/nuget/v3/index.json'
|
||||
symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet6-symbols/nuget/v3/index.json'
|
||||
|
||||
- template: \eng\common\templates\post-build\channels\generic-internal-channel.yml
|
||||
parameters:
|
||||
BARBuildId: ${{ parameters.BARBuildId }}
|
||||
PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }}
|
||||
artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
|
||||
dependsOn: ${{ parameters.publishDependsOn }}
|
||||
publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
|
||||
|
|
@ -298,8 +313,10 @@ stages:
|
|||
shippingFeed: 'https://pkgs.dev.azure.com/dnceng/internal/_packaging/dotnet5-internal/nuget/v3/index.json'
|
||||
symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/internal/_packaging/dotnet5-internal-symbols/nuget/v3/index.json'
|
||||
|
||||
- template: \eng\common\templates\post-build\channels\generic-internal-channel.yml
|
||||
- template: \eng\common\templates\post-build\channels\generic-public-channel.yml
|
||||
parameters:
|
||||
BARBuildId: ${{ parameters.BARBuildId }}
|
||||
PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }}
|
||||
artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
|
||||
dependsOn: ${{ parameters.publishDependsOn }}
|
||||
publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
|
||||
|
|
@ -308,12 +325,14 @@ stages:
|
|||
channelName: '.NET 5 RC 1'
|
||||
akaMSChannelName: 'net5/rc1'
|
||||
channelId: ${{ parameters.Net5RC1ChannelId }}
|
||||
transportFeed: 'https://pkgs.dev.azure.com/dnceng/internal/_packaging/dotnet5-internal-transport/nuget/v3/index.json'
|
||||
shippingFeed: 'https://pkgs.dev.azure.com/dnceng/internal/_packaging/dotnet5-internal/nuget/v3/index.json'
|
||||
symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/internal/_packaging/dotnet5-internal-symbols/nuget/v3/index.json'
|
||||
transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet5-transport/nuget/v3/index.json'
|
||||
shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet5/nuget/v3/index.json'
|
||||
symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet5-symbols/nuget/v3/index.json'
|
||||
|
||||
- template: \eng\common\templates\post-build\channels\generic-public-channel.yml
|
||||
parameters:
|
||||
BARBuildId: ${{ parameters.BARBuildId }}
|
||||
PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }}
|
||||
artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
|
||||
dependsOn: ${{ parameters.publishDependsOn }}
|
||||
publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
|
||||
|
|
@ -328,6 +347,8 @@ stages:
|
|||
|
||||
- template: \eng\common\templates\post-build\channels\generic-public-channel.yml
|
||||
parameters:
|
||||
BARBuildId: ${{ parameters.BARBuildId }}
|
||||
PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }}
|
||||
artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
|
||||
dependsOn: ${{ parameters.publishDependsOn }}
|
||||
publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
|
||||
|
|
@ -342,6 +363,8 @@ stages:
|
|||
|
||||
- template: \eng\common\templates\post-build\channels\generic-public-channel.yml
|
||||
parameters:
|
||||
BARBuildId: ${{ parameters.BARBuildId }}
|
||||
PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }}
|
||||
artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
|
||||
dependsOn: ${{ parameters.publishDependsOn }}
|
||||
publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
|
||||
|
|
@ -356,6 +379,8 @@ stages:
|
|||
|
||||
- template: \eng\common\templates\post-build\channels\generic-public-channel.yml
|
||||
parameters:
|
||||
BARBuildId: ${{ parameters.BARBuildId }}
|
||||
PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }}
|
||||
artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
|
||||
dependsOn: ${{ parameters.publishDependsOn }}
|
||||
publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
|
||||
|
|
@ -369,6 +394,8 @@ stages:
|
|||
|
||||
- template: \eng\common\templates\post-build\channels\generic-public-channel.yml
|
||||
parameters:
|
||||
BARBuildId: ${{ parameters.BARBuildId }}
|
||||
PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }}
|
||||
artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
|
||||
dependsOn: ${{ parameters.publishDependsOn }}
|
||||
publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
|
||||
|
|
@ -382,6 +409,8 @@ stages:
|
|||
|
||||
- template: \eng\common\templates\post-build\channels\generic-internal-channel.yml
|
||||
parameters:
|
||||
BARBuildId: ${{ parameters.BARBuildId }}
|
||||
PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }}
|
||||
artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
|
||||
dependsOn: ${{ parameters.publishDependsOn }}
|
||||
publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
|
||||
|
|
@ -395,6 +424,8 @@ stages:
|
|||
|
||||
- template: \eng\common\templates\post-build\channels\generic-public-channel.yml
|
||||
parameters:
|
||||
BARBuildId: ${{ parameters.BARBuildId }}
|
||||
PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }}
|
||||
artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
|
||||
dependsOn: ${{ parameters.publishDependsOn }}
|
||||
publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
|
||||
|
|
@ -408,6 +439,8 @@ stages:
|
|||
|
||||
- template: \eng\common\templates\post-build\channels\generic-public-channel.yml
|
||||
parameters:
|
||||
BARBuildId: ${{ parameters.BARBuildId }}
|
||||
PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }}
|
||||
artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
|
||||
dependsOn: ${{ parameters.publishDependsOn }}
|
||||
publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
|
||||
|
|
@ -421,6 +454,8 @@ stages:
|
|||
|
||||
- template: \eng\common\templates\post-build\channels\generic-public-channel.yml
|
||||
parameters:
|
||||
BARBuildId: ${{ parameters.BARBuildId }}
|
||||
PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }}
|
||||
artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
|
||||
dependsOn: ${{ parameters.publishDependsOn }}
|
||||
publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
|
||||
|
|
@ -434,6 +469,8 @@ stages:
|
|||
|
||||
- template: \eng\common\templates\post-build\channels\generic-public-channel.yml
|
||||
parameters:
|
||||
BARBuildId: ${{ parameters.BARBuildId }}
|
||||
PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }}
|
||||
artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
|
||||
dependsOn: ${{ parameters.publishDependsOn }}
|
||||
publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
|
||||
|
|
@ -447,6 +484,8 @@ stages:
|
|||
|
||||
- template: \eng\common\templates\post-build\channels\generic-internal-channel.yml
|
||||
parameters:
|
||||
BARBuildId: ${{ parameters.BARBuildId }}
|
||||
PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }}
|
||||
artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
|
||||
dependsOn: ${{ parameters.publishDependsOn }}
|
||||
publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
|
||||
|
|
@ -460,6 +499,8 @@ stages:
|
|||
|
||||
- template: \eng\common\templates\post-build\channels\generic-public-channel.yml
|
||||
parameters:
|
||||
BARBuildId: ${{ parameters.BARBuildId }}
|
||||
PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }}
|
||||
artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
|
||||
dependsOn: ${{ parameters.publishDependsOn }}
|
||||
publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
|
||||
|
|
@ -473,6 +514,8 @@ stages:
|
|||
|
||||
- template: \eng\common\templates\post-build\channels\generic-internal-channel.yml
|
||||
parameters:
|
||||
BARBuildId: ${{ parameters.BARBuildId }}
|
||||
PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }}
|
||||
artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
|
||||
dependsOn: ${{ parameters.publishDependsOn }}
|
||||
publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
|
||||
|
|
@ -486,6 +529,8 @@ stages:
|
|||
|
||||
- template: \eng\common\templates\post-build\channels\generic-public-channel.yml
|
||||
parameters:
|
||||
BARBuildId: ${{ parameters.BARBuildId }}
|
||||
PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }}
|
||||
artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
|
||||
dependsOn: ${{ parameters.publishDependsOn }}
|
||||
publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
|
||||
|
|
@ -499,6 +544,8 @@ stages:
|
|||
|
||||
- template: \eng\common\templates\post-build\channels\generic-public-channel.yml
|
||||
parameters:
|
||||
BARBuildId: ${{ parameters.BARBuildId }}
|
||||
PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }}
|
||||
artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
|
||||
dependsOn: ${{ parameters.publishDependsOn }}
|
||||
publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
|
||||
|
|
@ -512,6 +559,8 @@ stages:
|
|||
|
||||
- template: \eng\common\templates\post-build\channels\generic-public-channel.yml
|
||||
parameters:
|
||||
BARBuildId: ${{ parameters.BARBuildId }}
|
||||
PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }}
|
||||
artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
|
||||
dependsOn: ${{ parameters.publishDependsOn }}
|
||||
publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
|
||||
|
|
@ -525,6 +574,8 @@ stages:
|
|||
|
||||
- template: \eng\common\templates\post-build\channels\generic-public-channel.yml
|
||||
parameters:
|
||||
BARBuildId: ${{ parameters.BARBuildId }}
|
||||
PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }}
|
||||
artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }}
|
||||
dependsOn: ${{ parameters.publishDependsOn }}
|
||||
publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }}
|
||||
|
|
|
|||
|
|
@ -1,25 +1,23 @@
|
|||
parameters:
|
||||
BARBuildId: ''
|
||||
PromoteToChannelIds: ''
|
||||
|
||||
jobs:
|
||||
- job: setupMaestroVars
|
||||
displayName: Setup Maestro Vars
|
||||
variables:
|
||||
- template: common-variables.yml
|
||||
- name: BuildId
|
||||
value: $[ coalesce(variables.BARBuildId, 0) ]
|
||||
- name: PromoteToMaestroChannels
|
||||
value: $[ coalesce(variables.PromoteToChannelIds, 0) ]
|
||||
- name: PromoteToMaestroChannel
|
||||
value: $[ coalesce(variables.PromoteToMaestroChannelId, 0) ]
|
||||
pool:
|
||||
vmImage: 'windows-2019'
|
||||
steps:
|
||||
- checkout: none
|
||||
|
||||
- task: DownloadBuildArtifacts@0
|
||||
displayName: Download Release Configs
|
||||
condition: and(eq(variables.PromoteToMaestroChannels, 0), eq(variables.PromoteToMaestroChannel, 0))
|
||||
inputs:
|
||||
buildType: current
|
||||
artifactName: ReleaseConfigs
|
||||
- ${{ if eq(coalesce(parameters.PromoteToChannelIds, 0), 0) }}:
|
||||
- task: DownloadBuildArtifacts@0
|
||||
displayName: Download Release Configs
|
||||
inputs:
|
||||
buildType: current
|
||||
artifactName: ReleaseConfigs
|
||||
|
||||
- task: PowerShell@2
|
||||
name: setReleaseVars
|
||||
|
|
@ -28,7 +26,7 @@ jobs:
|
|||
targetType: inline
|
||||
script: |
|
||||
try {
|
||||
if ($Env:PromoteToMaestroChannels -eq 0 -and $Env:PromoteToMaestroChannel -eq 0) {
|
||||
if (!$Env:PromoteToMaestroChannels -or $Env:PromoteToMaestroChannels.Trim() -eq '') {
|
||||
$Content = Get-Content $(Build.StagingDirectory)/ReleaseConfigs/ReleaseConfigs.txt
|
||||
|
||||
$BarId = $Content | Select -Index 0
|
||||
|
|
@ -51,7 +49,7 @@ jobs:
|
|||
$BarId = $Env:BARBuildId
|
||||
$Channels = $Env:PromoteToMaestroChannels -split ","
|
||||
$Channels = $Channels -join "]["
|
||||
$Channels = "[$Channels][$Env:PromoteToMaestroChannel]"
|
||||
$Channels = "[$Channels]"
|
||||
|
||||
$IsStableBuild = $buildInfo.stable
|
||||
$AzureDevOpsProject = $buildInfo.azureDevOpsProject
|
||||
|
|
@ -75,3 +73,5 @@ jobs:
|
|||
}
|
||||
env:
|
||||
MAESTRO_API_TOKEN: $(MaestroApiAccessToken)
|
||||
BARBuildId: ${{ parameters.BARBuildId }}
|
||||
PromoteToMaestroChannels: ${{ parameters.PromoteToChannelIds }}
|
||||
|
|
|
|||
|
|
@ -28,8 +28,8 @@ param(
|
|||
|
||||
& $PSScriptRoot\Download.ps1 "https://dot.net/v1/dotnet-install.ps1" $PSScriptRoot\dotnet-install.ps1
|
||||
Write-Host "Download of dotnet-install.ps1 complete..."
|
||||
Write-Host "Installing SDK...& $PSScriptRoot\dotnet-install.ps1 -Architecture $arch -Version $sdkVersion -InstallDir $installDir"
|
||||
Invoke-Expression "& $PSScriptRoot\dotnet-install.ps1 -Architecture $arch -Version $sdkVersion -InstallDir $installDir"
|
||||
Write-Host "Installing Runtime...& $PSScriptRoot\dotnet-install.ps1 -Architecture $arch -Runtime dotnet -Version $runtimeVersion -InstallDir $installDir"
|
||||
Invoke-Expression "& $PSScriptRoot\dotnet-install.ps1 -Architecture $arch -Runtime dotnet -Version $runtimeVersion -InstallDir $installDir"
|
||||
Write-Host "InstallDotNet.ps1 complete..."
|
||||
Write-Host "Installing SDK...& $PSScriptRoot\dotnet-install.ps1 -Architecture $arch -Version $sdkVersion -InstallDir $installDir -NoPath"
|
||||
Invoke-Expression "& $PSScriptRoot\dotnet-install.ps1 -Architecture $arch -Version $sdkVersion -InstallDir $installDir -NoPath"
|
||||
Write-Host "Installing Runtime...& $PSScriptRoot\dotnet-install.ps1 -Architecture $arch -Runtime dotnet -Version $runtimeVersion -InstallDir $installDir -NoPath"
|
||||
Invoke-Expression "& $PSScriptRoot\dotnet-install.ps1 -Architecture $arch -Runtime dotnet -Version $runtimeVersion -InstallDir $installDir -NoPath"
|
||||
Write-Host "InstallDotNet.ps1 complete..."
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@
|
|||
},
|
||||
"msbuild-sdks": {
|
||||
"Yarn.MSBuild": "1.15.2",
|
||||
"Microsoft.DotNet.Arcade.Sdk": "5.0.0-beta.20411.8",
|
||||
"Microsoft.DotNet.Helix.Sdk": "5.0.0-beta.20411.8"
|
||||
"Microsoft.DotNet.Arcade.Sdk": "5.0.0-beta.20419.21",
|
||||
"Microsoft.DotNet.Helix.Sdk": "5.0.0-beta.20419.21"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
|
@ -57,7 +58,24 @@ namespace Microsoft.AspNetCore.Antiforgery
|
|||
{
|
||||
// Check the content-type before accessing the form collection to make sure
|
||||
// we report errors gracefully.
|
||||
var form = await httpContext.Request.ReadFormAsync();
|
||||
IFormCollection form;
|
||||
try
|
||||
{
|
||||
form = await httpContext.Request.ReadFormAsync();
|
||||
}
|
||||
catch (InvalidDataException ex)
|
||||
{
|
||||
// ReadFormAsync can throw InvalidDataException if the form content is malformed.
|
||||
// Wrap it in an AntiforgeryValidationException and allow the caller to handle it as just another antiforgery failure.
|
||||
throw new AntiforgeryValidationException(Resources.AntiforgeryToken_UnableToReadRequest, ex);
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
// Reading the request body (which happens as part of ReadFromAsync) may throw an exception if a client disconnects.
|
||||
// Wrap it in an AntiforgeryValidationException and allow the caller to handle it as just another antiforgery failure.
|
||||
throw new AntiforgeryValidationException(Resources.AntiforgeryToken_UnableToReadRequest, ex);
|
||||
}
|
||||
|
||||
requestToken = form[_options.FormFieldName];
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -136,6 +136,9 @@
|
|||
<data name="AntiforgeryToken_TokensSwapped" xml:space="preserve">
|
||||
<value>Validation of the provided antiforgery token failed. The cookie token and the request token were swapped.</value>
|
||||
</data>
|
||||
<data name="AntiforgeryToken_UnableToReadRequest" xml:space="preserve">
|
||||
<value>Unable to read the antiforgery request token from the posted form.</value>
|
||||
</data>
|
||||
<data name="AntiforgeryToken_UsernameMismatch" xml:space="preserve">
|
||||
<value>The provided antiforgery token was meant for user "{0}", but the current user is "{1}".</value>
|
||||
</data>
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.Primitives;
|
||||
|
|
@ -235,6 +237,56 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
|
|||
Assert.Null(tokenSet.RequestToken);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetRequestTokens_ReadFormAsyncThrowsIOException_ThrowsAntiforgeryValidationException()
|
||||
{
|
||||
// Arrange
|
||||
var ioException = new IOException();
|
||||
var httpContext = new Mock<HttpContext>();
|
||||
|
||||
httpContext.Setup(r => r.Request.Cookies).Returns(Mock.Of<IRequestCookieCollection>());
|
||||
httpContext.SetupGet(r => r.Request.HasFormContentType).Returns(true);
|
||||
httpContext.Setup(r => r.Request.ReadFormAsync(It.IsAny<CancellationToken>())).Throws(ioException);
|
||||
|
||||
var options = new AntiforgeryOptions
|
||||
{
|
||||
Cookie = { Name = "cookie-name" },
|
||||
FormFieldName = "form-field-name",
|
||||
HeaderName = null,
|
||||
};
|
||||
|
||||
var tokenStore = new DefaultAntiforgeryTokenStore(new TestOptionsManager(options));
|
||||
|
||||
// Act & Assert
|
||||
var ex = await Assert.ThrowsAsync<AntiforgeryValidationException>(() => tokenStore.GetRequestTokensAsync(httpContext.Object));
|
||||
Assert.Same(ioException, ex.InnerException);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetRequestTokens_ReadFormAsyncThrowsInvalidDataException_ThrowsAntiforgeryValidationException()
|
||||
{
|
||||
// Arrange
|
||||
var exception = new InvalidDataException();
|
||||
var httpContext = new Mock<HttpContext>();
|
||||
|
||||
httpContext.Setup(r => r.Request.Cookies).Returns(Mock.Of<IRequestCookieCollection>());
|
||||
httpContext.SetupGet(r => r.Request.HasFormContentType).Returns(true);
|
||||
httpContext.Setup(r => r.Request.ReadFormAsync(It.IsAny<CancellationToken>())).Throws(exception);
|
||||
|
||||
var options = new AntiforgeryOptions
|
||||
{
|
||||
Cookie = { Name = "cookie-name" },
|
||||
FormFieldName = "form-field-name",
|
||||
HeaderName = null,
|
||||
};
|
||||
|
||||
var tokenStore = new DefaultAntiforgeryTokenStore(new TestOptionsManager(options));
|
||||
|
||||
// Act & Assert
|
||||
var ex = await Assert.ThrowsAsync<AntiforgeryValidationException>(() => tokenStore.GetRequestTokensAsync(httpContext.Object));
|
||||
Assert.Same(exception, ex.InnerException);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(false, CookieSecurePolicy.SameAsRequest, null)]
|
||||
[InlineData(true, CookieSecurePolicy.SameAsRequest, true)]
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ namespace Microsoft.AspNetCore.Components
|
|||
(
|
||||
propertyName: property.Name,
|
||||
propertyType: property.PropertyType,
|
||||
setter: MemberAssignment.CreatePropertySetter(type, property, cascading: false)
|
||||
setter: new PropertySetter(type, property)
|
||||
)).ToArray();
|
||||
|
||||
return Initialize;
|
||||
|
|
|
|||
|
|
@ -144,7 +144,7 @@ namespace Microsoft.AspNetCore.Components.Reflection
|
|||
}
|
||||
}
|
||||
|
||||
static void SetProperty(object target, IPropertySetter writer, string parameterName, object value)
|
||||
static void SetProperty(object target, PropertySetter writer, string parameterName, object value)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
|
@ -246,13 +246,13 @@ namespace Microsoft.AspNetCore.Components.Reflection
|
|||
private class WritersForType
|
||||
{
|
||||
private const int MaxCachedWriterLookups = 100;
|
||||
private readonly Dictionary<string, IPropertySetter> _underlyingWriters;
|
||||
private readonly ConcurrentDictionary<string, IPropertySetter?> _referenceEqualityWritersCache;
|
||||
private readonly Dictionary<string, PropertySetter> _underlyingWriters;
|
||||
private readonly ConcurrentDictionary<string, PropertySetter?> _referenceEqualityWritersCache;
|
||||
|
||||
public WritersForType(Type targetType)
|
||||
{
|
||||
_underlyingWriters = new Dictionary<string, IPropertySetter>(StringComparer.OrdinalIgnoreCase);
|
||||
_referenceEqualityWritersCache = new ConcurrentDictionary<string, IPropertySetter?>(ReferenceEqualityComparer.Instance);
|
||||
_underlyingWriters = new Dictionary<string, PropertySetter>(StringComparer.OrdinalIgnoreCase);
|
||||
_referenceEqualityWritersCache = new ConcurrentDictionary<string, PropertySetter?>(ReferenceEqualityComparer.Instance);
|
||||
|
||||
foreach (var propertyInfo in GetCandidateBindableProperties(targetType))
|
||||
{
|
||||
|
|
@ -271,7 +271,10 @@ namespace Microsoft.AspNetCore.Components.Reflection
|
|||
$"The type '{targetType.FullName}' declares a parameter matching the name '{propertyName}' that is not public. Parameters must be public.");
|
||||
}
|
||||
|
||||
var propertySetter = MemberAssignment.CreatePropertySetter(targetType, propertyInfo, cascading: cascadingParameterAttribute != null);
|
||||
var propertySetter = new PropertySetter(targetType, propertyInfo)
|
||||
{
|
||||
Cascading = cascadingParameterAttribute != null,
|
||||
};
|
||||
|
||||
if (_underlyingWriters.ContainsKey(propertyName))
|
||||
{
|
||||
|
|
@ -298,17 +301,17 @@ namespace Microsoft.AspNetCore.Components.Reflection
|
|||
ThrowForInvalidCaptureUnmatchedValuesParameterType(targetType, propertyInfo);
|
||||
}
|
||||
|
||||
CaptureUnmatchedValuesWriter = MemberAssignment.CreatePropertySetter(targetType, propertyInfo, cascading: false);
|
||||
CaptureUnmatchedValuesWriter = new PropertySetter(targetType, propertyInfo);
|
||||
CaptureUnmatchedValuesPropertyName = propertyInfo.Name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public IPropertySetter? CaptureUnmatchedValuesWriter { get; }
|
||||
public PropertySetter? CaptureUnmatchedValuesWriter { get; }
|
||||
|
||||
public string? CaptureUnmatchedValuesPropertyName { get; }
|
||||
|
||||
public bool TryGetValue(string parameterName, [MaybeNullWhen(false)] out IPropertySetter writer)
|
||||
public bool TryGetValue(string parameterName, [MaybeNullWhen(false)] out PropertySetter writer)
|
||||
{
|
||||
// In intensive parameter-passing scenarios, one of the most expensive things we do is the
|
||||
// lookup from parameterName to writer. Pre-5.0 that was because of the string hashing.
|
||||
|
|
|
|||
|
|
@ -1,12 +1,55 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.Reflection
|
||||
{
|
||||
internal interface IPropertySetter
|
||||
internal sealed class PropertySetter
|
||||
{
|
||||
bool Cascading { get; }
|
||||
private static readonly MethodInfo CallPropertySetterOpenGenericMethod =
|
||||
typeof(PropertySetter).GetMethod(nameof(CallPropertySetter), BindingFlags.NonPublic | BindingFlags.Static)!;
|
||||
|
||||
void SetValue(object target, object value);
|
||||
private readonly Action<object, object> _setterDelegate;
|
||||
|
||||
public PropertySetter(Type targetType, PropertyInfo property)
|
||||
{
|
||||
if (property.SetMethod == null)
|
||||
{
|
||||
throw new InvalidOperationException($"Cannot provide a value for property " +
|
||||
$"'{property.Name}' on type '{targetType.FullName}' because the property " +
|
||||
$"has no setter.");
|
||||
}
|
||||
|
||||
var setMethod = property.SetMethod;
|
||||
|
||||
var propertySetterAsAction =
|
||||
setMethod.CreateDelegate(typeof(Action<,>).MakeGenericType(targetType, property.PropertyType));
|
||||
var callPropertySetterClosedGenericMethod =
|
||||
CallPropertySetterOpenGenericMethod.MakeGenericMethod(targetType, property.PropertyType);
|
||||
_setterDelegate = (Action<object, object>)
|
||||
callPropertySetterClosedGenericMethod.CreateDelegate(typeof(Action<object, object>), propertySetterAsAction);
|
||||
}
|
||||
|
||||
public bool Cascading { get; init; }
|
||||
|
||||
public void SetValue(object target, object value) => _setterDelegate(target, value);
|
||||
|
||||
private static void CallPropertySetter<TTarget, TValue>(
|
||||
Action<TTarget, TValue> setter,
|
||||
object target,
|
||||
object value)
|
||||
where TTarget : notnull
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
setter((TTarget)target, default!);
|
||||
}
|
||||
else
|
||||
{
|
||||
setter((TTarget)target, (TValue)value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,46 +44,5 @@ namespace Microsoft.AspNetCore.Components.Reflection
|
|||
|
||||
return dictionary.Values.SelectMany(p => p);
|
||||
}
|
||||
|
||||
public static IPropertySetter CreatePropertySetter(Type targetType, PropertyInfo property, bool cascading)
|
||||
{
|
||||
if (property.SetMethod == null)
|
||||
{
|
||||
throw new InvalidOperationException($"Cannot provide a value for property " +
|
||||
$"'{property.Name}' on type '{targetType.FullName}' because the property " +
|
||||
$"has no setter.");
|
||||
}
|
||||
|
||||
return (IPropertySetter)Activator.CreateInstance(
|
||||
typeof(PropertySetter<,>).MakeGenericType(targetType, property.PropertyType),
|
||||
property.SetMethod,
|
||||
cascading)!;
|
||||
}
|
||||
|
||||
class PropertySetter<TTarget, TValue> : IPropertySetter where TTarget : notnull
|
||||
{
|
||||
private readonly Action<TTarget, TValue> _setterDelegate;
|
||||
|
||||
public PropertySetter(MethodInfo setMethod, bool cascading)
|
||||
{
|
||||
_setterDelegate = (Action<TTarget, TValue>)Delegate.CreateDelegate(
|
||||
typeof(Action<TTarget, TValue>), setMethod);
|
||||
Cascading = cascading;
|
||||
}
|
||||
|
||||
public bool Cascading { get; }
|
||||
|
||||
public void SetValue(object target, object value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
_setterDelegate((TTarget)target, default!);
|
||||
}
|
||||
else
|
||||
{
|
||||
_setterDelegate((TTarget)target, (TValue)value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ namespace Microsoft.AspNetCore.Components.Routing
|
|||
/// <summary>
|
||||
/// Gets or sets a handler that should be called before navigating to a new page.
|
||||
/// </summary>
|
||||
[Parameter] public Func<NavigationContext, Task>? OnNavigateAsync { get; set; }
|
||||
[Parameter] public EventCallback<NavigationContext> OnNavigateAsync { get; set; }
|
||||
|
||||
private RouteTable Routes { get; set; }
|
||||
|
||||
|
|
@ -115,8 +115,7 @@ namespace Microsoft.AspNetCore.Components.Routing
|
|||
if (!_onNavigateCalled)
|
||||
{
|
||||
_onNavigateCalled = true;
|
||||
await RunOnNavigateWithRefreshAsync(NavigationManager.ToBaseRelativePath(_locationAbsolute), isNavigationIntercepted: false);
|
||||
return;
|
||||
await RunOnNavigateAsync(NavigationManager.ToBaseRelativePath(_locationAbsolute), isNavigationIntercepted: false);
|
||||
}
|
||||
|
||||
Refresh(isNavigationIntercepted: false);
|
||||
|
|
@ -206,9 +205,8 @@ namespace Microsoft.AspNetCore.Components.Routing
|
|||
}
|
||||
}
|
||||
|
||||
private async ValueTask<bool> RunOnNavigateAsync(string path, Task previousOnNavigate)
|
||||
internal async ValueTask RunOnNavigateAsync(string path, bool isNavigationIntercepted)
|
||||
{
|
||||
|
||||
// Cancel the CTS instead of disposing it, since disposing does not
|
||||
// actually cancel and can cause unintended Object Disposed Exceptions.
|
||||
// This effectivelly cancels the previously running task and completes it.
|
||||
|
|
@ -217,59 +215,35 @@ namespace Microsoft.AspNetCore.Components.Routing
|
|||
// before starting the next one. This avoid race conditions where the cancellation
|
||||
// for the previous task was set but not fully completed by the time we get to this
|
||||
// invocation.
|
||||
await previousOnNavigate;
|
||||
await _previousOnNavigateTask;
|
||||
|
||||
if (OnNavigateAsync == null)
|
||||
var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
|
||||
_previousOnNavigateTask = tcs.Task;
|
||||
|
||||
if (!OnNavigateAsync.HasDelegate)
|
||||
{
|
||||
return true;
|
||||
Refresh(isNavigationIntercepted);
|
||||
}
|
||||
|
||||
_onNavigateCts = new CancellationTokenSource();
|
||||
var navigateContext = new NavigationContext(path, _onNavigateCts.Token);
|
||||
|
||||
var cancellationTcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
|
||||
navigateContext.CancellationToken.Register(state =>
|
||||
((TaskCompletionSource)state).SetResult(), cancellationTcs);
|
||||
|
||||
try
|
||||
{
|
||||
if (Navigating != null)
|
||||
{
|
||||
_renderHandle.Render(Navigating);
|
||||
}
|
||||
await OnNavigateAsync(navigateContext);
|
||||
return true;
|
||||
}
|
||||
catch (OperationCanceledException e)
|
||||
{
|
||||
if (e.CancellationToken != navigateContext.CancellationToken)
|
||||
{
|
||||
var rethrownException = new InvalidOperationException("OnNavigateAsync can only be cancelled via NavigateContext.CancellationToken.", e);
|
||||
_renderHandle.Render(builder => ExceptionDispatchInfo.Throw(rethrownException));
|
||||
}
|
||||
// Task.WhenAny returns a Task<Task> so we need to await twice to unwrap the exception
|
||||
var task = await Task.WhenAny(OnNavigateAsync.InvokeAsync(navigateContext), cancellationTcs.Task);
|
||||
await task;
|
||||
tcs.SetResult();
|
||||
Refresh(isNavigationIntercepted);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_renderHandle.Render(builder => ExceptionDispatchInfo.Throw(e));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
internal async Task RunOnNavigateWithRefreshAsync(string path, bool isNavigationIntercepted)
|
||||
{
|
||||
// We cache the Task representing the previously invoked RunOnNavigateWithRefreshAsync
|
||||
// that is stored. Then we create a new one that represents our current invocation and store it
|
||||
// globally for the next invocation. This allows us to check inside `RunOnNavigateAsync` if the
|
||||
// previous OnNavigateAsync task has fully completed before starting the next one.
|
||||
var previousTask = _previousOnNavigateTask;
|
||||
var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
|
||||
_previousOnNavigateTask = tcs.Task;
|
||||
|
||||
// And pass an indicator for the previous task to the currently running one.
|
||||
var shouldRefresh = await RunOnNavigateAsync(path, previousTask);
|
||||
tcs.SetResult();
|
||||
if (shouldRefresh)
|
||||
{
|
||||
Refresh(isNavigationIntercepted);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void OnLocationChanged(object sender, LocationChangedEventArgs args)
|
||||
|
|
@ -277,7 +251,7 @@ namespace Microsoft.AspNetCore.Components.Routing
|
|||
_locationAbsolute = args.Location;
|
||||
if (_renderHandle.IsInitialized && Routes != null)
|
||||
{
|
||||
_ = RunOnNavigateWithRefreshAsync(NavigationManager.ToBaseRelativePath(_locationAbsolute), args.IsNavigationIntercepted);
|
||||
_ = RunOnNavigateAsync(NavigationManager.ToBaseRelativePath(_locationAbsolute), args.IsNavigationIntercepted);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,9 +10,7 @@ using Microsoft.AspNetCore.Components.Test.Helpers;
|
|||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.Test.Routing
|
||||
{
|
||||
|
|
@ -42,49 +40,26 @@ namespace Microsoft.AspNetCore.Components.Test.Routing
|
|||
{
|
||||
// Arrange
|
||||
var called = false;
|
||||
async Task OnNavigateAsync(NavigationContext args)
|
||||
Action<NavigationContext> OnNavigateAsync = async (NavigationContext args) =>
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
called = true;
|
||||
}
|
||||
_router.OnNavigateAsync = OnNavigateAsync;
|
||||
};
|
||||
_router.OnNavigateAsync = new EventCallback<NavigationContext>(null, OnNavigateAsync);
|
||||
|
||||
// Act
|
||||
await _renderer.Dispatcher.InvokeAsync(() => _router.RunOnNavigateWithRefreshAsync("http://example.com/jan", false));
|
||||
await _renderer.Dispatcher.InvokeAsync(() => _router.RunOnNavigateAsync("http://example.com/jan", false));
|
||||
|
||||
// Assert
|
||||
Assert.True(called);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CanHandleSingleFailedOnNavigateAsync()
|
||||
{
|
||||
// Arrange
|
||||
var called = false;
|
||||
async Task OnNavigateAsync(NavigationContext args)
|
||||
{
|
||||
called = true;
|
||||
await Task.CompletedTask;
|
||||
throw new Exception("This is an uncaught exception.");
|
||||
}
|
||||
_router.OnNavigateAsync = OnNavigateAsync;
|
||||
|
||||
// Act
|
||||
await _renderer.Dispatcher.InvokeAsync(() => _router.RunOnNavigateWithRefreshAsync("http://example.com/jan", false));
|
||||
|
||||
// Assert
|
||||
Assert.True(called);
|
||||
Assert.Single(_renderer.HandledExceptions);
|
||||
var unhandledException = _renderer.HandledExceptions[0];
|
||||
Assert.Equal("This is an uncaught exception.", unhandledException.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CanceledFailedOnNavigateAsyncDoesNothing()
|
||||
{
|
||||
// Arrange
|
||||
var onNavigateInvoked = 0;
|
||||
async Task OnNavigateAsync(NavigationContext args)
|
||||
Action<NavigationContext> OnNavigateAsync = async (NavigationContext args) =>
|
||||
{
|
||||
onNavigateInvoked += 1;
|
||||
if (args.Path.EndsWith("jan"))
|
||||
|
|
@ -92,22 +67,18 @@ namespace Microsoft.AspNetCore.Components.Test.Routing
|
|||
await Task.Delay(Timeout.Infinite, args.CancellationToken);
|
||||
throw new Exception("This is an uncaught exception.");
|
||||
}
|
||||
}
|
||||
var refreshCalled = false;
|
||||
};
|
||||
var refreshCalled = 0;
|
||||
_renderer.OnUpdateDisplay = (renderBatch) =>
|
||||
{
|
||||
if (!refreshCalled)
|
||||
{
|
||||
refreshCalled = true;
|
||||
return;
|
||||
}
|
||||
Assert.True(false, "OnUpdateDisplay called more than once.");
|
||||
refreshCalled += 1;
|
||||
return;
|
||||
};
|
||||
_router.OnNavigateAsync = OnNavigateAsync;
|
||||
_router.OnNavigateAsync = new EventCallback<NavigationContext>(null, OnNavigateAsync);
|
||||
|
||||
// Act
|
||||
var janTask = _renderer.Dispatcher.InvokeAsync(() => _router.RunOnNavigateWithRefreshAsync("http://example.com/jan", false));
|
||||
var febTask = _renderer.Dispatcher.InvokeAsync(() => _router.RunOnNavigateWithRefreshAsync("http://example.com/feb", false));
|
||||
var janTask = _renderer.Dispatcher.InvokeAsync(() => _router.RunOnNavigateAsync("http://example.com/jan", false));
|
||||
var febTask = _renderer.Dispatcher.InvokeAsync(() => _router.RunOnNavigateAsync("http://example.com/feb", false));
|
||||
|
||||
await janTask;
|
||||
await febTask;
|
||||
|
|
@ -115,28 +86,7 @@ namespace Microsoft.AspNetCore.Components.Test.Routing
|
|||
// Assert that we render the second route component and don't throw an exception
|
||||
Assert.Empty(_renderer.HandledExceptions);
|
||||
Assert.Equal(2, onNavigateInvoked);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CanHandleSingleCancelledOnNavigateAsync()
|
||||
{
|
||||
// Arrange
|
||||
async Task OnNavigateAsync(NavigationContext args)
|
||||
{
|
||||
var tcs = new TaskCompletionSource<int>();
|
||||
tcs.TrySetCanceled();
|
||||
await tcs.Task;
|
||||
}
|
||||
_renderer.OnUpdateDisplay = (renderBatch) => Assert.True(false, "OnUpdateDisplay called more than once.");
|
||||
_router.OnNavigateAsync = OnNavigateAsync;
|
||||
|
||||
// Act
|
||||
await _renderer.Dispatcher.InvokeAsync(() => _router.RunOnNavigateWithRefreshAsync("http://example.com/jan", false));
|
||||
|
||||
// Assert
|
||||
Assert.Single(_renderer.HandledExceptions);
|
||||
var unhandledException = _renderer.HandledExceptions[0];
|
||||
Assert.Equal("OnNavigateAsync can only be cancelled via NavigateContext.CancellationToken.", unhandledException.Message);
|
||||
Assert.Equal(2, refreshCalled);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -144,7 +94,7 @@ namespace Microsoft.AspNetCore.Components.Test.Routing
|
|||
{
|
||||
// Arrange
|
||||
var triggerCancel = new TaskCompletionSource();
|
||||
async Task OnNavigateAsync(NavigationContext args)
|
||||
Action<NavigationContext> OnNavigateAsync = async (NavigationContext args) =>
|
||||
{
|
||||
if (args.Path.EndsWith("jan"))
|
||||
{
|
||||
|
|
@ -153,7 +103,7 @@ namespace Microsoft.AspNetCore.Components.Test.Routing
|
|||
tcs.TrySetCanceled();
|
||||
await tcs.Task;
|
||||
}
|
||||
}
|
||||
};
|
||||
var refreshCalled = false;
|
||||
_renderer.OnUpdateDisplay = (renderBatch) =>
|
||||
{
|
||||
|
|
@ -164,11 +114,11 @@ namespace Microsoft.AspNetCore.Components.Test.Routing
|
|||
}
|
||||
Assert.True(false, "OnUpdateDisplay called more than once.");
|
||||
};
|
||||
_router.OnNavigateAsync = OnNavigateAsync;
|
||||
_router.OnNavigateAsync = new EventCallback<NavigationContext>(null, OnNavigateAsync);
|
||||
|
||||
// Act (start the operations then await them)
|
||||
var jan = _renderer.Dispatcher.InvokeAsync(() => _router.RunOnNavigateWithRefreshAsync("http://example.com/jan", false));
|
||||
var feb = _renderer.Dispatcher.InvokeAsync(() => _router.RunOnNavigateWithRefreshAsync("http://example.com/feb", false));
|
||||
var jan = _renderer.Dispatcher.InvokeAsync(() => _router.RunOnNavigateAsync("http://example.com/jan", false));
|
||||
var feb = _renderer.Dispatcher.InvokeAsync(() => _router.RunOnNavigateAsync("http://example.com/feb", false));
|
||||
triggerCancel.TrySetResult();
|
||||
|
||||
await jan;
|
||||
|
|
@ -180,16 +130,16 @@ namespace Microsoft.AspNetCore.Components.Test.Routing
|
|||
{
|
||||
// Arrange
|
||||
var cancelled = "";
|
||||
async Task OnNavigateAsync(NavigationContext args)
|
||||
Action<NavigationContext> OnNavigateAsync = async (NavigationContext args) =>
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
args.CancellationToken.Register(() => cancelled = args.Path);
|
||||
};
|
||||
_router.OnNavigateAsync = OnNavigateAsync;
|
||||
_router.OnNavigateAsync = new EventCallback<NavigationContext>(null, OnNavigateAsync);
|
||||
|
||||
// Act
|
||||
_ = _router.RunOnNavigateWithRefreshAsync("jan", false);
|
||||
_ = _router.RunOnNavigateWithRefreshAsync("feb", false);
|
||||
_ = _router.RunOnNavigateAsync("jan", false);
|
||||
_ = _router.RunOnNavigateAsync("feb", false);
|
||||
|
||||
// Assert
|
||||
var expected = "jan";
|
||||
|
|
@ -200,7 +150,7 @@ namespace Microsoft.AspNetCore.Components.Test.Routing
|
|||
public async Task RefreshesOnceOnCancelledOnNavigateAsync()
|
||||
{
|
||||
// Arrange
|
||||
async Task OnNavigateAsync(NavigationContext args)
|
||||
Action<NavigationContext> OnNavigateAsync = async (NavigationContext args) =>
|
||||
{
|
||||
if (args.Path.EndsWith("jan"))
|
||||
{
|
||||
|
|
@ -217,11 +167,11 @@ namespace Microsoft.AspNetCore.Components.Test.Routing
|
|||
}
|
||||
Assert.True(false, "OnUpdateDisplay called more than once.");
|
||||
};
|
||||
_router.OnNavigateAsync = OnNavigateAsync;
|
||||
_router.OnNavigateAsync = new EventCallback<NavigationContext>(null, OnNavigateAsync);
|
||||
|
||||
// Act
|
||||
var jan = _renderer.Dispatcher.InvokeAsync(() => _router.RunOnNavigateWithRefreshAsync("http://example.com/jan", false));
|
||||
var feb = _renderer.Dispatcher.InvokeAsync(() => _router.RunOnNavigateWithRefreshAsync("http://example.com/feb", false));
|
||||
var jan = _renderer.Dispatcher.InvokeAsync(() => _router.RunOnNavigateAsync("http://example.com/jan", false));
|
||||
var feb = _renderer.Dispatcher.InvokeAsync(() => _router.RunOnNavigateAsync("http://example.com/feb", false));
|
||||
|
||||
await jan;
|
||||
await feb;
|
||||
|
|
|
|||
|
|
@ -22,6 +22,10 @@
|
|||
"src\\Components\\WebAssembly\\DebugProxy\\src\\Microsoft.AspNetCore.Components.WebAssembly.DebugProxy.csproj",
|
||||
"src\\Components\\WebAssembly\\DevServer\\src\\Microsoft.AspNetCore.Components.WebAssembly.DevServer.csproj",
|
||||
"src\\Components\\WebAssembly\\JSInterop\\src\\Microsoft.JSInterop.WebAssembly.csproj",
|
||||
"src\\Components\\WebAssembly\\Sdk\\integrationtests\\Microsoft.NET.Sdk.BlazorWebAssembly.IntegrationTests.csproj",
|
||||
"src\\Components\\WebAssembly\\Sdk\\src\\Microsoft.NET.Sdk.BlazorWebAssembly.csproj",
|
||||
"src\\Components\\WebAssembly\\Sdk\\test\\Microsoft.NET.Sdk.BlazorWebAssembly.Tests.csproj",
|
||||
"src\\Components\\WebAssembly\\Sdk\\tools\\Microsoft.NET.Sdk.BlazorWebAssembly.Tools.csproj",
|
||||
"src\\Components\\WebAssembly\\Server\\src\\Microsoft.AspNetCore.Components.WebAssembly.Server.csproj",
|
||||
"src\\Components\\WebAssembly\\Server\\test\\Microsoft.AspNetCore.Components.WebAssembly.Server.Tests.csproj",
|
||||
"src\\Components\\WebAssembly\\WebAssembly.Authentication\\src\\Microsoft.AspNetCore.Components.WebAssembly.Authentication.csproj",
|
||||
|
|
@ -31,10 +35,9 @@
|
|||
"src\\Components\\WebAssembly\\testassets\\HostedInAspNet.Client\\HostedInAspNet.Client.csproj",
|
||||
"src\\Components\\WebAssembly\\testassets\\HostedInAspNet.Server\\HostedInAspNet.Server.csproj",
|
||||
"src\\Components\\WebAssembly\\testassets\\StandaloneApp\\StandaloneApp.csproj",
|
||||
"src\\Components\\WebAssembly\\Sdk\\src\\Microsoft.NET.Sdk.BlazorWebAssembly.csproj",
|
||||
"src\\Components\\WebAssembly\\Sdk\\test\\Microsoft.NET.Sdk.BlazorWebAssembly.Tests.csproj",
|
||||
"src\\Components\\WebAssembly\\Sdk\\tools\\Microsoft.NET.Sdk.BlazorWebAssembly.Tools.csproj",
|
||||
"src\\Components\\WebAssembly\\Sdk\\integrationtests\\Microsoft.NET.Sdk.BlazorWebAssembly.IntegrationTests.csproj",
|
||||
"src\\Components\\WebAssembly\\testassets\\Wasm.Authentication.Client\\Wasm.Authentication.Client.csproj",
|
||||
"src\\Components\\WebAssembly\\testassets\\Wasm.Authentication.Server\\Wasm.Authentication.Server.csproj",
|
||||
"src\\Components\\WebAssembly\\testassets\\Wasm.Authentication.Shared\\Wasm.Authentication.Shared.csproj",
|
||||
"src\\Components\\Web\\src\\Microsoft.AspNetCore.Components.Web.csproj",
|
||||
"src\\Components\\Web\\test\\Microsoft.AspNetCore.Components.Web.Tests.csproj",
|
||||
"src\\Components\\benchmarkapps\\Wasm.Performance\\ConsoleHost\\Wasm.Performance.ConsoleHost.csproj",
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ namespace Microsoft.AspNetCore.Components.Forms
|
|||
// really don't, you can pass an empty object then ignore it. Ensuring it's nonnull
|
||||
// simplifies things for all consumers of EditContext.
|
||||
Model = model ?? throw new ArgumentNullException(nameof(model));
|
||||
Properties = new EditContextProperties();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -62,6 +63,11 @@ namespace Microsoft.AspNetCore.Components.Forms
|
|||
/// </summary>
|
||||
public object Model { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a collection of arbitrary properties associated with this instance.
|
||||
/// </summary>
|
||||
public EditContextProperties Properties { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Signals that the value for the specified field has changed.
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,63 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.Forms
|
||||
{
|
||||
/// <summary>
|
||||
/// Holds arbitrary key/value pairs associated with an <see cref="EditContext"/>.
|
||||
/// This can be used to track additional metadata for application-specific purposes.
|
||||
/// </summary>
|
||||
public sealed class EditContextProperties
|
||||
{
|
||||
// We don't want to expose any way of enumerating the underlying dictionary, because that would
|
||||
// prevent its usage to store private information. So we only expose an indexer and TryGetValue.
|
||||
private Dictionary<object, object>? _contents;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value in the collection.
|
||||
/// </summary>
|
||||
/// <param name="key">The key under which the value is stored.</param>
|
||||
/// <returns>The stored value.</returns>
|
||||
public object this[object key]
|
||||
{
|
||||
get => _contents is null ? throw new KeyNotFoundException() : _contents[key];
|
||||
set
|
||||
{
|
||||
_contents ??= new Dictionary<object, object>();
|
||||
_contents[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value associated with the specified key, if any.
|
||||
/// </summary>
|
||||
/// <param name="key">The key under which the value is stored.</param>
|
||||
/// <param name="value">The value, if present.</param>
|
||||
/// <returns>True if the value was present, otherwise false.</returns>
|
||||
public bool TryGetValue(object key, [NotNullWhen(true)] out object? value)
|
||||
{
|
||||
if (_contents is null)
|
||||
{
|
||||
value = default;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return _contents.TryGetValue(key, out value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes the specified entry from the collection.
|
||||
/// </summary>
|
||||
/// <param name="key">The key of the entry to be removed.</param>
|
||||
/// <returns>True if the value was present, otherwise false.</returns>
|
||||
public bool Remove(object key)
|
||||
{
|
||||
return _contents?.Remove(key) ?? false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Xunit;
|
||||
|
||||
|
|
@ -252,6 +253,76 @@ namespace Microsoft.AspNetCore.Components.Forms
|
|||
Assert.True(editContext.IsModified(editContext.Field(nameof(EquatableModel.Property))));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Properties_CanRetrieveViaIndexer()
|
||||
{
|
||||
// Arrange
|
||||
var editContext = new EditContext(new object());
|
||||
var key1 = new object();
|
||||
var key2 = new object();
|
||||
var key3 = new object();
|
||||
var value1 = new object();
|
||||
var value2 = new object();
|
||||
|
||||
// Initially, the values are not present
|
||||
Assert.Throws<KeyNotFoundException>(() => editContext.Properties[key1]);
|
||||
|
||||
// Can store and retrieve values
|
||||
editContext.Properties[key1] = value1;
|
||||
editContext.Properties[key2] = value2;
|
||||
Assert.Same(value1, editContext.Properties[key1]);
|
||||
Assert.Same(value2, editContext.Properties[key2]);
|
||||
|
||||
// Unrelated keys are still not found
|
||||
Assert.Throws<KeyNotFoundException>(() => editContext.Properties[key3]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Properties_CanRetrieveViaTryGetValue()
|
||||
{
|
||||
// Arrange
|
||||
var editContext = new EditContext(new object());
|
||||
var key1 = new object();
|
||||
var key2 = new object();
|
||||
var key3 = new object();
|
||||
var value1 = new object();
|
||||
var value2 = new object();
|
||||
|
||||
// Initially, the values are not present
|
||||
Assert.False(editContext.Properties.TryGetValue(key1, out _));
|
||||
|
||||
// Can store and retrieve values
|
||||
editContext.Properties[key1] = value1;
|
||||
editContext.Properties[key2] = value2;
|
||||
Assert.True(editContext.Properties.TryGetValue(key1, out var retrievedValue1));
|
||||
Assert.True(editContext.Properties.TryGetValue(key2, out var retrievedValue2));
|
||||
Assert.Same(value1, retrievedValue1);
|
||||
Assert.Same(value2, retrievedValue2);
|
||||
|
||||
// Unrelated keys are still not found
|
||||
Assert.False(editContext.Properties.TryGetValue(key3, out _));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Properties_CanRemove()
|
||||
{
|
||||
// Arrange
|
||||
var editContext = new EditContext(new object());
|
||||
var key = new object();
|
||||
var value = new object();
|
||||
editContext.Properties[key] = value;
|
||||
|
||||
// Act
|
||||
var resultForExistingKey = editContext.Properties.Remove(key);
|
||||
var resultForNonExistingKey = editContext.Properties.Remove(new object());
|
||||
|
||||
// Assert
|
||||
Assert.True(resultForExistingKey);
|
||||
Assert.False(resultForNonExistingKey);
|
||||
Assert.False(editContext.Properties.TryGetValue(key, out _));
|
||||
Assert.Throws<KeyNotFoundException>(() => editContext.Properties[key]);
|
||||
}
|
||||
|
||||
class EquatableModel : IEquatable<EquatableModel>
|
||||
{
|
||||
public string Property { get; set; } = "";
|
||||
|
|
|
|||
|
|
@ -353,7 +353,7 @@ namespace Ignitor
|
|||
_hubConnection = builder.Build();
|
||||
|
||||
HubConnection.On<int, string>("JS.AttachComponent", OnAttachComponent);
|
||||
HubConnection.On<int, string, string>("JS.BeginInvokeJS", OnBeginInvokeJS);
|
||||
HubConnection.On<int, string, string, int, long>("JS.BeginInvokeJS", OnBeginInvokeJS);
|
||||
HubConnection.On<string>("JS.EndInvokeDotNet", OnEndInvokeDotNet);
|
||||
HubConnection.On<int, byte[]>("JS.RenderBatch", OnRenderBatch);
|
||||
HubConnection.On<string>("JS.Error", OnError);
|
||||
|
|
@ -401,9 +401,9 @@ namespace Ignitor
|
|||
NextAttachComponentReceived?.Completion?.TrySetResult(call);
|
||||
}
|
||||
|
||||
private void OnBeginInvokeJS(int asyncHandle, string identifier, string argsJson)
|
||||
private void OnBeginInvokeJS(int asyncHandle, string identifier, string argsJson, int resultType, long targetInstanceId)
|
||||
{
|
||||
var call = new CapturedJSInteropCall(asyncHandle, identifier, argsJson);
|
||||
var call = new CapturedJSInteropCall(asyncHandle, identifier, argsJson, resultType, targetInstanceId);
|
||||
Operations?.JSInteropCalls.Enqueue(call);
|
||||
JSInterop?.Invoke(call);
|
||||
|
||||
|
|
|
|||
|
|
@ -5,15 +5,19 @@ namespace Ignitor
|
|||
{
|
||||
public class CapturedJSInteropCall
|
||||
{
|
||||
public CapturedJSInteropCall(int asyncHandle, string identifier, string argsJson)
|
||||
public CapturedJSInteropCall(int asyncHandle, string identifier, string argsJson, int resultType, long targetInstanceId)
|
||||
{
|
||||
AsyncHandle = asyncHandle;
|
||||
Identifier = identifier;
|
||||
ArgsJson = argsJson;
|
||||
ResultType = resultType;
|
||||
TargetInstanceId = targetInstanceId;
|
||||
}
|
||||
|
||||
public int AsyncHandle { get; }
|
||||
public string Identifier { get; }
|
||||
public string ArgsJson { get; }
|
||||
public int ResultType { get; }
|
||||
public long TargetInstanceId { get; }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ namespace Microsoft.AspNetCore.Components.Server.Circuits
|
|||
JsonSerializer.Serialize(new[] { callId, success, resultOrError }, JsonSerializerOptions));
|
||||
}
|
||||
|
||||
protected override void BeginInvokeJS(long asyncHandle, string identifier, string argsJson)
|
||||
protected override void BeginInvokeJS(long asyncHandle, string identifier, string argsJson, JSCallResultType resultType, long targetInstanceId)
|
||||
{
|
||||
if (_clientProxy is null)
|
||||
{
|
||||
|
|
@ -83,7 +83,7 @@ namespace Microsoft.AspNetCore.Components.Server.Circuits
|
|||
|
||||
Log.BeginInvokeJS(_logger, asyncHandle, identifier);
|
||||
|
||||
_clientProxy.SendAsync("JS.BeginInvokeJS", asyncHandle, identifier, argsJson);
|
||||
_clientProxy.SendAsync("JS.BeginInvokeJS", asyncHandle, identifier, argsJson, (int)resultType, targetInstanceId);
|
||||
}
|
||||
|
||||
public static class Log
|
||||
|
|
|
|||
|
|
@ -59,13 +59,13 @@ namespace Microsoft.AspNetCore.Components.Server
|
|||
{
|
||||
private readonly IDataProtector _dataProtector;
|
||||
private readonly ILogger<ServerComponentDeserializer> _logger;
|
||||
private readonly ServerComponentTypeCache _rootComponentTypeCache;
|
||||
private readonly RootComponentTypeCache _rootComponentTypeCache;
|
||||
private readonly ComponentParameterDeserializer _parametersDeserializer;
|
||||
|
||||
public ServerComponentDeserializer(
|
||||
IDataProtectionProvider dataProtectionProvider,
|
||||
ILogger<ServerComponentDeserializer> logger,
|
||||
ServerComponentTypeCache rootComponentTypeCache,
|
||||
RootComponentTypeCache rootComponentTypeCache,
|
||||
ComponentParameterDeserializer parametersDeserializer)
|
||||
{
|
||||
// When we protect the data we use a time-limited data protector with the
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ namespace Microsoft.Extensions.DependencyInjection
|
|||
services.TryAddEnumerable(ServiceDescriptor.Singleton<IPostConfigureOptions<StaticFileOptions>, ConfigureStaticFilesOptions>());
|
||||
services.TryAddSingleton<CircuitFactory>();
|
||||
services.TryAddSingleton<ServerComponentDeserializer>();
|
||||
services.TryAddSingleton<ServerComponentTypeCache>();
|
||||
services.TryAddSingleton<RootComponentTypeCache>();
|
||||
services.TryAddSingleton<ComponentParameterDeserializer>();
|
||||
services.TryAddSingleton<ComponentParametersTypeCache>();
|
||||
services.TryAddSingleton<CircuitIdFactory>();
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework>
|
||||
<Description>Runtime server features for ASP.NET Core Components.</Description>
|
||||
|
|
@ -54,6 +54,8 @@
|
|||
<Compile Include="$(ComponentsSharedSourceRoot)src\CacheHeaderSettings.cs" Link="Shared\CacheHeaderSettings.cs" />
|
||||
<Compile Include="$(ComponentsSharedSourceRoot)src\ArrayBuilder.cs" LinkBase="Circuits" />
|
||||
<Compile Include="$(ComponentsSharedSourceRoot)src\ElementReferenceJsonConverter.cs" />
|
||||
<Compile Include="$(ComponentsSharedSourceRoot)src\ComponentParametersTypeCache.cs" />
|
||||
<Compile Include="$(ComponentsSharedSourceRoot)src\RootComponentTypeCache.cs" />
|
||||
|
||||
<Compile Include="..\..\Shared\src\BrowserNavigationManagerInterop.cs" />
|
||||
<Compile Include="..\..\Shared\src\JsonSerializerOptionsProvider.cs" />
|
||||
|
|
|
|||
|
|
@ -320,7 +320,7 @@ namespace Microsoft.AspNetCore.Components.Server.Circuits
|
|||
return new ServerComponentDeserializer(
|
||||
_ephemeralDataProtectionProvider,
|
||||
NullLogger<ServerComponentDeserializer>.Instance,
|
||||
new ServerComponentTypeCache(),
|
||||
new RootComponentTypeCache(),
|
||||
new ComponentParameterDeserializer(NullLogger<ComponentParameterDeserializer>.Instance, new ComponentParametersTypeCache()));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ using System.Reflection;
|
|||
namespace Microsoft.AspNetCore.Components
|
||||
{
|
||||
// A cache for root component types
|
||||
internal class ServerComponentTypeCache
|
||||
internal class RootComponentTypeCache
|
||||
{
|
||||
private readonly ConcurrentDictionary<Key, Type> _typeToKeyLookUp = new ConcurrentDictionary<Key, Type>();
|
||||
|
||||
|
|
@ -39,14 +39,14 @@ namespace Microsoft.AspNetCore.Components
|
|||
return assembly.GetType(key.Type, throwOnError: false, ignoreCase: false);
|
||||
}
|
||||
|
||||
private struct Key : IEquatable<Key>
|
||||
private readonly struct Key : IEquatable<Key>
|
||||
{
|
||||
public Key(string assembly, string type) =>
|
||||
(Assembly, Type) = (assembly, type);
|
||||
|
||||
public string Assembly { get; set; }
|
||||
public string Assembly { get; }
|
||||
|
||||
public string Type { get; set; }
|
||||
public string Type { get; }
|
||||
|
||||
public override bool Equals(object obj) => Equals((Key)obj);
|
||||
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.Web.Extensions
|
||||
{
|
||||
internal class BrowserFile : IBrowserFile
|
||||
{
|
||||
internal InputFile Owner { get; set; } = default!;
|
||||
|
||||
public int Id { get; set; }
|
||||
|
||||
public string Name { get; set; } = string.Empty;
|
||||
|
||||
public DateTime LastModified { get; set; }
|
||||
|
||||
public long Size { get; set; }
|
||||
|
||||
public string Type { get; set; } = string.Empty;
|
||||
|
||||
public string? RelativePath { get; set; }
|
||||
|
||||
public Stream OpenReadStream(CancellationToken cancellationToken = default)
|
||||
=> Owner.OpenReadStream(this, cancellationToken);
|
||||
|
||||
public Task<IBrowserFile> ToImageFileAsync(string format, int maxWidth, int maxHeight)
|
||||
=> Owner.ConvertToImageFileAsync(this, format, maxWidth, maxHeight);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.Web.Extensions
|
||||
{
|
||||
internal abstract class BrowserFileStream : Stream
|
||||
{
|
||||
private long _position;
|
||||
|
||||
protected BrowserFile File { get; }
|
||||
|
||||
protected BrowserFileStream(BrowserFile file)
|
||||
{
|
||||
File = file;
|
||||
}
|
||||
|
||||
public override bool CanRead => true;
|
||||
|
||||
public override bool CanSeek => false;
|
||||
|
||||
public override bool CanWrite => false;
|
||||
|
||||
public override long Length => File.Size;
|
||||
|
||||
public override long Position
|
||||
{
|
||||
get => _position;
|
||||
set => throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public override void Flush()
|
||||
=> throw new NotSupportedException();
|
||||
|
||||
public override int Read(byte[] buffer, int offset, int count)
|
||||
=> throw new NotSupportedException("Synchronous reads are not supported.");
|
||||
|
||||
public override long Seek(long offset, SeekOrigin origin)
|
||||
=> throw new NotSupportedException();
|
||||
|
||||
public override void SetLength(long value)
|
||||
=> throw new NotSupportedException();
|
||||
|
||||
public override void Write(byte[] buffer, int offset, int count)
|
||||
=> throw new NotSupportedException();
|
||||
|
||||
public override Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
|
||||
=> ReadAsync(new Memory<byte>(buffer, offset, count), cancellationToken).AsTask();
|
||||
|
||||
public override async ValueTask<int> ReadAsync(Memory<byte> buffer, CancellationToken cancellationToken = default)
|
||||
{
|
||||
int maxBytesToRead = (int)(Length - Position);
|
||||
|
||||
if (maxBytesToRead > buffer.Length)
|
||||
{
|
||||
maxBytesToRead = buffer.Length;
|
||||
}
|
||||
|
||||
if (maxBytesToRead <= 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
var bytesRead = await CopyFileDataIntoBuffer(_position, buffer.Slice(0, maxBytesToRead), cancellationToken);
|
||||
|
||||
_position += bytesRead;
|
||||
|
||||
return bytesRead;
|
||||
}
|
||||
|
||||
protected abstract ValueTask<int> CopyFileDataIntoBuffer(long sourceOffset, Memory<byte> destination, CancellationToken cancellationToken);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.Web.Extensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the data of a file selected from an <see cref="InputFile"/> component.
|
||||
/// </summary>
|
||||
public interface IBrowserFile
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the name of the file.
|
||||
/// </summary>
|
||||
string Name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the last modified date.
|
||||
/// </summary>
|
||||
DateTime LastModified { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the size of the file in bytes.
|
||||
/// </summary>
|
||||
long Size { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the MIME type of the file.
|
||||
/// </summary>
|
||||
string Type { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Opens the stream for reading the uploaded file.
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken">A cancellation token to signal the cancellation of streaming file data.</param>
|
||||
Stream OpenReadStream(CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Converts the current image file to a new one of the specified file type and maximum file dimensions.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The image will be scaled to fit the specified dimensions while preserving the original aspect ratio.
|
||||
/// </remarks>
|
||||
/// <param name="format">The new image format.</param>
|
||||
/// <param name="maxWith">The maximum image width.</param>
|
||||
/// <param name="maxHeight">The maximum image height</param>
|
||||
/// <returns>A <see cref="Task"/> representing the completion of the operation.</returns>
|
||||
Task<IBrowserFile> ToImageFileAsync(string format, int maxWith, int maxHeight);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.Web.Extensions
|
||||
{
|
||||
internal interface IInputFileJsCallbacks
|
||||
{
|
||||
Task NotifyChange(BrowserFile[] files);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,96 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Components.Rendering;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Microsoft.JSInterop;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.Web.Extensions
|
||||
{
|
||||
/// <summary>
|
||||
/// A component that wraps the HTML file input element and exposes a <see cref="Stream"/> for each file's contents.
|
||||
/// </summary>
|
||||
public class InputFile : ComponentBase, IInputFileJsCallbacks, IDisposable
|
||||
{
|
||||
private ElementReference _inputFileElement;
|
||||
|
||||
private IJSUnmarshalledRuntime? _jsUnmarshalledRuntime;
|
||||
|
||||
private InputFileJsCallbacksRelay? _jsCallbacksRelay;
|
||||
|
||||
[Inject]
|
||||
private IJSRuntime JSRuntime { get; set; } = default!;
|
||||
|
||||
[Inject]
|
||||
private IOptions<RemoteBrowserFileStreamOptions> Options { get; set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the event callback that will be invoked when the collection of selected files changes.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public EventCallback<InputFileChangeEventArgs> OnChange { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a collection of additional attributes that will be applied to the input element.
|
||||
/// </summary>
|
||||
[Parameter(CaptureUnmatchedValues = true)]
|
||||
public IDictionary<string, object>? AdditionalAttributes { get; set; }
|
||||
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
_jsUnmarshalledRuntime = JSRuntime as IJSUnmarshalledRuntime;
|
||||
}
|
||||
|
||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||
{
|
||||
if (firstRender)
|
||||
{
|
||||
_jsCallbacksRelay = new InputFileJsCallbacksRelay(this);
|
||||
await JSRuntime.InvokeVoidAsync(InputFileInterop.Init, _jsCallbacksRelay.DotNetReference, _inputFileElement);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void BuildRenderTree(RenderTreeBuilder builder)
|
||||
{
|
||||
builder.OpenElement(0, "input");
|
||||
builder.AddMultipleAttributes(1, AdditionalAttributes);
|
||||
builder.AddAttribute(2, "type", "file");
|
||||
builder.AddElementReferenceCapture(3, elementReference => _inputFileElement = elementReference);
|
||||
builder.CloseElement();
|
||||
}
|
||||
|
||||
internal Stream OpenReadStream(BrowserFile file, CancellationToken cancellationToken)
|
||||
=> _jsUnmarshalledRuntime != null ?
|
||||
(Stream)new SharedBrowserFileStream(JSRuntime, _jsUnmarshalledRuntime, _inputFileElement, file) :
|
||||
new RemoteBrowserFileStream(JSRuntime, _inputFileElement, file, Options.Value, cancellationToken);
|
||||
|
||||
internal async Task<IBrowserFile> ConvertToImageFileAsync(BrowserFile file, string format, int maxWidth, int maxHeight)
|
||||
{
|
||||
var imageFile = await JSRuntime.InvokeAsync<BrowserFile>(InputFileInterop.ToImageFile, _inputFileElement, file.Id, format, maxWidth, maxHeight);
|
||||
|
||||
imageFile.Owner = this;
|
||||
|
||||
return imageFile;
|
||||
}
|
||||
|
||||
Task IInputFileJsCallbacks.NotifyChange(BrowserFile[] files)
|
||||
{
|
||||
foreach (var file in files)
|
||||
{
|
||||
file.Owner = this;
|
||||
}
|
||||
|
||||
return OnChange.InvokeAsync(new InputFileChangeEventArgs(files));
|
||||
}
|
||||
|
||||
void IDisposable.Dispose()
|
||||
{
|
||||
_jsCallbacksRelay?.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.Web.Extensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Supplies information about an <see cref="InputFile.OnChange"/> event being raised.
|
||||
/// </summary>
|
||||
public class InputFileChangeEventArgs : EventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// The updated file entries list.
|
||||
/// </summary>
|
||||
public IReadOnlyList<IBrowserFile> Files { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a new <see cref="InputFileChangeEventArgs"/> instance.
|
||||
/// </summary>
|
||||
/// <param name="files">The updated file entries list.</param>
|
||||
public InputFileChangeEventArgs(IReadOnlyList<IBrowserFile> files)
|
||||
{
|
||||
Files = files;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.Web.Extensions
|
||||
{
|
||||
internal static class InputFileInterop
|
||||
{
|
||||
private const string JsFunctionsPrefix = "_blazorInputFile.";
|
||||
|
||||
public const string Init = JsFunctionsPrefix + "init";
|
||||
|
||||
public const string EnsureArrayBufferReadyForSharedMemoryInterop = JsFunctionsPrefix + "ensureArrayBufferReadyForSharedMemoryInterop";
|
||||
|
||||
public const string ReadFileData = JsFunctionsPrefix + "readFileData";
|
||||
|
||||
public const string ReadFileDataSharedMemory = JsFunctionsPrefix + "readFileDataSharedMemory";
|
||||
|
||||
public const string ToImageFile = JsFunctionsPrefix + "toImageFile";
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.JSInterop;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.Web.Extensions
|
||||
{
|
||||
internal class InputFileJsCallbacksRelay : IDisposable
|
||||
{
|
||||
private readonly IInputFileJsCallbacks _callbacks;
|
||||
|
||||
public IDisposable DotNetReference { get; }
|
||||
|
||||
public InputFileJsCallbacksRelay(IInputFileJsCallbacks callbacks)
|
||||
{
|
||||
_callbacks = callbacks;
|
||||
|
||||
DotNetReference = DotNetObjectReference.Create(this);
|
||||
}
|
||||
|
||||
[JSInvokable]
|
||||
public Task NotifyChange(BrowserFile[] files)
|
||||
=> _callbacks.NotifyChange(files);
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
DotNetReference.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.Web.Extensions
|
||||
{
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
internal struct ReadRequest
|
||||
{
|
||||
[FieldOffset(0)]
|
||||
public string InputFileElementReferenceId;
|
||||
|
||||
[FieldOffset(4)]
|
||||
public int FileId;
|
||||
|
||||
[FieldOffset(8)]
|
||||
public long SourceOffset;
|
||||
|
||||
[FieldOffset(16)]
|
||||
public byte[] Destination;
|
||||
|
||||
[FieldOffset(20)]
|
||||
public int DestinationOffset;
|
||||
|
||||
[FieldOffset(24)]
|
||||
public int MaxBytes;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,145 @@
|
|||
// 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.Buffers;
|
||||
using System.IO.Pipelines;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.JSInterop;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.Web.Extensions
|
||||
{
|
||||
internal class RemoteBrowserFileStream : BrowserFileStream
|
||||
{
|
||||
private readonly IJSRuntime _jsRuntime;
|
||||
private readonly ElementReference _inputFileElement;
|
||||
private readonly int _maxSegmentSize;
|
||||
private readonly PipeReader _pipeReader;
|
||||
private readonly CancellationTokenSource _fillBufferCts;
|
||||
private readonly TimeSpan _segmentFetchTimeout;
|
||||
|
||||
private bool _isReadingCompleted;
|
||||
private bool _isDisposed;
|
||||
|
||||
public RemoteBrowserFileStream(
|
||||
IJSRuntime jsRuntime,
|
||||
ElementReference inputFileElement,
|
||||
BrowserFile file,
|
||||
RemoteBrowserFileStreamOptions options,
|
||||
CancellationToken cancellationToken)
|
||||
: base(file)
|
||||
{
|
||||
_jsRuntime = jsRuntime;
|
||||
_inputFileElement = inputFileElement;
|
||||
_maxSegmentSize = options.SegmentSize;
|
||||
_segmentFetchTimeout = options.SegmentFetchTimeout;
|
||||
|
||||
var pipe = new Pipe(new PipeOptions(pauseWriterThreshold: options.MaxBufferSize, resumeWriterThreshold: options.MaxBufferSize));
|
||||
_pipeReader = pipe.Reader;
|
||||
_fillBufferCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
|
||||
|
||||
_ = FillBuffer(pipe.Writer, _fillBufferCts.Token);
|
||||
}
|
||||
|
||||
private async Task FillBuffer(PipeWriter writer, CancellationToken cancellationToken)
|
||||
{
|
||||
long offset = 0;
|
||||
|
||||
while (offset < File.Size)
|
||||
{
|
||||
var pipeBuffer = writer.GetMemory(_maxSegmentSize);
|
||||
var segmentSize = (int)Math.Min(_maxSegmentSize, File.Size - offset);
|
||||
|
||||
try
|
||||
{
|
||||
using var readSegmentCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
|
||||
readSegmentCts.CancelAfter(_segmentFetchTimeout);
|
||||
|
||||
var bytes = await _jsRuntime.InvokeAsync<byte[]>(
|
||||
InputFileInterop.ReadFileData,
|
||||
readSegmentCts.Token,
|
||||
_inputFileElement,
|
||||
File.Id,
|
||||
offset,
|
||||
segmentSize);
|
||||
|
||||
if (bytes.Length != segmentSize)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
$"A segment with size {bytes.Length} bytes was received, but {segmentSize} bytes were expected.");
|
||||
}
|
||||
|
||||
bytes.CopyTo(pipeBuffer);
|
||||
writer.Advance(segmentSize);
|
||||
offset += segmentSize;
|
||||
|
||||
var result = await writer.FlushAsync(cancellationToken);
|
||||
|
||||
if (result.IsCompleted)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
await writer.CompleteAsync(e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
await writer.CompleteAsync();
|
||||
}
|
||||
|
||||
protected override async ValueTask<int> CopyFileDataIntoBuffer(long sourceOffset, Memory<byte> destination, CancellationToken cancellationToken)
|
||||
{
|
||||
if (_isReadingCompleted)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int totalBytesCopied = 0;
|
||||
|
||||
while (destination.Length > 0)
|
||||
{
|
||||
var result = await _pipeReader.ReadAsync(cancellationToken);
|
||||
var bytesToCopy = (int)Math.Min(result.Buffer.Length, destination.Length);
|
||||
|
||||
if (bytesToCopy == 0)
|
||||
{
|
||||
if (result.IsCompleted)
|
||||
{
|
||||
_isReadingCompleted = true;
|
||||
await _pipeReader.CompleteAsync();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
var slice = result.Buffer.Slice(0, bytesToCopy);
|
||||
slice.CopyTo(destination.Span);
|
||||
|
||||
_pipeReader.AdvanceTo(slice.End);
|
||||
|
||||
totalBytesCopied += bytesToCopy;
|
||||
destination = destination.Slice(bytesToCopy);
|
||||
}
|
||||
|
||||
return totalBytesCopied;
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (_isDisposed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_fillBufferCts.Cancel();
|
||||
|
||||
_isDisposed = true;
|
||||
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Runtime.Versioning;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.Web.Extensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Repesents configurable options for <see cref="RemoteBrowserFileStream"/>.
|
||||
/// </summary>
|
||||
[UnsupportedOSPlatform("browser")]
|
||||
public class RemoteBrowserFileStreamOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the maximum segment size for file data sent over a SignalR circuit.
|
||||
/// The default value is 20K.
|
||||
/// <para>
|
||||
/// This only has an effect when using Blazor Server.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
public int SegmentSize { get; set; } = 20 * 1024; // SignalR limit is 32K.
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the maximum internal buffer size for unread data sent over a SignalR circuit.
|
||||
/// <para>
|
||||
/// This only has an effect when using Blazor Server.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
public int MaxBufferSize { get; set; } = 1024 * 1024;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the time limit for fetching a segment of file data.
|
||||
/// <para>
|
||||
/// This only has an effect when using Blazor Server.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
public TimeSpan SegmentFetchTimeout { get; set; } = TimeSpan.FromSeconds(3);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
// 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.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.JSInterop;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.Web.Extensions
|
||||
{
|
||||
internal class SharedBrowserFileStream : BrowserFileStream
|
||||
{
|
||||
private readonly IJSRuntime _jsRuntime;
|
||||
|
||||
private readonly IJSUnmarshalledRuntime _jsUnmarshalledRuntime;
|
||||
|
||||
private readonly ElementReference _inputFileElement;
|
||||
|
||||
public SharedBrowserFileStream(IJSRuntime jsRuntime, IJSUnmarshalledRuntime jsUnmarshalledRuntime, ElementReference inputFileElement, BrowserFile file)
|
||||
: base(file)
|
||||
{
|
||||
_jsRuntime = jsRuntime;
|
||||
_jsUnmarshalledRuntime = jsUnmarshalledRuntime;
|
||||
_inputFileElement = inputFileElement;
|
||||
}
|
||||
|
||||
protected override async ValueTask<int> CopyFileDataIntoBuffer(long sourceOffset, Memory<byte> destination, CancellationToken cancellationToken)
|
||||
{
|
||||
await _jsRuntime.InvokeVoidAsync(InputFileInterop.EnsureArrayBufferReadyForSharedMemoryInterop, cancellationToken, _inputFileElement, File.Id);
|
||||
|
||||
var readRequest = new ReadRequest
|
||||
{
|
||||
InputFileElementReferenceId = _inputFileElement.Id,
|
||||
FileId = File.Id,
|
||||
SourceOffset = sourceOffset
|
||||
};
|
||||
|
||||
if (MemoryMarshal.TryGetArray(destination, out ArraySegment<byte> destinationArraySegment))
|
||||
{
|
||||
readRequest.Destination = destinationArraySegment.Array!;
|
||||
readRequest.DestinationOffset = destinationArraySegment.Offset;
|
||||
readRequest.MaxBytes = destinationArraySegment.Count;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Worst case, we need to copy to a temporary array.
|
||||
readRequest.Destination = new byte[destination.Length];
|
||||
readRequest.DestinationOffset = 0;
|
||||
readRequest.MaxBytes = destination.Length;
|
||||
|
||||
destination.CopyTo(new Memory<byte>(readRequest.Destination));
|
||||
}
|
||||
|
||||
return _jsUnmarshalledRuntime.InvokeUnmarshalled<ReadRequest, int>(InputFileInterop.ReadFileDataSharedMemory, readRequest);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,142 @@
|
|||
(function () {
|
||||
|
||||
// Exported functions
|
||||
|
||||
function init(callbackWrapper, elem) {
|
||||
elem._blazorInputFileNextFileId = 0;
|
||||
|
||||
elem.addEventListener('click', function () {
|
||||
// Permits replacing an existing file with a new one of the same file name.
|
||||
elem.value = '';
|
||||
});
|
||||
|
||||
elem.addEventListener('change', function () {
|
||||
// Reduce to purely serializable data, plus an index by ID.
|
||||
elem._blazorFilesById = {};
|
||||
|
||||
const fileList = Array.prototype.map.call(elem.files, function (file) {
|
||||
const result = {
|
||||
id: ++elem._blazorInputFileNextFileId,
|
||||
lastModified: new Date(file.lastModified).toISOString(),
|
||||
name: file.name,
|
||||
size: file.size,
|
||||
type: file.type,
|
||||
};
|
||||
|
||||
elem._blazorFilesById[result.id] = result;
|
||||
|
||||
// Attach the blob data itself as a non-enumerable property so it doesn't appear in the JSON.
|
||||
Object.defineProperty(result, 'blob', { value: file });
|
||||
|
||||
return result;
|
||||
});
|
||||
|
||||
callbackWrapper.invokeMethodAsync('NotifyChange', fileList);
|
||||
});
|
||||
}
|
||||
|
||||
function toImageFile(elem, fileId, format, maxWidth, maxHeight) {
|
||||
var originalFile = getFileById(elem, fileId);
|
||||
|
||||
return new Promise(function (resolve) {
|
||||
var originalFileImage = new Image();
|
||||
originalFileImage.onload = function () { resolve(originalFileImage); };
|
||||
originalFileImage.src = URL.createObjectURL(originalFile.blob);
|
||||
}).then(function (loadedImage) {
|
||||
return new Promise(function (resolve) {
|
||||
var desiredWidthRatio = Math.min(1, maxWidth / loadedImage.width);
|
||||
var desiredHeightRatio = Math.min(1, maxHeight / loadedImage.height);
|
||||
var chosenSizeRatio = Math.min(desiredWidthRatio, desiredHeightRatio);
|
||||
|
||||
var canvas = document.createElement('canvas');
|
||||
canvas.width = Math.round(loadedImage.width * chosenSizeRatio);
|
||||
canvas.height = Math.round(loadedImage.height * chosenSizeRatio);
|
||||
canvas.getContext('2d').drawImage(loadedImage, 0, 0, canvas.width, canvas.height);
|
||||
canvas.toBlob(resolve, format);
|
||||
});
|
||||
}).then(function (resizedImageBlob) {
|
||||
var result = {
|
||||
id: ++elem._blazorInputFileNextFileId,
|
||||
lastModified: originalFile.lastModified,
|
||||
name: originalFile.name, // Note: we're not changing the file extension.
|
||||
size: resizedImageBlob.size,
|
||||
type: format,
|
||||
relativePath: originalFile.relativePath
|
||||
};
|
||||
|
||||
elem._blazorFilesById[result.id] = result;
|
||||
|
||||
// Attach the blob data itself as a non-enumerable property so it doesn't appear in the JSON.
|
||||
Object.defineProperty(result, 'blob', { value: resizedImageBlob });
|
||||
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
function ensureArrayBufferReadyForSharedMemoryInterop(elem, fileId) {
|
||||
return getArrayBufferFromFileAsync(elem, fileId).then(function (arrayBuffer) {
|
||||
getFileById(elem, fileId).arrayBuffer = arrayBuffer;
|
||||
});
|
||||
}
|
||||
|
||||
function readFileData(elem, fileId, startOffset, count) {
|
||||
return getArrayBufferFromFileAsync(elem, fileId).then(function (arrayBuffer) {
|
||||
return btoa(String.fromCharCode.apply(null, new Uint8Array(arrayBuffer, startOffset, count)));
|
||||
});
|
||||
}
|
||||
|
||||
function readFileDataSharedMemory(readRequest) {
|
||||
const inputFileElementReferenceId = Blazor.platform.readStringField(readRequest, 0);
|
||||
const inputFileElement = document.querySelector(`[_bl_${inputFileElementReferenceId}]`);
|
||||
const fileId = Blazor.platform.readInt32Field(readRequest, 4);
|
||||
const sourceOffset = Blazor.platform.readUint64Field(readRequest, 8);
|
||||
const destination = Blazor.platform.readInt32Field(readRequest, 16);
|
||||
const destinationOffset = Blazor.platform.readInt32Field(readRequest, 20);
|
||||
const maxBytes = Blazor.platform.readInt32Field(readRequest, 24);
|
||||
|
||||
const sourceArrayBuffer = getFileById(inputFileElement, fileId).arrayBuffer;
|
||||
const bytesToRead = Math.min(maxBytes, sourceArrayBuffer.byteLength - sourceOffset);
|
||||
const sourceUint8Array = new Uint8Array(sourceArrayBuffer, sourceOffset, bytesToRead);
|
||||
|
||||
const destinationUint8Array = Blazor.platform.toUint8Array(destination);
|
||||
destinationUint8Array.set(sourceUint8Array, destinationOffset);
|
||||
|
||||
return bytesToRead;
|
||||
}
|
||||
|
||||
// Local helpers
|
||||
|
||||
function getFileById(elem, fileId) {
|
||||
const file = elem._blazorFilesById[fileId];
|
||||
|
||||
if (!file) {
|
||||
throw new Error(`There is no file with ID ${fileId}. The file list may have changed.`);
|
||||
}
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
function getArrayBufferFromFileAsync(elem, fileId) {
|
||||
const file = getFileById(elem, fileId);
|
||||
|
||||
// On the first read, convert the FileReader into a Promise<ArrayBuffer>.
|
||||
if (!file.readPromise) {
|
||||
file.readPromise = new Promise(function (resolve, reject) {
|
||||
const reader = new FileReader();
|
||||
reader.onload = function () { resolve(reader.result); };
|
||||
reader.onerror = function (err) { reject(err); };
|
||||
reader.readAsArrayBuffer(file.blob);
|
||||
});
|
||||
}
|
||||
|
||||
return file.readPromise;
|
||||
}
|
||||
|
||||
window._blazorInputFile = {
|
||||
init,
|
||||
toImageFile,
|
||||
ensureArrayBufferReadyForSharedMemoryInterop,
|
||||
readFileData,
|
||||
readFileDataSharedMemory,
|
||||
};
|
||||
})();
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -7,11 +7,12 @@ import { shouldAutoStart } from './BootCommon';
|
|||
import { RenderQueue } from './Platform/Circuits/RenderQueue';
|
||||
import { ConsoleLogger } from './Platform/Logging/Loggers';
|
||||
import { LogLevel, Logger } from './Platform/Logging/Logger';
|
||||
import { discoverComponents, CircuitDescriptor } from './Platform/Circuits/CircuitManager';
|
||||
import { CircuitDescriptor } from './Platform/Circuits/CircuitManager';
|
||||
import { setEventDispatcher } from './Rendering/RendererEventDispatcher';
|
||||
import { resolveOptions, CircuitStartOptions } from './Platform/Circuits/CircuitStartOptions';
|
||||
import { DefaultReconnectionHandler } from './Platform/Circuits/DefaultReconnectionHandler';
|
||||
import { attachRootComponentToLogicalElement } from './Rendering/Renderer';
|
||||
import { discoverComponents, ServerComponentDescriptor } from './Services/ComponentDescriptorDiscovery';
|
||||
|
||||
let renderingFailed = false;
|
||||
let started = false;
|
||||
|
|
@ -29,7 +30,7 @@ async function boot(userOptions?: Partial<CircuitStartOptions>): Promise<void> {
|
|||
options.reconnectionHandler = options.reconnectionHandler || window['Blazor'].defaultReconnectionHandler;
|
||||
logger.log(LogLevel.Information, 'Starting up blazor server-side application.');
|
||||
|
||||
const components = discoverComponents(document);
|
||||
const components = discoverComponents(document, 'server') as ServerComponentDescriptor[];
|
||||
const circuit = new CircuitDescriptor(components);
|
||||
|
||||
const initialConnection = await initializeConnection(options, logger, circuit);
|
||||
|
|
@ -97,7 +98,7 @@ async function initializeConnection(options: CircuitStartOptions, logger: Logger
|
|||
|
||||
connection.on('JS.AttachComponent', (componentId, selector) => attachRootComponentToLogicalElement(0, circuit.resolveElement(selector), componentId));
|
||||
connection.on('JS.BeginInvokeJS', DotNet.jsCallDispatcher.beginInvokeJSFromDotNet);
|
||||
connection.on('JS.EndInvokeDotNet', (args: string) => DotNet.jsCallDispatcher.endInvokeDotNetFromJS(...(JSON.parse(args) as [string, boolean, unknown])));
|
||||
connection.on('JS.EndInvokeDotNet', (args: string) => DotNet.jsCallDispatcher.endInvokeDotNetFromJS(...(DotNet.parseJsonWithRevivers(args) as [string, boolean, unknown])));
|
||||
|
||||
const renderQueue = RenderQueue.getOrCreate(logger);
|
||||
connection.on('JS.RenderBatch', (batchId: number, batchData: Uint8Array) => {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { DotNet } from '@microsoft/dotnet-js-interop';
|
|||
import './GlobalExports';
|
||||
import * as Environment from './Environment';
|
||||
import { monoPlatform } from './Platform/Mono/MonoPlatform';
|
||||
import { renderBatch, getRendererer } from './Rendering/Renderer';
|
||||
import { renderBatch, getRendererer, attachRootComponentToElement, attachRootComponentToLogicalElement } from './Rendering/Renderer';
|
||||
import { SharedMemoryRenderBatch } from './Rendering/RenderBatch/SharedMemoryRenderBatch';
|
||||
import { shouldAutoStart } from './BootCommon';
|
||||
import { setEventDispatcher } from './Rendering/RendererEventDispatcher';
|
||||
|
|
@ -11,6 +11,8 @@ import { WebAssemblyConfigLoader } from './Platform/WebAssemblyConfigLoader';
|
|||
import { BootConfigResult } from './Platform/BootConfig';
|
||||
import { Pointer } from './Platform/Platform';
|
||||
import { WebAssemblyStartOptions } from './Platform/WebAssemblyStartOptions';
|
||||
import { WebAssemblyComponentAttacher } from './Platform/WebAssemblyComponentAttacher';
|
||||
import { discoverComponents, WebAssemblyComponentDescriptor } from './Services/ComponentDescriptorDiscovery';
|
||||
|
||||
let started = false;
|
||||
|
||||
|
|
@ -32,6 +34,9 @@ async function boot(options?: Partial<WebAssemblyStartOptions>): Promise<void> {
|
|||
}
|
||||
});
|
||||
|
||||
// Configure JS interop
|
||||
window['Blazor']._internal.invokeJSFromDotNet = invokeJSFromDotNet;
|
||||
|
||||
// Configure environment for execution under Mono WebAssembly with shared-memory rendering
|
||||
const platform = Environment.setPlatform(monoPlatform);
|
||||
window['Blazor'].platform = platform;
|
||||
|
|
@ -68,8 +73,31 @@ async function boot(options?: Partial<WebAssemblyStartOptions>): Promise<void> {
|
|||
const environment = options?.environment;
|
||||
|
||||
// Fetch the resources and prepare the Mono runtime
|
||||
const bootConfigResult = await BootConfigResult.initAsync(environment);
|
||||
const bootConfigPromise = BootConfigResult.initAsync(environment);
|
||||
|
||||
// Leverage the time while we are loading boot.config.json from the network to discover any potentially registered component on
|
||||
// the document.
|
||||
const discoveredComponents = discoverComponents(document, 'webassembly') as WebAssemblyComponentDescriptor[];
|
||||
const componentAttacher = new WebAssemblyComponentAttacher(discoveredComponents);
|
||||
window['Blazor']._internal.registeredComponents = {
|
||||
getRegisteredComponentsCount: () => componentAttacher.getCount(),
|
||||
getId: (index) => componentAttacher.getId(index),
|
||||
getAssembly: (id) => BINDING.js_string_to_mono_string(componentAttacher.getAssembly(id)),
|
||||
getTypeName: (id) => BINDING.js_string_to_mono_string(componentAttacher.getTypeName(id)),
|
||||
getParameterDefinitions: (id) => BINDING.js_string_to_mono_string(componentAttacher.getParameterDefinitions(id) || ''),
|
||||
getParameterValues: (id) => BINDING.js_string_to_mono_string(componentAttacher.getParameterValues(id) || ''),
|
||||
};
|
||||
|
||||
window['Blazor']._internal.attachRootComponentToElement = (selector, componentId, rendererId) => {
|
||||
const element = componentAttacher.resolveRegisteredElement(selector);
|
||||
if (!element) {
|
||||
attachRootComponentToElement(selector, componentId, rendererId);
|
||||
} else {
|
||||
attachRootComponentToLogicalElement(rendererId, element, componentId);
|
||||
}
|
||||
};
|
||||
|
||||
const bootConfigResult = await bootConfigPromise;
|
||||
const [resourceLoader] = await Promise.all([
|
||||
WebAssemblyResourceLoader.initAsync(bootConfigResult.bootConfig, options || {}),
|
||||
WebAssemblyConfigLoader.initAsync(bootConfigResult)]);
|
||||
|
|
@ -84,6 +112,28 @@ async function boot(options?: Partial<WebAssemblyStartOptions>): Promise<void> {
|
|||
platform.callEntryPoint(resourceLoader.bootConfig.entryAssembly);
|
||||
}
|
||||
|
||||
function invokeJSFromDotNet(callInfo: Pointer, arg0: any, arg1: any, arg2: any): any {
|
||||
const functionIdentifier = monoPlatform.readStringField(callInfo, 0)!;
|
||||
const resultType = monoPlatform.readInt32Field(callInfo, 4);
|
||||
const marshalledCallArgsJson = monoPlatform.readStringField(callInfo, 8);
|
||||
const targetInstanceId = monoPlatform.readUint64Field(callInfo, 20);
|
||||
|
||||
if (marshalledCallArgsJson !== null) {
|
||||
const marshalledCallAsyncHandle = monoPlatform.readUint64Field(callInfo, 12);
|
||||
|
||||
if (marshalledCallAsyncHandle !== 0) {
|
||||
DotNet.jsCallDispatcher.beginInvokeJSFromDotNet(marshalledCallAsyncHandle, functionIdentifier, marshalledCallArgsJson, resultType, targetInstanceId);
|
||||
return 0;
|
||||
} else {
|
||||
const resultJson = DotNet.jsCallDispatcher.invokeJSFromDotNet(functionIdentifier, marshalledCallArgsJson, resultType, targetInstanceId)!;
|
||||
return resultJson === null ? 0 : BINDING.js_string_to_mono_string(resultJson);
|
||||
}
|
||||
} else {
|
||||
const func = DotNet.jsCallDispatcher.findJSFunction(functionIdentifier, targetInstanceId);
|
||||
return func.call(null, arg0, arg1, arg2);
|
||||
}
|
||||
}
|
||||
|
||||
window['Blazor'].start = boot;
|
||||
if (shouldAutoStart()) {
|
||||
boot().catch(error => {
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ window['Blazor'] = {
|
|||
navigateTo,
|
||||
|
||||
_internal: {
|
||||
attachRootComponentToElement,
|
||||
navigationManager: navigationManagerInternalFunctions,
|
||||
domWrapper: domFunctions,
|
||||
Virtualize,
|
||||
|
|
|
|||
|
|
@ -1,12 +1,13 @@
|
|||
import { internalFunctions as navigationManagerFunctions } from '../../Services/NavigationManager';
|
||||
import { toLogicalRootCommentElement, LogicalElement } from '../../Rendering/LogicalElements';
|
||||
import { ServerComponentDescriptor } from '../../Services/ComponentDescriptorDiscovery';
|
||||
|
||||
export class CircuitDescriptor {
|
||||
public circuitId?: string;
|
||||
|
||||
public components: ComponentDescriptor[];
|
||||
public components: ServerComponentDescriptor[];
|
||||
|
||||
public constructor(components: ComponentDescriptor[]) {
|
||||
public constructor(components: ServerComponentDescriptor[]) {
|
||||
this.circuitId = undefined;
|
||||
this.components = components;
|
||||
}
|
||||
|
|
@ -54,221 +55,3 @@ export class CircuitDescriptor {
|
|||
}
|
||||
}
|
||||
|
||||
interface ComponentMarker {
|
||||
type: string;
|
||||
sequence: number;
|
||||
descriptor: string;
|
||||
}
|
||||
|
||||
export class ComponentDescriptor {
|
||||
public type: string;
|
||||
|
||||
public start: Node;
|
||||
|
||||
public end?: Node;
|
||||
|
||||
public sequence: number;
|
||||
|
||||
public descriptor: string;
|
||||
|
||||
public constructor(type: string, start: Node, end: Node | undefined, sequence: number, descriptor: string) {
|
||||
this.type = type;
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
this.sequence = sequence;
|
||||
this.descriptor = descriptor;
|
||||
}
|
||||
|
||||
public toRecord(): ComponentMarker {
|
||||
const result = { type: this.type, sequence: this.sequence, descriptor: this.descriptor };
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
export function discoverComponents(document: Document): ComponentDescriptor[] {
|
||||
const componentComments = resolveComponentComments(document);
|
||||
const discoveredComponents: ComponentDescriptor[] = [];
|
||||
for (let i = 0; i < componentComments.length; i++) {
|
||||
const componentComment = componentComments[i];
|
||||
const entry = new ComponentDescriptor(
|
||||
componentComment.type,
|
||||
componentComment.start,
|
||||
componentComment.end,
|
||||
componentComment.sequence,
|
||||
componentComment.descriptor,
|
||||
);
|
||||
|
||||
discoveredComponents.push(entry);
|
||||
}
|
||||
|
||||
return discoveredComponents.sort((a, b) => a.sequence - b.sequence);
|
||||
}
|
||||
|
||||
|
||||
interface ComponentComment {
|
||||
type: 'server';
|
||||
sequence: number;
|
||||
descriptor: string;
|
||||
start: Node;
|
||||
end?: Node;
|
||||
prerenderId?: string;
|
||||
}
|
||||
|
||||
function resolveComponentComments(node: Node): ComponentComment[] {
|
||||
if (!node.hasChildNodes()) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const result: ComponentComment[] = [];
|
||||
const childNodeIterator = new ComponentCommentIterator(node.childNodes);
|
||||
while (childNodeIterator.next() && childNodeIterator.currentElement) {
|
||||
const componentComment = getComponentComment(childNodeIterator);
|
||||
if (componentComment) {
|
||||
result.push(componentComment);
|
||||
} else {
|
||||
const childResults = resolveComponentComments(childNodeIterator.currentElement);
|
||||
for (let j = 0; j < childResults.length; j++) {
|
||||
const childResult = childResults[j];
|
||||
result.push(childResult);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
const blazorCommentRegularExpression = /\W*Blazor:[^{]*(.*)$/;
|
||||
|
||||
function getComponentComment(commentNodeIterator: ComponentCommentIterator): ComponentComment | undefined {
|
||||
const candidateStart = commentNodeIterator.currentElement;
|
||||
|
||||
if (!candidateStart || candidateStart.nodeType !== Node.COMMENT_NODE) {
|
||||
return;
|
||||
}
|
||||
if (candidateStart.textContent) {
|
||||
const componentStartComment = new RegExp(blazorCommentRegularExpression);
|
||||
const definition = componentStartComment.exec(candidateStart.textContent);
|
||||
const json = definition && definition[1];
|
||||
|
||||
if (json) {
|
||||
try {
|
||||
return createComponentComment(json, candidateStart, commentNodeIterator);
|
||||
} catch (error) {
|
||||
throw new Error(`Found malformed component comment at ${candidateStart.textContent}`);
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function createComponentComment(json: string, start: Node, iterator: ComponentCommentIterator): ComponentComment {
|
||||
const payload = JSON.parse(json) as ComponentComment;
|
||||
const { type, sequence, descriptor, prerenderId } = payload;
|
||||
if (type !== 'server') {
|
||||
throw new Error(`Invalid component type '${type}'.`);
|
||||
}
|
||||
|
||||
if (!descriptor) {
|
||||
throw new Error('descriptor must be defined when using a descriptor.');
|
||||
}
|
||||
|
||||
if (sequence === undefined) {
|
||||
throw new Error('sequence must be defined when using a descriptor.');
|
||||
}
|
||||
|
||||
if (!Number.isInteger(sequence)) {
|
||||
throw new Error(`Error parsing the sequence '${sequence}' for component '${json}'`);
|
||||
}
|
||||
|
||||
if (!prerenderId) {
|
||||
return {
|
||||
type,
|
||||
sequence: sequence,
|
||||
descriptor,
|
||||
start,
|
||||
};
|
||||
} else {
|
||||
const end = getComponentEndComment(prerenderId, iterator);
|
||||
if (!end) {
|
||||
throw new Error(`Could not find an end component comment for '${start}'`);
|
||||
}
|
||||
|
||||
return {
|
||||
type,
|
||||
sequence,
|
||||
descriptor,
|
||||
start,
|
||||
prerenderId,
|
||||
end,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function getComponentEndComment(prerenderedId: string, iterator: ComponentCommentIterator): ChildNode | undefined {
|
||||
while (iterator.next() && iterator.currentElement) {
|
||||
const node = iterator.currentElement;
|
||||
if (node.nodeType !== Node.COMMENT_NODE) {
|
||||
continue;
|
||||
}
|
||||
if (!node.textContent) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const definition = new RegExp(blazorCommentRegularExpression).exec(node.textContent);
|
||||
const json = definition && definition[1];
|
||||
if (!json) {
|
||||
continue;
|
||||
}
|
||||
|
||||
validateEndComponentPayload(json, prerenderedId);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function validateEndComponentPayload(json: string, prerenderedId: string): void {
|
||||
const payload = JSON.parse(json) as ComponentComment;
|
||||
if (Object.keys(payload).length !== 1) {
|
||||
throw new Error(`Invalid end of component comment: '${json}'`);
|
||||
}
|
||||
const prerenderedEndId = payload.prerenderId;
|
||||
if (!prerenderedEndId) {
|
||||
throw new Error(`End of component comment must have a value for the prerendered property: '${json}'`);
|
||||
}
|
||||
if (prerenderedEndId !== prerenderedId) {
|
||||
throw new Error(`End of component comment prerendered property must match the start comment prerender id: '${prerenderedId}', '${prerenderedEndId}'`);
|
||||
}
|
||||
}
|
||||
|
||||
class ComponentCommentIterator {
|
||||
|
||||
private childNodes: NodeListOf<ChildNode>;
|
||||
|
||||
private currentIndex: number;
|
||||
|
||||
private length: number;
|
||||
|
||||
public currentElement: ChildNode | undefined;
|
||||
|
||||
public constructor(childNodes: NodeListOf<ChildNode>) {
|
||||
this.childNodes = childNodes;
|
||||
this.currentIndex = -1;
|
||||
this.length = childNodes.length;
|
||||
}
|
||||
|
||||
public next(): boolean {
|
||||
this.currentIndex++;
|
||||
if (this.currentIndex < this.length) {
|
||||
this.currentElement = this.childNodes[this.currentIndex];
|
||||
return true;
|
||||
} else {
|
||||
this.currentElement = undefined;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -33,8 +33,8 @@ const defaultOptions: CircuitStartOptions = {
|
|||
configureSignalR: (_) => { },
|
||||
logLevel: LogLevel.Warning,
|
||||
reconnectionOptions: {
|
||||
maxRetries: 5,
|
||||
retryIntervalMilliseconds: 3000,
|
||||
maxRetries: 8,
|
||||
retryIntervalMilliseconds: 20000,
|
||||
dialogId: 'components-reconnect-modal',
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -12,9 +12,12 @@ export class DefaultReconnectDisplay implements ReconnectDisplay {
|
|||
|
||||
reloadParagraph: HTMLParagraphElement;
|
||||
|
||||
constructor(dialogId: string, private readonly document: Document, private readonly logger: Logger) {
|
||||
loader: HTMLDivElement;
|
||||
|
||||
constructor(dialogId: string, private readonly maxRetries: number, private readonly document: Document, private readonly logger: Logger) {
|
||||
this.modal = this.document.createElement('div');
|
||||
this.modal.id = dialogId;
|
||||
this.maxRetries = maxRetries;
|
||||
|
||||
const modalStyles = [
|
||||
'position: fixed',
|
||||
|
|
@ -37,6 +40,9 @@ export class DefaultReconnectDisplay implements ReconnectDisplay {
|
|||
this.message = this.modal.querySelector('h5')!;
|
||||
this.button = this.modal.querySelector('button')!;
|
||||
this.reloadParagraph = this.modal.querySelector('p')!;
|
||||
this.loader = this.getLoader();
|
||||
|
||||
this.message.after(this.loader);
|
||||
|
||||
this.button.addEventListener('click', async () => {
|
||||
this.show();
|
||||
|
|
@ -65,6 +71,7 @@ export class DefaultReconnectDisplay implements ReconnectDisplay {
|
|||
this.document.body.appendChild(this.modal);
|
||||
}
|
||||
this.modal.style.display = 'block';
|
||||
this.loader.style.display = 'inline-block';
|
||||
this.button.style.display = 'none';
|
||||
this.reloadParagraph.style.display = 'none';
|
||||
this.message.textContent = 'Attempting to reconnect to the server...';
|
||||
|
|
@ -78,6 +85,10 @@ export class DefaultReconnectDisplay implements ReconnectDisplay {
|
|||
}, 0);
|
||||
}
|
||||
|
||||
update(currentAttempt: number): void {
|
||||
this.message.textContent = `Attempting to reconnect to the server: ${currentAttempt} of ${this.maxRetries}`;
|
||||
}
|
||||
|
||||
hide(): void {
|
||||
this.modal.style.display = 'none';
|
||||
}
|
||||
|
|
@ -85,6 +96,7 @@ export class DefaultReconnectDisplay implements ReconnectDisplay {
|
|||
failed(): void {
|
||||
this.button.style.display = 'block';
|
||||
this.reloadParagraph.style.display = 'none';
|
||||
this.loader.style.display = 'none';
|
||||
this.message.innerHTML = 'Reconnection failed. Try <a href>reloading</a> the page if you\'re unable to reconnect.';
|
||||
this.message.querySelector('a')!.addEventListener('click', () => location.reload());
|
||||
}
|
||||
|
|
@ -92,7 +104,32 @@ export class DefaultReconnectDisplay implements ReconnectDisplay {
|
|||
rejected(): void {
|
||||
this.button.style.display = 'none';
|
||||
this.reloadParagraph.style.display = 'none';
|
||||
this.loader.style.display = 'none';
|
||||
this.message.innerHTML = 'Could not reconnect to the server. <a href>Reload</a> the page to restore functionality.';
|
||||
this.message.querySelector('a')!.addEventListener('click', () => location.reload());
|
||||
}
|
||||
|
||||
private getLoader(): HTMLDivElement {
|
||||
const loader = this.document.createElement('div');
|
||||
|
||||
const loaderStyles = [
|
||||
'border: 0.3em solid #f3f3f3',
|
||||
'border-top: 0.3em solid #3498db',
|
||||
'border-radius: 50%',
|
||||
'width: 2em',
|
||||
'height: 2em',
|
||||
'display: inline-block'
|
||||
];
|
||||
|
||||
loader.style.cssText = loaderStyles.join(';');
|
||||
loader.animate([
|
||||
{ transform: 'rotate(0deg)' },
|
||||
{ transform: 'rotate(360deg)' }
|
||||
], {
|
||||
duration: 2000,
|
||||
iterations: Infinity
|
||||
});
|
||||
|
||||
return loader;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,8 +20,8 @@ export class DefaultReconnectionHandler implements ReconnectionHandler {
|
|||
if (!this._reconnectionDisplay) {
|
||||
const modal = document.getElementById(options.dialogId);
|
||||
this._reconnectionDisplay = modal
|
||||
? new UserSpecifiedDisplay(modal)
|
||||
: new DefaultReconnectDisplay(options.dialogId, document, this._logger);
|
||||
? new UserSpecifiedDisplay(modal, options.maxRetries, document)
|
||||
: new DefaultReconnectDisplay(options.dialogId, options.maxRetries, document, this._logger);
|
||||
}
|
||||
|
||||
if (!this._currentReconnectionProcess) {
|
||||
|
|
@ -38,6 +38,8 @@ export class DefaultReconnectionHandler implements ReconnectionHandler {
|
|||
};
|
||||
|
||||
class ReconnectionProcess {
|
||||
static readonly MaximumFirstRetryInterval = 3000;
|
||||
|
||||
readonly reconnectDisplay: ReconnectDisplay;
|
||||
isDisposed = false;
|
||||
|
||||
|
|
@ -54,7 +56,13 @@ class ReconnectionProcess {
|
|||
|
||||
async attemptPeriodicReconnection(options: ReconnectionOptions) {
|
||||
for (let i = 0; i < options.maxRetries; i++) {
|
||||
await this.delay(options.retryIntervalMilliseconds);
|
||||
this.reconnectDisplay.update(i + 1);
|
||||
|
||||
const delayDuration = i == 0 && options.retryIntervalMilliseconds > ReconnectionProcess.MaximumFirstRetryInterval
|
||||
? ReconnectionProcess.MaximumFirstRetryInterval
|
||||
: options.retryIntervalMilliseconds;
|
||||
await this.delay(delayDuration);
|
||||
|
||||
if (this.isDisposed) {
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
export interface ReconnectDisplay {
|
||||
show(): void;
|
||||
update(currentAttempt: number): void;
|
||||
hide(): void;
|
||||
failed(): void;
|
||||
rejected(): void;
|
||||
|
|
|
|||
|
|
@ -8,7 +8,18 @@ export class UserSpecifiedDisplay implements ReconnectDisplay {
|
|||
|
||||
static readonly RejectedClassName = 'components-reconnect-rejected';
|
||||
|
||||
constructor(private dialog: HTMLElement) {
|
||||
static readonly MaxRetriesId = 'components-reconnect-max-retries';
|
||||
|
||||
static readonly CurrentAttemptId = 'components-reconnect-current-attempt';
|
||||
|
||||
constructor(private dialog: HTMLElement, private readonly maxRetries: number, private readonly document: Document) {
|
||||
this.document = document;
|
||||
|
||||
const maxRetriesElement = this.document.getElementById(UserSpecifiedDisplay.MaxRetriesId);
|
||||
|
||||
if (maxRetriesElement) {
|
||||
maxRetriesElement.innerText = this.maxRetries.toString();
|
||||
}
|
||||
}
|
||||
|
||||
show(): void {
|
||||
|
|
@ -16,6 +27,14 @@ export class UserSpecifiedDisplay implements ReconnectDisplay {
|
|||
this.dialog.classList.add(UserSpecifiedDisplay.ShowClassName);
|
||||
}
|
||||
|
||||
update(currentAttempt: number): void {
|
||||
const currentAttemptElement = this.document.getElementById(UserSpecifiedDisplay.CurrentAttemptId);
|
||||
|
||||
if (currentAttemptElement) {
|
||||
currentAttemptElement.innerText = currentAttempt.toString();
|
||||
}
|
||||
}
|
||||
|
||||
hide(): void {
|
||||
this.removeClasses();
|
||||
this.dialog.classList.add(UserSpecifiedDisplay.HideClassName);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,51 @@
|
|||
import { LogicalElement, toLogicalRootCommentElement } from '../Rendering/LogicalElements';
|
||||
import { WebAssemblyComponentDescriptor } from '../Services/ComponentDescriptorDiscovery';
|
||||
|
||||
export class WebAssemblyComponentAttacher {
|
||||
public preregisteredComponents: WebAssemblyComponentDescriptor[];
|
||||
|
||||
private componentsById: { [index: number]: WebAssemblyComponentDescriptor };
|
||||
|
||||
public constructor(components: WebAssemblyComponentDescriptor[]) {
|
||||
this.preregisteredComponents = components;
|
||||
const componentsById = {};
|
||||
for (let index = 0; index < components.length; index++) {
|
||||
const component = components[index];
|
||||
componentsById[component.id] = component;
|
||||
}
|
||||
this.componentsById = componentsById;
|
||||
}
|
||||
|
||||
public resolveRegisteredElement(id: string): LogicalElement | undefined {
|
||||
const parsedId = Number.parseInt(id);
|
||||
if (!Number.isNaN(parsedId)) {
|
||||
return toLogicalRootCommentElement(this.componentsById[parsedId].start as Comment, this.componentsById[parsedId].end as Comment);
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
public getParameterValues(id: number): string | undefined {
|
||||
return this.componentsById[id].parameterValues;
|
||||
}
|
||||
|
||||
public getParameterDefinitions(id: number): string | undefined {
|
||||
return this.componentsById[id].parameterDefinitions;
|
||||
}
|
||||
|
||||
public getTypeName(id: number): string {
|
||||
return this.componentsById[id].typeName;
|
||||
}
|
||||
|
||||
public getAssembly(id: number): string {
|
||||
return this.componentsById[id].assembly;
|
||||
}
|
||||
|
||||
public getId(index: number): number {
|
||||
return this.preregisteredComponents[index].id;
|
||||
}
|
||||
|
||||
public getCount(): number {
|
||||
return this.preregisteredComponents.length;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,354 @@
|
|||
export function discoverComponents(document: Document, type: 'webassembly' | 'server'): ServerComponentDescriptor[] | WebAssemblyComponentDescriptor[] {
|
||||
switch (type){
|
||||
case 'webassembly':
|
||||
return discoverWebAssemblyComponents(document);
|
||||
case 'server':
|
||||
return discoverServerComponents(document);
|
||||
}
|
||||
}
|
||||
|
||||
function discoverServerComponents(document: Document): ServerComponentDescriptor[] {
|
||||
const componentComments = resolveComponentComments(document, 'server') as ServerComponentComment[];
|
||||
const discoveredComponents: ServerComponentDescriptor[] = [];
|
||||
for (let i = 0; i < componentComments.length; i++) {
|
||||
const componentComment = componentComments[i];
|
||||
const entry = new ServerComponentDescriptor(
|
||||
componentComment.type,
|
||||
componentComment.start,
|
||||
componentComment.end,
|
||||
componentComment.sequence,
|
||||
componentComment.descriptor,
|
||||
);
|
||||
|
||||
discoveredComponents.push(entry);
|
||||
}
|
||||
|
||||
return discoveredComponents.sort((a, b): number => a.sequence - b.sequence);
|
||||
}
|
||||
|
||||
function discoverWebAssemblyComponents(document: Document): WebAssemblyComponentDescriptor[] {
|
||||
const componentComments = resolveComponentComments(document, 'webassembly') as WebAssemblyComponentDescriptor[];
|
||||
const discoveredComponents: WebAssemblyComponentDescriptor[] = [];
|
||||
for (let i = 0; i < componentComments.length; i++) {
|
||||
const componentComment = componentComments[i];
|
||||
const entry = new WebAssemblyComponentDescriptor(
|
||||
componentComment.type,
|
||||
componentComment.start,
|
||||
componentComment.end,
|
||||
componentComment.assembly,
|
||||
componentComment.typeName,
|
||||
componentComment.parameterDefinitions,
|
||||
componentComment.parameterValues,
|
||||
);
|
||||
|
||||
discoveredComponents.push(entry);
|
||||
}
|
||||
|
||||
return discoveredComponents.sort((a, b): number => a.id - b.id);
|
||||
}
|
||||
|
||||
interface ComponentComment {
|
||||
type: 'server' | 'webassembly';
|
||||
prerenderId?: string;
|
||||
}
|
||||
|
||||
interface ServerComponentComment {
|
||||
type: 'server';
|
||||
sequence: number;
|
||||
descriptor: string;
|
||||
start: Node;
|
||||
end?: Node;
|
||||
prerenderId?: string;
|
||||
}
|
||||
|
||||
interface WebAssemblyComponentComment {
|
||||
type: 'webassembly';
|
||||
typeName: string;
|
||||
assembly: string;
|
||||
parameterDefinitions?: string;
|
||||
parameterValues?: string;
|
||||
prerenderId?: string;
|
||||
start: Node;
|
||||
end?: Node;
|
||||
}
|
||||
|
||||
function resolveComponentComments(node: Node, type: 'webassembly' | 'server'): ComponentComment[] {
|
||||
if (!node.hasChildNodes()) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const result: ComponentComment[] = [];
|
||||
const childNodeIterator = new ComponentCommentIterator(node.childNodes);
|
||||
while (childNodeIterator.next() && childNodeIterator.currentElement) {
|
||||
const componentComment = getComponentComment(childNodeIterator, type);
|
||||
if (componentComment) {
|
||||
result.push(componentComment);
|
||||
} else {
|
||||
const childResults = resolveComponentComments(childNodeIterator.currentElement, type);
|
||||
for (let j = 0; j < childResults.length; j++) {
|
||||
const childResult = childResults[j];
|
||||
result.push(childResult);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
const blazorCommentRegularExpression = /\W*Blazor:[^{]*(?<descriptor>.*)$/;
|
||||
|
||||
function getComponentComment(commentNodeIterator: ComponentCommentIterator, type: 'webassembly' | 'server'): ComponentComment | undefined {
|
||||
const candidateStart = commentNodeIterator.currentElement;
|
||||
|
||||
if (!candidateStart || candidateStart.nodeType !== Node.COMMENT_NODE) {
|
||||
return;
|
||||
}
|
||||
if (candidateStart.textContent) {
|
||||
const componentStartComment = new RegExp(blazorCommentRegularExpression);
|
||||
const definition = componentStartComment.exec(candidateStart.textContent);
|
||||
const json = definition && definition.groups && definition.groups['descriptor'];
|
||||
|
||||
if (json) {
|
||||
try {
|
||||
const componentComment = parseCommentPayload(json);
|
||||
switch (type) {
|
||||
case 'webassembly':
|
||||
return createWebAssemblyComponentComment(componentComment as WebAssemblyComponentComment, candidateStart, commentNodeIterator);
|
||||
case 'server':
|
||||
return createServerComponentComment(componentComment as ServerComponentComment, candidateStart, commentNodeIterator);
|
||||
}
|
||||
} catch (error) {
|
||||
throw new Error(`Found malformed component comment at ${candidateStart.textContent}`);
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function parseCommentPayload(json: string): ComponentComment {
|
||||
const payload = JSON.parse(json) as ComponentComment;
|
||||
const { type } = payload;
|
||||
if (type !== 'server' && type !== 'webassembly') {
|
||||
throw new Error(`Invalid component type '${type}'.`);
|
||||
}
|
||||
|
||||
return payload;
|
||||
}
|
||||
|
||||
function createServerComponentComment(payload: ServerComponentComment, start: Node, iterator: ComponentCommentIterator): ServerComponentComment | undefined {
|
||||
const { type, descriptor, sequence, prerenderId } = payload;
|
||||
if (type !== 'server') {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (!descriptor) {
|
||||
throw new Error('descriptor must be defined when using a descriptor.');
|
||||
}
|
||||
|
||||
if (sequence === undefined) {
|
||||
throw new Error('sequence must be defined when using a descriptor.');
|
||||
}
|
||||
|
||||
if (!Number.isInteger(sequence)) {
|
||||
throw new Error(`Error parsing the sequence '${sequence}' for component '${JSON.stringify(payload)}'`);
|
||||
}
|
||||
|
||||
if (!prerenderId) {
|
||||
return {
|
||||
type,
|
||||
sequence: sequence,
|
||||
descriptor,
|
||||
start,
|
||||
};
|
||||
} else {
|
||||
const end = getComponentEndComment(prerenderId, iterator);
|
||||
if (!end) {
|
||||
throw new Error(`Could not find an end component comment for '${start}'`);
|
||||
}
|
||||
|
||||
return {
|
||||
type,
|
||||
sequence,
|
||||
descriptor,
|
||||
start,
|
||||
prerenderId,
|
||||
end,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function createWebAssemblyComponentComment(payload: WebAssemblyComponentComment, start: Node, iterator: ComponentCommentIterator): WebAssemblyComponentComment | undefined {
|
||||
const { type, assembly, typeName, parameterDefinitions, parameterValues, prerenderId } = payload;
|
||||
if (type !== 'webassembly') {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (!assembly) {
|
||||
throw new Error('assembly must be defined when using a descriptor.');
|
||||
}
|
||||
|
||||
if (!typeName) {
|
||||
throw new Error('typeName must be defined when using a descriptor.');
|
||||
}
|
||||
|
||||
if (!prerenderId) {
|
||||
return {
|
||||
type,
|
||||
assembly,
|
||||
typeName,
|
||||
// Parameter definitions and values come Base64 encoded from the server, since they contain random data and can make the
|
||||
// comment invalid. We could unencode them in .NET Code, but that would be slower to do and we can leverage the fact that
|
||||
// JS provides a native function that will be much faster and that we are doing this work while we are fetching
|
||||
// blazor.boot.json
|
||||
parameterDefinitions: parameterDefinitions && atob(parameterDefinitions),
|
||||
parameterValues: parameterValues && atob(parameterValues),
|
||||
start,
|
||||
};
|
||||
} else {
|
||||
const end = getComponentEndComment(prerenderId, iterator);
|
||||
if (!end) {
|
||||
throw new Error(`Could not find an end component comment for '${start}'`);
|
||||
}
|
||||
|
||||
return {
|
||||
type,
|
||||
assembly,
|
||||
typeName,
|
||||
// Same comment as above.
|
||||
parameterDefinitions: parameterDefinitions && atob(parameterDefinitions),
|
||||
parameterValues: parameterValues && atob(parameterValues),
|
||||
start,
|
||||
prerenderId,
|
||||
end,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function getComponentEndComment(prerenderedId: string, iterator: ComponentCommentIterator): ChildNode | undefined {
|
||||
while (iterator.next() && iterator.currentElement) {
|
||||
const node = iterator.currentElement;
|
||||
if (node.nodeType !== Node.COMMENT_NODE) {
|
||||
continue;
|
||||
}
|
||||
if (!node.textContent) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const definition = new RegExp(blazorCommentRegularExpression).exec(node.textContent);
|
||||
const json = definition && definition[1];
|
||||
if (!json) {
|
||||
continue;
|
||||
}
|
||||
|
||||
validateEndComponentPayload(json, prerenderedId);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function validateEndComponentPayload(json: string, prerenderedId: string): void {
|
||||
const payload = JSON.parse(json) as ComponentComment;
|
||||
if (Object.keys(payload).length !== 1) {
|
||||
throw new Error(`Invalid end of component comment: '${json}'`);
|
||||
}
|
||||
const prerenderedEndId = payload.prerenderId;
|
||||
if (!prerenderedEndId) {
|
||||
throw new Error(`End of component comment must have a value for the prerendered property: '${json}'`);
|
||||
}
|
||||
if (prerenderedEndId !== prerenderedId) {
|
||||
throw new Error(`End of component comment prerendered property must match the start comment prerender id: '${prerenderedId}', '${prerenderedEndId}'`);
|
||||
}
|
||||
}
|
||||
|
||||
class ComponentCommentIterator {
|
||||
|
||||
private childNodes: NodeListOf<ChildNode>;
|
||||
|
||||
private currentIndex: number;
|
||||
|
||||
private length: number;
|
||||
|
||||
public currentElement: ChildNode | undefined;
|
||||
|
||||
public constructor(childNodes: NodeListOf<ChildNode>) {
|
||||
this.childNodes = childNodes;
|
||||
this.currentIndex = -1;
|
||||
this.length = childNodes.length;
|
||||
}
|
||||
|
||||
public next(): boolean {
|
||||
this.currentIndex++;
|
||||
if (this.currentIndex < this.length) {
|
||||
this.currentElement = this.childNodes[this.currentIndex];
|
||||
return true;
|
||||
} else {
|
||||
this.currentElement = undefined;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
interface ServerComponentMarker {
|
||||
type: string;
|
||||
sequence: number;
|
||||
descriptor: string;
|
||||
}
|
||||
|
||||
export class ServerComponentDescriptor {
|
||||
public type: string;
|
||||
|
||||
public start: Node;
|
||||
|
||||
public end?: Node;
|
||||
|
||||
public sequence: number;
|
||||
|
||||
public descriptor: string;
|
||||
|
||||
public constructor(type: string, start: Node, end: Node | undefined, sequence: number, descriptor: string) {
|
||||
this.type = type;
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
this.sequence = sequence;
|
||||
this.descriptor = descriptor;
|
||||
}
|
||||
|
||||
public toRecord(): ServerComponentMarker {
|
||||
const result = { type: this.type, sequence: this.sequence, descriptor: this.descriptor };
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
export class WebAssemblyComponentDescriptor {
|
||||
private static globalId = 1;
|
||||
|
||||
public type: 'webassembly';
|
||||
|
||||
public typeName: string;
|
||||
|
||||
public assembly: string;
|
||||
|
||||
public parameterDefinitions?: string;
|
||||
|
||||
public parameterValues?: string;
|
||||
|
||||
public id: number;
|
||||
|
||||
public start: Node;
|
||||
|
||||
public end?: Node;
|
||||
|
||||
public constructor(type: 'webassembly', start: Node, end: Node | undefined, assembly: string, typeName: string, parameterDefinitions?: string, parameterValues?: string) {
|
||||
this.id = WebAssemblyComponentDescriptor.globalId++;
|
||||
this.type = type;
|
||||
this.assembly = assembly;
|
||||
this.typeName = typeName;
|
||||
this.parameterDefinitions = parameterDefinitions;
|
||||
this.parameterValues = parameterValues;
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
}
|
||||
}
|
||||
|
|
@ -57,15 +57,16 @@ function init(dotNetHelper: any, spacerBefore: HTMLElement, spacerAfter: HTMLEle
|
|||
return;
|
||||
}
|
||||
|
||||
const spacerSeparation = spacerAfter.offsetTop - (spacerBefore.offsetTop + spacerBefore.offsetHeight);
|
||||
const containerSize = entry.rootBounds?.height;
|
||||
|
||||
if (entry.target === spacerBefore) {
|
||||
dotNetHelper.invokeMethodAsync('OnSpacerBeforeVisible', entry.intersectionRect.top - entry.boundingClientRect.top, containerSize);
|
||||
dotNetHelper.invokeMethodAsync('OnSpacerBeforeVisible', entry.intersectionRect.top - entry.boundingClientRect.top, spacerSeparation, containerSize);
|
||||
} else if (entry.target === spacerAfter && spacerAfter.offsetHeight > 0) {
|
||||
// When we first start up, both the "before" and "after" spacers will be visible, but it's only relevant to raise a
|
||||
// single event to load the initial data. To avoid raising two events, skip the one for the "after" spacer if we know
|
||||
// it's meaningless to talk about any overlap into it.
|
||||
dotNetHelper.invokeMethodAsync('OnSpacerAfterVisible', entry.boundingClientRect.bottom - entry.intersectionRect.bottom, containerSize);
|
||||
dotNetHelper.invokeMethodAsync('OnSpacerAfterVisible', entry.boundingClientRect.bottom - entry.intersectionRect.bottom, spacerSeparation, containerSize);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,10 +3,18 @@ import { JSDOM } from 'jsdom';
|
|||
import { NullLogger } from '../src/Platform/Logging/Loggers';
|
||||
|
||||
describe('DefaultReconnectDisplay', () => {
|
||||
let testDocument: Document;
|
||||
|
||||
beforeEach(() => {
|
||||
const window = new JSDOM().window;
|
||||
|
||||
//JSDOM does not support animate function so we need to mock it
|
||||
window.HTMLDivElement.prototype.animate = jest.fn();
|
||||
testDocument = window.document;
|
||||
})
|
||||
|
||||
it ('adds element to the body on show', () => {
|
||||
const testDocument = new JSDOM().window.document;
|
||||
const display = new DefaultReconnectDisplay('test-dialog-id', testDocument, NullLogger.instance);
|
||||
const display = new DefaultReconnectDisplay('test-dialog-id', 6, testDocument, NullLogger.instance);
|
||||
|
||||
display.show();
|
||||
|
||||
|
|
@ -16,6 +24,7 @@ describe('DefaultReconnectDisplay', () => {
|
|||
expect(element!.style.display).toBe('block');
|
||||
expect(element!.style.visibility).toBe('hidden');
|
||||
|
||||
expect(display.loader.style.display).toBe('inline-block');
|
||||
expect(display.message.textContent).toBe('Attempting to reconnect to the server...');
|
||||
expect(display.button.style.display).toBe('none');
|
||||
|
||||
|
|
@ -27,8 +36,7 @@ describe('DefaultReconnectDisplay', () => {
|
|||
});
|
||||
|
||||
it ('does not add element to the body multiple times', () => {
|
||||
const testDocument = new JSDOM().window.document;
|
||||
const display = new DefaultReconnectDisplay('test-dialog-id', testDocument, NullLogger.instance);
|
||||
const display = new DefaultReconnectDisplay('test-dialog-id', 6, testDocument, NullLogger.instance);
|
||||
|
||||
display.show();
|
||||
display.show();
|
||||
|
|
@ -37,8 +45,7 @@ describe('DefaultReconnectDisplay', () => {
|
|||
});
|
||||
|
||||
it ('hides element', () => {
|
||||
const testDocument = new JSDOM().window.document;
|
||||
const display = new DefaultReconnectDisplay('test-dialog-id', testDocument, NullLogger.instance);
|
||||
const display = new DefaultReconnectDisplay('test-dialog-id', 6, testDocument, NullLogger.instance);
|
||||
|
||||
display.hide();
|
||||
|
||||
|
|
@ -46,8 +53,7 @@ describe('DefaultReconnectDisplay', () => {
|
|||
});
|
||||
|
||||
it ('updates message on fail', () => {
|
||||
const testDocument = new JSDOM().window.document;
|
||||
const display = new DefaultReconnectDisplay('test-dialog-id', testDocument, NullLogger.instance);
|
||||
const display = new DefaultReconnectDisplay('test-dialog-id', 6, testDocument, NullLogger.instance);
|
||||
|
||||
display.show();
|
||||
display.failed();
|
||||
|
|
@ -55,11 +61,11 @@ describe('DefaultReconnectDisplay', () => {
|
|||
expect(display.modal.style.display).toBe('block');
|
||||
expect(display.message.innerHTML).toBe('Reconnection failed. Try <a href=\"\">reloading</a> the page if you\'re unable to reconnect.');
|
||||
expect(display.button.style.display).toBe('block');
|
||||
expect(display.loader.style.display).toBe('none');
|
||||
});
|
||||
|
||||
it ('updates message on refused', () => {
|
||||
const testDocument = new JSDOM().window.document;
|
||||
const display = new DefaultReconnectDisplay('test-dialog-id', testDocument, NullLogger.instance);
|
||||
const display = new DefaultReconnectDisplay('test-dialog-id', 6, testDocument, NullLogger.instance);
|
||||
|
||||
display.show();
|
||||
display.rejected();
|
||||
|
|
@ -67,6 +73,18 @@ describe('DefaultReconnectDisplay', () => {
|
|||
expect(display.modal.style.display).toBe('block');
|
||||
expect(display.message.innerHTML).toBe('Could not reconnect to the server. <a href=\"\">Reload</a> the page to restore functionality.');
|
||||
expect(display.button.style.display).toBe('none');
|
||||
expect(display.loader.style.display).toBe('none');
|
||||
});
|
||||
|
||||
it('update message with current attempt', () => {
|
||||
const maxRetires = 6;
|
||||
const display = new DefaultReconnectDisplay('test-dialog-id', maxRetires, testDocument, NullLogger.instance);
|
||||
|
||||
display.show();
|
||||
|
||||
for (let index = 0; index < maxRetires; index++) {
|
||||
display.update(index);
|
||||
expect(display.message.innerHTML).toBe(`Attempting to reconnect to the server: ${index++} of ${maxRetires}`);
|
||||
}
|
||||
})
|
||||
});
|
||||
|
|
|
|||
|
|
@ -75,6 +75,23 @@ describe('DefaultReconnectionHandler', () => {
|
|||
expect(testDisplay.failed).toHaveBeenCalled();
|
||||
expect(reconnect).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
|
||||
it('invokes update on each attempt', async () => {
|
||||
const testDisplay = createTestDisplay();
|
||||
const reconnect = jest.fn().mockRejectedValue(null);
|
||||
const handler = new DefaultReconnectionHandler(NullLogger.instance, testDisplay, reconnect);
|
||||
const maxRetries = 6;
|
||||
|
||||
handler.onConnectionDown({
|
||||
maxRetries: maxRetries,
|
||||
retryIntervalMilliseconds: 5,
|
||||
dialogId: 'ignored'
|
||||
});
|
||||
|
||||
await delay(500);
|
||||
expect(testDisplay.update).toHaveBeenCalledTimes(maxRetries);
|
||||
|
||||
})
|
||||
});
|
||||
|
||||
function attachUserSpecifiedUI(options: ReconnectionOptions): Element {
|
||||
|
|
@ -92,6 +109,7 @@ function delay(durationMilliseconds: number) {
|
|||
function createTestDisplay(): ReconnectDisplay {
|
||||
return {
|
||||
show: jest.fn(),
|
||||
update: jest.fn(),
|
||||
hide: jest.fn(),
|
||||
failed: jest.fn(),
|
||||
rejected: jest.fn()
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.Forms
|
||||
|
|
@ -13,6 +12,8 @@ namespace Microsoft.AspNetCore.Components.Forms
|
|||
/// </summary>
|
||||
public static class EditContextFieldClassExtensions
|
||||
{
|
||||
private readonly static object FieldCssClassProviderKey = new object();
|
||||
|
||||
/// <summary>
|
||||
/// Gets a string that indicates the status of the specified field as a CSS class. This will include
|
||||
/// some combination of "modified", "valid", or "invalid", depending on the status of the field.
|
||||
|
|
@ -24,23 +25,34 @@ namespace Microsoft.AspNetCore.Components.Forms
|
|||
=> FieldCssClass(editContext, FieldIdentifier.Create(accessor));
|
||||
|
||||
/// <summary>
|
||||
/// Gets a string that indicates the status of the specified field as a CSS class. This will include
|
||||
/// some combination of "modified", "valid", or "invalid", depending on the status of the field.
|
||||
/// Gets a string that indicates the status of the specified field as a CSS class.
|
||||
/// </summary>
|
||||
/// <param name="editContext">The <see cref="EditContext"/>.</param>
|
||||
/// <param name="fieldIdentifier">An identifier for the field.</param>
|
||||
/// <returns>A string that indicates the status of the field.</returns>
|
||||
public static string FieldCssClass(this EditContext editContext, in FieldIdentifier fieldIdentifier)
|
||||
{
|
||||
var isValid = !editContext.GetValidationMessages(fieldIdentifier).Any();
|
||||
if (editContext.IsModified(fieldIdentifier))
|
||||
var provider = editContext.Properties.TryGetValue(FieldCssClassProviderKey, out var customProvider)
|
||||
? (FieldCssClassProvider)customProvider
|
||||
: FieldCssClassProvider.Instance;
|
||||
|
||||
return provider.GetFieldCssClass(editContext, fieldIdentifier);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Associates the supplied <see cref="FieldCssClassProvider"/> with the supplied <see cref="EditContext"/>.
|
||||
/// This customizes the field CSS class names used within the <see cref="EditContext"/>.
|
||||
/// </summary>
|
||||
/// <param name="editContext">The <see cref="EditContext"/>.</param>
|
||||
/// <param name="fieldCssClassProvider">The <see cref="FieldCssClassProvider"/>.</param>
|
||||
public static void SetFieldCssClassProvider(this EditContext editContext, FieldCssClassProvider fieldCssClassProvider)
|
||||
{
|
||||
if (fieldCssClassProvider is null)
|
||||
{
|
||||
return isValid ? "modified valid" : "modified invalid";
|
||||
}
|
||||
else
|
||||
{
|
||||
return isValid ? "valid" : "invalid";
|
||||
throw new ArgumentNullException(nameof(fieldCssClassProvider));
|
||||
}
|
||||
|
||||
editContext.Properties[FieldCssClassProviderKey] = fieldCssClassProvider;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,35 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Linq;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.Forms
|
||||
{
|
||||
/// <summary>
|
||||
/// Supplies CSS class names for form fields to represent their validation state or other
|
||||
/// state information from an <see cref="EditContext"/>.
|
||||
/// </summary>
|
||||
public class FieldCssClassProvider
|
||||
{
|
||||
internal readonly static FieldCssClassProvider Instance = new FieldCssClassProvider();
|
||||
|
||||
/// <summary>
|
||||
/// Gets a string that indicates the status of the specified field as a CSS class.
|
||||
/// </summary>
|
||||
/// <param name="editContext">The <see cref="EditContext"/>.</param>
|
||||
/// <param name="fieldIdentifier">The <see cref="FieldIdentifier"/>.</param>
|
||||
/// <returns>A CSS class name string.</returns>
|
||||
public virtual string GetFieldCssClass(EditContext editContext, in FieldIdentifier fieldIdentifier)
|
||||
{
|
||||
var isValid = !editContext.GetValidationMessages(fieldIdentifier).Any();
|
||||
if (editContext.IsModified(fieldIdentifier))
|
||||
{
|
||||
return isValid ? "modified valid" : "modified invalid";
|
||||
}
|
||||
else
|
||||
{
|
||||
return isValid ? "valid" : "invalid";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -5,7 +5,7 @@ namespace Microsoft.AspNetCore.Components.Web.Virtualization
|
|||
{
|
||||
internal interface IVirtualizeJsCallbacks
|
||||
{
|
||||
void OnBeforeSpacerVisible(float spacerSize, float containerSize);
|
||||
void OnAfterSpacerVisible(float spacerSize, float containerSize);
|
||||
void OnBeforeSpacerVisible(float spacerSize, float spacerSeparation, float containerSize);
|
||||
void OnAfterSpacerVisible(float spacerSize, float spacerSeparation, float containerSize);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,13 +13,24 @@ namespace Microsoft.AspNetCore.Components.Web.Virtualization
|
|||
/// </summary>
|
||||
public int Index { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The size of the placeholder in pixels.
|
||||
/// <para>
|
||||
/// For virtualized components with vertical scrolling, this would be the height of the placeholder in pixels.
|
||||
/// For virtualized components with horizontal scrolling, this would be the width of the placeholder in pixels.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
public float Size { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a new <see cref="PlaceholderContext"/> instance.
|
||||
/// </summary>
|
||||
/// <param name="index">The item index of the placeholder.</param>
|
||||
public PlaceholderContext(int index)
|
||||
/// <param name="size">The size of the placeholder in pixels.</param>
|
||||
public PlaceholderContext(int index, float size = 0f)
|
||||
{
|
||||
Index = index;
|
||||
Size = size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,6 +31,12 @@ namespace Microsoft.AspNetCore.Components.Web.Virtualization
|
|||
|
||||
private int _loadedItemsStartIndex;
|
||||
|
||||
private int _lastRenderedItemCount;
|
||||
|
||||
private int _lastRenderedPlaceholderCount;
|
||||
|
||||
private float _itemSize;
|
||||
|
||||
private IEnumerable<TItem>? _loadedItems;
|
||||
|
||||
private CancellationTokenSource? _refreshCts;
|
||||
|
|
@ -65,10 +71,10 @@ namespace Microsoft.AspNetCore.Components.Web.Virtualization
|
|||
public RenderFragment<PlaceholderContext>? Placeholder { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the size of each item in pixels.
|
||||
/// Gets the size of each item in pixels. Defaults to 50px.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public float ItemSize { get; set; }
|
||||
public float ItemSize { get; set; } = 50f;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the function providing items to the list.
|
||||
|
|
@ -88,7 +94,12 @@ namespace Microsoft.AspNetCore.Components.Web.Virtualization
|
|||
if (ItemSize <= 0)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
$"{GetType()} requires a positive value for parameter '{nameof(ItemSize)}' to perform virtualization.");
|
||||
$"{GetType()} requires a positive value for parameter '{nameof(ItemSize)}'.");
|
||||
}
|
||||
|
||||
if (_itemSize <= 0)
|
||||
{
|
||||
_itemSize = ItemSize;
|
||||
}
|
||||
|
||||
if (ItemsProvider != null)
|
||||
|
|
@ -154,11 +165,13 @@ namespace Microsoft.AspNetCore.Components.Web.Virtualization
|
|||
{
|
||||
// This is a rare case where it's valid for the sequence number to be programmatically incremented.
|
||||
// This is only true because we know for certain that no other content will be alongside it.
|
||||
builder.AddContent(renderIndex, _placeholder, new PlaceholderContext(renderIndex));
|
||||
builder.AddContent(renderIndex, _placeholder, new PlaceholderContext(renderIndex, _itemSize));
|
||||
}
|
||||
|
||||
builder.CloseRegion();
|
||||
|
||||
_lastRenderedItemCount = 0;
|
||||
|
||||
// Render the loaded items.
|
||||
if (_loadedItems != null && _itemTemplate != null)
|
||||
{
|
||||
|
|
@ -171,18 +184,22 @@ namespace Microsoft.AspNetCore.Components.Web.Virtualization
|
|||
foreach (var item in itemsToShow)
|
||||
{
|
||||
_itemTemplate(item)(builder);
|
||||
renderIndex++;
|
||||
_lastRenderedItemCount++;
|
||||
}
|
||||
|
||||
renderIndex += _lastRenderedItemCount;
|
||||
|
||||
builder.CloseRegion();
|
||||
}
|
||||
|
||||
_lastRenderedPlaceholderCount = Math.Max(0, lastItemIndex - _itemsBefore - _lastRenderedItemCount);
|
||||
|
||||
builder.OpenRegion(5);
|
||||
|
||||
// Render the placeholders after the loaded items.
|
||||
for (; renderIndex < lastItemIndex; renderIndex++)
|
||||
{
|
||||
builder.AddContent(renderIndex, _placeholder, new PlaceholderContext(renderIndex));
|
||||
builder.AddContent(renderIndex, _placeholder, new PlaceholderContext(renderIndex, _itemSize));
|
||||
}
|
||||
|
||||
builder.CloseRegion();
|
||||
|
|
@ -197,28 +214,45 @@ namespace Microsoft.AspNetCore.Components.Web.Virtualization
|
|||
}
|
||||
|
||||
private string GetSpacerStyle(int itemsInSpacer)
|
||||
=> $"height: {itemsInSpacer * ItemSize}px;";
|
||||
=> $"height: {itemsInSpacer * _itemSize}px;";
|
||||
|
||||
void IVirtualizeJsCallbacks.OnBeforeSpacerVisible(float spacerSize, float containerSize)
|
||||
void IVirtualizeJsCallbacks.OnBeforeSpacerVisible(float spacerSize, float spacerSeparation, float containerSize)
|
||||
{
|
||||
CalcualteItemDistribution(spacerSize, containerSize, out var itemsBefore, out var visibleItemCapacity);
|
||||
CalcualteItemDistribution(spacerSize, spacerSeparation, containerSize, out var itemsBefore, out var visibleItemCapacity);
|
||||
|
||||
UpdateItemDistribution(itemsBefore, visibleItemCapacity);
|
||||
}
|
||||
|
||||
void IVirtualizeJsCallbacks.OnAfterSpacerVisible(float spacerSize, float containerSize)
|
||||
void IVirtualizeJsCallbacks.OnAfterSpacerVisible(float spacerSize, float spacerSeparation, float containerSize)
|
||||
{
|
||||
CalcualteItemDistribution(spacerSize, containerSize, out var itemsAfter, out var visibleItemCapacity);
|
||||
CalcualteItemDistribution(spacerSize, spacerSeparation, containerSize, out var itemsAfter, out var visibleItemCapacity);
|
||||
|
||||
var itemsBefore = Math.Max(0, _itemCount - itemsAfter - visibleItemCapacity);
|
||||
|
||||
UpdateItemDistribution(itemsBefore, visibleItemCapacity);
|
||||
}
|
||||
|
||||
private void CalcualteItemDistribution(float spacerSize, float containerSize, out int itemsInSpacer, out int visibleItemCapacity)
|
||||
private void CalcualteItemDistribution(
|
||||
float spacerSize,
|
||||
float spacerSeparation,
|
||||
float containerSize,
|
||||
out int itemsInSpacer,
|
||||
out int visibleItemCapacity)
|
||||
{
|
||||
itemsInSpacer = Math.Max(0, (int)Math.Floor(spacerSize / ItemSize) - 1);
|
||||
visibleItemCapacity = (int)Math.Ceiling(containerSize / ItemSize) + 2;
|
||||
if (_lastRenderedItemCount > 0)
|
||||
{
|
||||
_itemSize = (spacerSeparation - (_lastRenderedPlaceholderCount * _itemSize)) / _lastRenderedItemCount;
|
||||
}
|
||||
|
||||
if (_itemSize <= 0)
|
||||
{
|
||||
// At this point, something unusual has occurred, likely due to misuse of this component.
|
||||
// Reset the calculated item size to the user-provided item size.
|
||||
_itemSize = ItemSize;
|
||||
}
|
||||
|
||||
itemsInSpacer = Math.Max(0, (int)Math.Floor(spacerSize / _itemSize) - 1);
|
||||
visibleItemCapacity = (int)Math.Ceiling(containerSize / _itemSize) + 2;
|
||||
}
|
||||
|
||||
private void UpdateItemDistribution(int itemsBefore, int visibleItemCapacity)
|
||||
|
|
@ -285,7 +319,7 @@ namespace Microsoft.AspNetCore.Components.Web.Virtualization
|
|||
private RenderFragment DefaultPlaceholder(PlaceholderContext context) => (builder) =>
|
||||
{
|
||||
builder.OpenElement(0, "div");
|
||||
builder.AddAttribute(1, "style", $"height: {ItemSize}px;");
|
||||
builder.AddAttribute(1, "style", $"height: {_itemSize}px;");
|
||||
builder.CloseElement();
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -30,15 +30,15 @@ namespace Microsoft.AspNetCore.Components.Web.Virtualization
|
|||
}
|
||||
|
||||
[JSInvokable]
|
||||
public void OnSpacerBeforeVisible(float spacerSize, float containerSize)
|
||||
public void OnSpacerBeforeVisible(float spacerSize, float spacerSeparation, float containerSize)
|
||||
{
|
||||
_owner.OnBeforeSpacerVisible(spacerSize, containerSize);
|
||||
_owner.OnBeforeSpacerVisible(spacerSize, spacerSeparation, containerSize);
|
||||
}
|
||||
|
||||
[JSInvokable]
|
||||
public void OnSpacerAfterVisible(float spacerSize, float containerSize)
|
||||
public void OnSpacerAfterVisible(float spacerSize, float spacerSeparation, float containerSize)
|
||||
{
|
||||
_owner.OnAfterSpacerVisible(spacerSize, containerSize);
|
||||
_owner.OnAfterSpacerVisible(spacerSize, spacerSeparation, containerSize);
|
||||
}
|
||||
|
||||
public async ValueTask DisposeAsync()
|
||||
|
|
|
|||
|
|
@ -97,7 +97,7 @@ namespace Microsoft.AspNetCore.Components.Virtualization
|
|||
Assert.NotNull(renderedVirtualize);
|
||||
|
||||
// Simulate a JS spacer callback.
|
||||
((IVirtualizeJsCallbacks)renderedVirtualize).OnAfterSpacerVisible(10f, 100f);
|
||||
((IVirtualizeJsCallbacks)renderedVirtualize).OnAfterSpacerVisible(10f, 50f, 100f);
|
||||
|
||||
// Validate that the exception is dispatched through the renderer.
|
||||
var ex = await Assert.ThrowsAsync<InvalidOperationException>(async () => await testRenderer.RenderRootComponentAsync(componentId));
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import * as Msal from 'msal';
|
||||
import { StringDict } from 'msal/lib-commonjs/MsalTypes';
|
||||
import { ClientAuthErrorMessage } from 'msal/lib-commonjs/error/ClientAuthError';
|
||||
import * as Msal from '@azure/msal-browser';
|
||||
import { StringDict } from '@azure/msal-common';
|
||||
|
||||
interface AccessTokenRequestOptions {
|
||||
scopes: string[];
|
||||
|
|
@ -52,34 +51,53 @@ interface AuthorizeServiceConfiguration extends Msal.Configuration {
|
|||
}
|
||||
|
||||
class MsalAuthorizeService implements AuthorizeService {
|
||||
readonly _msalApplication: Msal.UserAgentApplication;
|
||||
readonly _callbackPromise: Promise<AuthenticationResult>;
|
||||
private readonly _msalApplication: Msal.PublicClientApplication;
|
||||
private _account: Msal.AccountInfo | undefined;
|
||||
private _redirectCallback: Promise<AuthenticationResult | null> | undefined;
|
||||
|
||||
constructor(private readonly _settings: AuthorizeServiceConfiguration) {
|
||||
if (this._settings.auth?.knownAuthorities?.length == 0) {
|
||||
this._settings.auth.knownAuthorities = [new URL(this._settings.auth.authority!).hostname]
|
||||
}
|
||||
this._msalApplication = new Msal.PublicClientApplication(this._settings);
|
||||
}
|
||||
|
||||
// It is important that we capture the callback-url here as msal will remove the auth parameters
|
||||
// from the url as soon as it gets initialized.
|
||||
const callbackUrl = location.href;
|
||||
this._msalApplication = new Msal.UserAgentApplication(this._settings);
|
||||
getAccount() {
|
||||
if (this._account) {
|
||||
return this._account;
|
||||
}
|
||||
|
||||
// This promise will only resolve in callback-paths, which is where we check it.
|
||||
this._callbackPromise = this.createCallbackResult(callbackUrl);
|
||||
const accounts = this._msalApplication.getAllAccounts();
|
||||
if (accounts && accounts.length) {
|
||||
return accounts[0];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
async getUser() {
|
||||
const account = this._msalApplication.getAccount();
|
||||
return account?.idTokenClaims;
|
||||
const account = this.getAccount();
|
||||
if (!account) {
|
||||
return;
|
||||
}
|
||||
|
||||
const silentRequest = {
|
||||
redirectUri: this._settings.auth?.redirectUri,
|
||||
account: account,
|
||||
scopes: this._settings.defaultAccessTokenScopes
|
||||
};
|
||||
|
||||
const response = await this._msalApplication.acquireTokenSilent(silentRequest);
|
||||
return response.idTokenClaims;
|
||||
}
|
||||
|
||||
async getAccessToken(request?: AccessTokenRequestOptions): Promise<AccessTokenResult> {
|
||||
try {
|
||||
const newToken = await this.getTokenCore(request?.scopes);
|
||||
|
||||
return {
|
||||
status: AccessTokenResultStatus.Success,
|
||||
token: newToken
|
||||
};
|
||||
|
||||
} catch (e) {
|
||||
return {
|
||||
status: AccessTokenResultStatus.RequiresRedirect
|
||||
|
|
@ -88,12 +106,18 @@ class MsalAuthorizeService implements AuthorizeService {
|
|||
}
|
||||
|
||||
async getTokenCore(scopes?: string[]): Promise<AccessToken | undefined> {
|
||||
const tokenScopes = {
|
||||
redirectUri: this._settings.auth.redirectUri as string,
|
||||
const account = this.getAccount();
|
||||
if (!account) {
|
||||
return;
|
||||
}
|
||||
|
||||
const silentRequest = {
|
||||
redirectUri: this._settings.auth?.redirectUri,
|
||||
account: account,
|
||||
scopes: scopes || this._settings.defaultAccessTokenScopes
|
||||
};
|
||||
|
||||
const response = await this._msalApplication.acquireTokenSilent(tokenScopes);
|
||||
const response = await this._msalApplication.acquireTokenSilent(silentRequest);
|
||||
return {
|
||||
value: response.accessToken,
|
||||
grantedScopes: response.scopes,
|
||||
|
|
@ -106,9 +130,10 @@ class MsalAuthorizeService implements AuthorizeService {
|
|||
// Before we start any sign-in flow, clear out any previous state so that it doesn't pile up.
|
||||
this.purgeState();
|
||||
|
||||
const request: Msal.AuthenticationParameters = {
|
||||
redirectUri: this._settings.auth.redirectUri as string,
|
||||
state: await this.saveState(state)
|
||||
const request: Msal.AuthorizationUrlRequest = {
|
||||
redirectUri: this._settings.auth?.redirectUri,
|
||||
state: await this.saveState(state),
|
||||
scopes: []
|
||||
};
|
||||
|
||||
if (this._settings.defaultAccessTokenScopes && this._settings.defaultAccessTokenScopes.length > 0) {
|
||||
|
|
@ -130,7 +155,16 @@ class MsalAuthorizeService implements AuthorizeService {
|
|||
if (this._settings.defaultAccessTokenScopes?.length > 0) {
|
||||
// This provisions the token as part of the sign-in flow eagerly so that is already in the cache
|
||||
// when the app asks for it.
|
||||
await this._msalApplication.acquireTokenSilent(request);
|
||||
const account = this.getAccount();
|
||||
if (!account) {
|
||||
return this.error("No account to get tokens for.");
|
||||
}
|
||||
const silentRequest = {
|
||||
redirectUri: request.redirectUri,
|
||||
account: account,
|
||||
scopes: request.scopes,
|
||||
};
|
||||
await this._msalApplication.acquireTokenSilent(silentRequest);
|
||||
}
|
||||
} catch (e) {
|
||||
return this.error(e.errorMessage);
|
||||
|
|
@ -142,33 +176,45 @@ class MsalAuthorizeService implements AuthorizeService {
|
|||
}
|
||||
}
|
||||
|
||||
async signInCore(request: Msal.AuthenticationParameters): Promise<Msal.AuthResponse | Msal.AuthError | undefined> {
|
||||
if (this._settings.loginMode.toLowerCase() === "redirect") {
|
||||
try {
|
||||
this._msalApplication.loginRedirect(request);
|
||||
} catch (e) {
|
||||
return e;
|
||||
}
|
||||
async signInCore(request: Msal.AuthorizationUrlRequest): Promise<Msal.AuthenticationResult | Msal.AuthError | undefined> {
|
||||
const loginMode = this._settings.loginMode.toLowerCase();
|
||||
if (loginMode === 'redirect') {
|
||||
return this.signInWithRedirect(request);
|
||||
} else {
|
||||
try {
|
||||
return await this._msalApplication.loginPopup(request);
|
||||
} catch (e) {
|
||||
// If the user explicitly cancelled the pop-up, avoid performing a redirect.
|
||||
if (this.isMsalError(e) && e.errorCode !== ClientAuthErrorMessage.userCancelledError.code) {
|
||||
try {
|
||||
this._msalApplication.loginRedirect(request);
|
||||
} catch (e) {
|
||||
return e;
|
||||
}
|
||||
} else {
|
||||
return e;
|
||||
}
|
||||
return this.signInWithPopup(request);
|
||||
}
|
||||
}
|
||||
|
||||
private async signInWithRedirect(request: Msal.RedirectRequest) {
|
||||
try {
|
||||
return await this._msalApplication.loginRedirect(request);
|
||||
} catch (e) {
|
||||
return e;
|
||||
}
|
||||
}
|
||||
|
||||
private async signInWithPopup(request: Msal.PopupRequest) {
|
||||
try {
|
||||
return await this._msalApplication.loginPopup(request);
|
||||
} catch (e) {
|
||||
// If the user explicitly cancelled the pop-up, avoid performing a redirect.
|
||||
if (this.isMsalError(e) && e.errorCode !== Msal.BrowserAuthErrorMessage.userCancelledError.code) {
|
||||
this.signInWithRedirect(request);
|
||||
} else {
|
||||
return e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
completeSignIn() {
|
||||
return this._callbackPromise;
|
||||
async completeSignIn() {
|
||||
// Make sure that the redirect handler has completed execution before
|
||||
// completing sign in.
|
||||
await this._redirectCallback;
|
||||
const account = this.getAccount();
|
||||
if (account) {
|
||||
return this.success(account);
|
||||
}
|
||||
return this.operationCompleted();
|
||||
}
|
||||
|
||||
async signOut(state: any) {
|
||||
|
|
@ -241,7 +287,7 @@ class MsalAuthorizeService implements AuthorizeService {
|
|||
// msal.js doesn't support the state parameter on logout flows, which forces us to shim our own logout state.
|
||||
// The format then is different, as msal follows the pattern state=<<guid>>|<<user_state>> and our format
|
||||
// simple uses <<base64urlIdentifier>>.
|
||||
const appState = !isLogout ? this._msalApplication.getAccountState(state[0]) : state[0];
|
||||
const appState = !isLogout ? this.getAccountState(state[0]) : state[0];
|
||||
const stateKey = `${AuthenticationService._infrastructureKey}.AuthorizeService.${appState}`;
|
||||
const stateString = sessionStorage.getItem(stateKey);
|
||||
if (stateString) {
|
||||
|
|
@ -262,37 +308,35 @@ class MsalAuthorizeService implements AuthorizeService {
|
|||
}
|
||||
}
|
||||
|
||||
private async createCallbackResult(callbackUrl: string): Promise<AuthenticationResult> {
|
||||
// msal.js requires a callback to be registered during app initialization to handle redirect flows.
|
||||
// To map that behavior to our API we register a callback early and store the result of that callback
|
||||
// as a promise on an instance field to be able to serve the state back to the main app.
|
||||
const promiseFactory = (resolve: (result: Msal.AuthResponse) => void, reject: (error: Msal.AuthError) => void): void => {
|
||||
this._msalApplication.handleRedirectCallback(
|
||||
authenticationResponse => {
|
||||
resolve(authenticationResponse);
|
||||
},
|
||||
authenticationError => {
|
||||
reject(authenticationError);
|
||||
});
|
||||
}
|
||||
async initializeMsalHandler() {
|
||||
this._redirectCallback = this._msalApplication.handleRedirectPromise().then(
|
||||
(result: Msal.AuthenticationResult | null) => this.handleResult(result)
|
||||
).catch((error: any) => {
|
||||
if (this.isMsalError(error)) {
|
||||
return this.error(error.errorMessage);
|
||||
} else {
|
||||
return this.error(error);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
try {
|
||||
// Evaluate the promise to capture any authentication errors
|
||||
await new Promise<Msal.AuthResponse>(promiseFactory);
|
||||
// See https://github.com/AzureAD/microsoft-authentication-library-for-js/wiki/FAQs#q6-how-to-avoid-page-reloads-when-acquiring-and-renewing-tokens-silently
|
||||
if (window !== window.parent && !window.opener) {
|
||||
return this.operationCompleted();
|
||||
} else {
|
||||
const state = await this.retrieveState(callbackUrl);
|
||||
return this.success(state);
|
||||
}
|
||||
} catch (e) {
|
||||
if (this.isMsalError(e)) {
|
||||
return this.error(e.errorMessage);
|
||||
} else {
|
||||
return this.error(e);
|
||||
private handleResult(result: Msal.AuthenticationResult | null) {
|
||||
if (result != null) {
|
||||
this._account = result.account;
|
||||
return this.success(result.state);
|
||||
} else {
|
||||
return this.operationCompleted();
|
||||
}
|
||||
}
|
||||
|
||||
private getAccountState(state: string) {
|
||||
if (state) {
|
||||
const splitIndex = state.indexOf("|");
|
||||
if (splitIndex > -1 && splitIndex + 1 < state.length) {
|
||||
return state.substring(splitIndex + 1);
|
||||
}
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
private isMsalError(resultOrError: any): resultOrError is Msal.AuthError {
|
||||
|
|
@ -319,14 +363,15 @@ class MsalAuthorizeService implements AuthorizeService {
|
|||
export class AuthenticationService {
|
||||
|
||||
static _infrastructureKey = 'Microsoft.Authentication.WebAssembly.Msal';
|
||||
static _initialized = false;
|
||||
static _initialized: Promise<void>;
|
||||
static instance: MsalAuthorizeService;
|
||||
|
||||
public static async init(settings: AuthorizeServiceConfiguration) {
|
||||
if (!AuthenticationService._initialized) {
|
||||
AuthenticationService._initialized = true;
|
||||
AuthenticationService.instance = new MsalAuthorizeService(settings);
|
||||
AuthenticationService._initialized = AuthenticationService.instance.initializeMsalHandler();
|
||||
}
|
||||
return AuthenticationService._initialized;
|
||||
}
|
||||
|
||||
public static getUser() {
|
||||
|
|
|
|||
|
|
@ -13,6 +13,6 @@
|
|||
"webpack-cli": "^3.3.10"
|
||||
},
|
||||
"dependencies": {
|
||||
"msal": "^1.2.1"
|
||||
"@azure/msal-browser": "^2.0.0"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,20 @@
|
|||
# yarn lockfile v1
|
||||
|
||||
|
||||
"@azure/msal-browser@^2.0.0":
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@azure/msal-browser/-/msal-browser-2.0.0.tgz#09eb3ed2112bdcd11c751f1c0b9cec588b49b8c6"
|
||||
integrity sha512-0L4XksaXmtl870bQTPxbHCkxMEMmSbsgkkVpb6bvXg8ngOLWnkxvV6tstj84JtQHcJPjNYkYY41jgBQxgC4/KQ==
|
||||
dependencies:
|
||||
"@azure/msal-common" "1.0.0"
|
||||
|
||||
"@azure/msal-common@1.0.0":
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@azure/msal-common/-/msal-common-1.0.0.tgz#421f4859e6cb68cfacb03bb2c6c873efdffc76f0"
|
||||
integrity sha512-l/+1Z9kQWLAlMwJ/c3MGhy4ujtEAK/3CMUaUXHvjUIsQknLFRb9+b3id5YSuToPfAvdUkAQGDZiQXosv1I+eLA==
|
||||
dependencies:
|
||||
debug "^4.1.1"
|
||||
|
||||
"@webassemblyjs/ast@1.8.5":
|
||||
version "1.8.5"
|
||||
resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.8.5.tgz#51b1c5fe6576a34953bf4b253df9f0d490d9e359"
|
||||
|
|
@ -690,6 +704,13 @@ debug@^2.2.0, debug@^2.3.3:
|
|||
dependencies:
|
||||
ms "2.0.0"
|
||||
|
||||
debug@^4.1.1:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791"
|
||||
integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==
|
||||
dependencies:
|
||||
ms "^2.1.1"
|
||||
|
||||
decamelize@^1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
|
||||
|
|
@ -1667,12 +1688,10 @@ ms@2.0.0:
|
|||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
|
||||
integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=
|
||||
|
||||
msal@^1.2.1:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/msal/-/msal-1.2.1.tgz#08133e37ab0b9741866c89a3fadc55aadb980723"
|
||||
integrity sha512-Zo28eyRtT/Un+zcpMfPtTPD+eo/OqzsRER0k5dyk8Mje/K1oLlaEOAgZHlJs59Y2xyuVg8OrcKqSn/1MeNjZYw==
|
||||
dependencies:
|
||||
tslib "^1.9.3"
|
||||
ms@^2.1.1:
|
||||
version "2.1.2"
|
||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
|
||||
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
|
||||
|
||||
nan@^2.12.1:
|
||||
version "2.14.0"
|
||||
|
|
@ -2485,7 +2504,7 @@ ts-loader@^6.2.1:
|
|||
micromatch "^4.0.0"
|
||||
semver "^6.0.0"
|
||||
|
||||
tslib@^1.9.0, tslib@^1.9.3:
|
||||
tslib@^1.9.0:
|
||||
version "1.10.0"
|
||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a"
|
||||
integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Microsoft.Authentication.WebAssembly.Msal
|
||||
{
|
||||
|
|
@ -48,5 +49,10 @@ namespace Microsoft.Authentication.WebAssembly.Msal
|
|||
/// Gets or sets whether or not to navigate to the login request url after a successful login.
|
||||
/// </summary>
|
||||
public bool NavigateToLoginRequestUrl { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the set of known authority host names for the application.
|
||||
/// </summary>
|
||||
public IList<string> KnownAuthorities { get; set; } = new List<string>();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,17 +11,26 @@
|
|||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<!-- Set this to false because assemblies should not reference this assembly directly, (except for tests, of course). -->
|
||||
<IsProjectReferenceProvider>false</IsProjectReferenceProvider>
|
||||
|
||||
<!--
|
||||
This project compiles against Microsoft.AspNetCore.App from the SDK.
|
||||
This ensures that it's packaging output is correct and does not include local artifacts.
|
||||
-->
|
||||
<UseAspNetCoreSharedRuntime>true</UseAspNetCoreSharedRuntime>
|
||||
<DoNotApplyWorkaroundsToMicrosoftAspNetCoreApp>true</DoNotApplyWorkaroundsToMicrosoftAspNetCoreApp>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.AspNetCore" />
|
||||
<Reference Include="Microsoft.AspNetCore.Diagnostics" />
|
||||
<Reference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" />
|
||||
<Reference Include="Microsoft.AspNetCore.Components.Server" />
|
||||
<Reference Include="Microsoft.AspNetCore.ResponseCompression" />
|
||||
<FrameworkReference Include="Microsoft.AspNetCore.App" />
|
||||
|
||||
<ProjectReference
|
||||
Include="$(RepoRoot)src\Framework\App.Runtime\src\Microsoft.AspNetCore.App.Runtime.csproj"
|
||||
PrivateAssets="All"
|
||||
ReferenceOutputAssembly="false"
|
||||
SkipGetTargetFrameworkProperties="true" />
|
||||
|
||||
<Reference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" />
|
||||
<Compile Include="$(SharedSourceRoot)CommandLineUtils\**\*.cs" />
|
||||
<Reference Include="Microsoft.Extensions.Hosting" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Pack settings -->
|
||||
|
|
@ -36,19 +45,5 @@
|
|||
<NuspecProperty Include="PackageThirdPartyNoticesFile=$(PackageThirdPartyNoticesFile)" />
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="_FixupRuntimeConfig" BeforeTargets="_GenerateRuntimeConfigurationFilesInputCache">
|
||||
<ItemGroup>
|
||||
<_RuntimeFramework Include="@(RuntimeFramework)" />
|
||||
<RuntimeFramework Remove="@(RuntimeFramework)" />
|
||||
<RuntimeFramework Include="Microsoft.AspNetCore.App" FrameworkName="Microsoft.AspNetCore.App" Version="5.0.0-preview" />
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
|
||||
<Target Name="_UndoRuntimeConfigWorkarounds" AfterTargets="GenerateBuildRuntimeConfigurationFiles">
|
||||
<ItemGroup>
|
||||
<RuntimeFramework Remove="@(RuntimeFramework)" />
|
||||
<RuntimeFramework Include="@(_RuntimeFramework)" />
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -16,12 +16,7 @@ namespace WebAssembly.JSInterop
|
|||
// in driver.c in the Mono distribution
|
||||
/// See: https://github.com/mono/mono/blob/90574987940959fe386008a850982ea18236a533/sdks/wasm/src/driver.c#L318-L319
|
||||
|
||||
// We're passing asyncHandle by ref not because we want it to be writable, but so it gets
|
||||
// passed as a pointer (4 bytes). We can pass 4-byte values, but not 8-byte ones.
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
public static extern string InvokeJSMarshalled(out string exception, ref long asyncHandle, string functionIdentifier, string argsJson);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
public static extern TRes InvokeJSUnmarshalled<T0, T1, T2, TRes>(out string exception, string functionIdentifier, [AllowNull] T0 arg0, [AllowNull] T1 arg1, [AllowNull] T2 arg2);
|
||||
public static extern TRes InvokeJS<T0, T1, T2, TRes>(out string exception, ref JSCallInfo callInfo, [AllowNull] T0 arg0, [AllowNull] T1 arg1, [AllowNull] T2 arg2);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,27 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
using Microsoft.JSInterop;
|
||||
|
||||
namespace WebAssembly.JSInterop
|
||||
{
|
||||
[StructLayout(LayoutKind.Explicit, Pack = 4)]
|
||||
internal struct JSCallInfo
|
||||
{
|
||||
[FieldOffset(0)]
|
||||
public string FunctionIdentifier;
|
||||
|
||||
[FieldOffset(4)]
|
||||
public JSCallResultType ResultType;
|
||||
|
||||
[FieldOffset(8)]
|
||||
public string MarshalledCallArgsJson;
|
||||
|
||||
[FieldOffset(12)]
|
||||
public long MarshalledCallAsyncHandle;
|
||||
|
||||
[FieldOffset(20)]
|
||||
public long TargetInstanceId;
|
||||
}
|
||||
}
|
||||
|
|
@ -11,22 +11,40 @@ namespace Microsoft.JSInterop.WebAssembly
|
|||
/// Provides methods for invoking JavaScript functions for applications running
|
||||
/// on the Mono WebAssembly runtime.
|
||||
/// </summary>
|
||||
public abstract class WebAssemblyJSRuntime : JSInProcessRuntime
|
||||
public abstract class WebAssemblyJSRuntime : JSInProcessRuntime, IJSUnmarshalledRuntime
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override string InvokeJS(string identifier, string argsJson)
|
||||
protected override string InvokeJS(string identifier, string argsJson, JSCallResultType resultType, long targetInstanceId)
|
||||
{
|
||||
var noAsyncHandle = default(long);
|
||||
var result = InternalCalls.InvokeJSMarshalled(out var exception, ref noAsyncHandle, identifier, argsJson);
|
||||
var callInfo = new JSCallInfo
|
||||
{
|
||||
FunctionIdentifier = identifier,
|
||||
TargetInstanceId = targetInstanceId,
|
||||
ResultType = resultType,
|
||||
MarshalledCallArgsJson = argsJson ?? "[]",
|
||||
MarshalledCallAsyncHandle = default
|
||||
};
|
||||
|
||||
var result = InternalCalls.InvokeJS<object, object, object, string>(out var exception, ref callInfo, null, null, null);
|
||||
|
||||
return exception != null
|
||||
? throw new JSException(exception)
|
||||
: result;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void BeginInvokeJS(long asyncHandle, string identifier, string argsJson)
|
||||
protected override void BeginInvokeJS(long asyncHandle, string identifier, string argsJson, JSCallResultType resultType, long targetInstanceId)
|
||||
{
|
||||
InternalCalls.InvokeJSMarshalled(out _, ref asyncHandle, identifier, argsJson);
|
||||
var callInfo = new JSCallInfo
|
||||
{
|
||||
FunctionIdentifier = identifier,
|
||||
TargetInstanceId = targetInstanceId,
|
||||
ResultType = resultType,
|
||||
MarshalledCallArgsJson = argsJson ?? "[]",
|
||||
MarshalledCallAsyncHandle = asyncHandle
|
||||
};
|
||||
|
||||
InternalCalls.InvokeJS<object, object, object, string>(out _, ref callInfo, null, null, null);
|
||||
}
|
||||
|
||||
protected override void EndInvokeDotNet(DotNetInvocationInfo callInfo, in DotNetInvocationResult dispatchResult)
|
||||
|
|
@ -39,57 +57,32 @@ namespace Microsoft.JSInterop.WebAssembly
|
|||
// We pass 0 as the async handle because we don't want the JS-side code to
|
||||
// send back any notification (we're just providing a result for an existing async call)
|
||||
var args = JsonSerializer.Serialize(new[] { callInfo.CallId, dispatchResult.Success, resultOrError }, JsonSerializerOptions);
|
||||
BeginInvokeJS(0, "DotNet.jsCallDispatcher.endInvokeDotNetFromJS", args);
|
||||
BeginInvokeJS(0, "DotNet.jsCallDispatcher.endInvokeDotNetFromJS", args, JSCallResultType.Default, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invokes the JavaScript function registered with the specified identifier.
|
||||
/// </summary>
|
||||
/// <typeparam name="TResult">The .NET type corresponding to the function's return value type.</typeparam>
|
||||
/// <param name="identifier">The identifier used when registering the target function.</param>
|
||||
/// <returns>The result of the function invocation.</returns>
|
||||
public TResult InvokeUnmarshalled<TResult>(string identifier)
|
||||
=> InvokeUnmarshalled<object, object, object, TResult>(identifier, null, null, null);
|
||||
/// <inheritdoc />
|
||||
TResult IJSUnmarshalledRuntime.InvokeUnmarshalled<TResult>(string identifier)
|
||||
=> ((IJSUnmarshalledRuntime)this).InvokeUnmarshalled<object, object, object, TResult>(identifier, null, null, null);
|
||||
|
||||
/// <summary>
|
||||
/// Invokes the JavaScript function registered with the specified identifier.
|
||||
/// </summary>
|
||||
/// <typeparam name="T0">The type of the first argument.</typeparam>
|
||||
/// <typeparam name="TResult">The .NET type corresponding to the function's return value type.</typeparam>
|
||||
/// <param name="identifier">The identifier used when registering the target function.</param>
|
||||
/// <param name="arg0">The first argument.</param>
|
||||
/// <returns>The result of the function invocation.</returns>
|
||||
public TResult InvokeUnmarshalled<T0, TResult>(string identifier, T0 arg0)
|
||||
=> InvokeUnmarshalled<T0, object, object, TResult>(identifier, arg0, null, null);
|
||||
/// <inheritdoc />
|
||||
TResult IJSUnmarshalledRuntime.InvokeUnmarshalled<T0, TResult>(string identifier, T0 arg0)
|
||||
=> ((IJSUnmarshalledRuntime)this).InvokeUnmarshalled<T0, object, object, TResult>(identifier, arg0, null, null);
|
||||
|
||||
/// <summary>
|
||||
/// Invokes the JavaScript function registered with the specified identifier.
|
||||
/// </summary>
|
||||
/// <typeparam name="T0">The type of the first argument.</typeparam>
|
||||
/// <typeparam name="T1">The type of the second argument.</typeparam>
|
||||
/// <typeparam name="TResult">The .NET type corresponding to the function's return value type.</typeparam>
|
||||
/// <param name="identifier">The identifier used when registering the target function.</param>
|
||||
/// <param name="arg0">The first argument.</param>
|
||||
/// <param name="arg1">The second argument.</param>
|
||||
/// <returns>The result of the function invocation.</returns>
|
||||
public TResult InvokeUnmarshalled<T0, T1, TResult>(string identifier, T0 arg0, T1 arg1)
|
||||
=> InvokeUnmarshalled<T0, T1, object, TResult>(identifier, arg0, arg1, null);
|
||||
/// <inheritdoc />
|
||||
TResult IJSUnmarshalledRuntime.InvokeUnmarshalled<T0, T1, TResult>(string identifier, T0 arg0, T1 arg1)
|
||||
=> ((IJSUnmarshalledRuntime)this).InvokeUnmarshalled<T0, T1, object, TResult>(identifier, arg0, arg1, null);
|
||||
|
||||
/// <summary>
|
||||
/// Invokes the JavaScript function registered with the specified identifier.
|
||||
/// </summary>
|
||||
/// <typeparam name="T0">The type of the first argument.</typeparam>
|
||||
/// <typeparam name="T1">The type of the second argument.</typeparam>
|
||||
/// <typeparam name="T2">The type of the third argument.</typeparam>
|
||||
/// <typeparam name="TResult">The .NET type corresponding to the function's return value type.</typeparam>
|
||||
/// <param name="identifier">The identifier used when registering the target function.</param>
|
||||
/// <param name="arg0">The first argument.</param>
|
||||
/// <param name="arg1">The second argument.</param>
|
||||
/// <param name="arg2">The third argument.</param>
|
||||
/// <returns>The result of the function invocation.</returns>
|
||||
public TResult InvokeUnmarshalled<T0, T1, T2, TResult>(string identifier, T0 arg0, T1 arg1, T2 arg2)
|
||||
/// <inheritdoc />
|
||||
TResult IJSUnmarshalledRuntime.InvokeUnmarshalled<T0, T1, T2, TResult>(string identifier, T0 arg0, T1 arg1, T2 arg2)
|
||||
{
|
||||
var result = InternalCalls.InvokeJSUnmarshalled<T0, T1, T2, TResult>(out var exception, identifier, arg0, arg1, arg2);
|
||||
var callInfo = new JSCallInfo
|
||||
{
|
||||
FunctionIdentifier = identifier,
|
||||
ResultType = ResultTypeFromGeneric<TResult>()
|
||||
};
|
||||
|
||||
var result = InternalCalls.InvokeJS<T0, T1, T2, TResult>(out var exception, ref callInfo, arg0, arg1, arg2);
|
||||
|
||||
return exception != null
|
||||
? throw new JSException(exception)
|
||||
: result;
|
||||
|
|
|
|||
|
|
@ -36,6 +36,8 @@
|
|||
<Compile Include="..\src\BootJsonData.cs" LinkBase="Wasm" />
|
||||
<Compile Include="..\src\AssetsManifestFile.cs" LinkBase="Wasm" />
|
||||
<Compile Include="$(SharedSourceRoot)CommandLineUtils\**\*.cs" />
|
||||
|
||||
<EmbeddedResource Include="..\src\targets\BlazorWasm.web.config" />
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="GenerateTestData" BeforeTargets="GetAssemblyAttributes">
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
using System.IO;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Testing;
|
||||
using Microsoft.NET.Sdk.BlazorWebAssembly;
|
||||
using Xunit;
|
||||
|
||||
|
|
@ -88,6 +89,7 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
|
|||
}
|
||||
|
||||
[Fact]
|
||||
[QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/23756")]
|
||||
public async Task Publish_LazyLoadExplicitAssembly_Debug_Works()
|
||||
{
|
||||
// Arrange
|
||||
|
|
|
|||
|
|
@ -113,6 +113,7 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
|
|||
}
|
||||
|
||||
[Fact]
|
||||
[QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/23756")]
|
||||
public async Task Publish_WithoutLinkerAndCompression_IsIncremental()
|
||||
{
|
||||
// Arrange
|
||||
|
|
|
|||
|
|
@ -41,6 +41,8 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
|
|||
|
||||
// Verify web.config
|
||||
Assert.FileExists(result, publishDirectory, "web.config");
|
||||
var webConfigContent = new StreamReader(GetType().Assembly.GetManifestResourceStream("Microsoft.NET.Sdk.BlazorWebAssembly.IntegrationTests.BlazorWasm.web.config")).ReadToEnd();
|
||||
Assert.FileContentEquals(result, Path.Combine(publishDirectory, "web.config"), webConfigContent);
|
||||
Assert.FileCountEquals(result, 1, publishDirectory, "*", SearchOption.TopDirectoryOnly);
|
||||
|
||||
VerifyBootManifestHashes(result, blazorPublishDirectory);
|
||||
|
|
@ -141,11 +143,10 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
|
|||
serviceWorkerPath: Path.Combine("serviceworkers", "my-service-worker.js"),
|
||||
serviceWorkerContent: "// This is the production service worker",
|
||||
assetsManifestPath: "custom-service-worker-assets.js");
|
||||
|
||||
VerifyTypeGranularTrimming(result, blazorPublishDirectory);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/23756")]
|
||||
public async Task Publish_InRelease_Works()
|
||||
{
|
||||
// Arrange
|
||||
|
|
@ -434,7 +435,8 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
|
|||
Assert.Contains("System.Text.Json.dll", assemblies);
|
||||
|
||||
// No pdbs
|
||||
Assert.Null(bootJsonData.resources.pdb);
|
||||
// Testing this requires an update to the SDK in this repo. Re-enabling tracked via https://github.com/dotnet/aspnetcore/issues/25135
|
||||
// Assert.Null(bootJsonData.resources.pdb);
|
||||
Assert.Null(bootJsonData.resources.satelliteResources);
|
||||
|
||||
Assert.Contains("appsettings.json", bootJsonData.config);
|
||||
|
|
@ -906,16 +908,17 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
|
|||
|
||||
private void VerifyTypeGranularTrimming(MSBuildResult result, string blazorPublishDirectory)
|
||||
{
|
||||
var loggingAssemblyPath = Path.Combine(blazorPublishDirectory, "_framework", "Microsoft.Extensions.Logging.Abstractions.dll");
|
||||
Assert.FileExists(result, loggingAssemblyPath);
|
||||
var componentsShimAssemblyPath = Path.Combine(blazorPublishDirectory, "_framework", "Microsoft.AspNetCore.Razor.Test.ComponentShim.dll");
|
||||
Assert.FileExists(result, componentsShimAssemblyPath);
|
||||
|
||||
// ILogger is referenced by the app, so we expect it to be preserved
|
||||
Assert.AssemblyContainsType(result, loggingAssemblyPath, "Microsoft.Extensions.Logging.ILogger");
|
||||
// LogLevel is referenced by ILogger and therefore must be preserved.
|
||||
Assert.AssemblyContainsType(result, loggingAssemblyPath, "Microsoft.Extensions.Logging.LogLevel");
|
||||
// RouteView is referenced by the app, so we expect it to be preserved
|
||||
Assert.AssemblyContainsType(result, componentsShimAssemblyPath, "Microsoft.AspNetCore.Components.RouteView");
|
||||
|
||||
// NullLogger is not referenced by the app, and should be trimmed.
|
||||
Assert.AssemblyDoesNotContainType(result, loggingAssemblyPath, "Microsoft.Extensions.Logging.Abstractions.NullLogger");
|
||||
// RouteData is referenced by RouteView so we expect it to be preserved.
|
||||
Assert.AssemblyContainsType(result, componentsShimAssemblyPath, "Microsoft.AspNetCore.Components.RouteData");
|
||||
|
||||
// CascadingParameterAttribute is not referenced by the app, and should be trimmed.
|
||||
Assert.AssemblyDoesNotContainType(result, componentsShimAssemblyPath, "Microsoft.AspNetCore.Components.CascadingParameterAttribute");
|
||||
}
|
||||
|
||||
private static BootJsonData ReadBootJsonData(MSBuildResult result, string path)
|
||||
|
|
|
|||
|
|
@ -54,7 +54,18 @@ namespace Microsoft.NET.Sdk.BlazorWebAssembly
|
|||
}
|
||||
}
|
||||
|
||||
protected override string GenerateCommandLineCommands() => ToolAssembly;
|
||||
private static string Quote(string path)
|
||||
{
|
||||
if (string.IsNullOrEmpty(path) || (path[0] == '\"' && path[path.Length - 1] == '\"'))
|
||||
{
|
||||
// it's already quoted
|
||||
return path;
|
||||
}
|
||||
|
||||
return $"\"{path}\"";
|
||||
}
|
||||
|
||||
protected override string GenerateCommandLineCommands() => Quote(ToolAssembly);
|
||||
|
||||
protected override string GenerateResponseFileCommands()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -22,6 +22,9 @@ Copyright (c) .NET Foundation. All rights reserved.
|
|||
<IsPackable>false</IsPackable>
|
||||
|
||||
<WarnOnPackingNonPackableProject>false</WarnOnPackingNonPackableProject>
|
||||
|
||||
<!-- Turn off symbol publishing by default -->
|
||||
<CopyOutputSymbolsToPublishDirectory>false</CopyOutputSymbolsToPublishDirectory>
|
||||
</PropertyGroup>
|
||||
|
||||
<Import Sdk="Microsoft.NET.Sdk.Razor" Project="Sdk.props" />
|
||||
|
|
|
|||
|
|
@ -53,6 +53,14 @@ Copyright (c) .NET Foundation. All rights reserved.
|
|||
<!-- Trimmer defaults -->
|
||||
<PublishTrimmed Condition="'$(PublishTrimmed)' == ''">true</PublishTrimmed>
|
||||
<TrimMode Condition="'$(TrimMode)' == ''">link</TrimMode>
|
||||
<TrimmerRemoveSymbols Condition="'$(TrimmerRemoveSymbols)' == ''">false</TrimmerRemoveSymbols>
|
||||
|
||||
<!-- Runtime feature defaults to trim unnecessary code -->
|
||||
<EventSourceSupport Condition="'$(EventSourceSupport)' == ''">false</EventSourceSupport>
|
||||
<UseSystemResourceKeys Condition="'$(UseSystemResourceKeys)' == ''">true</UseSystemResourceKeys>
|
||||
<EnableUnsafeUTF7Encoding Condition="'$(EnableUnsafeUTF7Encoding)' == ''">false</EnableUnsafeUTF7Encoding>
|
||||
<HttpActivityPropagationSupport Condition="'$(HttpActivityPropagationSupport)' == ''">false</HttpActivityPropagationSupport>
|
||||
<DebuggerSupport Condition="'$(DebuggerSupport)' == '' and '$(Configuration)' != 'Debug'">false</DebuggerSupport>
|
||||
|
||||
<StaticWebAssetBasePath Condition="'$(StaticWebAssetBasePath)' == ''">/</StaticWebAssetBasePath>
|
||||
<BlazorCacheBootResources Condition="'$(BlazorCacheBootResources)' == ''">true</BlazorCacheBootResources>
|
||||
|
|
@ -69,6 +77,12 @@ Copyright (c) .NET Foundation. All rights reserved.
|
|||
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<!-- Configuration for the platform compatibility analyzer. See https://github.com/dotnet/designs/blob/master/accepted/2020/platform-exclusion/platform-exclusion.md#build-configuration-for-platforms -->
|
||||
<SupportedPlatform Remove="@(SupportedPlatform)" />
|
||||
<SupportedPlatform Include="browser" />
|
||||
</ItemGroup>
|
||||
|
||||
<Import Project="Microsoft.NET.Sdk.BlazorWebAssembly.ServiceWorkerAssetsManifest.targets" Condition="'$(ServiceWorkerAssetsManifest)' != ''" />
|
||||
|
||||
<Target Name="_ScrambleDotnetJsFileName" AfterTargets="ResolveRuntimePackAssets">
|
||||
|
|
@ -395,7 +409,7 @@ Copyright (c) .NET Foundation. All rights reserved.
|
|||
<ItemGroup>
|
||||
<_BlazorTypeGranularAssembly
|
||||
Include="@(ManagedAssemblyToLink)"
|
||||
Condition="'%(Extension)' == '.dll' AND ($([System.String]::Copy('%(Filename)').StartsWith('Microsoft.AspNetCore.')) or $([System.String]::Copy('%(Filename)').StartsWith('Microsoft.Extensions.')))">
|
||||
Condition="'%(Extension)' == '.dll' AND $([System.String]::Copy('%(Filename)').StartsWith('Microsoft.AspNetCore.'))">
|
||||
<Required>false</Required>
|
||||
<Preserve>all</Preserve>
|
||||
</_BlazorTypeGranularAssembly>
|
||||
|
|
@ -451,7 +465,7 @@ Copyright (c) .NET Foundation. All rights reserved.
|
|||
Condition="'%(ResolvedFileToPublish.RelativePath)' != 'web.config' AND !$([System.String]::Copy('%(ResolvedFileToPublish.RelativePath)').Replace('\','/').StartsWith('wwwroot/'))" />
|
||||
|
||||
<!-- Remove pdbs from the publish output -->
|
||||
<ResolvedFileToPublish Remove="@(ResolvedFileToPublish)" Condition="'$(BlazorWebAssemblyEnableDebugging)' != 'true' AND '%(Extension)' == '.pdb'" />
|
||||
<ResolvedFileToPublish Remove="@(ResolvedFileToPublish)" Condition="'$(CopyOutputSymbolsToPublishDirectory)' != 'true' AND '%(Extension)' == '.pdb'" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'@(ResolvedFileToPublish->AnyHaveMetadataValue('RelativePath', 'web.config'))' != 'true'">
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ namespace standalone
|
|||
{
|
||||
GC.KeepAlive(typeof(System.Text.Json.JsonSerializer));
|
||||
GC.KeepAlive(typeof(RazorClassLibrary.Class1));
|
||||
GC.KeepAlive(typeof(Microsoft.Extensions.Logging.ILogger));
|
||||
#if REFERENCE_classlibrarywithsatelliteassemblies
|
||||
GC.KeepAlive(typeof(classlibrarywithsatelliteassemblies.Class1));
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -0,0 +1,22 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting
|
||||
{
|
||||
internal class RegisteredComponentsInterop
|
||||
{
|
||||
private static readonly string Prefix = "Blazor._internal.registeredComponents.";
|
||||
|
||||
public static readonly string GetRegisteredComponentsCount = Prefix + "getRegisteredComponentsCount";
|
||||
|
||||
public static readonly string GetId = Prefix + "getId";
|
||||
|
||||
public static readonly string GetAssembly = Prefix + "getAssembly";
|
||||
|
||||
public static readonly string GetTypeName = Prefix + "getTypeName";
|
||||
|
||||
public static readonly string GetParameterDefinitions = Prefix + "getParameterDefinitions";
|
||||
|
||||
public static readonly string GetParameterValues = Prefix + "getParameterValues";
|
||||
}
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting
|
||||
|
|
@ -16,7 +17,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting
|
|||
/// and <paramref name="selector"/>.
|
||||
/// </summary>
|
||||
/// <param name="componentType">The component type. Must implement <see cref="IComponent"/>.</param>
|
||||
/// <param name="selector">The DOM element selector.</param>
|
||||
/// <param name="selector">The DOM element selector or component registration id for the component.</param>
|
||||
public RootComponentMapping(Type componentType, string selector)
|
||||
{
|
||||
if (componentType is null)
|
||||
|
|
@ -38,6 +39,19 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting
|
|||
|
||||
ComponentType = componentType;
|
||||
Selector = selector;
|
||||
Parameters = ParameterView.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of <see cref="RootComponentMapping"/> with the provided <paramref name="componentType"/>
|
||||
/// and <paramref name="selector"/>.
|
||||
/// </summary>
|
||||
/// <param name="componentType">The component type. Must implement <see cref="IComponent"/>.</param>
|
||||
/// <param name="selector">The DOM element selector or registration id for the component.</param>
|
||||
/// <param name="parameters">The parameters to pass to the component.</param>
|
||||
public RootComponentMapping(Type componentType, string selector, ParameterView parameters) : this(componentType, selector)
|
||||
{
|
||||
Parameters = parameters;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -49,5 +63,10 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting
|
|||
/// Gets the DOM element selector.
|
||||
/// </summary>
|
||||
public string Selector { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the parameters to pass to the root component.
|
||||
/// </summary>
|
||||
public ParameterView Parameters { get; }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,6 +34,17 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting
|
|||
/// <param name="componentType">The component type. Must implement <see cref="IComponent"/>.</param>
|
||||
/// <param name="selector">The DOM element selector.</param>
|
||||
public void Add(Type componentType, string selector)
|
||||
{
|
||||
Add(componentType, selector, ParameterView.Empty);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a component mapping to the collection.
|
||||
/// </summary>
|
||||
/// <param name="componentType">The component type. Must implement <see cref="IComponent"/>.</param>
|
||||
/// <param name="selector">The DOM element selector.</param>
|
||||
/// <param name="parameters">The parameters to the root component.</param>
|
||||
public void Add(Type componentType, string selector, ParameterView parameters)
|
||||
{
|
||||
if (componentType is null)
|
||||
{
|
||||
|
|
@ -45,7 +56,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting
|
|||
throw new ArgumentNullException(nameof(selector));
|
||||
}
|
||||
|
||||
Add(new RootComponentMapping(componentType, selector));
|
||||
Add(new RootComponentMapping(componentType, selector, parameters));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -138,7 +138,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting
|
|||
for (var i = 0; i < rootComponents.Length; i++)
|
||||
{
|
||||
var rootComponent = rootComponents[i];
|
||||
await _renderer.AddComponentAsync(rootComponent.ComponentType, rootComponent.Selector);
|
||||
await _renderer.AddComponentAsync(rootComponent.ComponentType, rootComponent.Selector, rootComponent.Parameters);
|
||||
}
|
||||
|
||||
await tcs.Task;
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting
|
|||
public sealed class WebAssemblyHostBuilder
|
||||
{
|
||||
private Func<IServiceProvider> _createServiceProvider;
|
||||
private RootComponentTypeCache _rootComponentCache;
|
||||
|
||||
/// <summary>
|
||||
/// Creates an instance of <see cref="WebAssemblyHostBuilder"/> using the most common
|
||||
|
|
@ -57,6 +58,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting
|
|||
|
||||
// Retrieve required attributes from JSRuntimeInvoker
|
||||
InitializeNavigationManager(jsRuntimeInvoker);
|
||||
InitializeRegisteredRootComponents(jsRuntimeInvoker);
|
||||
InitializeDefaultServices();
|
||||
|
||||
var hostEnvironment = InitializeEnvironment(jsRuntimeInvoker);
|
||||
|
|
@ -68,6 +70,38 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting
|
|||
};
|
||||
}
|
||||
|
||||
private void InitializeRegisteredRootComponents(WebAssemblyJSRuntimeInvoker jsRuntimeInvoker)
|
||||
{
|
||||
var componentsCount = jsRuntimeInvoker.InvokeUnmarshalled<object, object, object, int>(RegisteredComponentsInterop.GetRegisteredComponentsCount, null, null, null);
|
||||
if (componentsCount == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var registeredComponents = new WebAssemblyComponentMarker[componentsCount];
|
||||
for (var i = 0; i < componentsCount; i++)
|
||||
{
|
||||
var id = jsRuntimeInvoker.InvokeUnmarshalled<int, object, object, int>(RegisteredComponentsInterop.GetId, i, null, null);
|
||||
var assembly = jsRuntimeInvoker.InvokeUnmarshalled<int, object, object, string>(RegisteredComponentsInterop.GetAssembly, id, null, null);
|
||||
var typeName = jsRuntimeInvoker.InvokeUnmarshalled<int, object, object, string>(RegisteredComponentsInterop.GetTypeName, id, null, null);
|
||||
var serializedParameterDefinitions = jsRuntimeInvoker.InvokeUnmarshalled<int, object, object, string>(RegisteredComponentsInterop.GetParameterDefinitions, id, null, null);
|
||||
var serializedParameterValues = jsRuntimeInvoker.InvokeUnmarshalled<int, object, object, string>(RegisteredComponentsInterop.GetParameterValues, id, null, null);
|
||||
registeredComponents[i] = new WebAssemblyComponentMarker(WebAssemblyComponentMarker.ClientMarkerType, assembly, typeName, serializedParameterDefinitions, serializedParameterValues, id.ToString());
|
||||
}
|
||||
|
||||
var componentDeserializer = WebAssemblyComponentParameterDeserializer.Instance;
|
||||
foreach (var registeredComponent in registeredComponents)
|
||||
{
|
||||
_rootComponentCache = new RootComponentTypeCache();
|
||||
var componentType = _rootComponentCache.GetRootComponent(registeredComponent.Assembly, registeredComponent.TypeName);
|
||||
var definitions = componentDeserializer.GetParameterDefinitions(registeredComponent.ParameterDefinitions);
|
||||
var values = componentDeserializer.GetParameterValues(registeredComponent.ParameterValues);
|
||||
var parameters = componentDeserializer.DeserializeParameters(definitions, values);
|
||||
|
||||
RootComponents.Add(componentType, registeredComponent.PrerenderId, parameters);
|
||||
}
|
||||
}
|
||||
|
||||
private void InitializeNavigationManager(WebAssemblyJSRuntimeInvoker jsRuntimeInvoker)
|
||||
{
|
||||
var baseUri = jsRuntimeInvoker.InvokeUnmarshalled<object, object, object, string>(BrowserNavigationManagerInterop.GetBaseUri, null, null, null);
|
||||
|
|
@ -190,7 +224,8 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting
|
|||
Services.AddSingleton<NavigationManager>(WebAssemblyNavigationManager.Instance);
|
||||
Services.AddSingleton<INavigationInterception>(WebAssemblyNavigationInterception.Instance);
|
||||
Services.AddSingleton(new LazyAssemblyLoader(DefaultWebAssemblyJSRuntime.Instance));
|
||||
Services.AddLogging(builder => {
|
||||
Services.AddLogging(builder =>
|
||||
{
|
||||
builder.AddProvider(new WebAssemblyConsoleLoggerProvider(DefaultWebAssemblyJSRuntime.Instance));
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework>
|
||||
|
|
@ -15,13 +15,7 @@
|
|||
<Reference Include="Microsoft.Extensions.Logging" />
|
||||
<Reference Include="Microsoft.JSInterop.WebAssembly" />
|
||||
|
||||
<ProjectReference
|
||||
Include="..\..\..\Web.JS\Microsoft.AspNetCore.Components.Web.JS.npmproj"
|
||||
ReferenceOutputAssemblies="false"
|
||||
SkipGetTargetFrameworkProperties="true"
|
||||
UndefineProperties="TargetFramework"
|
||||
Private="false"
|
||||
Condition="'$(BuildNodeJS)' != 'false' and '$(BuildingInsideVisualStudio)' != 'true'" />
|
||||
<ProjectReference Include="..\..\..\Web.JS\Microsoft.AspNetCore.Components.Web.JS.npmproj" ReferenceOutputAssemblies="false" SkipGetTargetFrameworkProperties="true" UndefineProperties="TargetFramework" Private="false" Condition="'$(BuildNodeJS)' != 'false' and '$(BuildingInsideVisualStudio)' != 'true'" />
|
||||
|
||||
<SuppressBaselineReference Include="Microsoft.AspNetCore.Components.WebAssembly.HttpHandler" />
|
||||
</ItemGroup>
|
||||
|
|
@ -31,6 +25,11 @@
|
|||
<Compile Include="$(ComponentsSharedSourceRoot)src\JsonSerializerOptionsProvider.cs" />
|
||||
<Compile Include="$(ComponentsSharedSourceRoot)src\WebEventData.cs" />
|
||||
<Compile Include="$(ComponentsSharedSourceRoot)src\ElementReferenceJsonConverter.cs" />
|
||||
<Compile Include="$(ComponentsSharedSourceRoot)src\ComponentParametersTypeCache.cs" />
|
||||
<Compile Include="$(ComponentsSharedSourceRoot)src\RootComponentTypeCache.cs" />
|
||||
<Compile Include="$(SharedSourceRoot)Components\WebAssemblyComponentSerializationSettings.cs" Link="Prerendering/WebAssemblyComponentSerializationSettings.cs" />
|
||||
<Compile Include="$(SharedSourceRoot)Components\WebAssemblyComponentMarker.cs" Link="Prerendering/WebAssemblyComponentMarker.cs" />
|
||||
<Compile Include="$(SharedSourceRoot)Components\ComponentParameter.cs" Link="Prerendering/ComponentParameter.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,88 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components
|
||||
{
|
||||
internal class WebAssemblyComponentParameterDeserializer
|
||||
{
|
||||
private readonly ComponentParametersTypeCache _parametersCache;
|
||||
|
||||
public WebAssemblyComponentParameterDeserializer(
|
||||
ComponentParametersTypeCache parametersCache)
|
||||
{
|
||||
_parametersCache = parametersCache;
|
||||
}
|
||||
|
||||
public static WebAssemblyComponentParameterDeserializer Instance { get; } = new WebAssemblyComponentParameterDeserializer(new ComponentParametersTypeCache());
|
||||
|
||||
public ParameterView DeserializeParameters(IList<ComponentParameter> parametersDefinitions, IList<object> parameterValues)
|
||||
{
|
||||
var parametersDictionary = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
if (parameterValues.Count != parametersDefinitions.Count)
|
||||
{
|
||||
// Mismatched number of definition/parameter values.
|
||||
throw new InvalidOperationException($"The number of parameter definitions '{parametersDefinitions.Count}' does not match the number parameter values '{parameterValues.Count}'.");
|
||||
}
|
||||
|
||||
for (var i = 0; i < parametersDefinitions.Count; i++)
|
||||
{
|
||||
var definition = parametersDefinitions[i];
|
||||
if (definition.Name == null)
|
||||
{
|
||||
throw new InvalidOperationException("The name is missing in a parameter definition.");
|
||||
}
|
||||
|
||||
if (definition.TypeName == null && definition.Assembly == null)
|
||||
{
|
||||
parametersDictionary[definition.Name] = null;
|
||||
}
|
||||
else if (definition.TypeName == null || definition.Assembly == null)
|
||||
{
|
||||
throw new InvalidOperationException($"The parameter definition for '{definition.Name}' is incomplete: Type='{definition.TypeName}' Assembly='{definition.Assembly}'.");
|
||||
}
|
||||
else
|
||||
{
|
||||
var parameterType = _parametersCache.GetParameterType(definition.Assembly, definition.TypeName);
|
||||
if (parameterType == null)
|
||||
{
|
||||
throw new InvalidOperationException($"The parameter '{definition.Name} with type '{definition.TypeName}' in assembly '{definition.Assembly}' could not be found.");
|
||||
}
|
||||
try
|
||||
{
|
||||
var value = (JsonElement)parameterValues[i];
|
||||
var parameterValue = JsonSerializer.Deserialize(
|
||||
value.GetRawText(),
|
||||
parameterType,
|
||||
WebAssemblyComponentSerializationSettings.JsonSerializationOptions);
|
||||
|
||||
parametersDictionary[definition.Name] = parameterValue;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new InvalidOperationException("Could not parse the parameter value for parameter '{definition.Name}' of type '{definition.TypeName}' and assembly '{definition.Assembly}'.", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ParameterView.FromDictionary(parametersDictionary);
|
||||
}
|
||||
|
||||
public ComponentParameter[] GetParameterDefinitions(string parametersDefinitions)
|
||||
{
|
||||
return JsonSerializer.Deserialize<ComponentParameter[]>(parametersDefinitions, WebAssemblyComponentSerializationSettings.JsonSerializationOptions);
|
||||
}
|
||||
|
||||
public IList<object> GetParameterValues(string parameterValues)
|
||||
{
|
||||
return JsonSerializer.Deserialize<IList<object>>(parameterValues, WebAssemblyComponentSerializationSettings.JsonSerializationOptions);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -7,6 +7,7 @@ using System.Threading.Tasks;
|
|||
using Microsoft.AspNetCore.Components.RenderTree;
|
||||
using Microsoft.AspNetCore.Components.WebAssembly.Services;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.JSInterop;
|
||||
using Microsoft.JSInterop.WebAssembly;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.WebAssembly.Rendering
|
||||
|
|
@ -46,13 +47,14 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Rendering
|
|||
/// </summary>
|
||||
/// <typeparam name="TComponent">The type of the component.</typeparam>
|
||||
/// <param name="domElementSelector">A CSS selector that uniquely identifies a DOM element.</param>
|
||||
/// <param name="parameters">The parameters for the component.</param>
|
||||
/// <returns>A <see cref="Task"/> that represents the asynchronous rendering of the added component.</returns>
|
||||
/// <remarks>
|
||||
/// Callers of this method may choose to ignore the returned <see cref="Task"/> if they do not
|
||||
/// want to await the rendering of the added component.
|
||||
/// </remarks>
|
||||
public Task AddComponentAsync<TComponent>(string domElementSelector) where TComponent : IComponent
|
||||
=> AddComponentAsync(typeof(TComponent), domElementSelector);
|
||||
public Task AddComponentAsync<TComponent>(string domElementSelector, ParameterView parameters) where TComponent : IComponent
|
||||
=> AddComponentAsync(typeof(TComponent), domElementSelector, parameters);
|
||||
|
||||
/// <summary>
|
||||
/// Associates the <see cref="IComponent"/> with the <see cref="WebAssemblyRenderer"/>,
|
||||
|
|
@ -60,12 +62,13 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Rendering
|
|||
/// </summary>
|
||||
/// <param name="componentType">The type of the component.</param>
|
||||
/// <param name="domElementSelector">A CSS selector that uniquely identifies a DOM element.</param>
|
||||
/// <param name="parameters">The list of root component parameters.</param>
|
||||
/// <returns>A <see cref="Task"/> that represents the asynchronous rendering of the added component.</returns>
|
||||
/// <remarks>
|
||||
/// Callers of this method may choose to ignore the returned <see cref="Task"/> if they do not
|
||||
/// want to await the rendering of the added component.
|
||||
/// </remarks>
|
||||
public Task AddComponentAsync(Type componentType, string domElementSelector)
|
||||
public Task AddComponentAsync(Type componentType, string domElementSelector, ParameterView parameters)
|
||||
{
|
||||
var component = InstantiateComponent(componentType);
|
||||
var componentId = AssignRootComponentId(component);
|
||||
|
|
@ -82,7 +85,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Rendering
|
|||
componentId,
|
||||
_webAssemblyRendererId);
|
||||
|
||||
return RenderRootComponentAsync(componentId);
|
||||
return RenderRootComponentAsync(componentId, parameters);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
|
@ -95,7 +98,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Rendering
|
|||
/// <inheritdoc />
|
||||
protected override Task UpdateDisplayAsync(in RenderBatch batch)
|
||||
{
|
||||
DefaultWebAssemblyJSRuntime.Instance.InvokeUnmarshalled<int, RenderBatch, object>(
|
||||
((IJSUnmarshalledRuntime)DefaultWebAssemblyJSRuntime.Instance).InvokeUnmarshalled<int, RenderBatch, object>(
|
||||
"Blazor._internal.renderBatch",
|
||||
_webAssemblyRendererId,
|
||||
batch);
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Services
|
|||
var newAssembliesToLoad = assembliesToLoad.Where(assembly => !_loadedAssemblyCache.Contains(assembly));
|
||||
var loadedAssemblies = new List<Assembly>();
|
||||
|
||||
var count = (int)await ((WebAssemblyJSRuntime)_jsRuntime).InvokeUnmarshalled<string[], object, object, Task<object>>(
|
||||
var count = (int)await ((IJSUnmarshalledRuntime)_jsRuntime).InvokeUnmarshalled<string[], object, object, Task<object>>(
|
||||
GetDynamicAssemblies,
|
||||
newAssembliesToLoad.ToArray(),
|
||||
null,
|
||||
|
|
@ -91,7 +91,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Services
|
|||
return loadedAssemblies;
|
||||
}
|
||||
|
||||
var assemblies = ((WebAssemblyJSRuntime)_jsRuntime).InvokeUnmarshalled<object, object, object, object[]>(
|
||||
var assemblies = ((IJSUnmarshalledRuntime)_jsRuntime).InvokeUnmarshalled<object, object, object, object[]>(
|
||||
ReadDynamicAssemblies,
|
||||
null,
|
||||
null,
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Services
|
|||
_jsRuntime.InvokeVoid("console.error", formattedMessage);
|
||||
break;
|
||||
case LogLevel.Critical:
|
||||
_jsRuntime.InvokeUnmarshalled<string, object>("Blazor._internal.dotNetCriticalError", formattedMessage);
|
||||
((IJSUnmarshalledRuntime)_jsRuntime).InvokeUnmarshalled<string, object>("Blazor._internal.dotNetCriticalError", formattedMessage);
|
||||
break;
|
||||
default: // LogLevel.None or invalid enum values
|
||||
Console.WriteLine(formattedMessage);
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.JSInterop.WebAssembly;
|
||||
using Microsoft.JSInterop;
|
||||
|
||||
namespace Microsoft.AspNetCore.Components.WebAssembly.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// This class exists to enable unit testing for code that needs to call
|
||||
/// <see cref="WebAssemblyJSRuntime.InvokeUnmarshalled{T0, T1, T2, TResult}(string, T0, T1, T2)"/>.
|
||||
/// <see cref="IJSUnmarshalledRuntime.InvokeUnmarshalled{T0, T1, T2, TResult}(string, T0, T1, T2)"/>.
|
||||
///
|
||||
/// We should only use this in non-perf-critical code paths (for example, during hosting startup,
|
||||
/// where we only call this a fixed number of times, and not during rendering where it might be
|
||||
|
|
@ -22,6 +22,6 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Services
|
|||
public static WebAssemblyJSRuntimeInvoker Instance = new WebAssemblyJSRuntimeInvoker();
|
||||
|
||||
public virtual TResult InvokeUnmarshalled<T0, T1, T2, TResult>(string identifier, T0 arg0, T1 arg1, T2 arg2)
|
||||
=> DefaultWebAssemblyJSRuntime.Instance.InvokeUnmarshalled<T0, T1, T2, TResult>(identifier, arg0, arg1, arg2);
|
||||
=> ((IJSUnmarshalledRuntime)DefaultWebAssemblyJSRuntime.Instance).InvokeUnmarshalled<T0, T1, T2, TResult>(identifier, arg0, arg1, arg2);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue