-
Notifications
You must be signed in to change notification settings - Fork 9.8k
/
WebAssemblyNavigationManager.cs
104 lines (85 loc) · 3.86 KB
/
WebAssemblyNavigationManager.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System.Diagnostics.CodeAnalysis;
using Microsoft.AspNetCore.Components.Routing;
using Microsoft.Extensions.Logging;
using Microsoft.JSInterop;
using Interop = Microsoft.AspNetCore.Components.Web.BrowserNavigationManagerInterop;
namespace Microsoft.AspNetCore.Components.WebAssembly.Services;
/// <summary>
/// Default client-side implementation of <see cref="NavigationManager"/>.
/// </summary>
internal sealed partial class WebAssemblyNavigationManager : NavigationManager
{
private ILogger<WebAssemblyNavigationManager> _logger = default!;
/// <summary>
/// Gets the instance of <see cref="WebAssemblyNavigationManager"/>.
/// </summary>
public static WebAssemblyNavigationManager Instance { get; set; } = default!;
public WebAssemblyNavigationManager(string baseUri, string uri)
{
Initialize(baseUri, uri);
}
public void CreateLogger(ILoggerFactory loggerFactory)
{
if (_logger is not null)
{
throw new InvalidOperationException($"The {nameof(WebAssemblyNavigationManager)} has already created a logger.");
}
_logger = loggerFactory.CreateLogger<WebAssemblyNavigationManager>();
}
public void SetLocation(string uri, string? state, bool isInterceptedLink)
{
Uri = uri;
HistoryEntryState = state;
NotifyLocationChanged(isInterceptedLink);
}
public async ValueTask<bool> HandleLocationChangingAsync(string uri, string? state, bool intercepted)
{
return await NotifyLocationChangingAsync(uri, state, intercepted);
}
/// <inheritdoc />
[DynamicDependency(DynamicallyAccessedMemberTypes.PublicProperties, typeof(NavigationOptions))]
protected override void NavigateToCore(string uri, NavigationOptions options)
{
ArgumentNullException.ThrowIfNull(uri);
_ = PerformNavigationAsync();
async Task PerformNavigationAsync()
{
try
{
var shouldContinueNavigation = await NotifyLocationChangingAsync(uri, options.HistoryEntryState, false);
if (!shouldContinueNavigation)
{
Log.NavigationCanceled(_logger, uri);
return;
}
DefaultWebAssemblyJSRuntime.Instance.InvokeVoid(Interop.NavigateTo, uri, options);
}
catch (Exception ex)
{
// We shouldn't ever reach this since exceptions thrown from handlers are handled in HandleLocationChangingHandlerException.
// But if some other exception gets thrown, we still want to know about it.
Log.NavigationFailed(_logger, uri, ex);
}
}
}
/// <inheritdoc />
public override void Refresh(bool forceReload = false)
{
DefaultWebAssemblyJSRuntime.Instance.InvokeVoid(Interop.Refresh, forceReload);
}
protected override void HandleLocationChangingHandlerException(Exception ex, LocationChangingContext context)
{
Log.NavigationFailed(_logger, context.TargetLocation, ex);
}
protected override void SetNavigationLockState(bool value)
=> InternalJSImportMethods.Instance.NavigationManager_SetHasLocationChangingListeners((int)WebRendererId.WebAssembly, value);
private static partial class Log
{
[LoggerMessage(1, LogLevel.Debug, "Navigation canceled when changing the location to {Uri}", EventName = "NavigationCanceled")]
public static partial void NavigationCanceled(ILogger logger, string uri);
[LoggerMessage(2, LogLevel.Error, "Navigation failed when changing the location to {Uri}", EventName = "NavigationFailed")]
public static partial void NavigationFailed(ILogger logger, string uri, Exception exception);
}
}