Enhanced nav: support forceLoad
- Dominant language
- C#
- Stars
- 38.4k
- Forks
- 10.9k
- Avg merge
- 2d 6h
- Merged PRs (30d)
- 290
Description
Found by @DamianEdwards
During an enhanced nav request request (GET or POST), you can redirect using `NavigationManager.NavigateTo(url)`. However, the `forceLoad` parameter is currently completely ignored.
Currently:
* If the destination is an internal URL, the server replies with a 302, and the client-side code follows the redirection transparently then updates the URL via `history.replaceState` etc. So it is resolved as part of the enhanced nav without a full-page load, regardless of your `forceLoad` parameter.
* If the destination is an external URL, the server replies with a 200 and the header `blazor-enhanced-nav-redirect-location: ...url...`. Client-side code sees tis and does a full-page load to the target URL, regardless of your `forceLoad` parameter.
### Proposal
If you set `forceLoad: true`, then the server should use the `blazor-enhanced-nav-redirect-location` header in all cases, even for internal URLs. Then internal URLs can do a full-page reload if the developer wants/needs.
### Customer impact
Without this feature, you're stuck inside the enhanced nav system and can't break out of it, even if you know the target page needs to be loaded differently (for example because it may need to do a further redirection to an external URL).
A realistic scenario is for redirecting to internal non-Blazor endpoints, or to internal Blazor endpoints that themselves redirect to external URLs. For example, @DamianEdwards had a scenario where, during a form post, an API request may fail due to an expired token, and in that case he wanted to redirect to a `/login` page which in turn will redirect to an external ID provider.
Simply allowing the developer to use `forceLoad` to escape from the enhanced nav system avoids the limitations.
### Implementation
It should be trivial. In `EndpointHtmlRenderer.Prerendering.cs`, we have:
```cs
if (httpContext.Response.HasStarted)
{
// ... not applicable ...
}
else if (IsPossibleExternalDestination(httpContext.Request, navigationException.Location)
&& IsProgressivelyEnhancedNavigation(httpContext.Request))
{
// ... sets "blazor-enhanced-nav-redirect-location" and returns a 200
}
else
{
// ... does httpContext.Response.Redirect to issue the 302
}
```
I think we just need to amend the middle condition so it looks like:
```cs
else if ((IsPossibleExternalDestination(httpContext.Request, navigationException.Location) || navigationException.ForceLoad)
&& IsProgressivelyEnhancedNavigation(httpContext.Request))
```
Note that the `navigationException.ForceLoad` flag doesn't currently exist but would be simple to add, setting it based on the `NavigationOptions` that caused it to be thrown.
Contributor guide
Assessment
This issue has not been assessed yet.