24 June 2015

Custom oAuth login to Facebook for Windows Store apps

Intro: the joy of third party dependencies
At Wortell I am currently working on a Windows app that uses some kind of Facebook integration. Last Friday (June 20) something odd occurred: some POC code that I got from my awesome colleague Melvin Vermeer where I had been toying with (the code, to be clear – not Melvin ;) ), suddenly stopped working. Assuming I had messed something up, I started tinkering with it, then checked the Facebook settings to see if Melvin had used some odd setting that only worked temporarily. This was not the case – so I even tried it on a different computer and later at home (operating on the assumption I had somehow blacklisted the Wortell offices). To no avail. The error I kept getting was:

Given URL is not permitted by the Application configuration
One or more of the given URLs is not permitted by the App's settings. It must match the Website URL or Canvas URL, or the domain must be a subdomain of one of the App's domains.

Not a good way to start a weekend, I can tell you. Then I decided to employ the ‘wisdom of the crowd’, aka twitter. My fellow MVP András Vélvart responded immediately by acknowledging he had the same problem, and pointed me to this Facebook bug report.

I hadn’t messed anything up, neither had Melvin. Facebook itself had pulled the rug from under us.

Now at the point of this writing I have ascertained Facebook apparently have fixed the error, but that was not the case yesterday and with a deadline looming I needed a plan B very quickly, and I got one with the help of Tamás Deme, aka 'tomzorz', a Hungarian Windows Phone consumer MVP that I did not knew nor followed yet (shame on me!). Although the ‘normal’ way now works again, I decided to blog about the alternative approach anyway, to make sure this plan B is available to everyone in case, ehm … excrement hits the cooling device … again.

The prescribed way of getting a Facebook access token
In a world where everything works as it should you can get a Facebook token using WebAuthenticationBroker and a Facebook C# SDK, which is also available as a NuGet package. The code I got from my colleague basically came down to this:

using Facebook;

namespace FacebookNormal
{
  public sealed partial class MainPage : Page
  {
    private const string AppId = "your app id here";
    private const string ExtendedPermissions = 
      "publish_actions, user_managed_groups, user_groups";

    public MainPage()
    {
      this.InitializeComponent();
    }

    private async void ButtonBase_OnClick(object sender, RoutedEventArgs e)
    {
      var result = await AuthenticateFacebookAsync();
      var md = new MessageDialog("your token is: " + result);
      await md.ShowAsync();
    }

    private async Task<string> AuthenticateFacebookAsync()
    {
      try
      {
        var fb = new FacebookClient();

        var redirectUri = 
          WebAuthenticationBroker.GetCurrentApplicationCallbackUri().ToString();

        var loginUri = fb.GetLoginUrl(new
                                       {
                                         client_id = AppId,
                                         redirect_uri = redirectUri,
                                         scope = ExtendedPermissions,
                                         display = "popup",
                                         response_type = "token"
                                       });

        var callbackUri = new Uri(redirectUri, UriKind.Absolute);

        var authenticationResult =
          await
            WebAuthenticationBroker.AuthenticateAsync(
            WebAuthenticationOptions.None, 
            loginUri, callbackUri);

        return ParseAuthenticationResult(fb, authenticationResult);
      }
      catch (Exception ex)
      {
        return ex.Message;
      }
    }

    public string ParseAuthenticationResult(FacebookClient fb, 
                                            WebAuthenticationResult result)
    {
      switch (result.ResponseStatus)
      {
        case WebAuthenticationStatus.ErrorHttp:
          return "Error";
        case WebAuthenticationStatus.Success:

          var oAuthResult = fb.ParseOAuthCallbackUrl(new Uri(result.ResponseData));
          return oAuthResult.AccessToken;
        case WebAuthenticationStatus.UserCancel:
          return "Operation aborted";
      }
      return null;
    }
  }
}

You get the callback URL to your own app, create a login Url, ask the WebAuthenticationBroker to do it’s stuff and show the “connecting to a service” window with the Facebook login, you parse the result, and if all goes well, you have a token. All code sits in the code behind – this was a POC, so that is very much OK.

Plan B – using a custom login employing a WebView

