Downloading data using a Portable Class Library for Windows Phone and Windows 8

by Nick 16. June 2013 20:11

We’re going to take a bit of a side trip before we return to the data binding series. In this post we’re going to look at how to download data from a remote service. We’ll be using a json feed but this post should give you enough background to be able to download content from any service. There are two aspects to this post that I want to highlight:

1) We’ll be writing all the downloading and deserialization logic in a portable class library, which means it can be used across any number of target platforms.

2) We’ll be using the async-await pattern, which will greatly improve the readability of our code. I’ll illustrate the old way of downloading data for a point of reference only. I’d highly recommend getting on the asynchronous bandwagon “why await when you can async!”

We’ll be accessing a sample OData feed which is available via odata.org (http://services.odata.org/V3/OData/OData.svc/Products), which lists a number of products. You can either use the OData API Explorer (http://services.odata.org/ODataAPIExplorer/ODataAPIExplorer.html) or other tools such as Fiddler which will allow you to send http requests. The following image illustrates the formatted json response from a call to the Products url.

image

Since we want to run this across both Windows Phone and Windows I’ve got a solution with both a Windows Phone and a Windows 8 application. To this solution we’ll add a new Portable Class Library.

image 

When prompted I tweak the target frameworks – I’m not particularly interested in being limited by previous frameworks so I uncheck support for Silverlight and for Windows Phone 7.x.

image

 

Now to write some code – we’ll start with the old school way of downloading data. The following method creates a WebRequest. In order to get json data back from the OData site we need to specify the application/json Accept header. Calling BeginGetResponse invokes the GET request to retrieve data. The argument to this method is an anonymous method which is invoked when the request returns. After decoding the response, the callback passed into the DownloadJsonTheOldWay method is invoked.

public static void DownloadJsonTheOldWay<TData>
        (string url,Action<TData> callback)
{
        var req = WebRequest.CreateHttp(url);
        req.Accept = "application/json";
        req.BeginGetResponse(cb =>
        {
            var cbreq = cb.AsyncState as WebRequest;
            var resp = cbreq.EndGetResponse(cb);
            var serializer = new DataContractJsonSerializer(typeof(TData));
            using (var strm = resp.GetResponseStream())
            {
                var result = (TData)serializer.ReadObject(strm);
                callback(result);
            }
                    
        }, req);
}

 

Invoking this from our applications looks like:

protected override void OnNavigatedTo(NavigationEventArgs e)
{
    base.OnNavigatedTo(e);
    Helper.DownloadJsonTheOldWay<ProductData>
       ("http://services.odata.org/V3/OData/OData.svc/Products",DataFound);
}
 
private void DataFound(ProductData data)
{
    Debug.WriteLine(data!=null);
}

This is less than ideal as it means our application code is jumping around – easy to see in this isolated example but once our application grows in complexity it’ll be much harder to follow the flow of execution. Let’s try to improve this so that our code doesn’t jump around so much:

public static Task<TData> DownloadJsonTheOldWay<TData>(string url)
{
        var req = WebRequest.CreateHttp(url);
        req.Accept = "application/json";
        TData result = default(TData);
        var waiter = new ManualResetEvent(false);
        req.BeginGetResponse(cb =>
        {
            var cbreq = cb.AsyncState as WebRequest;
            var resp = cbreq.EndGetResponse(cb);
            var serializer = new DataContractJsonSerializer(typeof(TData));
            using (var strm = resp.GetResponseStream())
            {
                result = (TData)serializer.ReadObject(strm);
            }
            waiter.Set();
        }, req);
        waiter.WaitOne();
        return result;
}

 

In this code we’re using a ManualResetEvent to block the method until the request returns. Unfortunately if this method is invoked from the UI thread it will block that thread until the request returns – this is fine for Windows 8 but Windows Phone uses the UI thread as part of invoking web requests. The net effect is that this code will block indefinitely on Windows Phone.

Right, so we need to find a way to prevent the UI thread from being blocked. This can be done by invoking the previous attempt on a different thread. In fact we can leverage the async-await pattern:

public async static Task<TData> DownloadJsonTheOldWay<TData>(string url)
{
    return await Task.Run(() =>
        {
            var req = WebRequest.CreateHttp(url);
            req.Accept = "application/json";
            TData result = default(TData);
            var waiter = new ManualResetEvent(false);
            req.BeginGetResponse(cb =>
                {
                    var cbreq = cb.AsyncState as WebRequest;
                    var resp = cbreq.EndGetResponse(cb);
                    var serializer = new DataContractJsonSerializer(typeof(TData));
                    using (var strm = resp.GetResponseStream())
                    {
                        result = (TData)serializer.ReadObject(strm);
                    }
                    waiter.Set();
                }, req);
            waiter.WaitOne();
            return result;
        });
}

Now, the code in our application looks much cleaner:

protected async override void OnNavigatedTo(NavigationEventArgs e)
{
    base.OnNavigatedTo(e);
 
        var data = await Helper.DownloadJsonTheOldWay<ProductData>
                        ("http://services.odata.org/V3/OData/OData.svc/Products");
        Debug.WriteLine(data != null);
}

 

In fact, the pattern of BeginXXX, EndXXX is quite common amongst traditional .NET apis. So much so that as part of the asynchronous programming library there is a Factory method which can be used to simplify this code somewhat:

public async static Task<TData> DownloadJson<TData>(string url)
{
    var req = WebRequest.CreateHttp(url);
    req.Accept = "application/json";
    var resp = await Task.Factory.FromAsync<WebResponse>
                    (req.BeginGetResponse, req.EndGetResponse, null);
    var serializer = new DataContractJsonSerializer(typeof(TData));
    using (var strm = resp.GetResponseStream())
    {
        var data = (TData)serializer.ReadObject(strm);
        return data;
    }
}

 

The Factory.FromAsync brings together the BeginGetResponse and EndGetResponse into a single line to return the response of the request. This works well on Windows 8. However, on Windows Phone an exception is thrown as read stream buffering needs to be enabled. This is done by adding “req.AllowReadStreamBuffering = true;” before invoking the request. Unfortunately whilst adding this means the code works for Windows Phone, it then breaks for Windows 8.

The solution, and the last piece to our code, is some conditional logic to determine if the code is being invoked on Windows RT (ie Windows 8) or not. If it is, then read stream buffering is not enabled.

private static bool IsWinRT { get; set; }
static Helper ()
{
    var wrt = Type.GetType("Windows.ApplicationModel.DesignMode, Windows, ContentType=WindowsRuntime");
    if (wrt != null)
    {
        IsWinRT = true;
    }
 
}
public async static Task<TData> DownloadJson<TData>(string url)
{
    var req = WebRequest.CreateHttp(url);
    if (!IsWinRT)
    {
        req.AllowReadStreamBuffering = true;
    }
    req.Accept = "application/json";
    var resp = await Task.Factory.FromAsync<WebResponse>
              (req.BeginGetResponse, req.EndGetResponse, null);
    var serializer = new DataContractJsonSerializer(typeof(TData));
    using (var strm = resp.GetResponseStream())
    {
        var data = (TData)serializer.ReadObject(strm);
        return data;
    }
}

We can invoke this method from either Windows Phone or Windows 8, giving us a single line way to download and decode json from any remote uri.

image

Tags:

Introduction To Data Binding for Windows and Windows Phone (part 2)

by Nick 16. June 2013 17:16

<< Introduction To Data Binding for Windows and Windows Phone (part 1)

In the first part of this series we introduced the concept of data binding and how it can be used to associated an attribute on a visual element with a property on a data entity. The question we left unanswered is “why should we use data binding?”. There are countless answers to this question and rather than bore you with them I want to illustrate some of neat things you can do with a combination of data binding and the designer experience in both Visual Studio and Blend.

Example Requirements: Display a simple list of people; each person is represented by a Name and an Age; the list should display both Name and Age; when the user selects an item in the list, a MessageBox should be displayed indicating which person was selected.

We’re going to need a Person class:

public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
}

and an array of people:

var people = new[]
    {
        new Person {Name = "Fred", Age = 29},
        new Person {Name = "Matilda", Age = 13},
        new Person {Name = "Jane", Age = 33}
    };

We’ll create a ListBox on our page (we’ve added the SelectionChanged event handler at this point too so we don’t need to come back later…)

<Grid>
    <ListBox x:Name="PeopleList"
                SelectionChanged="PersonSelectionChanged" />
</Grid>

Let’s start off doing this the hard way, without data binding. We need to add each person in the people array into the ListBox:

foreach (var person in people)
{
    PeopleList.Items.Add(person);
}

Which displays as the following – we have the right number of rows in the ListBox but not the desired look.

image

A quick and dirty solution is to add DisplayMemberPath="Name" to the ListBox declaration. This yields a minor improvement where we can at least see the person’s name.

 image

In order to style the list any further for each person we need to create a ListBoxItem and child elements to represent the visual layout we want.

var textStyle = Application.Current.Resources["PhoneTextNormalStyle"] as Style;
foreach (var person in people)
{
    var lbi = new ListBoxItem();
    var sp = new StackPanel { 
          Orientation = System.Windows.Controls.Orientation.Horizontal };
    sp.Children.Add(new TextBlock { 
                      Text = person.Age.ToString(), 
                      Style = textStyle });
    sp.Children.Add(new TextBlock { 
                      Text = person.Name, 
                      Style = textStyle });
    lbi.Content = sp;
    PeopleList.Items.Add(lbi);
}

The structure for each person in the list is a horizontal StackPanel containing two TextBlock elements, displaying the Age and Name of the person. We’ve used one of the built in styles, PhoneTextNormalStyle, to try to improve the appearance of the TextBlocks.

image

Now, lets complete the example by writing the event handler which is going to display the name of the person that the user has selected in the list:

private void PersonSelectionChanged(object sender, 
                   SelectionChangedEventArgs e) {
            var lst = sender as ListBox;
            var lbi = lst.SelectedItem as ListBoxItem;
            .... some nasty code to get the Name out....

At this point we figure we have a problem – we can get the Name and Age values by looking for the appropriate TextBlocks and extracting the Text property. However, this doesn’t give us a reference to the Person object…. in fact the original person objects are now out of scope and no longer exist. We need a way to pass the Person object along for the ride. Let’s simply set the Tag property on the ListBoxItem (ie lbi.Tag = person; ). Completing the code we have:

private void PersonSelectionChanged(object sender, 
                   SelectionChangedEventArgs e)
{
    var lst = sender as ListBox;
    var lbi = lst.SelectedItem as ListBoxItem;
    var person = lbi.Tag as Person;
    MessageBox.Show(person.Name);
}

 

This is an incredibly simple, contrived, example and yet we’ve had to write quite a lot of code and do some hacky things in order to pass data around. Now imagine the scenario that the requirements change and that the order of the Age and Name should be reversed, or a vertical StackPanel should be used, or another property is added to the Person class which needs to be displayed. In this example it wouldn’t be that hard to find the line(s) of code to change but you can imagine that in a large complex system it would be a nightmare to find the write code, visualise what the item will look like and make the appropriate change. Wouldn’t it be nice if there was a design tool to help?

The good news is that by using data binding you:

a) get to reduce and simplify the code you write

b) get a design experience for constructing the user experience

At this point I’m going to step into Blend as I prefer its design experience over the limited designer in Visual Studio. Whilst most of the tool windows and the design surface are now shared between the products, there are still some design aspects that Blend has which Visual Studio doesn’t (such as being able to design Visual States). I also find that by switching tools I’m making a mental shift from developer mode to designer mode.

Open your solution in Blend.

The first thing we’re going to do is to create some sample data with the same shape as the data we need to display. When I say shape I’m referring to the object hierarchy and the properties on the classes. In this example we have an array of Person objects, each one with an Age (Number) and Name (String). So, we need to create design time data which has a collection of entities, each with an attribute called Age which is a Number, and an attribute called Name which is a String.

From the Data windows, select New Sample Data

image

Give your sample data a name, and hit OK (we’ll come back to the “enable sample data” option a little later).

image

In the Data window you can now adjust the names of the properties: Change Collection to PersonCollection, Property1 to Name and Property 2 to Age, and change the Type of Age to Number.

