Databinding a Windows FlipView with MVVM Light

MVVM Light is a great cross-platform MVVM Framework, and was chosen to be used in this example. However, it isn’t required to get the same results.

FlipViews were a great addition to the WIndows Control family for Windows Phone and Windows Store applications. It’s easily customized, simple to use, and can give your app a user friendly experience for anything from an image gallery, to a news reader. So let’s get to the code.

Let’s first build the model we are going to use for each of our views in our FlipView. I’m using a PCL for my Models and ViewModels and a Windows Phone 8.1 project for the xaml, but it works in the same fashion for Windows Store.

Here is our model:


public class RotatorItem
 {
     public string Title { get; set; }
     public string ImageUri { get; set; }
     public string Subtitle { get; set; }
 }

Now let’s look at a simple ViewModel with MVVM Light to hold our collection of SimpleRotatorItems.

public class LandingRotatorPageViewModel : ViewModelBase
 {
     #region Private Properties
     private ObservableCollection<RotatorItem> _rotatorItems;
     private RotatorItem _activeItem;
     #endregion

     #region Public Properties
     public ObservableCollection<RotatorItem> RotatorItems
     {
         get
         {
             return _rotatorItems;
         }
         set
         {
             Set(() => RotatorItems, ref _rotatorItems, value);
         }
     }
     public RotatorItem ActiveItem
     {
         get
         {
             return _activeItem;
         }
         set
         {
             Set(() => ActiveItem, ref _activeItem, value);
         }
     }

     #endregion
     public LandingRotatorPageViewModel()
     {
         var rotatorItems = new ObservableCollection<RotatorItem>();
         rotatorItems.Add(new RotatorItem { ImageUri = "/Assets/Logo.scale-240.png", Title = "Title 1", Subtitle = "Subtitle 1"});
         rotatorItems.Add(new RotatorItem { ImageUri = "/Assets/Logo.scale-240.png", Title = "Title 2", Subtitle = "Subtitle 2" });
         rotatorItems.Add(new RotatorItem { ImageUri = "/Assets/Logo.scale-240.png", Title = "Title 3", Subtitle = "Subtitle 3" });
         rotatorItems.Add(new RotatorItem { ImageUri = "/Assets/Logo.scale-240.png", Title = "Title 4", Subtitle = "Subtitle 4" });
         RotatorItems = rotatorItems;
         ActiveItem = rotatorItems.First();
     }
 }

Let’s go ahead now and get our markup done for our page with the FlipView:

<FlipView x:Name="SimpleFlipView" ItemsSource="{Binding RotatorItems}" Grid.Row="1" SelectionChanged="FlipView_SelectionChanged">
    <FlipView.ItemTemplate>
        <DataTemplate>
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="200" />
                    <RowDefinition Height="120" />
                    <RowDefinition Height="80" />
                </Grid.RowDefinitions>
                <Image Source="{Binding ImageUri}" Height="150" Grid.Row="0" VerticalAlignment="Top" Margin="0,50,0,0"/>
                <TextBlock TextWrapping="Wrap" TextAlignment="Center" Grid.Row="1" Text="{Binding Title}" FontSize="30" HorizontalAlignment="Center" Margin="20"></TextBlock>
                <TextBlock TextWrapping="Wrap" TextAlignment="Center" Grid.Row="2" FontSize="20" HorizontalAlignment="Center" Margin="20">
                    <Run Text="{Binding Subtitle}"></Run>
               </TextBlock>

            </Grid>
       </DataTemplate>
   </FlipView.ItemTemplate>
</FlipView>

Last but not least, let’s make sure our ViewModel is bound to our Page in our page Class:

 public sealed partial class MainPage : Page
 {
     private LandingRotatorPageViewModel _vm;
     public MainPage()
     {
          this.InitializeComponent();

          _vm = new LandingRotatorPageViewModel();
          this.DataContext = _vm;
     }

     /// <summary>
     /// Invoked when this page is about to be displayed in a Frame.
     /// </summary>
     /// <param name="e">Event data that describes how this page was reached.
     /// This parameter is typically used to configure the page.</param>
     protected override void OnNavigatedTo(NavigationEventArgs e)
     {
     }
}