This looks very much the same, except that I have replaced both the AuthenticateFacebookAsync and the ParseAuthenticationResult methods.
private const string FbSuccess = 
  "https://www.facebook.com/connect/login_success.html";

private async Task<string> AuthenticateFacebookAsync()
{
  try
  {
    var fb = new FacebookClient();

    var loginUri = fb.GetLoginUrl(new
    {
      client_id = AppId,
      redirect_uri = FbSuccess,
      scope = ExtendedPermissions,
      display = "popup",
      response_type = "token"
    });

    var authenticationResult =
      await
        FacebookAuthenticationBroker.AuthenticateAsync(loginUri);

    return ParseAuthenticationResult(authenticationResult);
  }
  catch (Exception ex)
  {
    return ex.Message;
  }
}

private static string ParseAuthenticationResult(string authResult)
{
  var pattern = 
    string.Format("{0}#access_token={1}&expires_in={2}", 
                  FbSuccess,"(?<access_token>.+)", "(?<expires_in>.+)");
  var match = Regex.Match(authResult, pattern);
  return match.Groups["access_token"].Value;
}

Now what is that mysterious FacebookAuthenticationBroker? The framework for that I got from Tamás, and I added some stuff to it

namespace FacebookCustom
{
  /// 
  /// This class is a helper to replace the default WebAuthenticationBroker
  /// 
  public static class FacebookAuthenticationBroker
  {
    public static Task AuthenticateAsync(Uri uri)
    {
      var tcs = new TaskCompletionSource();

      var w = new WebView
      {
        HorizontalAlignment = HorizontalAlignment.Stretch,
        VerticalAlignment = VerticalAlignment.Stretch,
        Margin = new Thickness(30.0),
      };

      var b = new Border
      {
        Background = 
          new SolidColorBrush(Color.FromArgb(255, 255, 255, 255)),
        Width = Window.Current.Bounds.Width,
        Height = Window.Current.Bounds.Height,
        Child = w
      };

      var p = new Popup
      {
        Width = Window.Current.Bounds.Width,
        Height = Window.Current.Bounds.Height,
        Child = b,
        HorizontalOffset = 0.0,
        VerticalOffset = 0.0
      };

      Window.Current.SizeChanged += (s, e) =>
          {
            p.Width = e.Size.Width;
            p.Height = e.Size.Height;
            b.Width = e.Size.Width;
            b.Height = e.Size.Height;
          };

      w.Source = uri;

      w.NavigationCompleted += (sender, args) =>
      {
        if (args.Uri != null)
        {
          if (args.Uri.OriginalString.Contains("access_token"))
          {
            tcs.SetResult(args.Uri.ToString());
            p.IsOpen = false;
          }
          if (args.Uri.OriginalString.Contains("error=access_denied"))
          {
            tcs.SetResult(null);
            p.IsOpen = false;
          }
        }
      };

      p.IsOpen = true;
      return tcs.Task;
    }
  }
}

A lot of it is just setting up a UI of a popup with a WebView, then navigating to the Facebook authentication url. This will show a ‘normal’ web Facebook login (without the “Connecting to service” header). The interesting part I annotated in red and bold – when this event handler detects either “access_token” or “error=access_denied” in the url it’s navigated to, it considers it’s work done. Facebook navigates to a page with an url that either contains one of these strings, and we have a token again. Or not.

I know, it’s crude, probably has a lot of edge cases, but it will get you through the day when time is tight ;)

One more thing
To get this to work, you will have to add in your Facebook app settings (on Facebook developer) under section “Settings/Advanced” the return url to whatever you decided to use for the Facebook success url ( see FbSuccess constant).

image

Conclusion
As always you can find a ready to run demo on GitHub although in this case ‘ready to run’ is stretching it a little, as you will need to define an app in Facebook developer to get this actually working. And a great big of thanks to my colleague and the awesome #wpdev community for getting this to work.

13 June 2015

View model driven animations using behaviors and MVVMLight in Xamarin Forms