image

Drag the PersonCollection node from the Data window across onto the PeopleList node on the Obejcts and Timeline window (note the help prompt that appears indicating what’s about to happen).

image

When you let the mouse go, you’ll see a new ListBox appear on the screen full of the sample data you just created.

image

Now all you need to do is to change the layout according to the requirements. Right-click the PeopleList node in the Objects and Timeline window and select Edit Additional Template; Edit Generated Items (ItemTemplate); Edit Current.

image

You’re now in template editing mode where you can modify the layout of each item in the list (you can think of the ItemTemplate being a cookie cutter or a mould for each item that will appear in the list).

Select the StackPanel and change the orientation to Horizontal via the Properties window.

image

Right-click on each TextBlock in turn and select Edit Style; Apply Resource; PhoneTextNormalStyle

image

Your layout, at design time, should look very similar to the desired output.

image

You can run the application to verify how it appears but you’ll notice that it is still displaying the design time data. We need to firstly disable design time data, at runtime, and secondly we need to actually wire up the real data.

To disable design time data at runtime, from the Data window, click the icon alongside the PeopleDataSource and uncheck the Enable When Running Application. Now when you run the application you won’t see the design time data.

image

In order to wire up data we need to take a closer look at what Blend did for us when we dragged across the design time data. Looking at the XAML you’ll see that the ItemTemplate and ItemsSource attributes have been specified. In actual fact, what you may not have realised is that you have just been adjusting the ItemTemplate attribute value when modifying the layout for each item. 

<Grid>
    <ListBox x:Name="PeopleList"
                SelectionChanged="PersonSelectionChanged"
                ItemTemplate="{StaticResource PersonCollectionItemTemplate}"
                ItemsSource="{Binding PersonCollection}" />
</Grid>

It’s the ItemsSource property that we’re particularly interested in – this is what determines where the items in the ListBox are going to be sourced from. This has been data bound to the PersonCollection property on the current DataContext (recall this from my previous post).

There is no DataContext explicitly set on the ListBox. So, the simplest solution to wiring up real data is to set the DataContext on the ListBox to be an entity that has a PersonCollection property which returns the Person entities which should be added to the ListBox. For this we’ll create a MainPageData class (this is kind of the prelude to a ViewModel which we’ll discuss in the context of the MVVM design pattern).

public class MainPageData
{
    public Person[] PersonCollection { get; set; }
}

 

Now all we need to do is to create an instance of our MainPageData and set it as the DataContext on the ListBox.

PeopleList.DataContext = new MainPageData 
                          {PersonCollection = people};

 

Furthermore, our event handler code can be simplified because the SelectedItem property now returns the actual data item (ie a Person) instead of a generic ListBoxItem.

private void PersonSelectionChanged
          (object sender, SelectionChangedEventArgs e)
{
    var lst = sender as ListBox;
    var person = lst.SelectedItem as Person;
    MessageBox.Show(person.Name);
}

 

You might be thinking “how is our data being wired up to the layout we defined in the designer for each item in the list?” The answer is in the ItemTemplate attribute of the ListBox. This references a static resource, PersonCollectionItemTemplate, which is defined elsewhere on the same page:

<phone:PhoneApplicationPage.Resources>
    <DataTemplate x:Key="PersonCollectionItemTemplate">
        <StackPanel Orientation="Horizontal">
            <TextBlock Text="{Binding Age}"
                        Style="{StaticResource PhoneTextNormalStyle}" />
            <TextBlock Text="{Binding Name}"
                        Style="{StaticResource PhoneTextNormalStyle}" />
        </StackPanel>
    </DataTemplate>
</phone:PhoneApplicationPage.Resources>

Here we can again see that the structure of each item in the list is a horizontal StackPanel with two TextBlock elements with Style set to PhoneTextNormalStyle. You’ll also notice that the Text attribute for each TextBlock has been data bound to the Age and Name properties respectively. Whilst no DataContext is explicitly defined for either TextBlock, nor the StackPanel, the DataContext is implicitly set to be the item in the list that is being rendered. In other words, when a Person object is being displayed in the list, this template is used to stamp out the appropriate visual elements. The DataContext for each element in the template is set to the Person object, and the data binding expression establishes an association between the Text attributes and the Age and Name properties on the Person object.

The upshot is that we have significant less C# code for wiring up the ListBox data and, other than setting the DataContext on the ListBox, it doesn’t manipulate the user interface. We also have a design time experience which will allow us to easily go back and tweak the layout of the ListBox items at any time in the future.

Hopefully you’ve started to see the power of data binding. This is just the tip of the iceberg and we’ll go into more detail in coming posts.

Tags:

Introduction To Data Binding for Windows and Windows Phone (part 1)

by Nick 15. June 2013 18:28

Introduction To Data Binding for Windows and Windows Phone (part 2) >>

Given how long Microsoft has been using XAML in one shape or another across a range of technologies (WPF, Silverlight, Windows Phone, XBox, Windows 8) it still surprises me how often I get asked about data binding. In this series we’re going to go back to basics and take a look at how to use data binding within you Window 8 and Windows Phone application. For the most part I’ll focus on Windows Phone but data binding across these platforms is relatively similar, so a lot of the concepts will carry across without me having to give multiple examples. Additionally, most of these concepts will apply equally well to data binding in Silverlight or WPF.

There are a couple of questions that we need to address:

- What is data binding?

- Why do we need data binding?

Let’s address the first question in this post by walking through an example. On our page we have two TextBlock elements that display the application title and the page name. These are illustrated with static placeholder text values (we’ll discuss design time data in a later post), which will be replaced with the actual values when the application is run.

image 

<StackPanel x:Name="TitlePanel">
    <TextBlock x:Name="ApplicationTitle" Text="MY APPLICATION" />    
    <TextBlock x:Name="PageTitle" Text="page name" />
</StackPanel>

Without data binding in order to update the Text property on the TextBlock elements you would have see code like this:

ApplicationTitle.Text = "DATA BINDING ROCKS!";
PageTitle.Text = "simple data binding";

Now, let’s do the same thing with data binding. Firstly, the XAML:

<StackPanel x:Name="TitlePanel" >
    <TextBlock x:Name="ApplicationTitle" Text="{Binding}" />
    <TextBlock x:Name="PageTitle" Text="{Binding}" />
</StackPanel>
 

Next, the code:

ApplicationTitle.DataContext = "DATA BINDING ROCKS!";
PageTitle.DataContext = "simple data binding";

If you look at the XAML instead of setting the Text property on the TextBlock elements to an explicit value, the attribute value is wrapped in { } – this essentially means that the value needs to be calculated some how (another typical usage of the { } value is for referencing a static resource). In this case the calculation is to create the data binding relationship between the Text property on the TextBlock and whatever is set as the current DataContext on the TextBlock. When we then set the DataContext on the TextBlock element it flows down into the Text property.

image

Where data binding starts to get more interesting is when you set the DataContext to be a more complex object. For example we might have a PageInfo class which contains the application title and page name:

var pi = new PageInfo
    {
        ApplicationTitle = "DATA BINDING ROCKS!",
        PageTitle = "simple data binding"
    };
 
ApplicationTitle.DataContext = pi;
PageTitle.DataContext = pi;

In this case we’re setting the DataContext on both TextBlock elements to be the PageInfo instance. When we run this what we see is that the data binding framework has literally just called “ToString()” on the object, which by default returns the type name as we can see in this image.

image

This isn’t what we want! What we want is that the first TextBlock should show the ApplicationTitle property and the second should show the PageTitle property. To do this we use the Path attribute on the data binding expression:

<StackPanel x:Name="TitlePanel" >
    <TextBlock x:Name="ApplicationTitle"
                Text="{Binding Path=ApplicationTitle}" />
    <TextBlock x:Name="PageTitle"
                Text="{Binding PageTitle}" />
</StackPanel>

In the second TextBlock the  “Path=” has been omitted to illustrate the shorthand way to specify the Path attribute. In both cases the binding expression is setting up a data binding relationship between the Text property on the TextBlock with the ApplicationTitle (or PageTitle) property on the current DataContext, which in this case is an instance of the PageInfo class.

An interesting aspect of the DataContext property on a UIElement is that by default it is inherited from its parent element. So for example in our scenario both TextBlock elements are situated within a StackPanel (ie the TitlePanel). By default (ie if the DataContext isn’t explicitly set on the TextBlock) they will both inherit the DataContext of the StackPanel. This means we could reduce our code to:

var pi = new PageInfo
    {
        ApplicationTitle = "DATA BINDING ROCKS!",
        PageTitle = "simple data binding"
    };
 
TitlePanel.DataContext = pi;

(At this point we can also remove the x:Name attribute on both TextBlock elements as they are no longer required)

Let’s just confirm our understanding of this:

- The  “{Binding ApplicationTitle}” expression is shorthand for  “{Binding Path=ApplicationTitle}”

