Silverlight Navigation and Authentication service - authentication

I am creating a silver light application using Navigation app template. It is for internal use and hence uses windows authenticatoin. There is a dashboard page which shows couple of records filtered by logged in users id. To get the user id (which is an int) I call a web service by overriding the GetAuthenticatedUser and pass the username (from IPrincipal). This service takes some time to return the details.
When I navigate to dashboard app, it renders completely with no data because the user service is a async operation and I am not able to make the rendering wait till my GetAuthenticatedUser finishes completely. So I created a Login page which just shows a progress bar till I get the user object and then navigate to dashboard. If someone tries to access the dashboard directly by using the URL, i want them to navigate back to Login page.
So in the dashboard constructor I added the following code
if (!UserService.Current.User.IsAuthenticated)
{
MessageBox.Show("Navigating away");
Frame objContainer = this.Parent as Frame;
objContainer.Navigate(new Uri("/Views/Login.xaml", UriKind.Relative));
}
Thogh I get the message box prompt, it does not actually take me to Login page but stays in dashboard page. I also tried putting this code in OnNavigatedTo override with no luck.
I also tried using NavigationService instead of Frame as below, with no luck
if (!UserService.Current.User.IsAuthenticated)
{
MessageBox.Show("Navigating away");
this.NavigationService.Navigate(new Uri("/Views/Login.xaml", UriKind.Relative));
}
it still does not work. Does anyone know how to make some page accessible only if I have fully valid user object? if they try to access the restricted page without this, I want them to be able to redirected to Login page, how can this be achieved?
I am using Silverlight 3 Beta
Shreedhar

I finally found a way around this. In the Constructo i Hooked up the Loaded event handler and in the event handler I am navigating to a different page and it works fine now.
public Dashboard()
{
InitializeComponent();
this.Loaded += new RoutedEventHandler(Dashboard_Loaded);
}
void Dashboard_Loaded(object sender, RoutedEventArgs e)
{
if (!UserService.Current.User.IsAuthenticated)
{
Frame objContainer = this.Parent as Frame;
if (objContainer != null)
{
objContainer.Navigate(new Uri("/Views/Login.xaml", UriKind.Relative));
}
}
}
This piece of code works just fine!
Shreedhar

Related

WP8.1 Silverlight - BackNavigation maintains the old NavigationEventArgs for OnNavigatedTo function

I am working on a Windows Phone 8.1 Silverlight app. In this app I have a launch string attached to the toast notification which helps in navigating to the MainPage with some parameters for e.g /MainPage.xaml?data=test
So when I click this notification, I am able to get this data value from NavigationEventArgs of OnNavigatedTo function of MainPage. Based on some logic associated with data I navigate to a new Test.xaml screen.
The problem is when I GoBack from this Test.xaml screen to MainPage.xaml, the old OnNavigatedTo NavigationEventArgs remains the same, i.e the Uri in NavigationEventArgs is being preserved.
Is there a way to delete the NavigationEventArgs once done and dealt with?
Please check the NavigationMode inside the OnNavigatedTo method on your main page for example if you will come back form test.xaml page e.NavigationMode==NavigationMode.Back will call and you can code there.
protected override void OnNavigatedTo ( NavigationEventArgs e )
{
if ( e.NavigationMode==NavigationMode.New )
{
//do somthing
}
if ( e.NavigationMode==NavigationMode.Back )
{
//do somthing
}
}
}

How to implement correct Back behaviour when using Frame.Navigate?