Intro
For some time now I have been making a number of behaviors implementing animations driven by view models for Windows and Windows Phone. Implementing animations in behaviors results into reusable animation building block without the need to copy and paste the functionality into code behind – or the need to remember how the internals exactly worked (you know they say a good programmer is a lazy programmer ;) ). I wanted to check if it would be possible to make animations for Xamarin Forms in a similar way, and it turns out to be possible. I have created a proof-of-concept that allows you to animate a kind of popup using a behavior, a view model and a little bit of code-behind plumbing. The popup folds open in a vertical direction from the center of the screen. It looks like this:

Setting the stage
I started out with a standard Xamarin Forms Portable project, and brought in my favorite MVVM framework MVVMLight. Then I added an empty StartPage.xaml to the portable project, and modified the constructor of the default App class to start with that page, in stead of with the default code:

public App()
{
  MainPage = new StartPage();
}

This is quite a standard way to set up a Xamarin Forms application using a XAML-based start page. I did not make it up myself ;) .

Passing startup events to the view model
A behavior in Xamarin.Forms has two events you can trap – OnAttachedTo and OnDetachingFrom – by basically overriding the methods with that name. But those are fired apparently before the visual element to which the behavior is attached to is loaded and made part of a layout: the attached object has no size, and no parent. To make matters more complicated, there is also no OnLoaded event on the attached object, like in WinRT XAML. So when do you know when the layout is ready?

It appears that on page level there is such an event: OnAppearing (and it’s counterpart OnDisppearing) which once again can be trapped by overriding those methods. What we need to do is pass the fact that these methods have been called to the view model. The more or less standard way to do that seems to be something like as follows. I first defined an interface:

namespace AnimationBehaviorDemo.ViewModels
{
  public interface IPageViewModelBase
  {
    void OnViewAppearing();
    void OnViewDisappearing();
  }
}

and then a base class implementing that interface. This is not strictly necessary, but I always feel compelled to make a base class for convenience, yet I don’t want to force myself or my fellow developers into always needing to use that base class. The interface allows me an escape route out of a possible undesirable inheritance kludge. I think that’s just good architecture.

using GalaSoft.MvvmLight;

namespace AnimationBehaviorDemo.ViewModels
{
  public class PageViewModelBase : 
     ViewModelBase, IPageViewModelBase
  {
    public virtual void OnViewAppearing()
    {
      ViewHasAppeared = true;
    }

    public virtual void OnViewDisappearing()
    {
      ViewHasAppeared = false;
    }

    private bool viewHasAppeared;
    public bool ViewHasAppeared
    {
      get { return viewHasAppeared; }
      set { Set(() => ViewHasAppeared, ref viewHasAppeared, value); }
    }
  }
}

And there we see the familiar MVVMLight syntax again. So great if you can use an awesome friend from the Windows ecosystem in a cross platform setting again (thanks Laurent!).

Anyway, now I can make a view model inheriting from PageViewModelBase (or at least implementing IPageViewModelBase), use it as binding context and pass the events to the view model using the code behind of the start page like this:

public partial class StartPage : ContentPage
{
  public StartPage()
  {
    InitializeComponent();
    BindingContext = new MyViewModel();
  }

  protected override void OnAppearing()
  {
    Context.OnViewAppearing();
    base.OnAppearing();
  }

  protected override void OnDisappearing()
  {
    Context.OnViewDisappearing();
    base.OnDisappearing();
  }

  private IPageViewModelBase Context
  {
    get { return (IPageViewModelBase)BindingContext; }
  }
}

In every page you make using this behavior then needs to have this kind of plumbing. Of course, you can define a nice base class for this as well, making the last three methods disappear again. Have a blast. I only have one page in this solution, so I leave it at this. The important thing is – we have now a way to pass the fact that the view is ready to the view model, a behavior can bind to this, and things can happen in the right order.

The view model
Using the PageViewModelBase as a starter, I add a simple command and a property for the behavior to bind to as well:

using System.Windows.Input;
using GalaSoft.MvvmLight.Command;

namespace AnimationBehaviorDemo.ViewModels
{
  public class AnimationViewModel : PageViewModelBase
  {
    public AnimationViewModel()
    {
      TogglePopup = new RelayCommand(DoTogglePopup);
    }
public ICommand TogglePopup { get; private set; } private void DoTogglePopup() { IsPopupVisible = !IsPopupVisible; } private bool isPopupVisible; public bool IsPopupVisible { get { return isPopupVisible; } set { Set(() => IsPopupVisible, ref isPopupVisible, value); } } } }