- Text=“{Binding ApplicationTitle” sets up a binding relationship between the Text property on the TextBlock with the ApplicationTitle on the current DataContext

- The DataContext of the TextBlock is inherited from its parent element, the TitlePanel StackPanel.

- We’re explicitly setting the DataContext on the TitlePanel, allowing it to be inherited by the TextBlock elements.

An alternative would be to set the DataContext on the entire page:

var pi = new PageInfo
    {
        ApplicationTitle = "DATA BINDING ROCKS!",
        PageTitle = "simple data binding"
    };
 
this.DataContext = pi;

 

In this case our code is being executed in the context of the page, so the “this” is the page and so we’re setting the DataContext on the page and allowing it to flow down to every element on the page.

The answer to the first question, “what is data binding?”, is that it’s about establishing an association between an attribute on a visual element with a data entity, or a property on a data entity. As we’ll see over the coming posts, data binding allows to separate the logic of our application from the way it is presented on the screen. This not only allows for cleaner and more manageable code, it also allows developers and designers to work independently on the same application.

In the next post we’ll look at why you should be using data binding and the saving it offers to application developers.

Tags:

Development

Some great SQLite for Windows Phone posts

by Nick 9. June 2013 20:22

Tags:

Development

Windows Azure Mobile Service to SQLite Data Sync for Windows Phone and Windows RT with Portable Class Libraries - Conflicts

by Nick 8. June 2013 20:02

In my previous post, Windows Azure Mobile Service to SQLite Data Sync…, I covered a simple framework for synchronising entities between Windows Azure Mobile Service (WAMS) and SQLite. Anyone familiar with synchronisation logic will of course have scoffed at this framework concluding that I haven’t dealt with cases where there are synchronisation conflicts, and they’d be correct. Well in actual fact I have: I assumed an optimistic resolution policy which states that the last update is the correct one to take. In this post I’ll cover a better approach to conflict resolution.

For the benefit of those who haven’t had to deal with synchronisation logic in the past, one of the common conflict scenarios is as follows:

- Users A and B both synchronise the same set of data so they both have local copies of the data, including a Person record: Person {Name = Jane, Age = 25}

- User A makes a change to the record: Person {Name = Jane, Age = 32}

- User B makes a change to the record:  Person {Name = Jane, Age = 30}

- User A synchronises with WAMS first, updating the server record to Person {Name = Jane, Age = 30}

- User B attempts to synchronise with WAMS

Current Scenario:

Under the current scenario the server record gets pulled down, effectively overwriting the record User B has updated

This assumes that User A’s update is correct, even though it was done before that of User B, just because User A synchronised before User B.

Alternate Scenario:

When User B attempts to synchronise, WAMS should reject the change, indicating that the record has changed since the last time User B synchronised. It should also return the current record, allowing User B to determine what the correct record is.

The question now becomes how do we extend the synchronisation logic presented in the previous post, to deal with this scenario.

WAMS 

The first step is to adjust WAMS to prevent updates to records where the data has changed since the last synchronisation. Note, we don’t need to handle inserts, since they are by definition unique (although it is possible that both User A and User B entered the same new record, they are unique and its up to the individual application to allow for duplicate records to be combined somehow).

When updated records are sent to WAMS the LastUpdated property is the same as when that record was last retrieved from WAMS (the LocalLastUpdated field is used to track records that have changed locally). As such, in the update script in WAMS it is possible to detect whether the record has been updated since the LastUpdated time. If it has we’ll return a 409 Conflict error, as per the following script.

function update(item, user, request) {
        console.log('Find existing entity with Id '+ item.id);
        var personTable = tables.getTable('Person');
    
        personTable.where({
            id: item.id
        }).read({
            success: checkLastUpdated,
            error: checkFailed
        });
 
    function checkLastUpdated(results) {
        if (results.length > 0) {
            console.log('Entity Id ' + results[0].id);
            if(results[0].LastUpdated>item.LastUpdated){
                console.log('Conflict found, not updating record');
                request.respond(statusCodes.CONFLICT,
                   "Entity has changed since last synchronisation");
            }
            else {
                console.log('No conflict, updating record');
                item.LastUpdated=new Date();
                request.execute();
            }
        }
        else {
            console.log('Entity search found no records');
            request.respond(statusCodes.NOT_FOUND,"Entity not found");
        }
    }
 
    function checkFailed()
    {
        console.log('Entity search failed');
        request.respond(statusCodes.NOT_FOUND,"Entity not found");
    }
}

 

If we run the application on two devices we can generate this conflict by synchronising both application instances. Changing the same record on both devices, synchronising one, and then synchronising the second. Note: The client side logic in part caters for this already by downloading changes from the server before uploading the client changes. If you jump over this in the debugger on the second client, you can see the 404 error that is raised when the conflict is detected:

image

If you check out the logs on WAMS you’ll see the output from the console.log statements that were in the update script:

image

 

Synchronisation Logic

There are two parts where we need to add conflict resolution:

- When server changes are downloaded – currently the updates from User A would be synchronised to the device, overwriting the changes from User B

- When local changes are uploaded – any conflicts with server records will result in a 409 failure.

 

Server Changes

To handle server changes we’ll add logic which will detect whether any of the downloaded changes conflict with any of the pending local changes. If there is a conflict, we need to store the downloaded record, alongside the local record, so that the user can choose which is the correct record. In this case we’re assigning the downloaded record a negative Id starting at –1000 (ie ConflictMarkerValue = –1). Whilst this limits us to 1000 new records (remember we assign new records a negative Id starting at –1) it means that we can effectively use the same table to store new, existing and conflict records.

// Check for update conflicts
var conflict = (from delta in updatedentities
                where delta.Id == entity.Id
                select delta).FirstOrDefault();
if (conflict != null)
{
    conflictsFound = true;
    var id = ConflictMarkerValue - entity.Id;
    var existing = await (from x in con.Table<TEntity>()
                    where x.Id == id
                    select x).FirstOrDefaultAsync();
    entity.Id = id;
    if (existing != null)
    {
                        
        await con.UpdateAsync(entity);
    }
    else
    {
        await con.InsertAsync(entity);
    }
    continue;
}

 

You’ll also note that we set the conflictsFound flag to true. After iterating through all the downloaded records, if conflictsFound is true, the Sync method exits, returning a completed value of false – this is because we don’t want to upload any local records until the downloaded conflicts have been resolved. This will actually cover us with the second part where a 409 error gets returned but we’ll come to that in a minute.

If synchronisation doesn’t complete correctly we’ll need a mechanism for the user to iterate through the records that are in conflict and determine which record is correct.

public async Task<List<Conflict<TEntity>>> RetrieveConflicts<TEntity>()
    where TEntity : class, ISyncableEntity, new()
{
    var con = await Connect();
    // Retrieve the list of conflicted local entities
    var updatedentities = await (from remote in con.Table<TEntity>()
                                    where remote.Id <ConflictMarkerValue
                                    select remote).ToListAsync();
    var list = new List<Conflict<TEntity>>();
    foreach (var remote in updatedentities)
    {
        var id = -(remote.Id - ConflictMarkerValue);
        var pair = await (from local in con.Table<TEntity>()
                            where local.Id == id && 
                                      local.Id>ConflictMarkerValue
                            select local).FirstOrDefaultAsync();
        list.Add(new Conflict<TEntity>{Local = pair, Remote = remote});
    }
    return list;
}

 

The list of conflicts can then be presented to the user, allowing them to make a decision as to which record they wish to keep:

image

When the user clicks the Accept Local or Accept Remote (clearly not a production-ready UX!) the ResolveConflict method is called:

public async Task ResolveConflict<TEntity>(Conflict<TEntity> conflict)
    where TEntity : class, ISyncableEntity, new()
{
    if(!conflict.ResolveLocal.HasValue)
         throw new Exception("Conflict not resolved");
 
    var con = await Connect();
            
    // Make sure we delete the conflicted record
    await con.DeleteAsync(conflict.Remote);
 
    if (conflict.ResolveLocal.Value)
    {
        conflict.Local.LastUpdated = conflict.Remote.LastUpdated;
        await con.UpdateAsync(conflict.Local);
    }
    else
    {
        conflict.Remote.LocalLastUpdated = DateTime.MaxValue;
        conflict.Remote.Id = conflict.Local.Id;
        await con.UpdateAsync(conflict.Remote);
    }
}

If the user selects the local record to keep, then we simply update the LastUpdated value to when the records was last retrieved (ie when the conflict was discovered). If the user selects to keep the remote record, we simply overwrite the existing record with the remote record. Either way the changes are currently local only, which means we still need to force a Sync in order for those changes to propagate back to the server.

 

Local Changes

If there is a failure whilst uploading local changes to do with a conflict then the server will have returned a 409 Conflict. This error needs to be detected and the conflict resolved. However, when the server returns a 409 it doesn’t return the current server value. As such, we actually need to force another synchronisation in order to download the conflicting records (see previous section). To do this, we simply need to call Sync again!

catch (MobileServiceInvalidOperationException ex)
{
    if(ex.Response.StatusCode == HttpStatusCode.Conflict)
    {
        syncAgain = true;
    }
}
 
// Try sync again - this should retrieve conflicts
if (syncAgain)
{
    return await Sync<TEntity>();
}

These additions will help reduce any issues with conflicts. There are still some areas of weakness, for example the server validation isn’t carried out in a transaction, allowing for a write in between the read and write logic.

Tags:

Windows Azure Mobile Service to SQLite Data Sync for Windows Phone and Windows RT with Portable Class Libraries

by Nick 8. June 2013 12:41

Following my 4 part series on using two different forms of SQLite across Windows Phone and Windows RT I thought I’d take a couple of hours to see how hard it would be to build a generic synchronisation framework that would allow me to synchronise data between SQLite and a Windows Azure Mobile Service (WAMS). Of course as I want it to work across both Windows Phone and Windows RT I want to make sure all my logic is contained within a Portable Class Library (PCL) – this is initially made possible by the awesome support the WAMS has for PCL. If you haven’t already read my previous posts on SQLite, here a summary list:

Windows (RT and Phone) and Sqlite (Part 1)
Windows (RT and Phone) and Sqlite (Part 2)
Windows (RT and Phone) and Sqlite (Part 3)
Windows (RT and Phone) and Sqlite (Part 4)

Now I apologise in advance, synchronisation is not simple, which may make this post long and hard to follow. I’m also certain that since I wrote this logic in the space of a couple of hours, I’m sure there are bugs I haven’t polished out – the idea here is to give you a heads up on how easily you can write this logic yourself.

We’ll start with some basics:

INotifyPropertyChanged

Since I want my entities to be bindable, and be able to update the UI, all my entities will need to implement INotifiyPropertyChanged. Rather than code this into each entity I, like many others, have a base class that implements this interface and exposes a helper method OnPropertyChanged which can be called when a property is changed.

public class NotifyBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged
                    ([CallerMemberName] string propertyName = null)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null) 
            handler(this, new PropertyChangedEventArgs(propertyName));
    }
}

 

ISyncableEntity

Let’s start with what this interface looks like:

public interface ISyncableEntity
{
    int Id { get; set; }
    bool IsDeleted { get; set; }
    DateTime LastUpdated { get; set; }
 
    DateTime LocalLastUpdated { get; set; }
}

All our entities are going to need to implement this interface because it exposes the minimal set of properties we need in order to do bi-directional synchronisation. By this I mean be able to push all local changes (insert, update, delete) up to WAMS, as well as receive updates back from WAMS (insert, update and delete).

WAMS uses an int as the primary key for all entities. This makes change tracking a little hard as you need to use negative ids to track new entities.

If you’re doing bi-directional synchronisation across any number of clients you need to do logical, not real deletes. This means that all entities will need an IsDeleted flag so that you can a) track local deletes and push them to WAMS before actually removing the local entity and b) so that you can pull a list of deleted entities from WAMS so that they can be removed locally.

The LastUpdated field is used to track when the entity was last updated server-side. Golden rule of synchronisation is never trust the client apps. The LocalLastUpdated field is used to track local updates (ie which entities have been modified) and is not synchronised to WAMS

 

BaseEntity

Rather than having to implement all those properties on each entity I added a BaseEntity which has these properties.

[DataContract]
public class BaseEntity : NotifyBase, ISyncableEntity
{
    [PrimaryKey,DataMember]
    public int Id { get; set; }
 
    [DataMember]
    public bool IsDeleted { get; set; }
 
    [DataMember]
    public DateTime LastUpdated { get; set; }
 
    [IgnoreDataMember]
    public DateTime LocalLastUpdated { get; set; }
}

You’ll notice that we’ve added the PrimaryKey attribute to the Id field and have marked the LocalLastUpdated field with the Ignore attribute. The Ignore attribute will prevent that field from being sent to WAMS.

 

Person

This is going to be the entity that I’m going to be synchronising. As you can image it’s going to inherit from BaseEntity. It also has the DataContract and DataMember attributes to aid with synchronisation.

[DataContract]
public class Person : BaseEntity
{
    private string name;
    [DataMember]
    public string Name
    {
        get { return name; }
        set
        {
            if (Name == value) return;
            name = value;
            OnPropertyChanged();
        }
    }
 
    private int age;
    [DataMember]
    public int Age
    {
        get { return age; }
        set
        {
            if (Age == value) return;
            age = value;
            OnPropertyChanged();
        }
    }
}

 

At this point it’s worth creating the corresponding table in WAMS. When you create it, you’ll see it appear with a single int Id column – don’t worry, the other columns will get created automatically as you start to synchronise data. Of course, when you go to production you’ll want to disable the dynamic schema capability of WAMS but for the timebeing it makes life easier.

 

MainViewModel

For my single page application I have MainPage.xaml with a corresponding view model, MainViewModel (as per code below). This also inherits from NotifyBase so that it can raise property change events to update the UI when values change. MainViewModel also exposes a StateChanged event which is raised when the view model wants the page to change visual state – I’m not a big fan of having string literals lying around so I use an enumeration to determine which state to go between. Essentially there are two states representing the list of people (Normal) and editing a person (EditPerson).

The MainViewModel has two properties that are exposed for data binding: People, an ObservableCollection of our Person entity, and CurrentPerson. CurrentPerson is used by the EditPerson state to allow the user to add or edit a person record.

The bulk of the heavy lifting has been abstracted away into the DataService class, which we’ll talk about in a minute. The DataService class needs to be initiated with an instance of the ISQLiteConnectionFactory, a path to where the database will be stored, and the endpoint and application key for the mobile service. It also requires a list of entity types that it needs to track and sync. With this information, it’s able to expose very simple methods for loading, saving, deleting and synchronising entities.

public class MainViewModel:NotifyBase
{
    #region ---------------------- Visual States ----------------------
 
    private enum States
    {
        Base,
        EditPerson,
        Normal
    }
    public event EventHandler<StateChangedEventArgs> StateChanged;
 
    #endregion  ---------------------- ----------------------
 
 
 
 
    #region  ---------------------- Data binding properties ----------------------
 
    private Person currentPerson;
    public Person CurrentPerson
    {
        get { return currentPerson; }
        set
        {
            if (CurrentPerson == value) return;
            currentPerson = value;
            OnPropertyChanged();
        }
    }
 
