I'm using Parse as a data store for an app, and I am implementing their Facebook Login functionality. AFAIK, this Login method isn't any different than other async methods so hopefully it applies.
So there is a Login.xaml page, that has a button for "Login with Facebook", and tapping this button takes you to the FacebookLogin.xaml page which contains only the WebBrowser
control as per the linked Parse documenation. In ContentPanel.Loaded
on FacebookLogin.xaml, I can use the following code to log in:
async void FacebookLogin()
{
try
{
user = await ParseFacebookUtils.LogInAsync(fbBrowser, new[] { "user_likes", "email" });
}
catch (OperationCanceledException oce)
{
// task was cancelled, try again
//task = null;
//FacebookLogin();
}
catch (Exception ex)
{
}
}
If I actually log in, it works, and I can navigate the user to the next page. The problem happens when I let the browser control load (so the async
method is waiting), and then hit the Back button, and then come back to the Facebook Login page again.
When I do this, an OperationCancelledException
is thrown, but I'm not sure how to handle it. What I've tried:
In the
catch
for theOperationCanceledException
, set re-initialize theWebBrowser
control to a new one. This had no effect.In the same
catch
, callFacebookLogin()
again, to retry. This also didn't work.I've also tried not using
await
and returning aTask<ParseUser>
but I wasn't sure how to go about doing that either.
Is there something I can do with the cancellation exception, or use a CancellationToken
to handle this better? I just want to properly handle the cancellation so that I can re-load the Facebook Login page if the user presses "Back".
SOLUTION:
Ok, after much guidance from @JNYRanger, I have come up with a working solution. There may be a better way, but this seems to work. Here is the entire code from my FacebookLogin.xaml:
public partial class LoginFacebook : PhoneApplicationPage
{
Task<ParseUser> task;
CancellationTokenSource source;
public LoginFacebook()
{
InitializeComponent();
ContentPanel.Loaded += ContentPanel_Loaded;
}
async void ContentPanel_Loaded(object sender, RoutedEventArgs e)
{
try {
source = new CancellationTokenSource();
task = ParseFacebookUtils.LogInAsync(fbBrowser, new[] { "user_likes" }, source.Token);
await task;
// Logged in! Move on...
}
catch (Exception ex) { task = null; }
}
protected override void OnBackKeyPress(System.ComponentModel.CancelEventArgs e)
{
if (task != null) source.Cancel(false);
base.OnBackKeyPress(e);
}
}
So basically, when "Back" is pressed, I use the CancellationToken
to request a cancel, which throws an exception. When the exception occurs, I set task
to null. Now, when re-navigating to the FacebookLogin page (without previously logging in), the task
can be successfully recreated.