Nothing special here – standard MVVMLight view model and syntax.

The animation behavior
I will be going through this step by step, to hopefully convey what I am doing here. The basics are the two methods I already have mentioned by name: OnAttachedTo and OnDetachingFrom
using System;
using Xamarin.Forms;

namespace AnimationBehaviorDemo.Behaviors
{
  public class FoldingPaneBehavior: Behavior<View>
  {
    private View associatedObject;

    private double desiredHeight;

    protected override void OnAttachedTo(View bindable)
    {
      base.OnAttachedTo(bindable);
      associatedObject = bindable;
      bindable.BindingContextChanged += (sender, e) =>
          BindingContext = associatedObject.BindingContext;
    }

    protected override void OnDetachingFrom(View bindable)
    {
      associatedObject = null;
      base.OnDetachingFrom(bindable);
    }
  }   
}    

This basically sets up the behavior, keeping a reference to the object it’s bound to. In the OnAttachedTo there is an odd piece of code. Basically, if you don’t use this, binding to the Bindable Properties that I will show later on will not work. I have no idea why this is. It took me quite some nosing around in the Xamarin forums and eventually I found this solution here in this thread. I am not sure if this is a recommendable way. But it seems to work.

Then we get to Bindable Properties, and I think of those as the Attached Dependency Properties of WinRT XAML (in fact, they have been in XAML since WPF). In fact, we need two: one to get notified of the view having appeared, and one for the popup needing to displayed (and hidden again). For the sake of brevity, I show only the property for the popup toggle:

#region IsPopupVisible Attached Dependency Property
public static readonly BindableProperty IsPopupVisibleProperty =
   BindableProperty.Create<SlidingPaneBehavior, bool>(t => t.IsPopupVisible,
   default(bool), BindingMode.OneWay,
   propertyChanged: OnIsPopupVisibleChanged);

public bool IsPopupVisible
{
  get
  {
    return (bool)GetValue(IsPopupVisibleProperty);
  }
  set
  {
    SetValue(IsPopupVisibleProperty, value);
  }
}

private static void OnIsPopupVisibleChanged(BindableObject bindable, 
                                            bool oldValue, bool newValue)
{
  var thisObj = bindable as SlidingPaneBehavior;
  if (thisObj != null)
  {
    thisObj.AnimatePopup(newValue);
  }
}
#endregion

Like Attached Dependecy Properties in Windows this is quite some code, a lot hinges on connecting the dots in the right way, and a part of it depends on naming conventions. To make life easier, I made a Visual Studio snippet for that. The whole purpose of this construct is to make sure the AnimatePopup method gets called with the right parameter whenever the bound property changes.

But first – initialization
The first Bindable Property – that I did not even show – is called OnViewHasAppeared, is bound to the OnViewHasAppeared of the view model, and fires a method that is (very originally) called Init:

private double unfoldingHeight;
private const double HeightFraction = 0.6;
private const double WidthFraction = 0.8;

private void Init()
{
  var p = associatedObject.ParentView;
  unfoldingHeight = Math.Round(p.Height * HeightFraction, 2);
  associatedObject.WidthRequest = Math.Round(p.Width * WidthFraction , 2);
  associatedObject.HeightRequest = 0;
  associatedObject.IsVisible = false;
}

This sets the width of the popup to 0.8 times that of the parent view, it’s height to 0 and it’s visibility to false, effectively creating an invisible pane. It also calculates the height to which the panel should be unfolded, that is, when it is unfolded – 0.6 times the height of the parent. Mind you, these values are now constants, but could just as well be properties as well, with values you could set from XAML - thus creating a more customizable experience.

The actual animation is done by these two methods and some more constants:

private const int FoldOutTime = 750;
private const int FoldInTime = 500;

private void AnimatePopup(bool show)
{
  if (show)
  {
    associatedObject.IsVisible = true;
    Animate(0, unfoldingHeight, FoldOutTime);
  }
  else
  {
    Animate(unfoldingHeight, 0, FoldInTime);
  }
}

