Skip to content

Commit 9b888e9

Browse files
authored
Blazor API Review: IUriHelper (#12425)
* Rename IUriHelper -> NavigationManager - Remove IUriHelper interface - Rename to NavigationManager - Remove all traces of old naming There's no functional or design change in this commit - just removing all traces of the old name. The next few iterations will try to improve the design. * Minor API tweaks to NavigationManager Making Initialize protected causes problems because right now the server-side code needs to deal with one of two different implementations, hence an exchange type is used. I followed the same pattern that was used for auth for symmetry but I have some *cool* thoughts. - We can remove this when we remove stateful prerendering - I have another idea to banish this pattern to the land of wind and ghosts If this ends up sticking around longer than a week in the code, lets discuss other ideas and try to improve the pattern. * Use hub method for server-side navigation * Get rid of async local * Add hub method test * Misc bikeshedding * Update src/Components/Server/src/Circuits/DefaultCircuitFactory.cs Co-Authored-By: campersau <buchholz.bastian@googlemail.com> * PR feedback
1 parent 59f6b85 commit 9b888e9

File tree

51 files changed

+717
-623
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+717
-623
lines changed

src/Components/Blazor/Blazor/ref/Microsoft.AspNetCore.Blazor.netstandard2.0.cs

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
11
// Copyright (c) .NET Foundation. All rights reserved.
22
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33

4+
namespace Microsoft.AspNetCore.Blazor
5+
{
6+
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
7+
public static partial class JSInteropMethods
8+
{
9+
[Microsoft.JSInterop.JSInvokableAttribute("NotifyLocationChanged")]
10+
public static void NotifyLocationChanged(string uri, bool isInterceptedLink) { }
11+
}
12+
}
413
namespace Microsoft.AspNetCore.Blazor.Hosting
514
{
615
public static partial class BlazorWebAssemblyHost
@@ -68,18 +77,6 @@ protected override void HandleException(System.Exception exception) { }
6877
protected override System.Threading.Tasks.Task UpdateDisplayAsync(in Microsoft.AspNetCore.Components.Rendering.RenderBatch batch) { throw null; }
6978
}
7079
}
71-
namespace Microsoft.AspNetCore.Blazor.Services
72-
{
73-
public partial class WebAssemblyUriHelper : Microsoft.AspNetCore.Components.UriHelperBase
74-
{
75-
internal WebAssemblyUriHelper() { }
76-
public static readonly Microsoft.AspNetCore.Blazor.Services.WebAssemblyUriHelper Instance;
77-
protected override void EnsureInitialized() { }
78-
protected override void NavigateToCore(string uri, bool forceLoad) { }
79-
[Microsoft.JSInterop.JSInvokableAttribute("NotifyLocationChanged")]
80-
public static void NotifyLocationChanged(string newAbsoluteUri, bool isInterceptedLink) { }
81-
}
82-
}
8380
namespace Microsoft.AspNetCore.Components.Builder
8481
{
8582
public static partial class ComponentsApplicationBuilderExtensions

src/Components/Blazor/Blazor/src/Hosting/WebAssemblyHostBuilder.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,16 +92,16 @@ private void CreateServiceProvider()
9292
services.AddSingleton<IWebAssemblyHost, WebAssemblyHost>();
9393
services.AddSingleton<IJSRuntime>(WebAssemblyJSRuntime.Instance);
9494
services.AddSingleton<IComponentContext, WebAssemblyComponentContext>();
95-
services.AddSingleton<IUriHelper>(WebAssemblyUriHelper.Instance);
95+
services.AddSingleton<NavigationManager>(WebAssemblyNavigationManager.Instance);
9696
services.AddSingleton<INavigationInterception>(WebAssemblyNavigationInterception.Instance);
9797
services.AddSingleton<ILoggerFactory, WebAssemblyLoggerFactory>();
9898
services.AddSingleton<HttpClient>(s =>
9999
{
100100
// Creating the URI helper needs to wait until the JS Runtime is initialized, so defer it.
101-
var uriHelper = s.GetRequiredService<IUriHelper>();
101+
var navigationManager = s.GetRequiredService<NavigationManager>();
102102
return new HttpClient
103103
{
104-
BaseAddress = new Uri(WebAssemblyUriHelper.Instance.GetBaseUri())
104+
BaseAddress = new Uri(navigationManager.BaseUri)
105105
};
106106
});
107107

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
using System.ComponentModel;
5+
using Microsoft.AspNetCore.Blazor.Services;
6+
using Microsoft.JSInterop;
7+
8+
namespace Microsoft.AspNetCore.Blazor
9+
{
10+
/// <summary>
11+
/// Contains methods called by interop. Intended for framework use only, not supported for use in application
12+
/// code.
13+
/// </summary>
14+
[EditorBrowsable(EditorBrowsableState.Never)]
15+
public static class JSInteropMethods
16+
{
17+
/// <summary>
18+
/// For framework use only.
19+
/// </summary>
20+
[JSInvokable(nameof(NotifyLocationChanged))]
21+
public static void NotifyLocationChanged(string uri, bool isInterceptedLink)
22+
{
23+
WebAssemblyNavigationManager.Instance.SetLocation(uri, isInterceptedLink);
24+
}
25+
}
26+
}

src/Components/Blazor/Blazor/src/Services/WebAssemblyNavigationInterception.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
using System.Threading.Tasks;
55
using Microsoft.AspNetCore.Components.Routing;
6-
using Interop = Microsoft.AspNetCore.Components.Web.BrowserUriHelperInterop;
6+
using Interop = Microsoft.AspNetCore.Components.Web.BrowserNavigationManagerInterop;
77

88
namespace Microsoft.AspNetCore.Blazor.Services
99
{
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
using System;
5+
using Microsoft.AspNetCore.Components;
6+
using Interop = Microsoft.AspNetCore.Components.Web.BrowserNavigationManagerInterop;
7+
8+
namespace Microsoft.AspNetCore.Blazor.Services
9+
{
10+
/// <summary>
11+
/// Default client-side implementation of <see cref="NavigationManager"/>.
12+
/// </summary>
13+
internal class WebAssemblyNavigationManager : NavigationManager
14+
{
15+
/// <summary>
16+
/// Gets the instance of <see cref="WebAssemblyNavigationManager"/>.
17+
/// </summary>
18+
public static readonly WebAssemblyNavigationManager Instance = new WebAssemblyNavigationManager();
19+
20+
// For simplicity we force public consumption of the BrowserNavigationManager through
21+
// a singleton. Only a single instance can be updated by the browser through
22+
// interop. We can construct instances for testing.
23+
internal WebAssemblyNavigationManager()
24+
{
25+
}
26+
27+
protected override void EnsureInitialized()
28+
{
29+
// As described in the comment block above, BrowserNavigationManager is only for
30+
// client-side (Mono) use, so it's OK to rely on synchronicity here.
31+
var baseUri = WebAssemblyJSRuntime.Instance.Invoke<string>(Interop.GetBaseUri);
32+
var uri = WebAssemblyJSRuntime.Instance.Invoke<string>(Interop.GetLocationHref);
33+
Initialize(baseUri, uri);
34+
}
35+
36+
public void SetLocation(string uri, bool isInterceptedLink)
37+
{
38+
Uri = uri;
39+
NotifyLocationChanged(isInterceptedLink);
40+
}
41+
42+
/// <inheritdoc />
43+
protected override void NavigateToCore(string uri, bool forceLoad)
44+
{
45+
if (uri == null)
46+
{
47+
throw new ArgumentNullException(nameof(uri));
48+
}
49+
50+
WebAssemblyJSRuntime.Instance.Invoke<object>(Interop.NavigateTo, uri, forceLoad);
51+
}
52+
}
53+
}

src/Components/Blazor/Blazor/src/Services/WebAssemblyUriHelper.cs

Lines changed: 0 additions & 85 deletions
This file was deleted.

src/Components/Components/ref/Microsoft.AspNetCore.Components.netstandard2.0.cs

Lines changed: 20 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -266,16 +266,6 @@ public sealed partial class InjectAttribute : System.Attribute
266266
{
267267
public InjectAttribute() { }
268268
}
269-
public partial interface IUriHelper
270-
{
271-
event System.EventHandler<Microsoft.AspNetCore.Components.Routing.LocationChangedEventArgs> OnLocationChanged;
272-
string GetAbsoluteUri();
273-
string GetBaseUri();
274-
void NavigateTo(string uri);
275-
void NavigateTo(string uri, bool forceLoad);
276-
System.Uri ToAbsoluteUri(string href);
277-
string ToBaseRelativePath(string baseUri, string locationAbsolute);
278-
}
279269
[System.AttributeUsageAttribute(System.AttributeTargets.Class, AllowMultiple=false, Inherited=true)]
280270
public sealed partial class LayoutAttribute : System.Attribute
281271
{
@@ -302,6 +292,20 @@ public partial class NavigationException : System.Exception
302292
public NavigationException(string uri) { }
303293
public string Location { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } }
304294
}
295+
public abstract partial class NavigationManager
296+
{
297+
protected NavigationManager() { }
298+
public string BaseUri { get { throw null; } protected set { } }
299+
public string Uri { get { throw null; } protected set { } }
300+
public event System.EventHandler<Microsoft.AspNetCore.Components.Routing.LocationChangedEventArgs> LocationChanged { add { } remove { } }
301+
protected virtual void EnsureInitialized() { }
302+
protected void Initialize(string baseUri, string uri) { }
303+
public void NavigateTo(string uri, bool forceLoad = false) { }
304+
protected abstract void NavigateToCore(string uri, bool forceLoad);
305+
protected void NotifyLocationChanged(bool isInterceptedLink) { }
306+
public System.Uri ToAbsoluteUri(string relativeUri) { throw null; }
307+
public string ToBaseRelativePath(string uri) { throw null; }
308+
}
305309
public abstract partial class OwningComponentBase : Microsoft.AspNetCore.Components.ComponentBase, System.IDisposable
306310
{
307311
protected OwningComponentBase() { }
@@ -383,23 +387,6 @@ public sealed partial class RouteAttribute : System.Attribute
383387
public RouteAttribute(string template) { }
384388
public string Template { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } }
385389
}
386-
public abstract partial class UriHelperBase : Microsoft.AspNetCore.Components.IUriHelper
387-
{
388-
protected UriHelperBase() { }
389-
public event System.EventHandler<Microsoft.AspNetCore.Components.Routing.LocationChangedEventArgs> OnLocationChanged { add { } remove { } }
390-
protected virtual void EnsureInitialized() { }
391-
public string GetAbsoluteUri() { throw null; }
392-
public virtual string GetBaseUri() { throw null; }
393-
public virtual void InitializeState(string uriAbsolute, string baseUriAbsolute) { }
394-
public void NavigateTo(string uri) { }
395-
public void NavigateTo(string uri, bool forceLoad) { }
396-
protected abstract void NavigateToCore(string uri, bool forceLoad);
397-
protected void SetAbsoluteBaseUri(string baseUri) { }
398-
protected void SetAbsoluteUri(string uri) { }
399-
public System.Uri ToAbsoluteUri(string href) { throw null; }
400-
public string ToBaseRelativePath(string baseUri, string locationAbsolute) { throw null; }
401-
protected void TriggerOnLocationChanged(bool isinterceptedLink) { }
402-
}
403390
}
404391
namespace Microsoft.AspNetCore.Components.CompilerServices
405392
{
@@ -637,16 +624,17 @@ public enum RenderTreeFrameType : short
637624
}
638625
namespace Microsoft.AspNetCore.Components.Routing
639626
{
627+
public partial interface IHostEnvironmentNavigationManager
628+
{
629+
void Initialize(string baseUri, string uri);
630+
}
640631
public partial interface INavigationInterception
641632
{
642633
System.Threading.Tasks.Task EnableNavigationInterceptionAsync();
643634
}
644-
[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
645-
public readonly partial struct LocationChangedEventArgs
635+
public partial class LocationChangedEventArgs : System.EventArgs
646636
{
647-
private readonly object _dummy;
648-
private readonly int _dummyPrimitive;
649-
public LocationChangedEventArgs(string location, bool isNavigationIntercepted) { throw null; }
637+
public LocationChangedEventArgs(string location, bool isNavigationIntercepted) { }
650638
public bool IsNavigationIntercepted { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } }
651639
public string Location { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } }
652640
}

src/Components/Components/src/IUriHelper.cs

Lines changed: 0 additions & 64 deletions
This file was deleted.

src/Components/Components/src/NavigationException.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
namespace Microsoft.AspNetCore.Components
77
{
88
/// <summary>
9-
/// Exception thrown when an <see cref="IUriHelper"/> is not able to navigate to a different url.
9+
/// Exception thrown when an <see cref="NavigationManager"/> is not able to navigate to a different url.
1010
/// </summary>
1111
public class NavigationException : Exception
1212
{

0 commit comments

Comments
 (0)