Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
126 changes: 126 additions & 0 deletions AspNetCore.sln
Original file line number Diff line number Diff line change
Expand Up @@ -1427,6 +1427,20 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Compon
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Components.Web.Extensions.Tests", "src\Components\Web.Extensions\test\Microsoft.AspNetCore.Components.Web.Extensions.Tests.csproj", "{157605CB-5170-4C1A-980F-4BAE42DB60DE}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "testassets", "testassets", "{2531F00A-54EB-4074-9C0B-9AF9FB3679DC}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BasicTestApp", "src\Components\test\testassets\BasicTestApp\BasicTestApp.csproj", "{85D67E40-4B11-48ED-8C43-34590A1FB9ED}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LazyTestContentPackage", "src\Components\test\testassets\LazyTestContentPackage\LazyTestContentPackage.csproj", "{C0EF53A5-5A94-4849-86B0-2297EA08D649}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ComponentsApp.App", "src\Components\test\testassets\ComponentsApp.App\ComponentsApp.App.csproj", "{4FDD820F-8397-41B7-956E-F257DD044BD8}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ComponentsApp.Server", "src\Components\test\testassets\ComponentsApp.Server\ComponentsApp.Server.csproj", "{CA7C7A53-446F-453A-A57B-78BB1443B8A8}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestContentPackage", "src\Components\test\testassets\TestContentPackage\TestContentPackage.csproj", "{B32C5882-2313-40D0-A003-2FF33724CFE6}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Components.TestServer", "src\Components\test\testassets\TestServer\Components.TestServer.csproj", "{26F88A06-319C-43F3-9FD9-8BC2D29F8C00}"
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}"
Expand Down Expand Up @@ -1455,6 +1469,12 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ObjectPool", "ObjectPool",
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.ObjectPool", "src\ObjectPool\src\Microsoft.Extensions.ObjectPool.csproj", "{CE5D01C2-6BBD-4F33-A1C4-A1479DA99CAD}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "testassets", "testassets", "{00B2DD87-7E2A-4460-BE1B-5E18B1062B7F}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "InteropClient", "src\Grpc\test\testassets\InteropClient\InteropClient.csproj", "{C3A0F425-669F-46A8-893F-CF449A6DAE56}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "InteropWebsite", "src\Grpc\test\testassets\InteropWebsite\InteropWebsite.csproj", "{19189670-E206-471D-94F8-7D3D545E5020}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -6757,6 +6777,78 @@ Global
{157605CB-5170-4C1A-980F-4BAE42DB60DE}.Release|x64.Build.0 = Release|Any CPU
{157605CB-5170-4C1A-980F-4BAE42DB60DE}.Release|x86.ActiveCfg = Release|Any CPU
{157605CB-5170-4C1A-980F-4BAE42DB60DE}.Release|x86.Build.0 = Release|Any CPU
{85D67E40-4B11-48ED-8C43-34590A1FB9ED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{85D67E40-4B11-48ED-8C43-34590A1FB9ED}.Debug|Any CPU.Build.0 = Debug|Any CPU
{85D67E40-4B11-48ED-8C43-34590A1FB9ED}.Debug|x64.ActiveCfg = Debug|Any CPU
{85D67E40-4B11-48ED-8C43-34590A1FB9ED}.Debug|x64.Build.0 = Debug|Any CPU
{85D67E40-4B11-48ED-8C43-34590A1FB9ED}.Debug|x86.ActiveCfg = Debug|Any CPU
{85D67E40-4B11-48ED-8C43-34590A1FB9ED}.Debug|x86.Build.0 = Debug|Any CPU
{85D67E40-4B11-48ED-8C43-34590A1FB9ED}.Release|Any CPU.ActiveCfg = Release|Any CPU
{85D67E40-4B11-48ED-8C43-34590A1FB9ED}.Release|Any CPU.Build.0 = Release|Any CPU
{85D67E40-4B11-48ED-8C43-34590A1FB9ED}.Release|x64.ActiveCfg = Release|Any CPU
{85D67E40-4B11-48ED-8C43-34590A1FB9ED}.Release|x64.Build.0 = Release|Any CPU
{85D67E40-4B11-48ED-8C43-34590A1FB9ED}.Release|x86.ActiveCfg = Release|Any CPU
{85D67E40-4B11-48ED-8C43-34590A1FB9ED}.Release|x86.Build.0 = Release|Any CPU
{C0EF53A5-5A94-4849-86B0-2297EA08D649}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C0EF53A5-5A94-4849-86B0-2297EA08D649}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C0EF53A5-5A94-4849-86B0-2297EA08D649}.Debug|x64.ActiveCfg = Debug|Any CPU
{C0EF53A5-5A94-4849-86B0-2297EA08D649}.Debug|x64.Build.0 = Debug|Any CPU
{C0EF53A5-5A94-4849-86B0-2297EA08D649}.Debug|x86.ActiveCfg = Debug|Any CPU
{C0EF53A5-5A94-4849-86B0-2297EA08D649}.Debug|x86.Build.0 = Debug|Any CPU
{C0EF53A5-5A94-4849-86B0-2297EA08D649}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C0EF53A5-5A94-4849-86B0-2297EA08D649}.Release|Any CPU.Build.0 = Release|Any CPU
{C0EF53A5-5A94-4849-86B0-2297EA08D649}.Release|x64.ActiveCfg = Release|Any CPU
{C0EF53A5-5A94-4849-86B0-2297EA08D649}.Release|x64.Build.0 = Release|Any CPU
{C0EF53A5-5A94-4849-86B0-2297EA08D649}.Release|x86.ActiveCfg = Release|Any CPU
{C0EF53A5-5A94-4849-86B0-2297EA08D649}.Release|x86.Build.0 = Release|Any CPU
{4FDD820F-8397-41B7-956E-F257DD044BD8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4FDD820F-8397-41B7-956E-F257DD044BD8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4FDD820F-8397-41B7-956E-F257DD044BD8}.Debug|x64.ActiveCfg = Debug|Any CPU
{4FDD820F-8397-41B7-956E-F257DD044BD8}.Debug|x64.Build.0 = Debug|Any CPU
{4FDD820F-8397-41B7-956E-F257DD044BD8}.Debug|x86.ActiveCfg = Debug|Any CPU
{4FDD820F-8397-41B7-956E-F257DD044BD8}.Debug|x86.Build.0 = Debug|Any CPU
{4FDD820F-8397-41B7-956E-F257DD044BD8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4FDD820F-8397-41B7-956E-F257DD044BD8}.Release|Any CPU.Build.0 = Release|Any CPU
{4FDD820F-8397-41B7-956E-F257DD044BD8}.Release|x64.ActiveCfg = Release|Any CPU
{4FDD820F-8397-41B7-956E-F257DD044BD8}.Release|x64.Build.0 = Release|Any CPU
{4FDD820F-8397-41B7-956E-F257DD044BD8}.Release|x86.ActiveCfg = Release|Any CPU
{4FDD820F-8397-41B7-956E-F257DD044BD8}.Release|x86.Build.0 = Release|Any CPU
{CA7C7A53-446F-453A-A57B-78BB1443B8A8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CA7C7A53-446F-453A-A57B-78BB1443B8A8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CA7C7A53-446F-453A-A57B-78BB1443B8A8}.Debug|x64.ActiveCfg = Debug|Any CPU
{CA7C7A53-446F-453A-A57B-78BB1443B8A8}.Debug|x64.Build.0 = Debug|Any CPU
{CA7C7A53-446F-453A-A57B-78BB1443B8A8}.Debug|x86.ActiveCfg = Debug|Any CPU
{CA7C7A53-446F-453A-A57B-78BB1443B8A8}.Debug|x86.Build.0 = Debug|Any CPU
{CA7C7A53-446F-453A-A57B-78BB1443B8A8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CA7C7A53-446F-453A-A57B-78BB1443B8A8}.Release|Any CPU.Build.0 = Release|Any CPU
{CA7C7A53-446F-453A-A57B-78BB1443B8A8}.Release|x64.ActiveCfg = Release|Any CPU
{CA7C7A53-446F-453A-A57B-78BB1443B8A8}.Release|x64.Build.0 = Release|Any CPU
{CA7C7A53-446F-453A-A57B-78BB1443B8A8}.Release|x86.ActiveCfg = Release|Any CPU
{CA7C7A53-446F-453A-A57B-78BB1443B8A8}.Release|x86.Build.0 = Release|Any CPU
{B32C5882-2313-40D0-A003-2FF33724CFE6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B32C5882-2313-40D0-A003-2FF33724CFE6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B32C5882-2313-40D0-A003-2FF33724CFE6}.Debug|x64.ActiveCfg = Debug|Any CPU
{B32C5882-2313-40D0-A003-2FF33724CFE6}.Debug|x64.Build.0 = Debug|Any CPU
{B32C5882-2313-40D0-A003-2FF33724CFE6}.Debug|x86.ActiveCfg = Debug|Any CPU
{B32C5882-2313-40D0-A003-2FF33724CFE6}.Debug|x86.Build.0 = Debug|Any CPU
{B32C5882-2313-40D0-A003-2FF33724CFE6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B32C5882-2313-40D0-A003-2FF33724CFE6}.Release|Any CPU.Build.0 = Release|Any CPU
{B32C5882-2313-40D0-A003-2FF33724CFE6}.Release|x64.ActiveCfg = Release|Any CPU
{B32C5882-2313-40D0-A003-2FF33724CFE6}.Release|x64.Build.0 = Release|Any CPU
{B32C5882-2313-40D0-A003-2FF33724CFE6}.Release|x86.ActiveCfg = Release|Any CPU
{B32C5882-2313-40D0-A003-2FF33724CFE6}.Release|x86.Build.0 = Release|Any CPU
{26F88A06-319C-43F3-9FD9-8BC2D29F8C00}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{26F88A06-319C-43F3-9FD9-8BC2D29F8C00}.Debug|Any CPU.Build.0 = Debug|Any CPU
{26F88A06-319C-43F3-9FD9-8BC2D29F8C00}.Debug|x64.ActiveCfg = Debug|Any CPU
{26F88A06-319C-43F3-9FD9-8BC2D29F8C00}.Debug|x64.Build.0 = Debug|Any CPU
{26F88A06-319C-43F3-9FD9-8BC2D29F8C00}.Debug|x86.ActiveCfg = Debug|Any CPU
{26F88A06-319C-43F3-9FD9-8BC2D29F8C00}.Debug|x86.Build.0 = Debug|Any CPU
{26F88A06-319C-43F3-9FD9-8BC2D29F8C00}.Release|Any CPU.ActiveCfg = Release|Any CPU
{26F88A06-319C-43F3-9FD9-8BC2D29F8C00}.Release|Any CPU.Build.0 = Release|Any CPU
{26F88A06-319C-43F3-9FD9-8BC2D29F8C00}.Release|x64.ActiveCfg = Release|Any CPU
{26F88A06-319C-43F3-9FD9-8BC2D29F8C00}.Release|x64.Build.0 = Release|Any CPU
{26F88A06-319C-43F3-9FD9-8BC2D29F8C00}.Release|x86.ActiveCfg = Release|Any CPU
{26F88A06-319C-43F3-9FD9-8BC2D29F8C00}.Release|x86.Build.0 = Release|Any CPU
{6B2734BF-C61D-4889-ABBF-456A4075D59B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6B2734BF-C61D-4889-ABBF-456A4075D59B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6B2734BF-C61D-4889-ABBF-456A4075D59B}.Debug|x64.ActiveCfg = Debug|Any CPU
Expand Down Expand Up @@ -6889,6 +6981,30 @@ Global
{CE5D01C2-6BBD-4F33-A1C4-A1479DA99CAD}.Release|x64.Build.0 = Release|Any CPU
{CE5D01C2-6BBD-4F33-A1C4-A1479DA99CAD}.Release|x86.ActiveCfg = Release|Any CPU
{CE5D01C2-6BBD-4F33-A1C4-A1479DA99CAD}.Release|x86.Build.0 = Release|Any CPU
{C3A0F425-669F-46A8-893F-CF449A6DAE56}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C3A0F425-669F-46A8-893F-CF449A6DAE56}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C3A0F425-669F-46A8-893F-CF449A6DAE56}.Debug|x64.ActiveCfg = Debug|Any CPU
{C3A0F425-669F-46A8-893F-CF449A6DAE56}.Debug|x64.Build.0 = Debug|Any CPU
{C3A0F425-669F-46A8-893F-CF449A6DAE56}.Debug|x86.ActiveCfg = Debug|Any CPU
{C3A0F425-669F-46A8-893F-CF449A6DAE56}.Debug|x86.Build.0 = Debug|Any CPU
{C3A0F425-669F-46A8-893F-CF449A6DAE56}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C3A0F425-669F-46A8-893F-CF449A6DAE56}.Release|Any CPU.Build.0 = Release|Any CPU
{C3A0F425-669F-46A8-893F-CF449A6DAE56}.Release|x64.ActiveCfg = Release|Any CPU
{C3A0F425-669F-46A8-893F-CF449A6DAE56}.Release|x64.Build.0 = Release|Any CPU
{C3A0F425-669F-46A8-893F-CF449A6DAE56}.Release|x86.ActiveCfg = Release|Any CPU
{C3A0F425-669F-46A8-893F-CF449A6DAE56}.Release|x86.Build.0 = Release|Any CPU
{19189670-E206-471D-94F8-7D3D545E5020}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{19189670-E206-471D-94F8-7D3D545E5020}.Debug|Any CPU.Build.0 = Debug|Any CPU
{19189670-E206-471D-94F8-7D3D545E5020}.Debug|x64.ActiveCfg = Debug|Any CPU
{19189670-E206-471D-94F8-7D3D545E5020}.Debug|x64.Build.0 = Debug|Any CPU
{19189670-E206-471D-94F8-7D3D545E5020}.Debug|x86.ActiveCfg = Debug|Any CPU
{19189670-E206-471D-94F8-7D3D545E5020}.Debug|x86.Build.0 = Debug|Any CPU
{19189670-E206-471D-94F8-7D3D545E5020}.Release|Any CPU.ActiveCfg = Release|Any CPU
{19189670-E206-471D-94F8-7D3D545E5020}.Release|Any CPU.Build.0 = Release|Any CPU
{19189670-E206-471D-94F8-7D3D545E5020}.Release|x64.ActiveCfg = Release|Any CPU
{19189670-E206-471D-94F8-7D3D545E5020}.Release|x64.Build.0 = Release|Any CPU
{19189670-E206-471D-94F8-7D3D545E5020}.Release|x86.ActiveCfg = Release|Any CPU
{19189670-E206-471D-94F8-7D3D545E5020}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -7604,6 +7720,13 @@ Global
{F71FE795-9923-461B-9809-BB1821A276D0} = {60D51C98-2CC0-40DF-B338-44154EFEE2FF}
{8294A74F-7DAA-4B69-BC56-7634D93C9693} = {F71FE795-9923-461B-9809-BB1821A276D0}
{157605CB-5170-4C1A-980F-4BAE42DB60DE} = {F71FE795-9923-461B-9809-BB1821A276D0}
{2531F00A-54EB-4074-9C0B-9AF9FB3679DC} = {0508E463-0269-40C9-B5C2-3B600FB2A28B}
{85D67E40-4B11-48ED-8C43-34590A1FB9ED} = {2531F00A-54EB-4074-9C0B-9AF9FB3679DC}
{C0EF53A5-5A94-4849-86B0-2297EA08D649} = {2531F00A-54EB-4074-9C0B-9AF9FB3679DC}
{4FDD820F-8397-41B7-956E-F257DD044BD8} = {2531F00A-54EB-4074-9C0B-9AF9FB3679DC}
{CA7C7A53-446F-453A-A57B-78BB1443B8A8} = {2531F00A-54EB-4074-9C0B-9AF9FB3679DC}
{B32C5882-2313-40D0-A003-2FF33724CFE6} = {2531F00A-54EB-4074-9C0B-9AF9FB3679DC}
{26F88A06-319C-43F3-9FD9-8BC2D29F8C00} = {2531F00A-54EB-4074-9C0B-9AF9FB3679DC}
{FED4267E-E5E4-49C5-98DB-8B3F203596EE} = {562D5067-8CD8-4F19-BCBB-873204932C61}
{6B2734BF-C61D-4889-ABBF-456A4075D59B} = {FED4267E-E5E4-49C5-98DB-8B3F203596EE}
{83371889-9A3E-4D16-AE77-EB4F83BC6374} = {FED4267E-E5E4-49C5-98DB-8B3F203596EE}
Expand All @@ -7618,6 +7741,9 @@ Global
{8A59AF88-4A82-46ED-977D-D909001F8107} = {6126DCE4-9692-4EE2-B240-C65743572995}
{E235DAAD-FE73-469E-B16F-F2B8E872E217} = {017429CC-C5FB-48B4-9C46-034E29EE2F06}
{CE5D01C2-6BBD-4F33-A1C4-A1479DA99CAD} = {E235DAAD-FE73-469E-B16F-F2B8E872E217}
{00B2DD87-7E2A-4460-BE1B-5E18B1062B7F} = {E763DA15-8F4E-446C-99B8-309053C75598}
{C3A0F425-669F-46A8-893F-CF449A6DAE56} = {00B2DD87-7E2A-4460-BE1B-5E18B1062B7F}
{19189670-E206-471D-94F8-7D3D545E5020} = {00B2DD87-7E2A-4460-BE1B-5E18B1062B7F}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {3E8720B3-DBDD-498C-B383-2CC32A054E8F}
Expand Down
19 changes: 9 additions & 10 deletions src/Components/Components/src/Routing/Router.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,12 @@ static readonly ReadOnlyDictionary<string, object> _emptyParametersDictionary
/// <summary>
/// Get or sets the content to display when asynchronous navigation is in progress.
/// </summary>
[Parameter] public RenderFragment Navigating { get; set; }
[Parameter] public RenderFragment? Navigating { get; set; }