    private readonly ObservableCollection<Person> people = new ObservableCollection<Person>();
    public ObservableCollection<Person> People
    {
        get { return people; }
    }
 
    #endregion  ---------------------- ----------------------
 
 
 
 
    #region ---------------------- Configure Data Service ----------------------
 
    private readonly DataService data = new DataService();
    public DataService Data
    {
        get
        {
            return data;
        }
    }
 
    public void Initialise(string databasePath, ISQLiteConnectionFactory sqLiteConnectionFactory)
    {
        Data.ConfigureDatabase(sqLiteConnectionFactory, databasePath, typeof(Person));
        Data.ConfigureMobileService("https://xxxx.azure-mobile.net/", "--not a real key--");
    }
 
    #endregion  ---------------------- ----------------------
 
 
 
    #region ---------------------- Local Operations ----------------------
 
    /// <summary>
    /// Load data into the people collection (which
    /// will automatically populate the UI)
    /// </summary>
    /// <returns></returns>
    public async Task Load()
    {
        var list = await Data.Load<Person>();
        People.Clear();
        foreach (var person in list)
        {
            People.Add(person);
        }
    }
 
    /// <summary>
    /// Save a new or existing person
    /// </summary>
    public async void SavePerson()
    {
        if (CurrentPerson == null) return;
 
        await Data.Save(CurrentPerson);
 
        if (!People.Contains(CurrentPerson))
        {
            People.Add(CurrentPerson);
        }
 
        CurrentPerson = null;
        StateChanged(this, States.Normal.ToString());
            
    }
 
    /// <summary>
    /// Delete the current person
    /// </summary>
    public async void DeletePerson()
    {
        await Data.Delete(CurrentPerson);
 
        if (People.Contains(CurrentPerson))
        {
            People.Remove(CurrentPerson);
        }
 
        CurrentPerson = null;
        StateChanged(this, States.Normal.ToString());
    }
 
    #endregion ---------------------- ----------------------
 
 
    #region ---------------------- Synchronisation (and reload) ----------------------
        
    /// <summary>
    /// Synchronise local data with WAMS
    /// </summary>
    public async void Sync()
    {
        await Data.Sync<Person>();
 
        await Load();
    }
 
    #endregion ---------------------- ----------------------
 
 
    /// <summary>
    /// Enter edit mode for a new person
    /// </summary>
    public void BeginAddPerson()
    {
        CurrentPerson = new Person();
        StateChanged(this, States.EditPerson.ToString());
    }
 
    /// <summary>
    /// Enter edit mode for an existing person
    /// </summary>
    /// <param name="p"></param>
    public void BeginEditPerson(Person p)
    {
        CurrentPerson = p;
        StateChanged(this, States.EditPerson.ToString());
    }
 
    /// <summary>
    /// Cancel the current edit
    /// </summary>
    public void CancelPersonEdit()
    {
        CurrentPerson = null;
        StateChanged(this, States.Normal.ToString());
 
    }
}

 

DataService

Now onto the good stuff… In this post I’m not going to go through the details of this class but it’s all here (and in the attached sample solution) for you to browse:

public class DataService
{
    private class SyncMarker
    {
        [PrimaryKey]
        public string TypeName { get; set; }
        public DateTime LastSynced { get; set; }
    }
 
 
    private MobileServiceClient MobileService { get; set; }
 
    private ISQLiteConnectionFactory Factory { get; set; }
    private string DatabasePath { get; set; }
    private string MobileServiceEndpoint { get; set; }
    private string MobileServiceApplicationKey { get;  set; }
 
    private Type[] Tables { get; set; }
 
    public void ConfigureDatabase
        (ISQLiteConnectionFactory factory, string path, params Type[] tables)
    {
        Factory = factory;
        DatabasePath = path;
        tables = tables ?? new Type[] {};
        Tables =  tables.Union(new[] {typeof (SyncMarker)}).ToArray();
    }
 
    public void ConfigureMobileService(string endpoint, string applicationKey)
    {
        MobileServiceEndpoint = endpoint;
        MobileServiceApplicationKey = applicationKey;
        MobileService = new MobileServiceClient(MobileServiceEndpoint, 
                                                MobileServiceApplicationKey);
    }
 
    private ISQLiteAsyncConnection connection;
    private async Task<ISQLiteAsyncConnection> Connect()
    {
        if (connection == null)
        {
            connection = Factory.CreateAsync(DatabasePath, true);
            await connection.CreateTablesAsync(Tables);
        }
        return connection;
    }
 
    public async Task<List<TEntity>> Load<TEntity>() 
        where TEntity : class, ISyncableEntity, new()
    {
                    var con = await Connect();
                    var list = await (from p in con.Table<TEntity>()
                                where p.IsDeleted!=true
                                select p).ToListAsync();
        return list;
    }
 
    public async Task Save<TEntity>(TEntity entity) 
        where TEntity : class, ISyncableEntity, new()
    {
        if (entity == null) return ;
 
        var con = await Connect();
        entity.LocalLastUpdated = DateTime.MaxValue;
        if (entity.Id != 0)
        {
            await con.UpdateAsync(entity);
        }
        else
        {
            var minentityId = await (from p in con.Table<TEntity>()
                                    where p.Id < 0
                                    orderby p.Id
                                    select p).FirstOrDefaultAsync();
            var minId = (minentityId != null ? minentityId.Id : 0) - 1;
            entity.Id = minId;
            entity.LastUpdated = DateTime.MinValue;
 
            await con.InsertAsync(entity);
        }
    }
 
    public async Task Delete<TEntity>(TEntity entity) 
        where TEntity : class, ISyncableEntity, new()
    {
        if (entity == null) return;
 
 
        var con = await Connect();
        entity.LocalLastUpdated = DateTime.MaxValue;
        entity.IsDeleted = true;
        if (entity.Id == 0)
        {
            // entity hasn't been saved locally, so simply return
            // nothing more to do (it's like cancel!)
        }
        else if (entity.Id > 0)
        {
            await con.UpdateAsync(entity);
        }
        else
        {
            // Id<0 indicates new entity which hasn't been sync'd
            // so can simply remove out of local db
            await con.DeleteAsync(entity);
        }
    }
 
    public async Task<DateTime?> LastSynced<TEntity>()
    {
        var con = await Connect();
        var typeName = typeof(TEntity).Name;
        var lastSynced = await (from marker in con.Table<SyncMarker>()
                                where marker.TypeName == typeName
                                select marker).FirstOrDefaultAsync();
        return lastSynced != null ? lastSynced.LastSynced : default(DateTime?);
    }
 
    public async Task UpdateLastSynced<TEntity>(DateTime lastUpdated)
    {
        var con = await Connect();
        var typeName = typeof(TEntity).Name;
        var lastSynced = await (from marker in con.Table<SyncMarker>()
                                where marker.TypeName == typeName
                                select marker).FirstOrDefaultAsync();
        if (lastSynced == null)
        {
            lastSynced = new SyncMarker 
            { TypeName = typeName, LastSynced = lastUpdated };
            await con.InsertAsync(lastSynced);
        }
        else
        {
            lastSynced.LastSynced = lastUpdated;
            await con.UpdateAsync(lastSynced);
        }
    }
 
 
    public async Task Sync<TEntity>() 
        where TEntity : class, ISyncableEntity, new()
    {
        var con = await Connect();
        var remoteTable = MobileService.GetTable<TEntity>();
 
        // Need to download existing entities
        var marker = await LastSynced<TEntity>();
        var dateTimeStamp = marker ?? DateTime.MinValue;
        var newTimeStamp = dateTimeStamp;
        var remoteentities = await(from p in remoteTable
                                    where p.LastUpdated > dateTimeStamp
                                    select p).ToListAsync();
        foreach (var entity in remoteentities)
        {
            var local = await (from p in con.Table<TEntity>()
                                where p.Id == entity.Id
                                select p).FirstOrDefaultAsync();
            entity.LocalLastUpdated = entity.LastUpdated;
            if (local != null)
            {
                if (!entity.IsDeleted)
                {
                    await con.UpdateAsync(entity);
                }
                else
                {
                    await con.DeleteAsync(local);
                }
            }
            else
            {
                if (!entity.IsDeleted)
                {
                    await con.InsertAsync(entity);
                }
            }
 
            newTimeStamp = newTimeStamp < entity.LastUpdated ? 
                entity.LastUpdated : newTimeStamp;
        }
 
        // Upload changed entities
        var updatedentities = await (from p in con.Table<TEntity>()
                                    where p.Id > 0 && 
                                    p.LocalLastUpdated > newTimeStamp
                                    select p).ToListAsync();
        foreach (var entity in updatedentities)
        {
 
            await remoteTable.UpdateAsync(entity);
            entity.LocalLastUpdated = entity.LastUpdated;
 
            if (!entity.IsDeleted)
            {
                await con.UpdateAsync(entity);
            }
            else
            {
                await con.DeleteAsync(entity);
            }
 
            newTimeStamp = newTimeStamp < entity.LastUpdated ? 
                entity.LastUpdated : newTimeStamp;
        }
 
        // Upload new entities
        var newentities = await (from p in con.Table<TEntity>()
                                where p.Id < 0
                                select p).ToListAsync();
        foreach (var entity in newentities)
        {
            await con.DeleteAsync(entity);
            entity.Id = 0;
            await remoteTable.InsertAsync(entity);
 
            entity.LocalLastUpdated = entity.LastUpdated;
            await con.InsertAsync(entity);
 
            newTimeStamp = newTimeStamp < entity.LastUpdated ? 
                entity.LastUpdated : newTimeStamp;
        }
 
        await UpdateLastSynced<TEntity>(newTimeStamp);
    }
}

 

Hopefully this gives you a foundation and you can work through the basics of doing data sync to the cloud…. Well, almost…. There is one thing that you may be wondering after trawling through this code. How does the LastUpdated property every get updated? As I mentioned before, with synchronisation you never trust the client. As such it’s the responsibility of the WAMS to update the LastUpdated property as part of both insert and update:

function insert(item, user, request) {
    item.LastUpdated= new Date();
    request.execute();
}
 
function update(item, user, request) {
    item.LastUpdated=new Date();
    request.execute();
}

 

You’ll need to amend the scripts for all entities you wish to sync.

Now, the final thing we haven’t looked at is what you do for conflicts. We’ve been overly optimistic and have assumed that last in wins. Not great if you have multiple users all writing data to the same records. We’ll leave this for a future post.

Tags:

Windows (RT and Phone) and Sqlite (Part 4)

by Nick 7. June 2013 20:02

This is the fourth (and final) part in a series on using Sqlite across both Windows RT and Windows Phone. To catch up I suggest you take a look at parts 1, 2 and 3:

Windows (RT and Phone) and Sqlite (Part 1)

Windows (RT and Phone) and Sqlite (Part 2)

Windows (RT and Phone) and Sqlite (Part 3)

Just to recap, here is my list of goals:

- Blendable: My project has to be designable in Blend at all times!

- Sqlite: I want to use sqlite to store relational data across both Win8 and WP applications

- PCL: I want to be able to do all my data access from a portable class library

- Objects Not SQL: I want to be able to read and write objects, rather than write sql statements

In part 3 we got most of the way using sqlite-winrt by abstracting the platforms specific implementations into a set of interfaces which were exposed by a portable class library (PCL). This meant we could have all our application logic in a reusable class library (ie another PCL). We’re going to use a similar technique in this post to do the same thing with sqlite-net. This should solve the last remaining issue which was being able to query using objects, not sql.

In part 2 we discussed briefly how to get started with sqlite-net. Essentially for Windows Phone you needed an additional native-to-managed bridge, in addition to referencing the SQLite for Windows Phone visual studio extension. When you add the sqlite-net from nuget you’ll have noticed that it added two files, SQLite.cs and SQLiteAsync.cs, which contain the LINQ style wrapper which makes it possible to read and write objects. It’s our goal to define a set of interfaces which can be extracted into a PCL.

Interfaces

As we did in the previous part with sqlite-winrt, the first step is to create a separate SQLitePCL project and to define a set of interfaces which map to the classes/methods which is exposed by Sqlite-net. I’m not going to bore you with the details but you can see from following image just a couple of the interfaces which will map to classes such as the SQliteConnection, TableMapping and Column.

