@@ -23,7 +23,7 @@ public class Router : IComponent, IHandleAfterRender, IDisposable
23
23
static readonly ReadOnlyDictionary < string , object > _emptyParametersDictionary
24
24
= new ReadOnlyDictionary < string , object > ( new Dictionary < string , object > ( ) ) ;
25
25
26
- RenderHandle _renderHandle ;
26
+ internal RenderHandle _renderHandle { get ; set ; }
27
27
string _baseUri ;
28
28
string _locationAbsolute ;
29
29
bool _navigationInterceptionEnabled ;
@@ -35,7 +35,7 @@ static readonly ReadOnlyDictionary<string, object> _emptyParametersDictionary
35
35
36
36
private bool _onNavigateCalled = false ;
37
37
38
- [ Inject ] private NavigationManager NavigationManager { get ; set ; }
38
+ [ Inject ] internal NavigationManager NavigationManager { get ; set ; }
39
39
40
40
[ Inject ] private INavigationInterception NavigationInterception { get ; set ; }
41
41
@@ -72,7 +72,7 @@ static readonly ReadOnlyDictionary<string, object> _emptyParametersDictionary
72
72
/// </summary>
73
73
[ Parameter ] public EventCallback < NavigationContext > OnNavigateAsync { get ; set ; }
74
74
75
- private RouteTable Routes { get ; set ; }
75
+ internal RouteTable Routes { get ; set ; }
76
76
77
77
/// <inheritdoc />
78
78
public void Attach ( RenderHandle renderHandle )
@@ -109,20 +109,24 @@ public async Task SetParametersAsync(ParameterView parameters)
109
109
throw new InvalidOperationException ( $ "The { nameof ( Router ) } component requires a value for the parameter { nameof ( NotFound ) } .") ;
110
110
}
111
111
112
+ var shouldRefresh = true ;
112
113
if ( ! _onNavigateCalled )
113
114
{
114
115
_onNavigateCalled = true ;
115
- await RunOnNavigateAsync ( NavigationManager . ToBaseRelativePath ( _locationAbsolute ) ) ;
116
+ shouldRefresh = await RunOnNavigateAsync ( NavigationManager . ToBaseRelativePath ( _locationAbsolute ) ) ;
117
+ }
118
+
119
+ if ( shouldRefresh )
120
+ {
121
+ Refresh ( isNavigationIntercepted : false ) ;
116
122
}
117
123
118
- Refresh ( isNavigationIntercepted : false ) ;
119
124
}
120
125
121
126
/// <inheritdoc />
122
127
public void Dispose ( )
123
128
{
124
129
NavigationManager . LocationChanged -= OnLocationChanged ;
125
- _onNavigateCts ? . Dispose ( ) ;
126
130
}
127
131
128
132
private static string StringUntilAny ( string str , char [ ] chars )
@@ -190,28 +194,28 @@ private void Refresh(bool isNavigationIntercepted)
190
194
}
191
195
}
192
196
193
- private async Task RunOnNavigateAsync ( string path )
197
+ internal async Task < bool > RunOnNavigateAsync ( string path )
194
198
{
195
199
// If this router instance does not provide an OnNavigateAsync parameter
196
200
// then we render the component associated with the route as per usual.
197
201
if ( ! OnNavigateAsync . HasDelegate )
198
202
{
199
- return ;
203
+ return await Task . FromResult ( true ) ;
200
204
}
201
205
202
206
// If we've already invoked a task and stored its CTS, then
203
207
// cancel the existing task.
204
- _onNavigateCts ? . Dispose ( ) ;
208
+ _onNavigateCts ? . Cancel ( ) ;
205
209
206
210
// Create a new cancellation token source for this instance
207
211
_onNavigateCts = new CancellationTokenSource ( ) ;
208
212
var navigateContext = new NavigationContext ( path , _onNavigateCts . Token ) ;
209
213
210
214
// Create a cancellation task based on the cancellation token
211
215
// associated with the current running task.
212
- var cancellationTaskSource = new TaskCompletionSource ( ) ;
216
+ var cancellationTcs = new TaskCompletionSource ( TaskCreationOptions . RunContinuationsAsynchronously ) ;
213
217
navigateContext . CancellationToken . Register ( state =>
214
- ( ( TaskCompletionSource ) state ) . SetResult ( ) , cancellationTaskSource ) ;
218
+ ( ( TaskCompletionSource ) state ) . SetResult ( ) , cancellationTcs ) ;
215
219
216
220
var task = OnNavigateAsync . InvokeAsync ( navigateContext ) ;
217
221
@@ -221,16 +225,24 @@ private async Task RunOnNavigateAsync(string path)
221
225
_renderHandle . Render ( Navigating ) ;
222
226
}
223
227
224
- await Task . WhenAny ( task , cancellationTaskSource . Task ) ;
228
+ var completedTask = await Task . WhenAny ( task , cancellationTcs . Task ) ;
229
+ if ( completedTask == task )
230
+ {
231
+ return await Task . FromResult ( true ) ;
232
+ }
233
+ return await Task . FromResult ( false ) ;
225
234
}
226
235
227
236
private async Task RunOnNavigateWithRefreshAsync ( string path , bool isNavigationIntercepted )
228
237
{
229
- await RunOnNavigateAsync ( path ) ;
230
- Refresh ( isNavigationIntercepted ) ;
238
+ var shouldRefresh = await RunOnNavigateAsync ( path ) ;
239
+ if ( shouldRefresh )
240
+ {
241
+ Refresh ( isNavigationIntercepted ) ;
242
+ }
231
243
}
232
244
233
- private void OnLocationChanged ( object sender , LocationChangedEventArgs args )
245
+ internal void OnLocationChanged ( object sender , LocationChangedEventArgs args )
234
246
{
235
247
_locationAbsolute = args . Location ;
236
248
if ( _renderHandle . IsInitialized && Routes != null )
0 commit comments