I have a Windows 10 Universal Windows Platform app with multiple pages, a main page, a list page and a details page and use the following to navigate to List page:
this.Frame.Navigate(typeof(ListPage), parameter);
When you are on the list page you can select an item which will launch a details page like so:
this.Frame.Navigate(typeof(DetailsPage), parameter);
Which works fine, the parameter is a selected Id or information then when using the Back button which on a Desktop app or Phone uses:
this.Frame.GoBack();
This always returns to the MainPage, that is when go from Main, to List to Details hitting back goes to Main, how do I get the GoBack to Go back to the previous page, it always seems to go home rather than the user expected behaviour, an ideas how to resolve this?
I’ve seen this before when you subscribe to the HardwareButtons.BackPressed event (or whatever the equivalent is in a Win10 UWP app) on a page, but then don’t unsubscribe from it. This means two event handlers get called when pressing Back, and both event handlers call Frame.GoBack().
I always subscribe to the event in the page’s NavigatedTo event, and unsubscribe in the NavigatedFrom event.
Could this be happening with your app?
If every page in your app should have the same behaviour, i.e. go back to the previous page, then subscribe to the back button event in the app class as suggested by #RoguePlanetoid in the comments:
SystemNavigationManager.GetForCurrentView().BackRequested += OnBackRequested;
The OnLaunched method would be a good place to do this. Don't forget to tell the OS to display the back button when the app is running on a desktop or tablet:
SystemNavigationManager.GetForCurrentView().AppViewBackButtonVisibility = AppViewBackButtonVisibility.Visible;
Then, add an event handler in the app class like this:
private void OnBackRequested(object sender, BackRequestedEventArgs e)
{
Frame rootFrame = Window.Current.Content as Frame;
if (rootFrame.CanGoBack)
{
e.Handled = true;
rootFrame.GoBack();
}
}
If you want different behaviour on different pages when back is pressed, i.e. ask the user to confirm losing their changes or something, then subscribe to the back button event in a pages OnNavigatedTo method (the code will be same as above), but make sure you unsubscribe in the page's OnNavigatedFrom event:
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
SystemNavigationManager.GetForCurrentView().BackRequested -= this.OnBackPressed;
base.OnNavigatedFrom(e);
}

Unable to navigate backward using hardware key in a Universal App

I navigate forward using Frame.Navigate but when I press the hardware back key on my phone I end up on the start screen and not the page I just visited.
What might be wrong?
The reason behind your problem is, you are creating a Blank Page. If you're creating a blank page, you should define what the app has to do when the back button is fired.
Better, consider adding "Basic page". It will have backstack by nature. If you are navigating from the MainPage to the Basic Page and when you pressed back button at the Basic Page it will back to the MainPage.
I hope this could solve your problem!
If you want to use Blank Page in your application, you need to use like this on your page where you wanna override back button:
add this in your header:
using Windows.Phone.UI.Input;
and then in your constructor:
HardwareButtons.BackPressed += HardwareButtons_BackPressed;
add this anywhere in your code:
void HardwareButtons_BackPressed(object sender, BackPressedEventArgs e)
{
HardwareButtons.BackPressed -= HardwareButtons_BackPressed;
this.Frame.Navigate(typeof(MainPage));
e.Handled = true;
}
You've probably forgotten to use the NavigationHelper included in the template of the universal app.
You should use it like this on every page:
NavigationHelper _navigationHelper;
public LoginPage()
{
this.InitializeComponent();
_navigationHelper = new NavigationHelper(this);
}

Win 8.1 Metro Hub Navigation