image

Platform Implementations

For each platform we need to implement these interfaces. This is really a matter of taking the sqlite-net classes, defined in SQLite.cs and SQliteAsync.cs and modifying them to implement the defined interfaces. This isn’t quite as simple as adjusting the class signature to include the appropriate interface but it isn’t far off.

We need to create a separate class library for each platform, eg SQLiteWinRT and SQLiteWP8. It doesn’t matter which platform you start with (I did the phone implementation first) since you’ll be referencing the same classes using the “add as link” technique discussed in the previous post. You might be thinking, if we’re simply going to be adding the same classes to both libraries why they can’t be all in the shared PCL. The answer lies in the conditional compilation statements at the top of the sqlite-net files – these determine how the classes are built for the respective platforms.

You’ll also need to add a class which will act as a connection factory:

public class SQLiteConnectionFactory : ISQLiteConnectionFactory
{
    public ISQLiteConnection Create(string address)
    {
        return new SQLiteConnection(address);
    }
}


Again, this class can be shared across both class libraries.

Application PCL

In the portable class library for your application you can now access Sqlite using a LINQ style interface (ie using objects, not sql). The only thing your PCL needs is a reference to an implementation of the ISQLiteConnectionFactory interface. In the following code for simplicity we’re doing this with a public property on the DataAccessClass but in a real application you might want to use a DI framework to inject this as required.

public class DataAccessClass
{
    public ISQLiteConnectionFactory Factory { get; set; }
    public void DoSomeStuff(string path)
    {
        using (var con = Factory.Create(path))
        {
            con.BeginTransaction();
            con.CreateTable<Person>();
            con.Insert(new Person { Name = "Nick", Age = 15 });
 
            var people = con.Table<Person>().ToArray();
            Debug.WriteLine(people.Length);
            con.Commit();
        }
    }
 
    public class Person
    {
        [PrimaryKey, AutoIncrement]
        public int Id { get; set; }
        public string Name { get; set; }
        public int Age { get; set; }
    }
}

Assigning a Platform Implementation

The last thing you need to do, before you start accessing sqlite (eg calling the DoSomeStuff method) is to pass in the platform specific ISQLiteConnectionFactory implementation. As I mentioned you can do this using your favourite DI framework. In the following snippet I’m simply assigning it in the code behind of our sample application (not an ideal way to do it but super simple for demonstration of the concept!). The following code is from the MainPage.xaml.cs file in the Windows Phone application but the Windows RT code is exactly the same, just referencing the SQLiteWinRT namespace for the platform specific implementation.

 

public static string DB_PATH = Path.Combine(Path.Combine
                   (ApplicationData.Current.LocalFolder.Path, "sample.sqlite"));
protected override void OnNavigatedTo(NavigationEventArgs e)
{
    base.OnNavigatedTo(e);
 
    var factory = new SQLiteConnectionFactory();
 
    var dac = new DataAccessClass();
    dac.Factory = factory;
 
    dac.DoSomeStuff(DB_PATH);
 
}

 

And there you have it…. accessing data using objects from within your PCL. So let’s do another recap of our goals:

- Sqlite: Tick!

- PCL: Tick!

- Objects Not SQL: Tick!

- Blendable: Tick! (assuming you installed the update I mentioned in part 3).

 

I’ve included a sample project which includes all of the libraries and code discussed.

Tags:

Development

Windows (RT and Phone) and Sqlite (Part 3)

by Nick 4. June 2013 06:28

This is the third part in a series on using Sqlite across both Windows RT and Windows Phone. To catch up I suggest you take a look at parts 1 and 2:

Windows (RT and Phone) and Sqlite (Part 1)

Windows (RT and Phone) and Sqlite (Part 2)

Just to recap, here is my list of goals:

- Blendable: My project has to be designable in Blend at all times!

- Sqlite: I want to use sqlite to store relational data across both Win8 and WP applications

- PCL: I want to be able to do all my data access from a portable class library

- Objects Not SQL: I want to be able to read and write objects, rather than write sql statements

So far the PCL support has been non-existent. In this post we’re going to look at adding support so that you can access data from within your portable class library. When I thought to do this I figured it’d be an easy job of creating a bunch of interfaces and a factory, or two. It wasn’t too hard but there was a bit more to it than I expected. We’ll start with using the sqlite-winrt library, and I suspect it might be in part 4 of this series when I return to sqlite-net.

The primary problem we have is that our PCL can’t access any libraries that are winrt or wp specific. Since Sqlite-winrt is essentially two libraries, one for winrt and one for wp, this means we can’t access them directly from within our PCL. However, if we were to have an interface, declared in a PCL, that is implemented by each platform, then we can simply pass the implementation into our PCL and it’s none the wiser (standard DI stuff really). This means step one has to be to provide a PCL interface and a subsequent implementation for each platform:

Interfaces

The interfaces were relatively easy to define, considering you can open a .winmd in tools like ILSpy and you’ll be able to see the internal interfaces declared in sqlite-winrt. I’ve only included the interfaces for IDatabaseFactory and IDatabase here. The rest are included in the attached source code at the end of this post. These interfaces need to be declared in a stand alone portable class library (they could be in your application pcl but that would remove any possible reuse between projects)

public interface IDatabaseFactory
{
    Task<IDatabase> CreateInstance(string file);
    Task<IDatabase> CreateInstance(string folder, string name);
}
 
public interface IDatabase:IDisposable
{
    string Path { get; }
    Task OpenAsync();
    Task OpenAsync(SqliteOpenMode openMode);
    Task<IStatement> PrepareStatementAsync(string cmd);
    Task ExecuteStatementAsync(string cmd);
    long GetLastInsertedRowId();
}

 

Proxy Implementations

For each platform we need to implement these interfaces. Essentially the implementation is just going to proxy calls through to the sqlite-winrt library for the respective platform. For example, here is the implementation of the IDatabaseFactory interface.

public class DatabaseFactory : IDatabaseFactory
{
    public async Task<IDatabase> CreateInstance(string file)
    {
        var proxy = new DatabaseProxy();
        var sf = await StorageFile.GetFileFromPathAsync(file);
        proxy.Instance = new Database(sf);
        return proxy;
    }
 

public async Task<IDatabase> CreateInstance(string folder,

string name)

    {
        var proxy = new DatabaseProxy();
        var sfolder = await StorageFolder.GetFolderFromPathAsync(folder);

var sf = await sfolder.CreateFileAsync(name,

CreationCollisionOption.OpenIfExists);

        proxy.Instance = new Database(sf);
        return proxy;
    }
}

 

You might be thinking “really, I need to implement it twice?” Well the good news is that you only need to write the code once. sqlite-winrt has the same set of apis for both Windows 8 and Windows Phone, so whilst you do indeed need to create a class library for each platform, you can actually share the code between the projects (simply add the code file as a linked file using “Add as Link” in Visual Studio).

Application PCL

In the portable class library for your application you can now access Sqlite. The only thing your PCL needs is a reference to an implementation of the IDatabaseFactory interface. In the following code for simplicity we’re doing this with a public property on the DataAccessClass but in a real application you might want to use a DI framework to inject this as required.

public class DataAccessClass
{
    public IDatabaseFactory Factory { get; set; }
 
    public async Task<string> DoSomeDatabaseStuff(string dbPath)
    {
        // Create a new SQLite instance for the file 
        using (var db = await Factory.CreateInstance(dbPath))
        {
 
            // Open the database asynchronously
            await db.OpenAsync(SqliteOpenMode.OpenReadWrite);
 
            try
            {
                await db.ExecuteStatementAsync
("CREATE TABLE Cities (rowid INTEGER PRIMARY KEY ASC, CityName TEXT);");
                await db.ExecuteStatementAsync
("INSERT INTO Cities (rowid, CityName) VALUES (1, 'Perth');");
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
                // Table exists....    
                // TODO: Improve this so we're not throwing an exception 
                // for a common case!
            }
                
 
 
            // Prepare a SQL statement to be executed
            var statement = await db.PrepareStatementAsync
("SELECT rowid, CityName FROM Cities;");
 
            // Loop through all the results and add to the collection
            if(await statement.StepAsync())
            {
                return statement.GetIntAt(0) + ": " + statement.GetTextAt(1);
            }
            return null;
        }
    }
}

 

Assigning a Platform Implementation

The last thing you need to do, before you start accessing sqlite (eg calling the DoSomeDatabaseStuff method) is to pass in the platform specific IDatabaseFactory implementation. As I mentioned you can do this using your favourite DI framework. In the following snippet I’m simply assigning it in the code behind of our sample application (not an ideal way to do it but super simple for demonstration of the concept!). The following code is from the MainPage.xaml.cs file in the Windows Phone application

protected override async void OnNavigatedTo(NavigationEventArgs e)
{
    base.OnNavigatedTo(e);
 
    await CreateCitiesDatabase();
}
 
private async Task CreateCitiesDatabase()
{
    // Get the file from the install location  
    var file =
        await
        ApplicationData.Current.LocalFolder.CreateFileAsync
        ("cities.db", CreationCollisionOption.OpenIfExists);
 
    var dal = new DataAccessClass();
    var factory = new DatabaseFactory();
    dal.Factory = factory;
 
    var data = await dal.DoSomeDatabaseStuff(file.Path);
    Debug.WriteLine(data);
}

 

And there you have it…. accessing code from within your PCL. So let’s do another recap of our goals:

- Sqlite: Tick!

- PCL: Tick! We fixed this

- Objects Not SQL: Fail (still but this solution will suit some people)

- Blendable: BAM! Fail. Doh! my solution is no longer Blendable.

Unfortunately we’ve broken our ability to design our application in Blend. This is hit and miss, if you get to this point and everything is still Blendable then you’re luckier than me. The good news is that there is a fix and it has nothing to do with us writing more code, or changing our existing code.

FIX: Install Visual Studio Update 3 Note – it is currently at RC, so whilst it is probably quite stable and safe to install, you do so at your own risk. If you’re risk adverse, you may want to wait until it RTMs.

With that fix in place, the only thing let is using Objects Not SQL. More on that in the next post.

Download Solution

Tags:

Windows (RT and Phone) and Sqlite (Part 2)

by Nick 2. June 2013 19:57

In part 2 of this series we’re going to look at the second option that I presented on the use of sqlite which was to use the sqlite-net wrapper.

Just to recap, here is my list of goals:

- Blendable: My project has to be designable in Blend at all times!

- Sqlite: I want to use sqlite to store relational data across both Win8 and WP applications

- PCL: I want to be able to do all my data access from a portable class library

- Objects Not SQL: I want to be able to read and write objects, rather than write sql statements

For a more detailed understanding of these goals, check out Part 1.

Here’s a brief getting started walk through for sqlite-net .

- You’ll need to start by installing the SQLite for Windows and SQLite for Windows Phone extensions. If you’re only interested in supporting one of the platforms then you just need to install the extensions for that platform.

Links
SQLite for Windows Runtime
SQLite for Windows Phone

- You can either use these links to the extensions, or you can search the Visual Studio gallery from within Visual Studio. Go to Tools –> Extensions and Updates; search Online for SQLite. You’ll need to restart Visual Studio after installing both extensions.

- Create both a Windows Phone and a Windows 8 project within the same solution.

- For Windows Phone you’ll need an additional library that acts as a bridge between the native and managed world. This is the sqlite-net-wp8 library – Just because it’s on git, you don’t need to clone it; simply click the Zip download button to take a copy of the library.

image

- Unblock and extract the sqlite-net-wp8 library and copy the project into your solution folder.

- Add the sqlite-net-wp8 project into your solution.

- Add a reference from your Windows Phone project to the sqlite-net-wp8 project

- Add a reference to the SQLite for Windows Runtime extension to your Windows 8 project

image

- Next, you need to add sqlite-net from nuget – install this into both Windows 8 and Windows Phone projects. You should see it add both Sqlite.cs and SqliteAsync.cs files to these projects. These files project an easy to use, linq style, wrapper around Sqlite (remember our Objects not Sql goal!)

image