Now that the Page’s DataContext is set to our ViewModel, the binding we placed on the FlipView element ‘ItemSource=”{Binding RotatorItems}”‘ will bind our FlipView’s Items to the items we created in the constructor for our ViewModel, and will use our ItemTemplate to create our items from the fields on the RotatorItems.

Now let’s take a look at our final result:

FlipView Item
First FlipView Item bound to ViewModel
wp_ss_20150502_0002
Second FlipView Item

So there you have it. An easy solution to using the Windows FlipView Control to display content that is bound to a ViewModel.

Advertisement

Adding a Simple Refresh Token to OAuth Bearer Tokens

If you’re using a .NET as your web platform and are looking to expand it to another platform such as mobile applications, and need to authenticate users from that external application, one of the best ways of going about it is through the use of OAuth Bearer Tokens.

James Randall has a great post here about getting started with the OAuth Bearer token Authentication. This post isn’t going to focus on getting started, but will use this example to expand upon.

Using Bearer (access) Tokens allows you to authenticate users without having to send their password through the pipes with each request. Using an access token in your header will let you authorize requests to your api as well as through SignalR or other web services.

Here is an example of the authorization header sent with a request to authorize a user:
“Authorize Bearer YOUR_ACCESS_TOKEN”

However, what happens when this token expires? Of course, you can set an outrageously long expiration date, but that is a security nightmare. You don’t want to store the users password locally to continuously send requests to get a new token. You also don’t want to require the user to re-login every time the token expires.

The solution? Refresh tokens! A refresh token will allow you to receive a new access token after it expires without sending the user’s password.

The first step is to create a RefreshTokenProvider that we can add during our Startup processing. Here is a simple Provider that will work for this example:


 public class SimpleRefreshTokenProvider : IAuthenticationTokenProvider
 {
    private static ConcurrentDictionary<string, AuthenticationTicket> _refreshTokens = new ConcurrentDictionary<string, AuthenticationTicket>();

     public async Task CreateAsync(AuthenticationTokenCreateContext context)
     {
         var guid = Guid.NewGuid().ToString();

         // maybe only create a handle the first time, then re-use for same client
         // copy properties and set the desired lifetime of refresh token
         var refreshTokenProperties = new AuthenticationProperties(context.Ticket.Properties.Dictionary)
         {
             IssuedUtc = context.Ticket.Properties.IssuedUtc,
             ExpiresUtc = DateTime.UtcNow.AddYears(1)
         };
         var refreshTokenTicket = new AuthenticationTicket(context.Ticket.Identity, refreshTokenProperties);

         //_refreshTokens.TryAdd(guid, context.Ticket);
         _refreshTokens.TryAdd(guid, refreshTokenTicket);

         // consider storing only the hash of the handle
         context.SetToken(guid);
     }

     public async Task ReceiveAsync(AuthenticationTokenReceiveContext context)
     {
         AuthenticationTicket ticket;
         if (_refreshTokens.TryRemove(context.Token, out ticket))
         {
             context.SetTicket(ticket);
         }
     }

     public void Create(AuthenticationTokenCreateContext context)
     {
         throw new NotImplementedException();
     }

     public void Receive(AuthenticationTokenReceiveContext context)
     {
         throw new NotImplementedException();
     }
 }

We can now use this provider to add the setting to our Startup.Auth.cs:


 OAuthOptions = new OAuthAuthorizationServerOptions
 {
     TokenEndpointPath = new PathString("/Token"),
     Provider = new ApplicationOAuthProvider(PublicClientId, UserManagerFactory),
     AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),
     AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(60),
     AllowInsecureHttp = true,
     RefreshTokenProvider = new SimpleRefreshTokenProvider() //REFERENCE TO PROVIDER

 };

