Can't Navigate Back to Xamaran Shell Page After First Visit - xamarin

I must not understand the concept correctly and I am doing something - though I don't get what.
I have a page ("page2") that is on the Shell/Flyout. Once on this page, for any number of reason (when it first loads, on an action, etc.) the user is redirected to "page3" that uses Shell.Current.GoToAsync("page3?id=xxxx") to go to a page that is in the global routes. That works.
If I try to go back to "page2" - using await Shell.Current.GoToAsync("///page2") "page3" gets displayed. I cannot step into anything - no OnDisappearing, OnAppearing, ctor,
What am I missing here?

I am not sure if you're looking for a way to go back one page but if you are the easiest way to do so is like:
Shell.Current.Navigation.PopAsync();

Related

Wicket (1.6) stateless form resets paging

I've already tried to find anything about that problem but I guess I either was not sure how to shortly describe the problem to find a solution or nobody else had that before which I can't think of. Maybe my thinking is wrong, too.
I have a stateless wicket 1.6 form with an ajax supporting panel (WebMarkupContainer with output id). The panel holds a dataview with paging navigator. The dataview itself is filled by a DataProvider.
The panel shows some entries from the database and below that is the navigator. by clicking any page on the navigator, the panel is refreshed (ajax) and shows content from that page. The page itself is not re-rendered by the browser.
When I now leave the page by navigating to another internal page (so basically when leaving the dataview-panel-page in any way) to open a detail page or so and then return to that dataview-page the navigator is resetted (because it's stateless I guess). The navigator can't remember which page to show and begins at the top of the first page again.
The question is: How can I solve this? I would like to i.ex. navigate to page 2 and then temporary leave the page for another internal page. When returning I want to be on page 2, focussed on the record where I clicked the link to "details" before. This also happens when I just open a new page in a new Browser tab.
Thank you!
Here's some code:
final WebMarkupContainer gamesPanel = new AjaxContainer("gamesPanel");
final DataView<Game> dataView =
new GameDataView("gameOverview", targetCurrencyModel, searchTextModel, gameFilterModel,
new GameDataProvider(searchTextModel, gameFilterModel, targetCurrencyModel));
dataView.setItemsPerPage(ITEMS_PER_PAGE);
gamesPanel.add(dataView);
final XNPagingNavigator navigator = new XNPagingNavigator("navigator", dataView);
navigator.setOutputMarkupId(true);
add(navigator);
You guys can try what I mean: The page I'm talking about is http://www.xbox-now.de. Just navigate to page 2, then click on details and return to main page.
I think you might use History API to push a new state when you click on navigation bar. In the new URL for the state you can include a parameter that indicates the index of the current navigator page.
You can customize your AJAX link in order to perform this operations when user click on it.
For more details on History API see Updating address bar with new URL without hash or reloading the page
I solved this in the NoWicket framework by introducing a model aware page cache which reuses page instances when hashcode/equals matches in the page model. You can see the implementation in the GitHub repo, try this implementation of the IPageFactory wrapper as a starting point, but it is more code involved there, just check out the code, debug the example and navigate the code to understand it better in order to apply it to your application. See your use case in action by trying this data table example in the documentation website (which you can also debug locally): http://invesdwin.de/nowicket/ajaxdatatable
Try changing the paging index, navigate to a different page and navigate back to the data table example page. You will still see the paging index that you left there.
Thank you guys for your replies. I've done it now another way. Used the base code from here and modified it in some ways. Added some nice css AttributeModifiers to indicate the actual page:
item.add(new AttributeModifier("class", new PageLinkCssModel(pageable, pageIndex, "active")));
Then I modified some code to add or reset the page parameter, that it's 1) used only once and 2) keeps all the actual page parameters which were there before adding own ones. So I am just appending the page number now. This way I can keep my initially mount path like www.foo.bar/path/path/path. Complete URL would now look like: www.foo.bar/path/path?page=123.
To pass my entered page (i.e. page=5) to the data provider I just had to override the providers iterator. It should start with the page I entered. Due to the ugly generated navigator URLs (which are extremly bad for SEO) I now have nice looking urls which are working independently what wasn't possible before. And that's also the reason why I could not get back to the correct page. The navigator URL was not lookup-able by wicket.
new DataView<GamePrice>("gamePriceOverview", new GameDetailDataProvider(gameId, targetRegion) {
#Override
public Iterator<GamePrice> iterator(final long first, final long count) {
return super.iterator(ITEMS_PER_PAGE * getCurrentPage(), count);
}
getCurrentPage() comes from the base template and gets the actual page number entered (if one is entered):
public long getCurrentPage() {
// -1 weil zero based
return getRequest().getQueryParameters().getParameterValue("page").toString() != null
? (getRequest().getQueryParameters().getParameterValue("page").toLong() - 1)
: 0;
}
So instead of having ugly SEO-unfriendly URLs which are also not compatible to work independant (directly enter the generated url) I now have the same URL I expect with an added page-parameter.
URL now would looks like:
http://localhost:8080/game/4249/de/doom-preorder?page=2
URL before was:
localhost:8080/game/4249/DE/doom-preorder?0-1.ILinkListener-gamePrices-navigator-navigation-2-pageLink
If I now go back from the detail page to the main index with active "Bookmarkable-Navigator", I correctly come back to the page and position where I left it (because of bookmarkable page links).
That's how I achieved this problem with a nice bonus: User- and SEO-friendly URLs.

How does capybara/selenium grab current URL? Issue with single page site

I am using ruby and capybara(which leverages selenium) to automate walking through a website. After navigating to a new page I verify that the new page URL is what i'm expecting. My issue comes when I walk through an order funnel that is a single page but loads different views.
Some code...
I create my session instance then have additional code opening the browser and walking to a certain point in the website that I wont include
$session = Capybara::Session.new(:selenium)
My line for checking the browser URL without search params ie: everything after '?'
if url == $session.current_url.to_s.split("?")[0]
urlCorrect = true
end
This code works fine when my URL is
https://www.homepage.com
Then I click on a link that takes me to my order funnel ... https://www.homepage.com/order#/orderpage1?option1=something&option2=somethingelse
My function still matches the expected URL. But the issue comes when I move to the second page of the order funnel :
https://www.homepage.com/order#/orderpage2?option1=something&option2=somethingelse
My capybara code to get current url still returns the URL from orderpage1. Im guessing its because there is no postback when moving from orderpage1 to orderpage2 but i dont know how to force a postback or tell capybara to re-grab the url
Any advice will be appreciated.
Thanks
Quick Edit: I forgot to mention this behavior is only in IE. Chrome and Firefox both work correctly with the exact same code
Capybara grabs the current_url by querying the browser - it doesn't cache it. The issue you're probably running into is that clicking the link to move to the next page doesn't wait for the page change to happen, so if you call current_url before the page load has happened you'll still get the original url. There are two solutions for that - 1. use capybara to look for content that doesn't appear until the new page is loaded ( have_content ), 2. use the has_current_path? method which will wait/retry for a period of time until the current_path/url match
$session.has_current_path?('expected path')
There are options if you want to match against the full url, and you can use a regex to match as well - http://www.rubydoc.info/gems/capybara/Capybara/SessionMatchers#has_current_path%3F-instance_method
Thanks to Tom Walpole for finding the bug report for this issue. This link sums up the root of the issue and provides a few workarounds if anyone else is encountering this issue.
https://github.com/angular/protractor/issues/132

Wicket Page cahing in DefaultPageStore

Recently I've overridden Wicket's DefaultPageStore methods serializePage and deserializePage and enhanced them with logging to track time spent in them.
I discovered that deserializePage is never called because the actual page is always retrieved from the SessionEntry#sessionCache.
I suspect this is due to my page setting setVersionPagesByDefault(false) which creates the situation where there is only current version of a page which is serialized in the SessionEntry and then (needlessly) in the DefaultPageStore from where it's never deserialized.
If this suspicion is correct, I'm then able to make method serializePage a no-op a and skip serialization, which currently takes 3 or 7 seconds (DeflatedJavaSerializer) for page X.
I did not detect any side-effects so far, so my question is: is this safe? And if not, then why?
I'm considering this only as temporary solution until I'm able to move the data from the page to proper cache.
Here is some info on page versioning: http://wicket.apache.org/guide/guide/versioningCaching.html
If you do not need support for back button, you can disable page versioning - it has not side effects, assuming that your pages handle back button correctly. Jumping back to the page that has no state can create page without initial parameters. Like for example: you jump from page A to B and provide some arguments to B. Now user is on page C and clicks back button. This will result in redirect to page B, but no arguments will be passed this time. If you would use page versioning, wicket would only deserialize page B and execute rendering again.
Here is also one possibility to disable page store:
http://maciej-miklas.blogspot.de/2013/09/wicket-6-disable-page-serialization.html

Problem showing a messaje to the user using ASP MVC TempData

I'm using TempData to show a message to the user. I put a string in the TempData and later I read the string, and if it is not empty, then I show a DIV that contain the message.
All works fine, and if the user refresh the page the message are not shown (Thats what I want). The problem is that if the user navigate to other page and then press the back button in the browser, then the message are shown again, and I do not want this.
What could I do to avoid this behaviour?
Thanks.
This is the code I use to read the TempData (Razor + VB). There is a DIV #commonMessage, with this code I put the string inside the div and show it. As I said before, it's working, but the only problem is that the TempData is still there if the user click back in the browser.
#If Not IsNothing(TempData("MessageUser")) AndAlso TempData("MessageUser") <> String.Empty Then
Dim str As String = TempData("MessageUser")
#<script type="text/javascript">
$(document).ready(function () {
$('#commonMessage').html("#str");
$('#commonMessage').delay(400).slideDown(400).delay(4000).slideUp(400);
})
</script>
End If
EDIT: Seems like the TempData are being catched, because if I Disable the cache for the action where I'm showing the message (Using the Attribute System.Web.Mvc.OutputCache(NoStore:=True, Duration:=0, VaryByParam:="*")) the problem dissapears. But It would be better I we could find a method that not involve disabling the cache...
REQUESTED EDIT: I'm very newby in ASP, so I try to clarify what i'm triying to do. When an user performs an action (edit a client, for example), I redirect the client to the client list page, and I show a message that tell to the user "The client data was update susessfully". I'm triying to do it in a way that makes the message to be show only once. Maybe the TempData is not the right way (I don't know, 'cos i'm learning yet), but the target is to show a message to an user only once (no matter if the urser refresh or if the user go to other page and then press back in the browser)... using TempData or using something more adequate to our purpose.
Essentially, you are wanting TempData to do what you want, rather than using the right tool for what you want.
TempData is, by design, intended to be used for caching data across HTTP redirections. That is what it exists for. It is not clear from your post if this is the scenario that you are using.
Ie:
Page redirection, with data in TempData, that is then displayed to the user. Refresh the page you have arrived on, and the TempData is no longer there (there has been no redirection, just a refresh).
If the user then navigates to another page, then uses the back button, the browser will have cached the html of your page and will redisplay that. That is the correct behaviour.
I also think that in your testing, you are getting it wrong. Ie, by disabling the caching, you are just knocking out TempData altogether and you will not get the correct behaviour. Ie, the message will NEVER appear, not just when you hit the back button.
Your jQuery looks inefficient. You are making it do things it doesn't need to do. You could use razor to populate your div with your message. Set the div to not display, ie:
<div id="commonMessage" style="display:none;">
Then use jQuery to show it:
$('#commonMessage').show();
Your post isn't that clear, but in summary, I would say you are seeing what you should.
Maybe you should describe, in an Edit, what you want your app to do. That way it would be easier to answer. As things stand, you have told us what happens and what you put in your view, but it is not clear what you expect.
You should also understand TempData better: it only persists between Controller actions, ie, when a redirect occurs. It stores its data in the Session store, which I believe is affected by the caching attribute you mention.

Transfer Full Control (Navigation)

My question was little diff.
From MainPage.xaml, I am using 'NavigationService.Navigate(new Uri("/Page1.xaml", UriKind.Relative));'. It does not goes to Page1.xaml immediately. It just creates an Now the control does not completely goes to Page1.xaml. It again starts execution what is written on the next line to NavigationService.Navigate(new Uri("/Page1.xaml", UriKind.Relative)).
I have to transfer full control towards Page1.xaml, when I return from Page1 then it must resume the remaining execution of MainPage.xaml.
Plz Help.
Navigating to another page is not a synchronous process where you call the page and wait for a return result.
When you pass control to another page, it is effectively something that you fire off and forget.
Any subsequent processing you want to do when you get control back in the original page should be handled in one of the corresponding events/overrides for that page - Loaded, OnNavigatedTo for example.
So when the user navigates back from Page1, you want to do something on MainPage? Override OnNavigatedTo in MainPage and handle the navigation that way. I don't think there's a really elegant way to determining that the navigation was due to a "backward" navigation - you may need to use PhoneApplicationService.Current.State to work that out.
Note that this due to tombstoning etc, this could be a different instance of MainPage from the original one.
Either way, you won't be able to just continue from where you left off within a method. You need to think in a more event-based way.

Resources