/// <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 Func<NavigationContext, Task>? OnNavigateAsync { get; set; }

private RouteTable Routes { get; set; }

Expand Down Expand Up @@ -195,10 +195,6 @@ internal virtual void Refresh(bool isNavigationIntercepted)

private async ValueTask<bool> RunOnNavigateAsync(string path, Task previousOnNavigate)
{
if (OnNavigateAsync == null)
{
return true;
}

// Cancel the CTS instead of disposing it, since disposing does not
// actually cancel and can cause unintended Object Disposed Exceptions.
Expand All @@ -210,6 +206,11 @@ private async ValueTask<bool> RunOnNavigateAsync(string path, Task previousOnNav
// invocation.
await previousOnNavigate;

if (OnNavigateAsync == null)
{
return true;
}

_onNavigateCts = new CancellationTokenSource();
var navigateContext = new NavigationContext(path, _onNavigateCts.Token);

Expand All @@ -227,14 +228,12 @@ private async ValueTask<bool> RunOnNavigateAsync(string path, Task previousOnNav
if (e.CancellationToken != navigateContext.CancellationToken)
{
var rethrownException = new InvalidOperationException("OnNavigateAsync can only be cancelled via NavigateContext.CancellationToken.", e);
_renderHandle.Render(builder => ExceptionDispatchInfo.Capture(rethrownException).Throw());
return false;
_renderHandle.Render(builder => ExceptionDispatchInfo.Throw(rethrownException));
}
}
catch (Exception e)
{
_renderHandle.Render(builder => ExceptionDispatchInfo.Capture(e).Throw());
return false;
_renderHandle.Render(builder => ExceptionDispatchInfo.Throw(e));
}

return false;
Expand Down
Original file line number Diff line number Diff line change
@@ -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.Threading.Tasks;
using Microsoft.JSInterop;

namespace Microsoft.AspNetCore.Components.Web.Extensions.Head
{
internal static class HeadManagementJSRuntimeExtensions
{
private const string JsFunctionsPrefix = "_blazorHeadManager";

public static ValueTask SetTitleAsync(this IJSRuntime jsRuntime, string title)
{
return jsRuntime.InvokeVoidAsync($"{JsFunctionsPrefix}.setTitle", title);
}

public static ValueTask AddOrUpdateHeadTagAsync(this IJSRuntime jsRuntime, TagElement tag, string id)
{
return jsRuntime.InvokeVoidAsync($"{JsFunctionsPrefix}.addOrUpdateHeadTag", tag, id);
}

public static ValueTask RemoveHeadTagAsync(this IJSRuntime jsRuntime, string id)
{
return jsRuntime.InvokeVoidAsync($"{JsFunctionsPrefix}.removeHeadTag", id);
}
}
}
67 changes: 67 additions & 0 deletions src/Components/Web.Extensions/src/HeadManagement/HeadTagBase.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;
using System.Collections.Generic;
using System.Text.Json;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components.Rendering;
using Microsoft.JSInterop;

namespace Microsoft.AspNetCore.Components.Web.Extensions.Head
{
/// <summary>
/// Serves as a base for components that represent tags in the HTML head.
/// </summary>
public abstract class HeadTagBase : ComponentBase, IDisposable
{
private readonly string _id = Guid.NewGuid().ToString("N");

private TagElement _tagElement;

private bool _hasRendered;

[Inject]
private IJSRuntime JSRuntime { get; set; } = default!;

/// <summary>
/// Gets or sets a collection of additional attributes that will be applied to the meta element.
/// </summary>
[Parameter(CaptureUnmatchedValues = true)]
public IReadOnlyDictionary<string, object>? Attributes { get; set; }

/// <summary>
/// Gets the name of the tag being represented.
/// </summary>
protected abstract string TagName { get; }

/// <inheritdoc />
protected override void OnParametersSet()
{
_tagElement = new TagElement(TagName, Attributes);
}

/// <inheritdoc />
protected override async Task OnAfterRenderAsync(bool firstRender)
{
_hasRendered = true;

await JSRuntime.AddOrUpdateHeadTagAsync(_tagElement, _id);
}

/// <inheritdoc />
protected override void BuildRenderTree(RenderTreeBuilder builder)
{
builder.AddMarkupContent(0, $"<!--Head:{JsonSerializer.Serialize(_tagElement, JsonSerializerOptionsProvider.Options)}-->");
}

/// <inheritdoc />
public void Dispose()
{
if (_hasRendered)
{
_ = JSRuntime.RemoveHeadTagAsync(_id);
}
}
}
}
14 changes: 14 additions & 0 deletions src/Components/Web.Extensions/src/HeadManagement/Link.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// 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.Head
{
/// <summary>
/// A component that adds a link tag to the HTML head.
/// </summary>
public sealed class Link : HeadTagBase
{
/// <inheritdoc />
protected override string TagName => "link";
}
}
14 changes: 14 additions & 0 deletions src/Components/Web.Extensions/src/HeadManagement/Meta.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// 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.Head
{
/// <summary>
/// A component that adds a meta tag to the HTML head.
/// </summary>
public sealed class Meta : HeadTagBase
{
/// <inheritdoc />
protected override string TagName => "meta";
}
}
Loading