private void Animate(double start, double end, uint runningTime)
{
  var animation = new Animation(
    d => associatedObject.HeightRequest = d, start, end, Easing.SpringOut);

  animation.Commit(associatedObject, "Unfold", length: runningTime, 
    finished: (d, b) =>
  {
    if (associatedObject.Height.Equals(0))
    {
      associatedObject.IsVisible = false;
    }
  });
}

If the popup should be displayed (triggered by the change on the IsPopupDisplayed property) it first sets the popup’s visibility to true (although it’s still effectively invisible, as it has zero height) and then it launches an animation that goes from 0 to the unfoldingHeight in about 750ms. The Animate method then creates the actual animation, that animates the HeightRequest using and easing method (also a familiar friend from our good old Storyboards). By calling the Commit on it, you actually launch the animation, and you can apparently also make some kind of callback running when the animation is finished – in this case, when it determines the height is 0 (thus the popup has been folding in) – it should make it invisible again. Take note that the folding back goes a bit faster than the unfolding – 500ms in stead of 750ms. They could be the same, of course. It’s just a nice touch.

Putting it all together
In Xamarin Forms XAML, it then looks like this:

<Grid>

  <StackLayout HorizontalOptions="StartAndExpand" VerticalOptions="StartAndExpand">
    <Button Text="Open Popup" HorizontalOptions="Center" VerticalOptions="Start"
        IsEnabled="{Binding IsPopupVisible, Converter={StaticResource InverseBooleanConverter}}"
        Command="{Binding TogglePopup}"></Button>
    <Label Text="Here be some text" FontSize="25"></Label>
    <Label Text="Some more text" FontSize="20"></Label>
  </StackLayout>

  <ContentView BackgroundColor="Green" 
               HorizontalOptions="CenterAndExpand" 
               VerticalOptions="CenterAndExpand" >
    <ContentView.Behaviors >
      <behaviors:FoldingPaneBehavior 
        ViewHasAppeared ="{Binding ViewHasAppeared}" 
        IsPopupVisible="{Binding IsPopupVisible}"/>
    </ContentView.Behaviors>
    <StackLayout>
      <Label Text="Here is my popup" FontSize="20"></Label>
      <Button Text="Close popup" HorizontalOptions="Center"
     IsEnabled="{Binding IsPopupVisible}"
     Command="{Binding TogglePopup}"></Button>
    </StackLayout>
  </ContentView>
  
</Grid

imageimage

First you have the StackLayout containing the initial user interface, then the ContentView that contains the ugly green popup and the behavior. Notice the button on the initial UI gets disabled by binding to IsPopupVisible too, using a bog standard InverseBooleanConverter that I took from here. I think it’s actually the same as the WinRT value converter but I was too lazy to check ;)

Caveat emptor
Warning – you mileage may vary with this approach. I am not very versed in Xamarin Forms yet and I have no idea what amount of rules I am now violating. I find the hack in OnAttachedTo a bit worrisome, and I wonder if is has side effects. In addition, Xamarin Forms is a very rapidly evolving platform so anything I write today may be obsolete tomorrow. Also, this behavior does not yet take into account any changes in screen size (or rotation) that may occur after the behavior is initialized. I don’t doubt though this could be added.

Conclusion
With this article I hope I have given you some thought about how to write reusable x-plat animation blocks that can be wired together using behaviors. I still think it’s very important to keep such stuff from code behind as much as possible (although never loosing track of practicality – if some effect can be created using two lines of code behind, it’s not very smart to write a bazillion lines of code just to avoid that). What is sorely missed in this environment is my old friend Blend, which in a Windows environment can be used to drag behaviors on top of elements and wire some properties together in a simple UI. In Xamarin, it’s hand coding XAML all the way. Still, it’s an improvement over putting all this stuff in code behind.

As usual, a sample solution can be found on GitHub. This includes the snippet for creating Bindable Properties.

Credits and thanks
I want to thank two of my fellow developers colleagues at Wortell for being an inspiration to this blog post: Bruce Wilkins for showing me the two events that occur when a Xamarin Forms page loads and unloads, and Edwin van Manen for showing me the Xamarin Forms animation basics. They made me understand some parts that I needed to connect the dots and make this technique work.