In a Hub view App with subItems Pages, my question is when I navigate to a sub item detail Page and then use command navigate goback, the view always returns to pageroot hub section01.
How can I return the MainHub Page to the original calling section that went to the sub page in the first place?
My research has been fruitless. I don't think snaps are my answer but hey any advice is appreciated.
I apologize if this is a very simple question but...
Thx.
Ok. Thanks for the answers. After looking at this problem for three days I have found a solution but not quite an answer.
this.NavigationCacheMode = Windows.UI.Xaml.Navigation.NavigationCacheMode.Enabled;
By enabling Navigation Caching the page will return to it's sender position. However I still desire to return to the Hub root page to a specific section. If anyone still has info on how to achieve this I would be grateful.
Seasons Greetings.
Well the newbie here has also discovered the MyHub.ScrollToSection(MyHub.Sections[0]);
This allows you to navigate directly to a section thereby bringing it into the current view.
I'm trying to find an answer to the same question. This is what I've found so far. I welcome any better solutions.
Option 1
Enable caching for the page. Note that this must be set in the page constructor or XAML. This will increase memory usage but will improve performance of your app when you navigate back to a cached page.
this.NavigationCacheMode = Windows.UI.Xaml.Navigation.NavigationCacheMode.Enabled;
More information here: http://msdn.microsoft.com/en-us/library/windows/apps/xaml/windows.ui.xaml.controls.page.navigationcachemode.aspx
Option 2
Manually save a controls state between page navigations. The example below is using the NavigationHelper class which is added to a new Windows Store project by default.
private void OnNavigationHelperSaveState(obj sender, SaveStateEventArgs e)
{
e.PageState["SelectedSection"] = this.MainHub.SectionsInView;
}
private void OnNavigationHelperLoadState(obj sender, LoadStateEventArgs e)
{
if (e.PageState != null)
{
var sections = e.PageState["SelectedSection"] as IList<HubSection>;
if (sections != null && sections.Any())
{
this.MainHub.ScrollToSection(sections[0]);
}
}
}
More information here: http://msdn.microsoft.com/en-gb/library/windows/apps/hh986968.aspx
you could get the Hub's descendant scrollviewer and register to scrollchanged events, store the scrollOffsets and restore them as soon as the user navigates back to the page by applying the values to the hub's scrollviewer.
I guess you would have to register to the hub's loaded event to get the descending scrollviewer (you can use an Extension method from WinRt XAML Toolkit that allows you to get the descendants by Type (e.g. Scrollviewer)
greetings!
you can delete un back stack with this :
if(this.Frame.CanGoBack)
{
this.Frame.BackStack.RemoveAt(0);
}
Have you tried what i suggested?
Unforunately Hub can't be extended to do this and access it's Scrollviewer so you have to do this with an attached Property or plainly in your page.cs .
First you register an handler for the Loaded event of your hub. In the handler you get the descending scrollviewer (with the help of WINRT XAML Toolkit maybe) and register for it's ViewChanged Event.
You store the paremeters you like somewhere they don't get deleted on page navigation and restore and attach them to the scrollviewer on backwards-navigation.
I can give you example code in the afternoon.
Greetings
It's not a ridiculous request. Try this:
public static class Concurrency
{
public static HubSection GotoSection { get; set; }
}
public class MainPage : Page
{
protected override void OnNavigatedTo(NavigationEventArgs e)
{
if (Concurrency.GotoSection != null)
MainHub.ScrollToSection(Concurrency.GotoSection);
Concurrency.GotoSection = null;
base.OnNavigatedTo(e);
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
Concurrency.GotoSection = MainHub.SectionsInView.First();
base.OnNavigatedFrom(e);
}
}
The reason this.NavigationCacheMode = Windows.UI.Xaml.Navigation.NavigationCacheMode.Enabled; may not be the correct solution is because you might want your hub to be refreshed. If the detail page resulted in an edit (or especially a delete) a back navigation would show stale data, and subject your app to un unexpected state if the user interacts with dead data.
Best of luck!
Enable cache mode on your page at initialization
public MainHubPage()
{
. .......
this.NavigationCacheMode = NavigationCacheMode.Enabled;
.......
}
You need to add Loaded method to Page constructor.
MainHub.Loaded += async (s, e) => await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
//here you can scroll
MainHub.ScrollToSection(Loyaltysection);
});

Save the page state when navigating out

Say I have two pages, A and B.
The user can modify things on page A then navigate to page B.
When he is on page B, he clicks the "Back" button to go to page A.
Everything that has been done previously is lost.
There is a way to get the exact same state by using
this.NavigationCacheMode =
Windows.UI.Xaml.Navigation.NavigationCacheMode.Enabled;
But is there a way to know whether the page is opened for the first time a by using the back button?
yes it is:
protected override void OnNavigatedTo(NavigationEventArgs e)
{
if (e.NavigationMode == NavigationMode.Back)
{
// LoadPreviousSate...
}
}
You also should've a look at ApplicationExecutionState (in OnLaunched event in App.xaml). If you navigate to Page B, Apps suspends, App continues, user navigates to Page A the NavigationMode will be New!