dotnet / dotnet/aspnetcore

Enhanced nav: support forceLoad

Open
#53,605 3 comments 5 reactions 0 assignees View on GitHub
area-blazor
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

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.