I managed to find the solution for this issue. It happens because apparently, when using MonoGame it is not possible to access Application.Current.RootVisual
, thus throwing this exception.
As reported in page 438 of the Windows 8 and Windows Phone 8 Game Development book:
Windows Phone applications cannot interact with the XAML controls from within the game class code as the game code runs in a different thread that is not allowed to access UI components. To deal with this, the Dispatcher object is used to queue the updates for processing by the UI thread.
In Facebook.Client's code (available in their GitHub repo), there is a line in PhoneWebAuthentication.cs
that does this:
PhoneApplicationFrame rootFrame = Application.Current.RootVisual as PhoneApplicationFrame;
This is the line that causes the exception and disrupts the behavior of LoginAsync()
.
I have opened an issue in their GitHub page.
For now, if you want LoginAsync()
to work in WP8 using MonoGame (it does not cause redirections, thus being exactly what I was looking for!), you will need to download the source code of Facebook.Client for Windows Phone 8 from the GitHub repo mentioned above and link it in your project. After that, make your AuthenticateAsync()
function look like the one below:
public static Task<WebAuthenticationResult> AuthenticateAsync(WebAuthenticationOptions options, Uri startUri, Uri endUri)
{
if (options != WebAuthenticationOptions.None)
{
throw new NotImplementedException("This method does not support authentication options other than 'None'.");
}
WebAuthenticationBroker.StartUri = startUri;
WebAuthenticationBroker.EndUri = endUri;
WebAuthenticationBroker.AuthenticationInProgress = true;
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
(Application.Current.RootVisual as PhoneApplicationFrame).Navigate(new Uri("/Facebook.Client;component/loginpage.xaml", UriKind.Relative));
});
Task<WebAuthenticationResult> task = Task<WebAuthenticationResult>.Factory.StartNew(() =>
{
authenticateFinishedEvent.WaitOne();
return new WebAuthenticationResult(responseData, responseStatus, responseErrorDetail);
});
return task;
}