Saturday, August 24, 2013

Azure Mobile Services & Portable Class Libraries - Part 2 Authentication Cont'd

,
In Part 1 I covered a simple implementation of the Authentication feature and portable class libraries from the Azure Mobile Services SDK.  However, as mentioned in the "Good & Bad So Far" section; there is not a whole lot of code reuse other than the Azure endpoint and secret key.  Let's refactor a bit by adding some interfaces, conditional compile statements and the MVVM Light Event Bus to help the same solution operate cleaner.

The "after" code for part one is available here.

Building Our Core

PortableAzure.Core is our Portable Class Library that is being shared with the Windows 8 and  Windows Phone project in the attempt to reuse as much code as possible.  However, as mentioned in Part 1 the authentication portion of the Azure Mobile Service SDK is a platform specific implementation due to the UX pieces of that component and how it is presented varies.

Platform Adapter (PlatformAdapter.cs)

In the Services folder, add a new class called PlatformAdapter.cs.  This is an abstract class that will be used as the base class for the platform specific implementation.

    public abstract class PlatformAdapter
    {
        public static PlatformAdapter Current { get; set; }
        public abstract IIdentity Identity { get; }
    }

Identity (IIdentity.cs)

Add a new Identity interface, IIdentity.cs to be used as the implementation to execute the Authenticate method as well as store the MobileServiceUser upon logging in.

    public interface IIdentity
    {
        void Authenticate();
        MobileServiceUser User { get; set; }
    }


 Messages

Add a Messages folder to the root and a class called LoginMessage.cs to newly created folder.

Using the Event Bus from MVVM Light, a LoginMessage will be sent from the platform specific MainPage.xaml then subsequently handled in the MainViewModel.  The LoginMessage is just an empty class at this point.

    namespace PortableAzure.Core.Messages {
        public class LoginMessage { } 
    }

Adding Adapters to the Platforms

On each plaftform we need to now inherit from the PlatformAdapter.cs class in the Services namespace from the Core library as well as implement the IIdentity interface thus replacing the code shown in part one with this code.

Windows Phone

Add an "Adapters" folder to the root of the project and then a Platform.cs class which inherits from PlatformAdapter.

namespace PortableAzure.Phone8.Adapters
{
    public class Platform : PlatformAdapter
    {
        public IIdentity _identity = new Identity();

        public override IIdentity Identity
        {
            get
            {
                return _identity;
            }
        }
    }
}


Next, add the Identity class which is where all of the heavy lifting is done for the login logic.

namespace PortableAzure.Phone8.Adapters
{
    public class Identity : IIdentity
    {
        public async void Authenticate()
        {
            var app = ((App)Application.Current);

            string message = string.Empty;

            while (this.User == null)
            {
                try
                {
                    User = await app.Azure.MobileService.LoginAsync(MobileServiceAuthenticationProvider.Twitter);

                    message = string.Format("You are now logged in - {0}", User.UserId);
                }

                catch (InvalidOperationException)
                {
                    message = "You must log in. Login Required";
                }
            }

            MessageBox.Show(message);
        }

        public MobileServiceUser User { get; set; }
    }
}   
   
   
   
Now that the Windows Phone implementation is complete we need to tell the Service library what is the current class is for the PlaformAdapater.  This is set in the App.xaml.cs class in the App contstructor:

public App()
{
   Azure = new AzureMobileServices();

   PortableAzure.Core.Services.PlatformAdapter.Current = new Platform();

   ...

Windows 8

To implement the PlatformAdapter class in the Windows 8 application, you could follow the same steps as documented for the Phone project, but that is duplication and not manageable over time.

So in this case we will use add the existing Identity and Platform classes then add conditional compile statements to the areas of the classes where needed to address the small differences for Windows versus Phone.

Add Existing item by holding the Alt key and dragging the file, or the whole folder from the Phone project to the Windows 8 Project.  Thanks Matt Hidinger for this little trick. You could also just go through the right click -> add existing -> add as link process but now that you know the "Hold Alt + Drag" why??

Here are the completed Platform and Identity classes.  You will need to repeat the setting of the current platform in the App.xaml.cs constructor.

Platform.cs


#if NETFX_CORE

namespace PortableAzure.Win8.Adapters

#endif



#if WINDOWS_PHONE

namespace PortableAzure.Phone8.Adapters

#endif

{
    public class Platform : PlatformAdapter
    {
        public IIdentity _identity = new Identity();

        public override IIdentity Identity
        {
            get
            {
                return _identity;
            }
        }
    }
}

Identity.cs

#if NETFX_CORE

namespace PortableAzure.Win8.Adapters

#endif


#if WINDOWS_PHONE

namespace PortableAzure.Phone8.Adapters

#endif

{
    public class Identity : IIdentity
    {
        public async void Authenticate()
        {

#if WINDOWS_PHONE

            var app = ((App)Application.Current);

#endif


#if NETFX_CORE

            var app = ((PortableAzure.Win8.App)(Windows.UI.Xaml.Application.Current));

#endif

            string message = string.Empty;

            while (this.User == null)
            {
                try
                {
                    User = await app.Azure.MobileService.LoginAsync(MobileServiceAuthenticationProvider.Twitter);

                    message = string.Format("You are now logged in - {0}", User.UserId);

                }

                catch (InvalidOperationException)
                {
                    message = "You must log in. Login Required";
                }
            }

#if WINDOWS_PHONE

            MessageBox.Show(message);

#endif

#if NETFX_CORE

            var messageDialog = new Windows.UI.Popups.MessageDialog(message);

            await messageDialog.ShowAsync();

#endif

        }

        public MobileServiceUser User { get; set; }

    }

}

Note, be sure to use the full namespace OR add more #if at the top for the imports.

Cleanup & Consolidation

Now that there is a single place where the application executes the call to Authenticate, through the magic of #if and reusing existing files, time to delete some code.  Nice right?

In Part, each of the front end projects had code in the MainPage.xaml.cs file within the "Loaded" handler to execute the Azure authentication code.  That can be replaced by using the Event Messaging Bus provided by MVVM Light and sending the LoginMessage.

Messenger.Default.Send<LoginMessage>(new LoginMessage());

In the MainViewModel, add the handler in the constructor and the Login subroutine to call the Authenticate method in the Identity interface.

 public MainViewModel()
 {
     Messenger.Default.Register<LoginMessage>(this, m => { Login(); });
  }

 public void Login()
 {
     if (PlatformAdapter.Current.Identity.User == null)
     {
         try
         {
           PlatformAdapter.Current.Identity.Authenticate();
         }
          catch (Exception ex)
         {
             Debug.WriteLine(ex.ToString());
         }
     }
 }

Now when either platform is run, the Login entry point happens in the MainViewModel upon loading of the main page.  Another option, if you wanted to eliminate the messaging, would be to add a login button and have the ICommand call the Login method thus eliminating any code behind in the MainPage.xaml but that depends on your applications needs.

Windows Phone
Windows 8 / RT



Wrapping Up Authentication

One item to mention, in this example every time the app is run on either platform the user will have to authenticate.  When the MobileServiceUser is successfully authenticated, there are two properties that you can save; MobileServiceAuthenticationToken and UserId respectively.  In a subsequent execution of the app, create a new instance of the MobileServiceUser and set the CurrentUser property of the AzureMobileService.MobileService. For Example:

var user = new MobileServiceUser(mySavedUserId);

user.MobileServiceAuthenticationToken = mySavedMobileServiceAuthenticationToken;

App.MobileService.CurrentUser = user;

Part 1 and Part 2 has shown a simple introduction of how to use portable class libraries with Azure Mobile Services and through the use of a little indirection reuse all the code possible BUT also keep the MVVM implementation and code organization as clean as possible.

Final Code for Part 2 located here

Read more →

Monday, August 5, 2013

Azure Mobile Services & Portable Class Libraries - Part 1 Authentication

,
Azure Mobile Services is undoubtedly one of the best platforms to emerge from the Azure group over the last year. If you are a mobile developer and not taking advantage of it; I encourage you to do so.  There are many video and blog posts available to get you started at http://www.windowsazure.com/en-us/develop/mobile/ .

One of the features you may not be aware of is Azure Mobile Services is a Portable Class Library (PCL) available through nuget. If you are not familiar with PCL's see my "Move Your ViewModels" series.

There is a caveat however when using Azure Mobile Services in your PCL; although all of the data calls to the services are available, using the Identity feature is not and must be implemented in a platform specific way.

The Identity feature allows your application to leverage the user's Microsoft, Google, Facebook or Twitter account to login to the application and abstract the overhead of OAuth or provider specific authentication models into a single call.

var user = MobileService.LoginAsync(MobileServiceAuthenticationProvider.Twitter);

The Challenge - Maximize Code Reuse

There is no secret that Model-View-View-Model (MVVM) is a preferred pattern for xaml developers, but it is also know that sometimes breaking patterns is needed either due to time constraints or other restrictions.

In the effort to maintain the MVVM pattern in this scenario a platform abstraction is needed to accomplish to goal of reusing as much code as possible.  Matt Hidinger did a great talk at BUILD 2013 this year on this topic, give a watch on his blog.

Scenario - Setting up your solution

I won't walk through setting up a Mobile Service on Azure, see this post for instructions, so let's assume we have a Windows Phone & Windows Store application where we'd like to share code in a Portable Class Library and allow the user to login with their Twitter account. The project solution should contain 3 projects:


  • PortableAzure.Win8 - Windows 8 Blank  Application
  • PortableAzure.Phone8 - Windows Phone 8 Application
  • PortableAzure.Core - Portable Class Library Project
    •  .NET Framework 4.0 & higher
    • Windows Phone 7.5 & higher
    • Windows Store Apps

I have added the following nuget packages to the projects

  • Microsoft.Net.Http
  • Portable.MvvmLightLibs
  • WindowsAzure.MobileServices

There is some plumbing related to the MVVM structure that is needed as well.  Get the "before" code here http://sdrv.ms/14ufYYZ , your solution explorer should look like the image here ->.


Adding Azure 


Assumption(s) - you have created a Azure Mobile Service.

First, you will want to add a new class to the Services folder in the PortableAzure.Core project and call it AzureMobileServices. I have also added an empty interface out of habit and to use for IoC (Inversion of Control).

namespace PortableAzure.Core.Services
{
    public class AzureMobileServices : IAzureMobileServices
    {
        public MobileServiceClient MobileService = new MobileServiceClient(
            "https://portableazure.azure-mobile.net/",
            "[your app key]"
        );
        public AzureMobileServices()
        {
        }
    }
    public interface IAzureMobileServices
    {
    }
}


The app key and url comes from the Azure portal when you complete the setup; you will want to choose "Connect to an Existing Project". Either Windows Phone or Windows 8 is an acceptable choice.

Next step is to setup the Twitter authentication, or other provider of your choosing.  (reference)

Now that that is complete, we'll add the necessary platform specific code to the Windows Phone & Windows 8 platforms to prompt the user to login using their Twitter account.

Windows Phone

Open the App.xaml.cs and create a new property for the AzureMobileService class from the Core project.

    public partial class App : Application
    {
        /// <summary>
        /// Provides easy access to the root frame of the Phone Application.
        /// </summary>
        /// <returns>The root frame of the Phone Application.</returns>
        public static PhoneApplicationFrame RootFrame { get; private set; } 
        public AzureMobileServices Azure { get; private set; } 
        /// <summary>
        /// Constructor for the Application object.
        /// </summary>
        public App()

Then in the App constructor create the new instance of the AzureMobileService class.

Azure = new AzureMobileServices();
 In order to prompt the user, open the MainPage.xaml.cs file and add the following code to the PhoneApplicationPage_Loaded event.

 private async void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
        {
            MobileServiceUser user = null;
            while (user == null)
            {
                string message;
                try
                {
                    user = await((App)Application.Current).Azure.MobileService.LoginAsync(MobileServiceAuthenticationProvider.Twitter);
                    message = string.Format("You are now logged in - {0}", user.UserId);
                }
                catch (InvalidOperationException)
                {
                    message = "You must log in. Login Required";
                }
                MessageBox.Show(message);
            }
        }


Windows 8

The implementation is essentially the same for Windows 8 with the exception of how to show a message box.

private async void Page_Loaded(object sender, RoutedEventArgs e)
        {
            MobileServiceUser user = null;
            while (user == null)
            {
                string message;
                try
                {
                    user = await((App)Application.Current).Azure.MobileService.LoginAsync(MobileServiceAuthenticationProvider.Twitter);
                    message = string.Format("You are now logged in - {0}", user.UserId);
                }
                catch (InvalidOperationException)
                {
                    message = "You must log in. Login Required";
                }
                var dialog = new MessageDialog(message);
                dialog.Commands.Add(new UICommand("OK"));
                await dialog.ShowAsync();

            }
        }

The Good & Bad - so far

To this point everything is working great and we have now effectively added the authentication to each platform using the Identity features in Azure Mobile Services. But other than the url and the key of the Azure Mobile Service; there isn't a lot of code reuse in this scenario.

This is a necessity when there are platform specific implementations of a feature.  In this case, the UI needs to present differently and cannot re-use the xaml or controls that are a part of the login utility for the specified provider.

The bad part of this is it breaks the MVVM pattern to a degree by putting some of the logic in the code behind.

In the next installment, I'll show how to add an abstraction layer and use the MVVM Light Event Bus to push some of this code back to our view models.

Here is the completed code for Part 1.





Read more →

Thursday, March 28, 2013

Cross Mobile Development with Icenium

,
I have recently spent some time with Telerik's new product offering for cross mobile development called Icenium and I have to say it is quite nice.  Paired with KendoUI Mobile you can't go wrong with a great set of tools for cross mobile platform development if you are an HTML + CSS + JavaScript developer.

Icenium

Icenium is a cloud based IDE, there is also a Windows WPF Click-Once app, that allows you as a developer to leverage your existing HTML, CSS and JavaScript skills to develop hybrid cross mobile platform applications.  Assistance of publishing your applications to the Google Play and Apple Store, integrated debugging and development environment, source control integration (including Git) and much more.  See http://www.icenium.com for more information.

I will mention also that the underlying bits of Icenium is PhoneGap (Apache-Cordova) which provides and API through JavaScript (cordova.js) to the device functions such as the camera other hardware capabilities.  For more information on that piece, Jim Cowart (@ifandelse) recently did a blog entry on their blog - "Demystifying Cordova and PhoneGap".

Getting Started

Head over to Icenium.com and click the "Get Started" button. Choose either the browser (cloud) based IDE or download the Windows app.


Once the application is launched select New Project -> Cross Platform Device Application (Kendo UI Mobile). Name the project "MyBloodPressure" and click Ok.

In doing so, Icenium presents the built in "Hello World" type template. Shows how geolocation, transitions, styling using Kendo UI Mobile etc.  If you run the application by either hitting F5 or clicking the "Run" icon atop the IDE you'll also see the awesome tools for viewing the various mobile devices currently supported as well.

After you spend a few minutes playing with the emulators and realizing how cool that all is, we'll rip out some stuff add some sauce to this and get cooking.

Reorganizing the Project for Organization

I'm a very big proponent of being able to look at a project and know what the heck is going without having to hunt down someone or run the code and step through it to find out how it's all composed.  

In a C#/XAML world in I use the MVVM pattern with MVVM Light for my projects. I like to see the view folder, viewmodel folder etc. when developing the app.  For doing so here I will leverage RequireJS  for structuring the organization.  

Removing unnecessary files

Delete the hello-world.js from the scripts folder as we will not be using this for the project.

Folder structure

First, lets create a few folders.  At the root of the project create an app folder that contains view, viewmodel and model.

For any scripts that are 3rd party libraries, I prefer to put those in the scripts folder and any that are related directly to the application specific functionality I organize them within the app folder appropriately.  Given that, I'll move the kendo.mobile.min.js, jquery.min.js and also add require.js to the scripts folder

Next, add a new JavaScript file to the app folder by right clicking and selecting add new file. Name is main.js; this will be the entry point to the application.

Also add a JavaScript file to the app folder named app.js, this will serve as the singelton for exposing the viewmodels and could also be referred to as the view model locator.

First item of business is to tell require.js where to find the modules we either have or will be creating in our application. Add the following to main.js to configure require.js.

require.config({
    paths: {
        jQuery: "../scripts/jquery.min",
        kendo: "../scripts/kendo.mobile.min",
        view: "../app/view",
        viewmodel: "../app/viewmodel",
        app: "../app"
    },
    shim: {
        jQuery: {
            exports: "jQuery"
        },
        kendo: {
            deps: ["jQuery"],
            exports: "kendo"
        }
    }
});

What this is doing, if you are not familiar, is telling require.js that when a module is defined like

define(['viewmodel/bp'], function(bp) { ... } );

it knows to go look for bp.js inside of the "[root]/app/viewmodel" folder and not a relative path etc.  In the shim portion of the code we are stating that kendo has a dependency on jQuery and should wait for that library to load first.  For more information on requirejs and the config method see http://requirejs.org/docs/api.html#config .

Finally in the main.js file add the following to create the app module, put it in scope and init the application.

var app;
require(["app/app"], function (application) {
    console.log('initializing');
    app = application;
    app.init();
});

Last order of business is to add the code to app.js to tell kendo to initialize the mobile application.  Here is the full app.js code for now.

define(["jQuery", "kendo"], function ($, kendo) {
    var _kendoApplication;
    return {
        init: function () {
            console.log('app init');
            _kendoApplication = new kendo.mobile.Application(document.body,
                    { transition: "slide", layout: "mobile-tabstrip" });
        }
    }
});   

The init function is called when the application first fires up setting the transitons of the app the 'slide' and telling kendo what the layout root of the app is; in this case 'mobile-tabstrip'.

Wiring Up Index.html

Now that the scripts, view, viewmodel, entry points etc. are all setup; open index.html.

In the <head> tag remove everything except the references to the .css and cordova.js files and the we need to add the script reference to main and require.js for our entry point.  After that all scripts will be loaded using AMD and require.js . 

    <head>
        <title></title>
        <meta charset="utf-8" />
        <script src="cordova.js"></script>
        <script data-main="app/main" src="scripts/require.js"></script>
        <link href="kendo/styles/kendo.mobile.all.min.css" rel="stylesheet" />
        <link href="styles/main.css" rel="stylesheet" />
    </head>

Also remove the script tag at the bottom of the file that refers to the kendo.mobile.application as we have now moved that to the app.js init function.

Finally, remove all <div> tag sections with a data-role of view other that the first one.  These will be separated into individual html files and stored in the views folder in Part 2 of the series.  The final html document should appear as:

<!DOCTYPE html>
<html>
    <head>
        <title></title>
        <meta charset="utf-8" />
        <script src="cordova.js"></script>
        <script data-main="app/main" src="scripts/require.js"></script>
        <link href="kendo/styles/kendo.mobile.all.min.css" rel="stylesheet" />
        <link href="styles/main.css" rel="stylesheet" />
    </head>
    <body>
        <div data-role="view" id="tabstrip-home" data-title="Hello World!">
            <h1>Welcome!</h1>
            <p>
                Icenium&trade; enables you to build cross-platform device applications regardless of your
                development platform by combining the convenience of a local development toolset with the
                power and flexibility of the cloud.
            </p>
        </div>
     
        <div data-role="layout" data-id="mobile-tabstrip">
            <header data-role="header">
                <div data-role="navbar">
                    <span data-role="view-title"></span>
                </div>
            </header>
            <div data-role="footer">
                <div data-role="tabstrip">
                    <a href="#tabstrip-home" data-icon="home">Home</a>
                    <a href="#tabstrip-uiinteraction" data-icon="share">UI Interaction</a>
                    <a href="#tabstrip-geolocation" data-icon="globe">Geolocation</a>
                </div>
            </div>
        </div>
     
    </body>
</html>

Conclusion

If you run the application you can see that the application still operates as it did in the very beginning, with the exception of the additional views not appearing, but the advantage here is that the overall structure allows for manageability moving forward as complexity is added to the project through data services and additional views. 

If there is something that you would like to see in a series or have a question please add a comment. 




Read more →

Monday, March 25, 2013

Custom Routing with IRouteConstraint for ASP.NET Web API

,
I will admit that Regex and I do not speak anymore.  In fact, even when we did it was never a really nice conversation and sometimes ended in me cursing and/or leaving the room.

If you have had this same experience when creating custom routes in ASP.NET MVC then you know what I'm talking about.

IRouteConstraint
IRouteConstraint has been around for some time in MVC, but it is also available in Web API too because of course it is based on the same stack for routing.

Undoubtedly, the most difficult part of routes is debugging or getting the Regex right. I recently re-lived this experience when having to create a custom API route for a project something along the lines of

/api/{controller}/{model}/{road}/{id}

where {model} must exist in a list of valid string values and {road} is a pattern of XX9999 and then obviously the {id} must be an integer for the specific record in the list.

So, initially you start putting the Regex together for the id, "^\d+$", and then the road might be something like   "^[a-zA-Z]{2}\d{4}$".  But how should I handle the in list for the {model} param?

Sure we could put together the Regex for that, but debugging all of this is a pain even in the short term.  Also if the constraint itself is something of an edge case where the value must be a filename that exists, or a guid in memory etc; IRouteConstraint is the answer.

IRouteConstraint requires you to implement one method, Match, which returns a boolean. In the method below we are looking for one of the values being passed in the values[] parameter to a list used in the constructor.


    public class FromValuesListConstraint : IRouteConstraint
    {
        public FromValuesListConstraint(params string[] values)
        {
            this._values = values;
        }
        private readonly string[] _values;
        public bool Match(HttpContextBase httpContext,
            Route route,
            string parameterName,
            RouteValueDictionary values,
            RouteDirection routeDirection)
        {
            // Get the value called "parameterName" from the
            // RouteValueDictionary called "value"
            string value = values[parameterName].ToString();
             // Return true is the list of allowed values contains
            // this value.
            return _values.Contains(value, StringComparer.CurrentCultureIgnoreCase);
        }
    }


In order to use this from the WebApiConfig.cs class, create your route like the following.


config.Routes.MapHttpRoute(
               name: "CustomRouteNoDayOrAction",
               routeTemplate: "api/{controller}/{model}/{road}/{id}",
               defaults: null,
               constraints: new
               {
                   model = new FromValuesListConstraint("ford", "chevy", "dodge", "toyota"),
                   road = @"^[a-zA-Z]{2}\d{4}$",
                   id = @"^\d+$"
               }
);

When you run and test your routes, you can now put a break point on the FromValuesListConstraint Match method and debug the routing.




Read more →

Wednesday, February 6, 2013

South Florida Code Camp

,
I will be giving two talks this Saturday at South Florida Code Camp, being held at Nova University in Ft. Lauderdale, Fl.  For directions and more information visithttp://www.fladotnet.com/codecamp/. Schedule for other sessions here.

My Sessions


Read more →
Powered by Blogger.
 
Creative Commons License
TattooCoder.com by Shayne Boyer is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.