- Open the project properties page for the Windows Phone project by double-clicking on the properties node in Solution Explorer. Add USE_WP8_NATIVE_SQLITE to the Conditional compilation symbols for All Configurations and All Platforms via the Build tab.

image

- We’re almost there, we just need to write some code. Add the following code to the MainPage.xaml.cs pages (remembering to add the appropriate using statements).

public static string DB_PATH = Path.Combine(

Path.Combine(ApplicationData.Current.LocalFolder.Path,

"sample.sqlite"));

protected override void OnNavigatedTo(NavigationEventArgs e)
{
    base.OnNavigatedTo(e);
 
    using (var con = new SQLiteConnection(DB_PATH))
    {
        con.BeginTransaction();
        con.CreateTable<Person>();
        con.Insert(new Person { Name = "Nick", Age = 15 });
 
        var people = con.Table<Person>().ToArray();
        Debug.WriteLine(people.Length);
        con.Commit();
    }
}
 
public class Person
{
    [PrimaryKey, AutoIncrement]
    public int Id { get; set; }
    public string Name { get; set; }
    public int Age { get; set; }
}

 

- At this point we have all the bits we need but you’ll probably find when you attempt to run either application you’ll run into build errors to do with the supported architectures. You’ll need to alter the build configuration (right-click on the solution in Solution Explorer and select Configuration Manager). Remember you need x86 for the emulator and ARM for debugging on a real device (and the store).

image

With the correct configuration set, you should be all good to go to continue using sqlite

So, how did we go with our goals

- Blendable: Tick! We haven’t done anything to break this requirement

- Sqlite: Tick! Again, we’re using Sqlite

- PCL: Fail – Again, we don’t have a PCL – we’ll need another wrapper to make this happen

- Objects Not SQL: Tick! Woot! we’re stepping in the right direction now with working with objects

Stay tuned for the next instalment when we look at fixing the PCL issue.

Tags:

Windows (RT and Phone) and Sqlite (Part 1)

by Nick 2. June 2013 15:40

Increasingly the projects that we’re undertaking at Built to Roam and Pixel and Sons span both Windows Phone and Windows 8 (aka WinRT). For anyone who’s worked across these platforms you’ll be aware that they’re similar, yet frustratingly different, requiring a significant amount of rework when building applications for both. We’ve attempted to minimise this through the use of both MVVM and Portable Class Libraries. The former allows us to have view models that work across both platforms, the latter allow us to house those view models (and a large proportion of our application logic) in a reusable library that is shared (without the need to recompile) between both our Windows 8 and Windows Phone applications.

One of the areas that we’ve avoided to date is the need to store data using an actual database (across both platforms). We’ve had Windows Phone projects where we’ve used Linq to Sql or the managed wrapper for sqlite; for other projects we’ve chosed to store either xml or json to a flat file on disk. This post is about the learnings taken from a relatively frustrating week trying to see how Microsoft has delivered (or hasn’t delivered) on their announcement last year to support sqlite across both Windows Phone and Windows 8.

Firstly, let me talk about my goals:

- Blendable: My project has to be designable in Blend at all times!

- Sqlite: I want to use sqlite to store relational data across both Win8 and WP applications

- PCL: I want to be able to do all my data access from a portable class library

- Objects Not SQL: I want to be able to read and write objects, rather than write sql statements

Let’s go through these in detail:

Blendable

You might think this a silly requirement when referring to data access. However, I have this as a prerequisite for any library or component that I’m considering. If it ain’t Blendable, it doesn’t make it through the door. I work with some awesome designers who actually know how to work with XAML. I don’t want them hand crafting it, or ideally opening VS, as this just lowers their productivity.

Sqlite

Well duh! Although actually it’s not such a silly requirement – in a lot of cases there is a massive trade off between flat files (super simple) and database (quick but frustrating to work with). More often than not, flat files win as we’re not scanning large number of items by index or doing large complex joins (that’s server stuff, typically).

PCL

I want to reuse an entire library without recompiling across both Windows 8 and Windows Phone, not just share code with # conditional compilation blocks.

Objects Not SQL

Seriously, this is like writing apps in HTML v’s XAML (oh wait, people still do this….let me think of a better example). Writing data access by hand crafting sql statements is for muppets, particularly on a client device where you shouldn’t be doing massive heavy lifting. Do this, and you should be considering which mainframe you’re going to be maintaining in 5 years time. Get with the program, use some object to sql mapper that doesn’t mean you’re writing sql code for client applications.

 

I think I’ve been pretty clear on my goals, so lets get into it and look at the options:

1) Use the existing managed sqlite library that was created for Window Phone 7.

(this one has been discounted as I don’t believe we’re after a managed implementation of sqlite as we’re not going to get the level of performance we really want)

2) Use sqlite-net (in conjunction with sqlite-net-wp8, a native to managed wrapper layer for Windows Phone)

3) Use the recently announced sqlite-winrt across on codeplex

I’m sure there might be other options but these are the ones I’ll be covering in these posts. This post we’ll actually take a look at the third option, sqlite-winrt, which has recently been announced on the Windows Phone developer blog.

Sqlite-Winrt: SQLite WinRT wrapper for WinRT (ie Window8 and Windows Phone)

Here are the steps I went through in my quick exploration:

- Go to the sqlite-winrt project on codeplex: http://sqlwinrt.codeplex.com

- Switch to the source code tab (there’s no actual releases yet) and click the download button

image

- When prompted save the zip file, then open windows explorer and “unblock” the zip file (right-click on file, select properties, click unblock button)

- Unzip the downloaded file and attempt to open the solution by double-clicking the .sln file (currently SqliteWinRTComponents.sln).

*** At this point I get a “failed to open project” notice from Visual Studio because I haven’t installed both the SQLite for Windows and SQLite for Windows Phone extensions. If you’re only interested in supporting one of the platforms then you just need to install the extensions for that platform, and simply ignore the error since it is just pointing out it can’t load one of the projects.

Links
   SQLite for Windows Runtime
   SQLite for Windows Phone

- Restart and Reload solution if you had to install one or more of the extensions

- At this point you should double-check you can build both projects. You can’t run anything because you only have two libraries (one for WinRT and one for Windows Phone)

- Add a Windows Phone application

- Add a reference to the SQLiteWinRTPhone library to your Windows Phone application.

- Update the MainPage.xaml.cs file to include the following code:

using System;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Navigation;
using SQLiteWinRTPhone;
using Windows.Storage;
 
namespace SqliteWPTest
{
    public partial class MainPage
    {
        public MainPage()
        {
            InitializeComponent();
        }
 
        protected override async void OnNavigatedTo(NavigationEventArgs e)
        {
            base.OnNavigatedTo(e);
 
            await CreateCitiesDatabase();
        }
 
        private async Task CreateCitiesDatabase()
        {
            // Get the file from the install location  
            var file =
                await
                ApplicationData.Current.LocalFolder.CreateFileAsync
              ("cities.db", CreationCollisionOption.OpenIfExists);
 
            // Create a new SQLite instance for the file 
            using (var db = new Database(file))
            {
 
                // Open the database asynchronously
                await db.OpenAsync(SqliteOpenMode.OpenReadWrite);
 
                await db.ExecuteStatementAsync
("CREATE TABLE Cities (rowid INTEGER PRIMARY KEY ASC, CityName TEXT);");
 
                await db.ExecuteStatementAsync
("INSERT INTO Cities (rowid, CityName) VALUES (1, 'Perth');");
 
                // Prepare a SQL statement to be executed

var statement = await db.PrepareStatementAsync

("SELECT rowid, CityName FROM Cities;");

 
                // Loop through all the results and display them
                while (await statement.StepAsync())
                    MessageBox.Show(statement.GetIntAt(0) + ": " + statement.GetTextAt(1));
            }
        }
    }
}

 

- Ok, you’re good to run (at least on the emulator) This will work the first time through but fail the next because it attempts to create the Cities table multiple time. I’ll leave it to you to refine the code.

- You might also want to run on a device. When I switched targets to Device I got the following error when attempting to debug:

image

- To fix this, right-click on your solution in Solution Explorer and select Configuration Manager. Change the Active solution platform to ARM.

image

- Rinse and repeat for WinRT. Make sure you reference the correct SQLite wrapper (Resharper caught me out here and automatically added a reference to the phone wrapper). Also, you’ll need to change MessageBox to use the MessageDialog class.

The question is now how did we go on our goals:

- Blendable: Tick! We haven’t done anything to break this requirement

- Sqlite: Tick! We’ll we’re using SQLite, right! You can validate this by copying the db file out of isolated storage onto your host computer and using a tool like sqlitebrowser to open it

- PCL: Fail – not a PCL in sight. The code is tightly coupled with the Sqlite wrappers. Looks like we’re going to have to add another indirection layer here to get this to work….

- Objects Not SQL: Fail. Hmmm, I’m not going any further here. I can see this as being useful for those wishing to write raw sql but for me, I’m going to invest time elsewhere.

 

That’s enough sqlite for one day. I’ll be back with part 2 where we’ll look at sqlite-net and how you can use this to give you objects instead of sql. Part 3 will look at how we can fix the lack of PCL support (for both sqlite-winrt and sqlite-net).

Tags:

Windows Phone App Manager

by Nick 17. April 2013 12:53

We’ve been working closely with the local enterprise sales team at Microsoft around the opportunities to use Windows Phone in the enterprise. Personally I think this is where Windows Phone is going to absolutely rule the roost – integration into Exchange, Sharepoint, Office apps, and of course device management through your favourite MDM solution. Something that comes up early in this discussion is “how do I build a company hub for my organisation?” Well we’ve recently released the first version of the Windows Phone App Manager to the Windows 8 store.

 

image

Windows Phone App Manager app for Windows in the Windows Store

http://apps.microsoft.com/webpdp/app/bcc487fc-d810-4c83-ab17-e58785478a8f

Learn more about Windows Phone App Manager by Built to Roam Pty Ltd and download it from the Windows Store

 

We’ve also been working on a getting started guide – this is particularly important with this release as we’re still working through refining the UX so make it easier for companies to build their company hub.

Update: The Windows Phone App Manager has been updated to include the ability to specify floors, rooms and internal directions using NFC.

Tags:

Windows Phone Developer Workshop

by Nick 17. April 2013 12:44
Adelaide Windows Phone 8 Developers Workshop Fri/Sat, May 3rd and 4th

Calling all SA Adelaide based Mobile developers, Microsoft and Nokia are delighted to announce that we’ve have extended the Windows Phone 8 Developer series of workshops to now include Adelaide.

Windows Phone 8 is a huge step forward, not only maintaining compatibility with existing Windows Phone apps, but embraces a number of core Windows 8 technologies, bringing significant performance improvements, support for managed and native C++ development, in app purchase, wallet, NFC, developer access to the Bluetooth and speech APIs, and more. See Windows Phone 8 developer platform highlights.

This two day workshop is scheduled for Friday May 3rd and Saturday May 4th. The first day is a presentation day that will get you up to speed with the Windows Phone 8 developer platform. Day two (Saturday) is a hands on labs day to guide you through the experience of building Windows Phone apps.

REGISTER

Day 1 - Presentation Day

Day 2 - Hands on Labs Day

Tags:

Announcements

Authentication Issues with Windows Azure Mobile Services

by Nick 14. March 2013 17:33

Here are just a couple of gotchas I ran into whilst setting up a Windows Azure Mobile Service to accept login requests from all four providers: Microsoft Account, Facebook, Twitter, Google.

Firstly, grab the site url for your mobile service – On the Dashboard tab the “Mobile Service Url” is on the right under “quick glance”

image

 

Microsoft Account (Instructions)

image

- The name of my application contained words that weren’t allowed. This includes trademarked words such as “Windows Phone”. Unfortunately this meant that when I attempted to set the Redirect URI  and hit Save, nothing appears to happen – the error is not visible as it’s on a different tab. Solution was to change the Application name, then hey presto it works.

 

Google (Instructions)

image

- Make sure you set the type to Web application

- When I created the client id I could only set the site/hostname. You actually need to go back and edit the settings to set the redirect uri to “https://[your mobile service].azure-mobile.net/login/google (note the /login/google at the end)

 

