-
Notifications
You must be signed in to change notification settings - Fork 10.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added additional boolean parameter "replace" to NavigationManager.NavigateTo #25752
Added additional boolean parameter "replace" to NavigationManager.NavigateTo #25752
Conversation
…igateTo So instead of pushing the new uri into the browser history, we replace the uri in the browser history
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Modified NavigateTo be source and binary compatible with previous versions See: to https://github.com/dotnet/roslyn/blob/master/docs/Adding%20Optional%20Parameters%20in%20Public%20API.md
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks again for this, @MariovanZeist!
I hope you don't mind the large collection of suggestions I'm posting here. The core point I'm suggesting is that we can and should do this without it being a breaking change to people's existing unit tests. Everyone who has existing fake/mock implementations of NavigationManager
should be able to keep their existing code working. We can achieve this by leaving the existing NavigateToCore
alone, and having the new overload act as an independent parallel code path.
I know that makes it less of a clean change, and doesn't immediately get us to a world where people implementing NavigationManager
only have a single NavigateToCore
to override. However the only people who have to override both overloads will be framework/platform authors, and that's the sort of thing platform authors can figure out just fine. Application developers only subclass NavigationManager
for unit tests, and in that case, they will only need to override the overload that their own unit test is actually using, so this will make sense.
Is it essential that, in the long term, we find some way to obsolete the (string, bool)
overload? It's not clear to me that is essential. It more seems like a nice-to-have for framework developers, but won't make much (perhaps any) difference to application developers.
src/Components/WebAssembly/WebAssembly.Authentication/test/RemoteAuthenticationServiceTests.cs
Outdated
Show resolved
Hide resolved
Thank you for submitting this for API review. This will be reviewed by @dotnet/aspnet-api-review at the next meeting of the ASP.NET Core API Review group. Please ensure you take a look at the API review process documentation and ensure that:
|
@MariovanZeist Sorry for the disruption, but we had an API review meeting in which we realised that Reasoning: a flags enum is sufficient for current use cases, extensible in the future if we end up with more flags, avoids the problems of both Hope this is OK! |
!!!IMPORTANT!!!! I have also added a pragma to disable a warning which should NOT be disabled. It's only added to get it reviewed and fixed. #pragma warning disable RS0027 // Public API with optional parameter(s) should have the most parameters amongst its public overloads. Is added to the NavigationManager Before merging this should be addressed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Applied remarks.
This makes the PR a lot cleaner and with fewer changes.
Making the NavigationOptions an Enum instead of a class is a better solution, especially as these are all just flags.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@SteveSandersonMS Thanks for the review. I have implemented your suggestions.
There is 1 issue that we need to resolve before we merge. That is the pragma I added.
Review comment is added to source code.
src/Components/WebAssembly/WebAssembly/src/Services/WebAssemblyNavigationManager.cs
Outdated
Show resolved
Hide resolved
This is great, @MariovanZeist. Thanks very much! I agree the current state of this PR is very good. It's a nice clean simple change. The only thing missing before we can merge is test coverage. If you wanted, you could add unit test coverage for each of the More importantly though, we need coverage in the E2E tests to show that the new APIs actually do what they claim to do in real browsers. In
Is this possible? Thanks again! |
The forceLoad flag would be ignored if not loading the same Uri
@SteveSandersonMS Besides the above-mentioned tests, I added a 3rd. ( |
|
if (forceLoad) { | ||
location.replace(uri); | ||
} else { | ||
history.replaceState(null, '', absoluteUri) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This logic looks wrong to me. What happens if isWithinBaseUriSpace(absoluteUri)
is false, force
is false, and replace
is true?
What I'd expect is: since this is an external navigation, the force param is irrelevant, and the replace
flag means we should be calling location.replace
.
What the logic appears to do is call history.replaceState
, which won't produce a useful behavior because it's only doing HTML5-style client-side navigation and won't trigger an actual external page load.
Here's the full truth table I'd expect (ignoring the Force-loading the same URL you're already on special case):
isWithinBaseUriSpace(absoluteUri) | Force | Replace | Expected behavior |
---|---|---|---|
false | false | false | location.href = url (append external page load to history) |
false | false | true | location.replace (replace with external page load on history) |
false | true | false | location.href = url (append external page load to history) |
false | true | true | location.replace (replace with external page load on history) |
true | false | false | performInternalNavigation(absoluteUri, false, false) (calls history.pushState ) |
true | false | true | performInternalNavigation(absoluteUri, false, true) (calls history.replaceState ) |
true | true | false | location.href = url (append external page load to history) |
true | true | true | location.replace (replace with external page load on history) |
Do you agree with this list? Could you check how it corresponds to the implementation? I think the only combination that's currently wrong is the one I mentioned at the top of this comment.
I suspect that before this PR, the logic here was already wrong in that it didn't handle replace
without also force
. That was OK before because it wasn't really proper public API. But since this is becoming proper public API now, we should make sure all the combinations of parameters work correctly.
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@MariovanZeist This looks really good to me. Thanks for submitting it! I think there's just one more implementation issue to resolve and then we should be ready to merge this. |
Hi MariovanZeist. |
Continuing this work at #33751 |
Added optional boolean "replace" to Navigationmanager.NavigateTo
setting boolean to true will replace the uri in the browser history, instead of the default action that pushes the new uri onto the browsers history stack.
The core navigation infrastructure already has a functional "replace" parameter, but this parameter was not publicly exposed.
Addresses #25540
API review notes
This section is by @SteveSandersonMS and refers to the outcome I'm proposing with my suggestions below, rather than the current implementation.
The proposal is to add the following APIs in
Microsoft.AspNetCore.Components
, also showing selected existing APIs for context:The main compromise in this design is around back-compatibility. I'm proposing we prioritise keeping people's existing unit test code working. If we didn't have to do that, we'd outright replace the existing
NavigateToCore
method with the new one, or at least obsolete the older one. However I don't see a way to obsolete the older one, sinceNavigateTo(string, bool)
has to continue calling it, otherwise that will break anyone who has an existing mock or fake of NavigationManager.I think the end result of this compromise is totally fine, in that for application developers, there's no drawback at all. The only people who have an extra method to overload is us (or other platform authors).