Now we have our access token that expires every hour, and a refresh token that expires every year. The time-spans to use for both of these is completely up to you.

Now we can use requests like these with our external application-

Authorize with username and password:

Method: POST
Url: http://yourdomain/Token?username=yourusername&password=yourpassword&grant_type=password

Response:

{

"access_token":"VSt0JjzP-9PO6OFk-i_dp7Xs7RA4JTai_nv1FXxTiZ-iMoYjCt42Jw8eJqV66EouqAxnsHIUzDucHKSQUhEch9tftf_dNgi0pDKFUZn5UVJ0rybZ8keG4LjT2oI851D1OnE0Ij0KnEr5ox_RNFpYW5Srqj_4Uy4uYkhrOLKxo3TEt_nBFNhVsvTAxoY5ggDdTK_th945XzeZeXjRSX-j8clYJpaxAUmA-Z38qhbyXiq29wSZKswhloaHcIVIJDXe9Fhpfe1nM4IfJT5Lwy1tjYH4XIphd7UX_nprX4JEwlJUFENJE9E-Gq6y7deXQa7j3JXIg8YBtvcR0Mj0Fjxhj6Bdaq2hCE1Ot6KgZUxOzzRkiuJlkMoQgmg8T2MM6STfQnX-cEd328n6oYgYBxg34kLbi8NGSHiAKEtxcF8Fuj7gizMOCK91iaVQTf_7UsJIkW6KFGeGLz0MG8A71jj-kNjzSFApYGo6VCoQJqXzREY",

"token_type":"bearer",

"expires_in": 3600,

"refresh_token":"969c9b04-afe5-48a3-9353-62509f71e906",

"userName":"yourusername",

".issued":"Thu, 30 Apr 2015 02:21:08 GMT",

".expires":"Thu, 30 Apr 2015 02:22:08 GMT"

}

Authorize with username and refresh token:

Method: POST
Url: http://yourdomain/Token?username=yourusername&refresh_token=969c9b04-afe5-48a3-9353-62509f71e906&grant_type=refresh_token

Response:

{

"access_token":"SAPmj6kWat4KcwhASsTkkuQ0hxeIZaq4ztZBduHV_Mr-0SoxzQZ61ojdiXDtUIo_ptfbuzx5sA9_3-GpPWZhQ702qvAXdYSnMy_OUVVypfVkP-9mUsS7iR_4uFd67MFrSVEfQ4Er1Tm9AiFLC1j4kR7WjAmZgn6YuhU1Z3NNOFMu6UGEutJEWZte4mcnHinYKxskwVt_45DBGqEaLQ1OQoPhYwLTPGIhAcvsjiVLOxHCWp46bfYOyP5tVBoZxoaftuYyQfEgOkeU44TRWdGRZBh6vKWKdjWqa-qpy8fCNoJkwpSSjWYGEyhG4IkDyRCRGpCfMHP5rbP6dfaWAAchk7qQCmcia_vuEFoZWFWER6_LFe58avh_ZqfmJQhl7lVaM4z5SEKmKP4RPXgK32T4jQEqoisOGi66bcueLzRGmCsW2BlBnxPC1QloY_VQR8bEoCqK7_C0haMH7t30sJz_2Cz9CgnMnIjeyVhdcQsg_4U",

"token_type":"bearer",

"expires_in": 3600,

"refresh_token":"9a773700-0b48-411e-9138-1fc0e266d8a9",

"userName":"yourusername",

".issued":"Thu, 30 Apr 2015 02:21:08 GMT",

".expires":"Thu, 30 Apr 2015 02:22:08 GMT"

}

This is obviously very simplified and lacks typical uses with things like Client Ids and handling proper storage and error handling, but it will hopefully help you get started with your Authorization layer for any external applications through Web API.