Facebook

image

- Check the website with Facebook login, and specify the site URL

 

Twitter

image

- You need to specify both the website url and the callback uri

 

Hopefully this helps someone get up and running in less time than it took me!

Tags:

Built to Roam Offices and Staff

by Nick 26. February 2013 04:49

It’s been an whirlwind start to the new year for Built to Roam. We’ve just got back from the US and so I thought it’d be a perfect opportunity to share some of the exciting things that are in the pipeline for Built to Roam this year:

New Office

That’s right, we’re stepping out and now have an awesome office space located in North Sydney. This will allow us to be more productive and have a suitable work space for the team as we grow.

New Staff

Yes, you read it right, we’re growing. We’re super happy to have Dave Lasike (and more apps) join us at Built to Roam.  There is so much interest in Windows Phone and Windows 8 that we’re going to need all hands on deck this year to make sure we continue to deliver amazing apps for both platforms.

New Business

In the past building amazing apps typically meant working with an external design team, whether internal to the customer we’re working with or another design studio. This has meant on a number of occasions working with the team at Automatic Studio, lead by the Metro Modern UI wizard, Shane Morris. We’re super proud to announce that we’ve worked together again, this time in the form of a new design and development agency, Pixel and Sons

New Opportunities

If you thought last year was exciting with the release of Windows Phone 8 and Windows 8, you’re not alone. With momentum building for both platforms, this year will see a number of big name brands appear across the whole ecosystem. Our advice is don’t get left behind, make sure you contact us so that we can assist you take advantage of these new platforms and extend the reach of your product set.

Tags:

Announcements

Windows Phone 8 Jumpstart Content and Samples

by Nick 15. January 2013 05:12
  • Videos via Channel 9

Mod 01a: Introducing Windows Phone 8 Development Part 1
Mod 01b: Introducing Windows Phone 8 Development Part 2
Mod 02: Designing Windows Phone 8 Apps
Mod 03: Building Windows Phone 8 Apps
Mod 04: Files and Storage on Windows Phone 8
Mod 05: Windows Phone 8 Application Lifecycle
Mod 06: Background Agents
Mod 07: Tiles and Lock Screen Notifications
Mod 08: Push Notifications
Mod 09: Using Phone Resources in Windows Phone 8
Mod 10: App to App Communication in Windows Phone 8
Mod 11: Network Communication in Windows Phone 8
Mod 12: Proximity Sensors and Bluetooth in Windows Phone 8
Mod 13: Speech Input in Windows Phone 8
Mod 14: Maps and Location in Windows Phone 8
Mod 15: Wallet Support
Mod 16: In-App Purchasing
Mod 17: The Windows Phone Store
Mod 18: Enterprise App Architecture
Mod 19: Windows Phone 8 and Windows 8 Cross Platform Development
Mod 20: Mobile Web

Samples

Windows Phone 8 JumpStart- Contoso Cookbook Step 1, Initial Layout

Windows Phone 8 JumpStart- Contoso Cookbook Step 2, Styles and Alignment

Windows Phone 8 JumpStart- Contoso Cookbook Step 3, Design Time Data

Windows Phone 8 JumpStart- Contoso Cookbook Step 4, Data Binding

Windows Phone 8 JumpStart- Contoso Cookbook Step 5, List Templates

Windows Phone 8 JumpStart- Contoso Cookbook Step 6, Page Navigation

Windows Phone 8 JumpStart- Contoso Cookbook Step 7, Application Bar

Windows Phone 8 JumpStart- Contoso Cookbook Step 8, Landscape Orientation

Windows Phone 8 JumpStart- Contoso Cookbook Step 9, Screen Resolutions

Windows Phone 8 JumpStart- Contoso Cookbook Step 10, Localization

Windows Phone 8 JumpStart- Contoso Cookbook Step 11, Page Transitions

Windows Phone 8 JumpStart- Module 4 Storage Demos

Windows Phone 8 JumpStart- Module 5 Application Lifecycle Demo

Windows Phone 8 JumpStart- Module 6 Background Agents Demo

Windows Phone 8 JumpStart- Module 7 Tiles and Lockscreen Notifications Demos

Windows Phone 8 JumpStart- Module 8 Push Notifications Demos

Windows Phone 8 JumpStart- Module 9 Using Phone Resources Demos

Windows Phone 8 JumpStart- Module 10 App to App Communication

Windows Phone 8 JumpStart- Module 11 Networking Demos

Windows Phone 8 JumpStart- Module 12 NFC and Bluetooth Demos

Windows Phone 8 JumpStart- Module 13 Speech Demos

Windows Phone 8 JumpStart- Module 14 Location and Maps Demos

Windows Phone 8 JumpStart- Module 15 Wallet Demos

Windows Phone 8 JumpStart- Module 16 In-App Purchasing Demo

Windows Phone 8 JumpStart- Module 17 Windows Phone Store Demos

Windows Phone 8 JumpStart- Module 19 Windows Phone 8 & Windows 8 Cross Platform

Windows Phone 8 JumpStart- Managed App Calling Native Library

Windows Phone 8 JumpStart- PhotoSnap

Windows Phone 8 JumpStart- Location Tracker

Tags:

Windows Phone 8 SDK - Deploying Multiple Enterprise Applications

by Nick 3. December 2012 19:12

I’ve already talked about the basics of enterprise application deployment with Windows Phone 8, which you can find in the following two posts.

Windows Phone 8 SDK- Enterprise Application Deployment

Windows Phone 8 SDK- Enterprise Applications (part 2)

In this post we’re going to look at how you can start to manage and deploy multiple enterprise applications. Of course, there will be some organisations who use an MDM provider (for example Silverback) which will facilitate the deployment of applications to specific groups of employees. However, there will be some organisations that elect not to use an MDM, and yet still want to deploy multiple enterprise applications. For this you can use some of the new APIs in Windows Phone 8 to enumerate installed applications and prompt for installation of applications.

Let’s put this in a bit of context – a common starting point is to roll out a company hub style application. By this we mean a simple enterprise application (ie signed by the enterprise for internal distribution) which might list internal news, relevant links and a list of other enterprise applications that are available for installation. The company hub might also require the user to enter credentials in order to personalise these items (eg present only applications that the user should have access to)

image

If the user clicks on these applications there are a number of ways that the company hub can install the selected application. Assuming that the application is stored on a remote server you can simply launch the uri pointing to the xap file.

private void InstallAppClick(object sender, RoutedEventArgs e)
{
    var url = new Uri("http://mydomain.com/myapp.xap");
    Launcher.LaunchUriAsync(url);
}

Whilst this will work, assuming that the enterprise certificate that the application has been signed with is already installed on the device, it doesn’t provide a great experience for the user. Another alternative is to use the AddPackageAsync method on the InstallationManager.

private async void InstallAppClick(object sender, RoutedEventArgs e)
{
    var url = new Uri("http://mydomain.com/myapp.xap");
    var status = InstallationManager.AddPackageAsync("MyApp", url);
    status.Progress += UpdateProgress;
    await status;
}
private void UpdateProgress(IAsyncOperationWithProgress<PackageInstallResult, uint> asyncinfo, uint progressinfo)
{
    // Update UI with progress
}

The return value from the AddPackageAsync method can be used to retrieve installation progress information that can be displayed within the company hub whilst the application is being installed.

Both these alternatives download the xap in clear form from the remote server. Whilst this might be ok if the user is on an intranet, it’s not a great solution if you want to make applications accessible to remote users (which you would hope would be the case since they’re mobile….). In this case you really need to ensure the application is encrypted or protected somehow to prevent the applications from being decompiled. The script for signing the applications does not provide any level of protection – it simply invokes a native compile of the dlls and then signs both dlls and xap. As such you should consider applying your own level of protection, which in turn means we need an alternative method to install the applications via the company hub.

One solution is to package the other applications into the company hub. Each application needs to be created and then signed using the enterprise certificate. They’re then added to the company hub project with the build action property set to Content – this ensures they’re packaged with the company hub. Once the company hub has been installed the user can select one of the applications packaged with the company hub for installation. Since the application isn’t downloaded there is no way to intercept it, so no further protection is required. This method again uses the AddPackageAsync but this time with a uri that points to a file packaged with the company hub (progress reporting has been omitted for brevity). Alternatively you can also use the Launcher.LaunchFileAsync with a reference to the file but again this doesn’t report on the installation progress.

private async void InstallAppClick(object sender, RoutedEventArgs e)
{
    var file = await StorageFile.GetFileFromApplicationUriAsync(new System.Uri("ms-appx:///myapp.xap"));
    var fullSystemPath = new Uri("file://" + file.Path);
    await InstallationManager.AddPackageAsync("MyApp", fullSystemPath);
}

One thing to note here is the slightly unusual path syntax that is required by the AddPackageAsync method. It will not work with either a relative uri or a uri starting with ms-appx or ms-appdata.

The downside of this method is that you need to bundle all the other applications into the company hub, even if they’re not relevant to the current user. A better solution is to download an encrypted application from a remote server, decrypt it locally, and then install the application from isolated storage. In this post we won’t cover the first two steps, as this is up to the organisation as to how they wish to encrypt the application file and distribute the keys to the company hub application so it can decrypt the application file. The last step is actually similar to installing an application that is packaged with the company hub. However, this time the file is stored in isolated storage, which slightly changes the way the file path is constructed (you could also use new Uri(“ms-appdata://local/MyApp.xap”) rather than using the LocalFolder).

private async void InstallAppClick(object sender, RoutedEventArgs e)
{
    var storageFolder = ApplicationData.Current.LocalFolder;
    var file = await storageFolder.GetFileAsync("MyApp.xap");
    var fullSystemPath = new Uri("file://" + file.Path);
    await InstallationManager.AddPackageAsync("MyApp", fullSystemPath);
}

In this post you’ve seen how you can install additional enterprise applications from a company hub. In deciding which method to use you should consider both the sensitivity of the application logic and the risk of data being intercepted.

Tags:

Development

DNS Client for Windows and Windows Phone

by Nick 7. November 2012 11:02

Don’t ask why, but I needed to be able to do a dns record lookup for a srv record from a Windows Phone application. I went looking for a library that could do this and came up with Phone Net Tools (http://phonenettools.codeplex.com/) – this seems a great library but fairly rudimentary support for DNS queries. I also came across a great post by Rob Philpott on CodeProject (http://www.codeproject.com/Articles/12072/C-NET-DNS-query-component) – it’s a bit dated and for legacy technologies (I needed to upgrade everything to even run it!). Whilst this option seemed to be more painful to update the architecture seemed to lead itself to being extended to support srv records. The net effect is there is yet another library on codeplex, this one dedicated to doing DNS lookups from a Windows 8 or Windows Phone application.

At the moment I’ve only got the Windows Phone version uploaded to the Windows and Windows Phone DNS Library. It’s relatively simple to use:

// create a DNS request
var request = new Request();

var domain = "builttoroam.com";
var type = DnsType.MX;
var dnsServer = IPAddress.Parse("203.0.178.191");

// create a question for this domain and DNS CLASS
request.AddQuestion(new Question(domain, type, DnsClass.IN));

// send it to the DNS server and get the response
//Response response =

var resp = await Resolver.Lookup(request, dnsServer);
foreach (var answer in resp.Answers)
{
    Debug.WriteLine("{0}", answer.Record);   
}

Tags: ,

Development | Announcements

Develop for Windows Phone and Windows using Portable Class Library

by Nick 4. November 2012 07:50

In the past I wasn’t a big fan of the Portable Class Library as I felt it imposed more restrictions than necessary and would constrain/frustrate developers more than it would actually solve a problem. However, in recent times a couple of things have happened that have made this whole experience a lot better.

Firstly, we no longer need to drag out VS2010 to do Windows Phone 7 development. The new Windows Phone 8 SDK plugs into VS2012 and allows for both WP7 and WP8 app development. This means that if you’re going to be targeting multiple versions of WP you can do so in the same solution.

Next, the release of Microsoft.Bcl.Async on nuget – ok, you’re probably thinking what’s that? Well a while ago Microsoft published the Async programming CTP. Whilst it had a go-live license and could be used in your Windows Phone 7 project it was a hassle to install in VS2010 (due to a weird set of dependencies which were broken with subsequent updates to VS) and didn’t support VS2012 at all. The Microsoft.Bcl.Async package is the replacement for the Async CTP, allowing you to do asynchronous programming in WP7 apps. Of course, both Win8 and WP8 support async programming out of the box.

Ok, on to using a Portable Class Library. The concept here is that you want to build a single, managed, library that can be referenced by applications targeting different platforms. Let’s walk through a simple example.

We’re going to start by creating three different applications within the sample solution: SimplePCLTestApp.WP7, SimplePCLTestApp.WP8 and SimplePCLTestApp.Win8. As the project names suggest the projects should be targetting WP7, WP8 and Win8 respectively. We’re then going to also create a Portable Class Library called SimplePCL. Note, when you go to create the PCL you’ll see a prompt similar to the following image. This allows you to specify which frameworks your going to be targeting. In this case we’ll take the default options as we’re not going to be building for XBox.

image

The next thing to do is to add the Microsoft.Bcl.Async nuget package into the WP7 and PCL projects. The following image illustrates the package that you’re after.

image

Unfortunately at the moment when you attempt to add this package it won’t give you the option to add it to the PCL. It appears there is some incompatibilities with the current version of the nuget package for Microsoft.Bcl.Async and the PCL. Luckily it’s relatively easy to fix manually:

> Unload the PCL project
> Right-click on the PCL project and select Edit SimplePCL.csproj
> Now, replace the following element

<ItemGroup>
  <!-- A reference to the entire .NET Framework is automatically included -->
</ItemGroup>

With

<ItemGroup>
<Reference Include="Microsoft.Threading.Tasks">
    <HintPath>..\packages\Microsoft.Bcl.Async.1.0.12-beta\lib\sl4-windowsphone71\Microsoft.Threading.Tasks.dll</HintPath>
  </Reference>
  <Reference Include="Microsoft.Threading.Tasks.Extensions">
    <HintPath>..\packages\Microsoft.Bcl.Async.1.0.12-beta\lib\sl4-windowsphone71\Microsoft.Threading.Tasks.Extensions.dll</HintPath>
  </Reference>
  <Reference Include="Microsoft.Threading.Tasks.Extensions.Phone">
    <HintPath>..\packages\Microsoft.Bcl.Async.1.0.12-beta\lib\sl4-windowsphone71\Microsoft.Threading.Tasks.Extensions.Phone.dll</HintPath>
  </Reference>
  <Reference Include="System.Runtime">
    <HintPath>..\packages\Microsoft.Bcl.1.0.11-beta\lib\sl4-windowsphone71\System.Runtime.dll</HintPath>
  </Reference>
  <Reference Include="System.Threading.Tasks">
    <HintPath>..\packages\Microsoft.Bcl.1.0.11-beta\lib\sl4-windowsphone71\System.Threading.Tasks.dll</HintPath>
  </Reference>
</ItemGroup>

> Save, and reload the PCL project

The last preparatory step is to add a reference to the PCL project to each of our applications. This is done as per normal by right-clicking the project, selecting Add Reference, and then selecting the PCL project from the solution node.

We’re now ready to start writing some code. We’ll rename Class1 to ExampleClass and add the following code:

public class ExampleClass:INotifyPropertyChanged {
    private string name;
    public string Name {
        get { return name; }
        set {
            if (Name == value) return;
            name = value;
            OnPropertyChanged();
        }
    }
 
    public event PropertyChangedEventHandler PropertyChanged;
   [NotifyPropertyChangedInvocator]
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }

    private readonly ManualResetEvent sleepEvent = new ManualResetEvent(false);
    public async Task UpdateName(string newName)  {
        await Task.Factory.StartNew(() =>
                                        {
                                            // This will sleep waiting for a signal that will never happen!
                                            sleepEvent.WaitOne(1000);

                                       });
    Name = newName;
   }
}

This simple class illustrates a couple of different things:

- The use of INotifyPropertyChanged – almost essential for view models, which you will probably want to share across projects if you’re using MVVM. Note the OnPropertyChanged method uses the CallerMemberName attribute, rather than the property name having to be specified when the method is called.

- The UpdateName method is an asynchronous method which launches a background task using Task.StartNew. This is to simulate some long running task (eg service call, or disk I/O). There is no support for Thread.Sleep in the PCL so we’ve used a workaround which involves waiting for a reset event that will never happen.

- The Name property is updated after the background task has completed. If this method was invoked on the UI thread then it’s safe to update the Name property, since the PropertyChanged event also needs to be invoked on the UI thread to prevent a cross threading violation.

We can then add the following code to the main page of each of our applications:

protected async override void OnNavigatedTo(NavigationEventArgs e)
{
    base.OnNavigatedTo(e);


    var example = new ExampleClass();
    example.PropertyChanged+=ExamplePropertyChanged;
    example.Name = "Initial Name";
    Debug.WriteLine("-------------------------");
    await example.UpdateName("Updated Name");
    Debug.WriteLine("-------------------------");
}

private void ExamplePropertyChanged(object sender, PropertyChangedEventArgs e)
{
    var ex = sender as ExampleClass;
    Debug.WriteLine(ex.Name);
}

Running this, in all cases, should yield the following Debug output (you may see some additional assembly/type loading information as well):

Initial Name
-------------------------
Updated Name
-------------------------

And there you have it. An example of how you can use a Portable Class Library to abstract our your platform independent code.

Tags:

Development

Windows Phone 8 SDK: Accessing Content from an SD Card

by Nick 4. November 2012 04:20

Before you get all excited and worked up about the fact that you can use an SD card with the new Windows Phone SDK there are a couple of limitations that you need to be aware of. Keep in mind that one of the primary scenarios that was being solved was the distribution of apps (errr, did I mention apps…. this is limited to Enterprise apps) and content, rather than being an extension to the device storage.

- You can only access file types that you’ve registered for (this excludes the standard file format – which is a bit nasty if you want your app to say process images or documents supplied on an SD card).

- You can only read from SD card.

Ok, with these limitations in mind, let’s take a shot at reading from an SD card.

First up, we need to get an SD card (oh and a real Windows Phone 8 device to work with) and put some content on it. In this scenario we’re going to use a sqlite database called mydata.sqlite. I simply inserted the Micro SD card, using an SD card adapter, into my laptop and copied across the existing sqlite file. I then inserted the card into my Windows Phone 8 device.

Next, I opened my Windows Phone 8 project and added a couple of nuget packages. These are only required if you’re using sqlite, if you’re using some other file type, you don’t need to worry about these packages.

wp7sqlite – This is a managed implementation of sqlite
sqlite-net – This is a super-easy wrapper that you can use in order to access the content.

image

Unfortunately, whilst these two packages were designed to work together, for some reason the versions that are in nuget are incompatible, requiring some minor modifications to get them to work. Luckily this is mostly a matter of replacing “out” with “ref” in a couple of methods.

The next thing to do is to declare our intent to a) read from the SD card and b) what file types we want to be able to access. Double-click the WMAppManifest.xml to open the designer, switch to the Capabilities tab and check the ID_CAP_REMOVABLE_STORAGE capability.

image

Close the manifest designer, right-click on the WMAppManifest.xml file and select Open With. Select XML (Text) Editor and hit Ok. You need to add a FileTypeAssociation element into the Extensions element. If Extensions doesn’t exist, you may need to create that too – it needs to sit after the Tokens element but before the ScreenResolutions element.

</Tokens>
   <Extensions>
     <FileTypeAssociation Name="sqlite" TaskID="_default" NavUriFragment="fileToken=%s">
       <SupportedFileTypes>
         <FileType ContentType="application/sqlite">.sqlite</FileType>
       </SupportedFileTypes>
     </FileTypeAssociation>
   </Extensions>
   <ScreenResolutions>

Now all that’s left is to write some code in order to access the content from the sd card. If you’re simply going to read from the files you can do so in situ. However, in this case we’re eventually going to want to write to the file, so we’re going to copy it to Isolated Storage first.

// Connect to the current SD card.
var sdCard = (await ExternalStorage.GetExternalStorageDevicesAsync()).FirstOrDefault();

var routeFiles = await sdCard.GetFileAsync("mydata.sqlite");
using (var source = await routeFiles.OpenForReadAsync())
using (
    var target = IsolatedStorageFile.GetUserStoreForApplication()
                                    .OpenFile("writeablecopy.sqlite", FileMode.Create, FileAccess.Write))
{
    await source.CopyToAsync(target);
}

var db = new SQLiteAsyncConnection("writeablecopy.sqlite");
var existing = await db.QueryAsync<MyDataObject>("select * from data");
var data = existing.ToArray();

Don’t forget you’ll want to add appropriate error detection and check that an SD card even exists before you attempt to read from it. For those following the sqlite portion, the MyDataObject class is a relatively simply class, the sqlite-net wrapper handles the conversion between the sqlite data and the .net types:

public class MyDataObject
{
    [PrimaryKey, AutoIncrement]
    public int Id { get; set; }
    public string Name { get; set; }
}

Tags:

Development

Cancel My Newspaper Subscription: Would a Real Journalist Please Stand Up!

by Nick 31. October 2012 09:21

Over the last 48 hours Microsoft has launched Windows Phone 8 (press kit here) and the developer tools, the Windows Phone 8 SDK. Unfortunately there seems to be a spate of bad journalist here in Australia. Rather than actually spending time the platform they insist on quoting other, somewhat biased, journalist. Specifically this piece by Ben Grubb at SMH (http://www.smh.com.au/digital-life/mobiles/windows-phone-8-cant-catch-big-two-20121030-28hed.html). Let’s drill in and see what Ben said quoted:

- First, he states that Microsoft is so far behind Android and iOS that it sees RIM as it’s main rival. This comment is completely out of context and he provides no actual basis. It’s a reality that RIM is the closest in market share, so of course they are the next target in terms of just acquiring market share. This in itself doesn’t mean that Microsoft isn’t looking to capture a much larger market share. If you look at device features, variety, developer platform/tools etc, Microsoft isn’t lagging. In terms of apps, there is a way to go before we get to where Android or iOS is but that’s a result of how long the platform has been around more than anything.

- Next, he says that analysts are saying Microsoft is wrong and has no hope…. Really, again who said this. If this is what you believe, then how about putting your name to this comment.

- It’s great that the only quotes from Microsoft is about how hard it is to compete in a market that’s heavily saturated by the incumbent platforms. Well duh! this isn’t news. How about giving us a run down on all the new features of Windows Phone 8, instead of boring us with the obvious.

- I’m not going to bore you with any more of the quotes, rather than any useful commentary that Ben could have offered if he’d actually bothered to use a Windows Phone 8 device. However I’ll leave you with one last example. Ben quotes Joseph Sweeney of IBRS who has made the comment that he didn’t “really see much new”. Hmmm, and adding a fifth row of icons on the iphone 5 was a ground breaking UI change was it. Here’s a list of some of the changes that are in Windows Phone 8 (I’ll leave it to you to work out whether you think they’re new or not):

* Live Tiles – this in itself is not new. However, apps can now take advantage of three different sizes, the ability to flip and cycle content through the tiles.

* Kid’s corner – an isolated area of the phone where kids can play without parents worrying about their data or wallet being compromised.

* Lock screen – an app can surface content and information directly to the lock screen

* VOIP – the integration of Skype (and other third party VOIP apps) is at a low level, making it ultra efficient (ie won’t drain your battery) and always on (so you can always receive chat and calls)

* Rooms – an area where you can share content with a group of people

* Wallet - I originally had this in here but the other smartphone platforms are all doing their own interpretation of this so it's not really new.

And this is just to cover some of the consumer features that I believe add to an already awesome phone platform. If you want to see an example of a journalist who has actually taken the time with a phone then read the following http://www.informationweek.com/byte/personal-tech/slick-windows-phone-8-an-acquired-taste/240012565

Tags:

Development

Powered by BlogEngine.NET 2.0.0.36

Automotive Theme by Car Leasing Experts

 

Page List