Nick's .NET Travels

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

Timeout of HttpWebrequest and WCF service calls on Windows Phone

Firstly, I’m ashamed that the Windows Phone team didn’t do a better job of providing an ability to set a Timeout for either HttpWebRequest, WebClient and WCF service requests. You might be thinking…. but it’s Silverlight and everything’s Async all the time. Well you’d be correct in that thought process but just because something is asynchronous, doesn’t mean that the user isn’t sitting there waiting for something to complete.

For example say you have a simple form that the user has to fill in before they can proceed (eg “create user” form). Clearly if they are on a good network then you’d hope that the service request returns almost instantaneously and the user is cleared to proceed within the app. However, if for whatever reason the request takes longer than expected (slow network, busy server etc) you don’t want the user to sit there indefinitely. After about 10-20 seconds they’re going to get frustrated and probably close and then uninstall your application. Simple solution is to put a Timeout on your service calls so that you can notify that there is something wrong and that they should try again later or check their connection.

Simple you say…. not so. There is no Timeout property that you can set on either HttpWebRequest, WebClient or on the WCF proxy classes that are generated by Add Service Reference. Luckily there are a number of good posts already on the web that cover the basics of implementing a timeout for doing HttpWebRequests (for example this post on stackoverflow).

What isn’t as well covered is how to implement a Timeout for WCF service calls. The challenge with implementing a Timeout property is trying to wrap the asynchronous pattern that the WCF proxy generates. For example if you have a service method called “Authenticate” the proxy will have a AuthenticateAsync method and an AuthenticateCompleted event. Attempting to use these to implement a Timeout is going to result in some very messy code. The other thing to consider is that .NET is evolving towards having true asynchronous support in the form of asynchronous method support. This is built in for WinRT and can be incorporated into your Windows Phone applications today using the Async CTP.

In this post we’re going to use the Async CTP to do two things. Firstly, wrap the fictitious Authenticate service call into an asynchronous operation and secondly give it Timeout support, again through the use of an async operation. The code is implemented as a partial class to the proxy class that is generated when you do  “Add Service Reference”. It does required you to implement the first method for each service method that you want to wrap.

namespace PhoneApp30.MyServices
{
    public partial class SimpleServiceClient    {
        public async Task<string> Authenticate(string username, string password, object state = null)
        {
            return await Async( (cb,st)=>
                Channel.BeginAuthenticate(username,password,cb,st),
                Channel.EndAuthenticate, state);
        }
        private async Task<TResult> Async<TResult>(
            Func<AsyncCallback, object, IAsyncResult> beginMethod,
            Func<IAsyncResult, TResult> endMethod,
            object state)
        {
         
            var method = Task<TResult>.Factory.FromAsync(
                beginMethod,
                endMethod, state);
            return await InvokeWithTimeout(method);
        }
        public async Task<TResult> InvokeWithTimeout<TResult>(Task<TResult> method)
        {
            var newTask = Task.Factory.StartNew(() =>
            {
                if (!method.Wait(30*1000))
                {
                    Abort();
                    throw new TimeoutException();
                }
                return method.Result;
            });
            return await newTask;
        }
    }
}

Now we can call the Authenticate method from our code in a relatively synchronous manner. Note the difference is that this won’t block the UI as it is an asynchronous operation.

async void MainPage_Loaded(object sender, RoutedEventArgs e)
{
    try{
    var client = new SimpleServiceClient();
    var result = await client.Authenticate();
    Console.WriteLine(result);
    }
    catch(TimeoutException ex){
        // Handle timeout 
    }
}

TripleDes Encryption with Key and IV for Windows Phone

Given how long TripleDes has been around you would have thought that it would be just part of any decent platform. Not so! Unfortunately Windows Phone support for cryptography in the core apis seems to be quite lacking (although it does now have DPAPI support for protecting local data). There also seems to be a lack of good documentation/examples on how to get existing code bases to work. It turns out that it’s not that hard if you reuse the massive Bouncy Castle cryptography library (http://www.bouncycastle.org/csharp/). Here are the steps to encrypt and decrypt with TripleDes using the Bouncy Castle library for Windows Phone.

The first step is to download the source code from http://www.bouncycastle.org/csharp/. Whilst there are binaries there I didn’t see a set built for Windows Phone.

With the source code downloaded, you’ll need to expand the zip and copy the contents of the \bccrypto-net-1.7-src\csharp\crypto folder into a new Windows Phone Class Library project. You’ll most likely have to exclude the default AssemblyInfo.cs file too in order for it to compile.

Next step is to reference the class library from your application and now you’re good to start using the API.

We’ll start by declaring a very basic UI – in this case made up of an input TextBox for the value to be encrypted, then two output TextBlocks for the encrypted and the subsequent decrypted values. There are two Buttons to instigate the encryption and decryption to make the process easier to follow.

<StackPanel x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
    <TextBox x:Name="TextToEncrypt"
               Text="Text to encrypt" />
   <Button Content="Encrypt"
            Click="EncryptText" />
   <TextBlock x:Name="TextToDecrypt" />
    <Button Content="Decrypt"
            Click="DecryptText" />
    <TextBlock x:Name="DecryptedText" />
</StackPanel>

To perform the encryption we’re going to need a Key and an Initialization Vector (IV). The following is a randomly created key and doesn’t correlate to any production or test keys that I’m aware of.

private static readonly byte[] Key = new byte[]
                                            {
                                                34, 77, 23, 23, 43, 73, 23, 43,
                                                2, 64, 23, 67, 34, 12, 32, 5,
                                                3, 64, 75, 23, 54, 23, 12, 52
                                            };

private static readonly byte[] IV = new byte[] { 2,45,123,22,66,234,45,34 };

The majority of the work is done in the RunTripleDes method, which takes two parameters: the input value and whether you want it encrypted (true) or decrypted (false). The important thing in this method is to make sure you initiate the Cipher engine with the correct parameters. The following uses the parameters that are consistent with the default TripleDESCryptoServiceProvider that is available to applications written using the full .NET Framework (ie Mode is CBC and Padding is PKCS7). If your encryption needs are different then look through the CipherUtilities class to see what parameters you need to specify in the GetCipher method and then make sure you provide the appropriately structured parameter to the Init method.

public byte[] RunTripleDes(byte[] input, bool encrypt)
{              
        var keyParam = new DesEdeParameters(Key);
        var ivParam = new ParametersWithIV(keyParam, IV);
        var engine = CipherUtilities.GetCipher("DESede/CBC/PKCS7PADDING");
        engine.Init(encrypt, ivParam);
        var output = engine.DoFinal(input);
        return output;
}

To make the code a little easier to follow, we’ll add Encrypt and Decrypt methods to wrap the RunTripleDes method.

public byte[] Encrypt(byte[] input)
{
    return RunTripleDes(input, true);
}
public byte[] Decrypt(byte[] input)
{
    return RunTripleDes(input, false);
}

Lastly, we just need to invoke these methods from the respective button Click event handlers.

private void EncryptText(object sender, RoutedEventArgs e)
{
    var input = Encoding.UTF8.GetBytes(TextToEncrypt.Text);
    var encryptedValue = Encrypt(input);
    TextToDecrypt.Text = Convert.ToBase64String(encryptedValue);
}

private void DecryptText(object sender, RoutedEventArgs e)
{
    var input = Convert.FromBase64String(TextToDecrypt.Text);

    var decryptedValue = Decrypt(input);
    DecryptedText.Text = Encoding.UTF8.GetString(decryptedValue, 0, decryptedValue.Length);
}

You’ll have noticed that we use the UTF8 encoder to convert the input text into a byte array for encryption but that we use the ToBase64String static method on the Convert class to convert the encrypted byte array into text for displaying. We could use the UTF8 encoder to do this but you’d find that when you attempt to convert back to a byte array you may lose bytes. Using ToBase64String and FromBase64String ensures you don’t lose any data in the conversion back and forth from string format – this is particularly important if you’re going to send the encrypted data across the wire (for example a SOAP or REST service)

Ok, let’s give this a whirl – running the application you should be able to enter some text in the TextBox, click the Encrypt button and see the encrypted data, then click the Decrypt button to see the original text appear again (as in the image below).

image

Hope this helps you get started using Bouncy Castle for working with TripleDes in your Windows Phone application.

Missing Background Image on Panorama Control breaks ContextMenu and Causes Performance Issues in Windows Phone Applications

Warning: If you are using a background image for a Panorama control in your application, make sure you get the path correct. Here’s why:

Today I was working on a relatively complex application that uses the Panorama control on the main page of the application. It also has a context menu on items in a couple of the panes with the panorama control. Up until this afternoon everything seemed to work fine. However, as we get close to finishing the project I decided to go through and clean up the images that were included in the project (if you’ve ever worked with a designer or spent a lot of time in Blend you’ll understand why I have to do this step!). Now in most cases your application will continue to work even if the path to your images are wrong – you just won’t see an image where you expect to. This can make it a little hard to ensure you haven’t broken anything as part of the clean up process.

After doing the clean up I did notice that I’d broken a couple of image paths but figured that I’d fixed most of them. I did however also notice that the application was performing really slowly, like it would take a second or so to add a character into a textbox. As I mentioned this is a relatively complex application so I thought that I must have broken some logic in the background causing a perf issue. What I didn’t realise was that the perf issue was related to my image clean up.

Figuring I’d come back to sort out the perf issue later (I’ve been focussed on getting one part of the app finished today so head was in a different place in the app dev cycle) it wasn’t until I noticed another bug that I had to stop what I was doing and address the issue (although at the time I figured it was unrelated). It turned out that none of the the context menus (from the Silverlight toolkit) were working. OMG I thought, what have I done now…. I even thought I’d ping Jeff and see whether he had any gems of wisdom.

One of my golden rules is that I always use source control. Whether it is a simple project I’m working on by myself, or a large project, I always check in my code and frequently. The context menus had been working so I then spent the next hour trawling back through the source control history until I got back to a working version. I then walked forward gradually trying to isolate the issue. Eventually it came down to a missing “/” in the path to the background image for the Panorama control…. really…. yes, really!!! If you get the background image path wrong you will:

- Cause MAJOR performance issues in your application as the panorama control will continually look for the background image (well I’m guessing that’s what it’s doing but either way it’s a major UI performance drain)

- Prevent any ContextMenus from working on that page of your application

- There are probably other controls that may not work well.

Disclaimer: You might be thinking “why didn’t he notice the missing background image”…. in most case you’d be right as the background is usually hard to miss. In this particular instance the background image is very very subtle, just enough to give some visual feedback when the user pans. It looks great but you actually don’t notice it missing unless you’re looking for it.

Bookmark for Mobile App Design Guidelines

Windows Phone

Themes for Windows Phone
http://msdn.microsoft.com/en-us/library/ff769554(v=vs.92).aspx

User Experience Design Guidelines for Windows Phone
http://msdn.microsoft.com/en-us/library/hh202915(v=vs.92).aspx

 

Android

http://developer.android.com/design/index.html

 

iOS

iOS Human Interface Guidelines
http://developer.apple.com/library/ios/#documentation/UserExperience/Conceptual/MobileHIG/Introduction/Introduction.html

Framework Exceptions in Windows Phone

One of the switches that I often enable in Visual Studio is for it to notify my whenever an exception is thrown. This includes exceptions that are thrown internally by the .NET Framework. To enable this option, launch the Exceptions window from the Debug menu.

image

Select the Common Language Runtime Exceptions and check the Thrown checkbox. Click OK to apply this change

image

Now when you run your application you will see any exceptions that are raised, even if they are handles by you or the .NET Framework. Unfortunately sometimes this can be a bit of a drag because the .NET Framework does quite often throw exceptions, sometimes for legitimate reasons, sometimes not so. One such case is for both the CheckBox and RadioButton (actually the ToggleButton which is the base control is the source of this issue). After enabling Exceptions, add the following xaml to a new project.

<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
    <CheckBox Content="Checkbox 1" />
</Grid>

Run your application and you will see the following, completely meaningless, exception being raised.

image

If you look at the call stack, apparently something is calling ToString on the ToggleButton control (ie the base control for the CheckBox you just added).

image

If you examine the ToString code, you’ll see something similar to the following, and you can see the reference to Resx.GetString. From the callstack this seems to be the issue.

public override string ToString()
{
    string text = base.ToString();
    string text2 = (base.Content ?? "").ToString();
    bool? isChecked = this.IsChecked;
    return string.Format(CultureInfo.InvariantCulture, Resx.GetString("ToggleButton_ToString_FormatString"), new object[]
    {
        text,
        text2,
        isChecked.HasValue ? isChecked.Value.ToString() : "null"
    });
}

Following this even further you eventually get to the internal Resx constructor where you can see that it attempts to load an assembly (see second line of the above callstack). This is the line that is failing, because the System.Windows.debug.resources assembly doesn’t exist for us developers Sad smile

internal Resx()
{
    Assembly assembly = base.GetType().Assembly;
    this.resources = new ResourceManager("System.Windows", assembly);
    string assemblyString = "System.Windows.debug.resources, Version=2.0.5.0, Culture=en-US, PublicKeyToken=7cec85d7bea7798e";
    try
    {
       Assembly assembly2 = Assembly.Load(assemblyString);
        this.debugResources = new ResourceManager("System.Windows.debug", assembly2);
    }
    catch (FileNotFoundException)
    {
    }
    this.fallbackResources = new ResourceManager("mscorlib", typeof(object).Assembly);
}

 

The work around for this is relatively simple. Create your own Checkbox class that inherits from CheckBox and override the ToString method.

public class MyCheckBox:CheckBox
{
    public override string ToString()
    {
        return string.Empty;
    }
}

Add this to your layout in place of the CheckBox

<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
    <PhoneApp23:MyCheckBox Content="Checkbox 1" />
</Grid>

Run: Look, no Exceptions!

NOTE: Whilst the fact that the exception is thrown in the first place probably isn’t great coding, it has little, if any, effect on your app running in production. I’ve described this work around purely to get around the annoyance of the FileNotFoundException being picked up (the other way would be to specifically exclude this type of exception in the Exceptions dialog). Some ad-hoc testing indicates that this exception has an insignificant effect on performance or rendering times.

SocialViewer gets Windows Phone Mango treatment

As some of you may be aware I was involved in a project last year to enable developers to quickly build reading style applications. This started off as a simple template allowing users to pull in RSS data but exploded to be much more versatile. The template was made available at http://socialviewer.codeplex.com and is freely available for any Windows Phone developer to download and use.

Since the initial version we’ve made a number of enhancements to both functionality and the default look and feel. Over the festive season I started transitioning (and upgrading) the template to take advantage of the new Mango features. The configuration file (where you could previously only configure the feeds and lists for the application) now allows you to control layout, Ads and integration with various social networks.

I’m going to be doing a series of posts over the coming weeks on some of the new features of the Social Viewer template. We’ll start today with a recap of getting started with the template.

Step 1: Download the template

Go to http://socialviewer.codeplex.com and download the latest build from the Source Code tab. IMPORTANT: At this stage the latest version is still an Alpha release, which means that it’s probably not suitable for publishing apps. We’re hoping to get an official release out this month and would love any feedback you have.

Step 2: Unblock the Download

Gotta love Windows security – make sure you right-click the downloaded file, select Properties and then click the Unblock button.

image

Step 3: Extract the Download

Extract all the files from the changeset. There should be two files: a Zip file which is the template (don’t extract this file), and an OUT OF DATE word document that talks about the template (which for the time being you can ignore).

Step 4: Installing the Template

Copy the Zip file that was extracted out of the changeset (should be called BuiltToRoam.SocialViewer.Template.Zip) and place this file into your Visual Studio Templates folder. For example my templates folder is the following. Note that I added the “Silverlight for Windows Phone” sub-folder so that the template appears with all the other Windows Phone project templates.

C:\Users\Nick\Documents\Visual Studio 2010\Templates\ProjectTemplates\Visual C#\Silverlight for Windows Phone

Step 5: Run Visual Studio

Visual Studio should automatically pick up the new template even if it is already running. However, if you’re updating from a previous version of the SocialViewer template, you may need to restart Visual Studio for it to pick up the new version.

Step 6: Create a New SocialViewer Project

File –> New –> Project

Select the SocialViewer template and give the project a new name. The is currently a bug that means if you put a space in your project name you’re going to enter a word of pain. DO NOT PUT SPACES IN PROJECT NAME

image

Step 7: Run

That’s it…. out of the box you should literally be able to just run the newly created project. Please do not simply create a new project and publish it via Marketplace. That’s not the intent!

Here are some screen shots of the latest build:

image image image image

Main panorama: What’s new - vertical list of new feed items; Recent – hubtiles with images from Flickr; link list to pivot page, website (ie built to roam) and the about page.

image image image

On demand pivot (sources are only downloaded when the pivot is accessed). Reading page illustrating two different layouts: The default; WebBrowser for RSS feed items

image image

The Settings and About pages. Note the long list of social providers that can be used within your applications (See the configuration file) and the variety of data sources that you can consume (again, see configuration file).

Nokia Windows Phone Competition

I just realised that I haven’t posted for a while on this blog. I have however been posting across at both Visual Studio Magazine (Mobile Corner) and on BuildMobile (Windows Phone). A full list of postings and books is available here

 

image        image

The core purpose of this post is to let you know, or remind you, that we’re currently running a competition where you can win a Nokia Windows Phone by answering a question and tweeting a link. The full details and conditions for entry are outlined in the post, Win a Nokia Windows Phone. So far we’re posted four questions, with more to come. Don’t worry if you haven’t answered any so far, you can go back and answer the existing questions as entries will stay open until the competition closes.

Question 1: List a navigation API and provide a short example of how you might use it within your application?

Question 2: Other than the controls that ship with the Windows Phone SDK, what controls do you use in your application, and how do they make your application rock?

Question 3: Discuss one feature, or design, of an application you’ve worked on (doesn’t have to be published) that makes it distinctly Windows Phone?

Question 4: List an API (or a set of APIs) that allow developers to build Windows Phone applications that integrate with either device hardware or into the core platform (e.g. integration into one of the hubs)?

Windows Phone Mango Feature Update

Over at BuildMobile.com I posted about all the awesomeness that is Windows Phone 7.5 (aka the Mango update). There are a couple of features that I either overlooked or were announced after that post went to air:

- Firstly, if I wasn’t clear: The final version of the Windows Phone SDK 7.1 is now available and can be downloaded via the Web Platform Installer (WebPI).

- Not only is the Microsoft Advertising Ad Control included within the SDK, it’s also now available in 11 countries, including Australia.

- There is now a web version of the Marketplace allowing you to purchase and invoke the download of applications directly to your phone.

- Windows Phone 7.5 supports Internet Sharing (ie tethering). Unfortunately this won’t immediately be available on all devices across all carriers but the potential is there – complaining to your telco might affect their decision to roll it out….

- The UserVoice site for Windows Phone has reopened for continual feedback on new product features.

Windows Phone LINQ to SQL and the INotifyPropertyChanged and INotifyPropertyChanging Interfaces

With Windows Phone 7.5 (aka Mango) we finally get access to SQL Server Compact  via LINQ to SQL from within our applications. In my previous post Change Tracking with SQL Server Compact (LINQ to SQL) on Windows PhoneI demonstrated that you can make use of some additional functionality of SSCE that wouldn’t otherwise be accessible via the managed apis. One of the other things I encourage developers to do is to use Visual Studio or SQL Server Management Studio to actually create their database structure, then use the SqlMetal command line tool to generate the necessary class files. The main reason I do this is because there is an awful lot of repetitive code that you should implement for each table and column in your database. Not only is this a waste of your time to write, it’s also very likely you’ll insert an error or two and then waste countless hours trying to debug your code.

Ok, onto the topic of this post. Lets start with a minimal entity called Movie with appropriate attributes for use with LINQ to SQL:

[Table]
public class Movie {
    [Column(IsPrimaryKey = true,
        IsDbGenerated = true,
        DbType = "INT NOT NULL Identity",
        CanBeNull = false,
        AutoSync = AutoSync.OnInsert)]
    public int MovieId { get; set; }

    [Column]
    public string  Name { get; set; }
 
    [Column]
    public int Year { get; set; }
}

Unlike most examples that you may have seen, the Movie class doesn’t implement either INotifyPropertyChanged or INotifyPropertyChanging. You might be thinking that these interfaces are required for LINQ to SQL to work properly. This is a complete fallacy, LINQ to SQL will work fine with this minimal implementation.

Here’s a couple of points about these two interfaces:

INotifyPropertyChanged

- You only need to implement this interface if you data class is going to change and you want those changes to propagate through to the UI.

- This interface is not required for LINQ to SQL to work

- This interface is not required to do read-once data binding

- If you’re going to be reading data from the data base and simply displaying it on the screen then you can, and should, leave this interface off as it just adds unnecessary clutter (KISS!)

INotifyPropertyChanging

- This interface is not required for LINQ to SQL to work

- This interface is not used by data binding

- You should however implement this interface to facilitate better memory management from LINQ to SQL

Here is an extract from the MSDN documentation around this interface.

http://msdn.microsoft.com/en-us/library/hh286406(v=VS.92).aspx#BKMK_MinimizingMemoryUsage

image

Let’s see this in action:

We’ll start with the Movie class without the INotifyPropertyChanging interface. The database is currently populated with a single Movie. We’ll run the following code and use the performance analysis tool in Visual Studio to examine what the impact is on memory.

var ms = dc.Movies.ToArray();

Thread.Sleep(5000);

Console.WriteLine("*******************************************");
Console.WriteLine("                We're done!!!");
Console.WriteLine("*******************************************");

From the Debug menu load the Windows Phone Performance Analysis

image

Select Memory profiling and click the Launch Application link

image

Note that in the code above we were using Console.WriteLine to indicate when the 5 second sleep has finished. One of the issues with the performance tool is that because the debugger is not attached you can’t see anything in the Visual Studio Output window. However, the emulator does have a console window which you can enable so that you can see the Console.Writeline output.

Follow this link to enable the console window on your computer: Windows Phone 7 Console Window on 64 bit machine

image

Now, lets drill into the performance report. Note that you can see two instances of the Movie class have been loaded into memory. This is consistent with what the MSDN documentation said would happen.

image

Now, let’s implement INotifyPropertyChanging. For example the Name property now looks like this

private string name;
[Column]
public string Name
{
    get { return name; }
    set
    {
        if (name == value) return;
        NotifyPropertyChanging("Name");
        name = value;
    }
}

And, let’s change our code so that in addition to loading the Movie into memory, we’ll change the Name property after five seconds.

var ms = dc.Movies.ToArray();

Thread.Sleep(5000);

ms.First().Name = "Changed name";
Thread.Sleep(5000);

Console.WriteLine("*******************************************");
Console.WriteLine("                We're done!!!");
Console.WriteLine("*******************************************");

Now when we run the performance analysis we should see that for the first five seconds there is one Movie in memory. Then when we change the Name property a second instance is created to track the original and changed entities. This is hard to see in the performance tool as the Movie entity is tiny. However, thanks to John from Soul Solutions for pointing out this simple but effective trick I added a 10Mb byte array to the Movie class. This makes it much easier to see when each Movie instance is created in the performance analysis.

private byte[] bytes = new byte[1024*1024*10];

The output:

image

In the first time block there is a single Movie instance, as expected. Then when we modify the Name property (at approx 15 time marker) another 10Mb block is allocated to a second Movie instance. Of course, don’t forget to remove the 10Mb byte array when you are finished debugging your memory management!

This illustrates how important it is to implement INotifyPropertyChanging if you have a large number or large entities in your LINQ to SQL database.

Change Tracking with SQL Server Compact (LINQ to SQL) on Windows Phone

As you are probably aware the Mango update for Windows Phone (ie Windows Phone OS 7.1) will include support for LINQ to SQL. According to Microsoft you shouldn’t need to know or care that this is SQL Server Compact (SQL CE) since they’ve limited access to the database to a set of managed wrappers, namely LINQ to SQL. Unfortunately this only represents a subset of the true capabilities of SQL CE. One of the sorely missing features is of course synchronization, as there is no support for Merge Replication, RDA or Sync Framework. In fact, even doing your own synchronization logic is crippled by the fact that you can’t tap into the native change tracking that SQL CE offers….. well, not using a supported set of APIs.

If we work on the assumption that what ships with Windows Phone OS 7.1 is actually SQL CE v3.5+ (to indicate that there have been some changes to the database engine to support Windows Phone but that the majority of core SQL CE functionality is there), then we can assume that the change tracking functionality, which is part of the SQL CE db engine, is available in the underlying database engine. It’s just not accessible via the managed interface (ie LINQ to SQL). However, if you’ve ever taken a look at change tracking in SQL CE you’d have noticed that all the information relating to  change tacking is maintained in private tables (__sysOCSTrackedObjects, __sysOCSDeletedRows and __sysTxCommitSequence) and private columns in the tracked tables (__sysChangeTxBsn. __sysInsertTxBsn, __sysTrackingContext). So in theory if change tracking was enabled (we’ll cover that in a minute) all we need to do in order to retrieve this information is to map these tables and columns. For the purpose of this post I’m just going to map the __sysChangeTxBsn column in the Person table. The bulk of this code was generated using the SqlMetal tool, although you might also want to try out Erik’s SQL Server Compact Toolbox . The bolded code was manually added to map the __sysChangeTxBsn column (the property ChangeTx is read only as you don’t want to modify this directly).

[global::System.Data.Linq.Mapping.TableAttribute()]
public partial class Person : INotifyPropertyChanging, INotifyPropertyChanged
{    
    private static PropertyChangingEventArgs emptyChangingEventArgs = new PropertyChangingEventArgs(String.Empty);
   
    private System.Guid _Id;
   private string _Name;

    private int? _ChangeTx;

    #region Extensibility Method Definitions
    partial void OnLoaded();
    partial void OnValidate(System.Data.Linq.ChangeAction action);
    partial void OnCreated();
    partial void OnIdChanging(System.Guid value);
    partial void OnIdChanged();
    partial void OnNameChanging(string value);
    partial void OnNameChanged();
    #endregion
   
    public Person() {
        OnCreated();
    }
   
    [global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_Id", DbType="UniqueIdentifier NOT NULL", IsPrimaryKey=true)]
    public System.Guid Id {
        get {
            return this._Id;
        }
        set {
            if ((this._Id != value)) {
                this.OnIdChanging(value);
                this.SendPropertyChanging();
                this._Id = value;
                this.SendPropertyChanged("Id");
                this.OnIdChanged();
            }
        }
    }
   
    [global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_Name", DbType="NVarChar(100)")]
    public string Name {
        get {
            return this._Name;
        }
        set {
            if ((this._Name != value))
            {
                this.OnNameChanging(value);
                this.SendPropertyChanging();
                this._Name = value;
                this.SendPropertyChanged("Name");
                this.OnNameChanged();
            }
        }
    }

   [global::System.Data.Linq.Mapping.ColumnAttribute(
                 
Storage = "_ChangeTx",
                  Name="__sysChangeTxBsn", 
                  DbType = "bigint")]
    public int? ChangeTx {
        get {
            return this._ChangeTx;
        }
    }

    public event PropertyChangingEventHandler PropertyChanging; 
    public event PropertyChangedEventHandler PropertyChanged;
   
    protected virtual void SendPropertyChanging() {
        if ((this.PropertyChanging != null)) {
            this.PropertyChanging(this, emptyChangingEventArgs);
        }
    }
   
    protected virtual void SendPropertyChanged(String propertyName) {
        if ((this.PropertyChanged != null)) {
            this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

Now that you’ve mapped this column you actually need to enable change tracking. As I’ve indicated previously there is no way to do this via LINQ to SQL, which means that if you want to enable change tracking you’ll need to create your database on a platform that supports ADO.NET which includes the API to enable change tracking. For me this was a simple Windows Forms application.

Create your SQL Server Compact database using the designer tools in either SQL Management Studio or Visual Studio (my database is called ChangeData.sdf). Next, add this database file to a newly created Windows Forms application and set the Build Action to Content, and make sure that it is copied to the output directory. Add a button to the form and then in the Click event handler add the following code – this opens a connection to the database file in the executing directory and enables change tracking on the Person table.

private void button1_Click(object sender, EventArgs e) {
    var cnstr = "Data Source=" +
                Path.GetDirectoryName(Assembly.GetExecutingAssembly().GetName().CodeBase).Replace("file:\\","") +
               
\\ChangeData.sdf;Persist Security Info=False;;

   var connection = new SqlCeConnection(cnstr);
    connection.Open();

    var tracker = new SqlCeChangeTracking(connection);
    tracker.EnableTracking("Person", TrackingKeyType.PrimaryKey, TrackingOptions.All);
}

Run the Windows Forms application and click the button. You’re done, change tracking is enabled on your database file. Copy this database file (make sure you get the one that is in the executing folder for the Windows Forms application) into your Windows Phone application. Again make sure the Build property is set to Content.

Ok, now to write some code against your change tracking database. The first thing we’re going to do is to copy the database that is packaged with the application from the installation folder (appdata, where it’s read only) into isolated storage (isostore, where it’s read-write). The following code then iterates through all the Person entities (I created a few sample records in the database via Visual Studio) and modifies the Name property.

void MainPage_Loaded(object sender, RoutedEventArgs e) {
    CopyReferenceDatabase("ChangeData.sdf", "ChangeData.sdf");
 
   string ReferenceDBConnectionString = "Data Source=isostore:/ChangeData.sdf";
   using (var db = new ChangeData(ReferenceDBConnectionString)) {
        var people = from person in db.Persons
                               select person;
        foreach (var p in people) {
           p.Name = p.Name + " updated";
        }
        db.SubmitChanges();
    }
}

public static void CopyReferenceDatabase(string referenceDatabaseName,
                                                                               string isolatedStorageDatabaseName) {
    var iso = IsolatedStorageFile.GetUserStoreForApplication();
    if (iso.FileExists(isolatedStorageDatabaseName)) return;

    using (var input = Application.GetResourceStream(
            new Uri(referenceDatabaseName, UriKind.Relative)).Stream) {
        using (var output = iso.CreateFile(isolatedStorageDatabaseName)) {
            var readBuffer = new byte[4096];
            int bytesRead;

            while ((bytesRead = input.Read(readBuffer, 0, readBuffer.Length)) > 0) {
                output.Write(readBuffer, 0, bytesRead);
            }
        }
    }
}

Now to see the effects of change tracking. If you set a break point in the for loop you can take a look at the ChangeTx property on the Person entities. If you run the application a few times you’ll see that this value changes each time you update the Person entities.

image

If you want to interrogate the database file further you can export the file from either the emulator or a real device using the Isolated Storage Explorer Tool:

c:\Program Files (x86)\Microsoft SDKs\Windows Phone\v7.1\Tools\IsolatedStorageExplorerTool>ISETool.exe ts xd 3abccaef-453b-4345-8f0e-7861873ddbf9 c:\temp\emu_export

The parameters for ISETool.exe are:
ts – Take snapshot (copy entire isolated storage files/folders for the specified application)
xd – Emulator (use de for actual, unlocked, device)
3abccaef-453b-4345-8f0e-7861873ddbf9 – The guid of the specified application. This is the ProductID attribute from the WMAppManifest.xml file for your application.
c:\temp\emu_export – The folder on the host computer that you want to push the snapshot too. I recommend specifying an empty folder.

Once you’ve exported the database file you can then connect to it via Visual Studio or SQL Management Studio. Note that in the designer both the private tables and private columns are hidden. However, if you run a SQL statement (eg select * from Person) you’ll see the private columns.

And that’s essentially it – you’ve got a change tracking enabled database which you can use to synchronize data back to a server. You might like to combine this with OData, in which case you might want to take a look at how I implement change tracking on the server side using WCF Data Services and Entity Framework (http://nicksnettravels.builttoroam.com/post/2010/08/03/OData-Synchronization-with-WCF-Data-Services.aspx).

Posting Twitter Status Update from Windows Phone

In my post Twitter in a Windows Phone 7 App across at BuildMobile I covered how to authenticate against Twitter using OAuth1. What I didn’t cover in that post is how you can then use the Access Token to interact with the Twitter API. In this post I’ll show you how you can post a status update to Twitter from your Windows Phone application.

Let’s start by creating a TextBox and a Button. Obviously the TextBox will be for the status to be posted and the Button will be to submit the Tweet:

<TextBox x:Name="TweetText"/>
<Button Content="Tweet" Click="TweetClick" />

Some points/gotchas to note:

* The user will have had to been authenticated prior to hitting this button or the post will fail.
* Twitter does not allow the same message to be repeatedly posted – if during testing you attempt to post the same test message, don’t be surprised if it fails!
* If your Windows Phone application is going to post messages to Twitter it need to request Read/Write (and potentially Direct Message) permissions to the users Twitter account.  This is not enabled by default when you create the application in Twitter, you have to go to the Settings tab and adjust the Application Type eg

image

Essentially in order to post a status update to Twitter you simply need to create the appropriately formed HttpWebRequest. The request will be a POST and you’ll include “status=<new status>” as the body of the POST. The url of the request will be “statuses/update.json” off the Twitter base API url. Note that the .json indicates that the response will come back as json. You can specify .xml if you’d prefer an XML response.

private void TweetClick(object sender, RoutedEventArgs e) {
    var requestParameters = new Dictionary<string, string>();
    var body = "status=" + UrlEncode(this.TweetText.Text);
    requestParameters[OAuthPostBodyKey] = body;

    var postUrl = "http://api.twitter.com/1/statuses/update.json";
    var request = CreateRequest("POST", postUrl, requestParameters);
    request.BeginGetRequestStream(reqresult => {
        var req = reqresult.AsyncState as HttpWebRequest;
        using (var strm = req.EndGetRequestStream(reqresult))
        using (var writer = new StreamWriter(strm)) {
            writer.Write(body);
        }
        req.BeginGetResponse(result => {
            try {
                var req2 = result.AsyncState as HttpWebRequest;
                if (req2 == null) throw new ArgumentNullException("result", "Request parameter is null");
                using (var resp = req.EndGetResponse(result))
                using (var strm = resp.GetResponseStream())
                using (var reader = new StreamReader(strm)) {
                    var responseText = reader.ReadToEnd();

                  Dispatcher.BeginInvoke(() => MessageBox.Show("Tweeted!"));
                }
            }
            catch {
                Dispatcher.BeginInvoke(() => MessageBox.Show("Unable to tweet"));
            }
        }, req);
    }, request);
}

If you followed the code on my BuildMobile post there are a couple of changes we need to make in order to support posting. The first enables us to pass in a Dictionary into the CreateRequest method. This is so that we can specify the body of the post which needs to be used in the calculation of the signature.

private WebRequest CreateRequest(string httpMethod, string requestUrl, IDictionary<string, string> requestParameters = null) {
    if (requestParameters == null) {
        requestParameters = new Dictionary<string, string>();
    }
    var secret = "";
    if (!string.IsNullOrEmpty(token)) {
        requestParameters[OAuthTokenKey] = token;
    secret = tokenSecret;
    }
    if (!string.IsNullOrEmpty(pin)) {
        requestParameters[OAuthVerifierKey] = pin;
    }
    var url = new Uri(requestUrl);
    var normalizedUrl = requestUrl;
    if (!string.IsNullOrEmpty(url.Query)) {
    normalizedUrl = requestUrl.Replace(url.Query, "");
    }
    var signature = GenerateSignature(httpMethod, normalizedUrl, url.Query, requestParameters, secret);
    requestParameters[OAuthSignatureKey] = UrlEncode(signature);

    var request = WebRequest.CreateHttp(normalizedUrl);
    request.Method = httpMethod;
    request.Headers[HttpRequestHeader.Authorization] = GenerateAuthorizationHeader(requestParameters);
    return request;
}

The other change we need to make is to the GenerateAuthorizationHeader method. Because the status itself will be passed as a form parameter in the body of the POST it shouldn’t be included in the authorization header. As such we need to modify the method to ignore any parameters that do not begin with “oauth_”.

public static string GenerateAuthorizationHeader(IDictionary<string, string> requestParameters)
{     var paras = new StringBuilder();     foreach (var param in requestParameters)     {
        if (!param.Key.StartsWith("oauth_")) continue;
        if (paras.Length > 0) paras.Append(",");         paras.Append(param.Key + "=\"" + param.Value + "\"");     }     return "OAuth " + paras;
}

 

And there we have it. Code that will enable your Windows Phone application to post to Twitter.

Windows Live Id Authentication using Messenger Connect for Windows Phone

If you saw my post on BuildMobile.com you would have seen that I used the “token” response_type when initially specifying the login url. This works well for getting a short lived access token but the wl.offline_access scope is effectively ignored – the expiry time comes back as 3600. This is completely useless for a Windows Phone application where you don’t want to have to reprompt the user every time they run the application. Luckily, despite the failings in the current implementation, there is a work around which involves a few more steps and uses the “code” response_type.

I’m not going to step through the entire process, instead, here is the code that you should be able to use – it’s based on my post Using Windows Live ID in a WP7 Appon BuildMobile.com so should be easy enough to follow.

Notes:
- You need to replace both <your_client_id> and <your_client_secret> with the corresponding values for your application
- In a production application you should not have the client id or client secret in plain text in your application - ideally this should be held on a server and only exposed to the client app over ssl and never persisted in the client app. 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using System.Text;
using System.Windows;
using System.Windows.Navigation;

namespace WLTest
{
    public partial class MainPage
    {
        // Constructor
        public MainPage()
        {
            InitializeComponent();
        }

        private void AuthenticateClick(object sender, RoutedEventArgs e)
        {
            var uriParams = new Dictionary<string, string>()
                                {
                                    {"client_id", "<your_client_id>"},
                                    {"response_type", "code"},
                                    {"scope", "wl.signin,wl.basic,wl.offline_access"},
                                    {"redirect_uri", "https://oauth.live.com/desktop"},
                                    {"display", "touch"}
                                };
            StringBuilder urlBuilder = new StringBuilder();
            foreach (var current in uriParams)
            {
                if (urlBuilder.Length > 0)
                {
                    urlBuilder.Append("&");
                }
                var encoded = HttpUtility.UrlEncode(current.Value);
                urlBuilder.AppendFormat("{0}={1}", current.Key, encoded);
            }
            var loginUrl = "https://oauth.live.com/authorize?" + urlBuilder.ToString();

            AuthenticationBrowser.Navigate(new Uri(loginUrl));
            AuthenticationBrowser.Visibility = Visibility.Visible;


        }

        public string AccessToken { get; set; }
        public string RefreshToken { get; set; }

        private void BrowserNavigated(object sender, NavigationEventArgs e)
        {
            if (e.Uri.AbsoluteUri.ToLower().Contains("https://oauth.live.com/desktop"))
            {
                var query = (from pair in e.Uri.Query.Trim('?').Split('&')
                             let bits = pair.Split('=')
                             where bits.Length == 2
                             select new KeyValuePair<string, string>(bits[0], bits[1])).ToArray();

                var code =
                    query.Where(kvp => kvp.Key == "code").Select(kvp => HttpUtility.UrlDecode(kvp.Value)).FirstOrDefault
                        ();
                if (string.IsNullOrEmpty(code))
                {
                    var error =
                        query.Where(kvp => kvp.Key == "error").Select(kvp => HttpUtility.UrlDecode(kvp.Value)).
                            FirstOrDefault();
                    var error_desc =
                        query.Where(kvp => kvp.Key == "error_description").Select(
                            kvp => HttpUtility.UrlDecode(kvp.Value)).FirstOrDefault();
                    MessageBox.Show("Error: " + error + "\n" + error_desc);
                    AuthenticationBrowser.Visibility = System.Windows.Visibility.Collapsed;
                    return;
                }

                var uriParams = new Dictionary<string, string>()
                                    {
                                        {"client_id", "<your_client_id>"},
                                        {"client_secret", "<your_client_secret>"},
                                        {"redirect_uri", "https://oauth.live.com/desktop"},
                                        {"code", HttpUtility.UrlEncode(code)},
                                        {"grant_type", "authorization_code"}
                                    };
                StringBuilder urlBuilder = new StringBuilder();
                foreach (var current in uriParams)
                {
                    if (urlBuilder.Length > 0)
                    {
                        urlBuilder.Append("&");
                    }
                    var encoded = HttpUtility.UrlEncode(current.Value);
                    urlBuilder.AppendFormat("{0}={1}", current.Key, encoded);
                }
                var tokenUri = "https://oauth.live.com/token?" + urlBuilder.ToString();

                var request = HttpWebRequest.CreateHttp(tokenUri);
                request.BeginGetResponse(result =>
                                             {
                                                 var req = result.AsyncState as HttpWebRequest;
                                                 using (var resp = req.EndGetResponse(result))

                                                 using (var strm = resp.GetResponseStream())
                                                 {
                                                     var serializer =
                                                         new DataContractJsonSerializer(
                                                             typeof (WindowsLiveAuthorizationCode));
                                                     var authorization =
                                                         serializer.ReadObject(strm) as WindowsLiveAuthorizationCode;
                                                     AccessToken = authorization.AccessToken;
                                                     RefreshToken = authorization.RefreshToken;

                                                     this.Dispatcher.BeginInvoke(() => MessageBox.Show(
                                                         "Access granted"));
                                                     RequestUserProfile();
                                                 }
                                             }, request);

                AuthenticationBrowser.Visibility = System.Windows.Visibility.Collapsed;
            }
          
        }

 


        private void RequestUserProfile()
        {
            var profileUrl = string.Format("https://apis.live.net/v5.0/me?access_token={0}",
                                           HttpUtility.UrlEncode(AccessToken));
            var request = HttpWebRequest.Create(new Uri(profileUrl));
            request.Method = "GET";
            request.BeginGetResponse(result =>
                                         {
                                             try
                                             {
                                                 var resp = (result.AsyncState as HttpWebRequest).EndGetResponse(result);
                                                 using (var strm = resp.GetResponseStream())
                                                 {
                                                     var serializer =
                                                         new DataContractJsonSerializer(typeof (WindowsLiveProfile));
                                                     var profile =
                                                         serializer.ReadObject(strm) as WindowsLiveProfile;
                                                     this.Dispatcher.BeginInvoke((Action<WindowsLiveProfile>) ((user) => {
                                                                            this.UserIdText.Text = user.Id;
                                                                            this.UserNameText.Text = user.Name;
                                                                                                                   }),
                                                                                 profile);
                                                 }
                                             }
                                             catch (Exception ex)
                                             {
                                                 this.Dispatcher.BeginInvoke(() =>
                                                                             MessageBox.Show("Unable to attain profile information"));
                                             }
                                         }, request);
        }

        [DataContract]
        public class WindowsLiveProfile
        {
            [DataMember(Name = "id")]
            public string Id { get; set; }

            [DataMember(Name = "name")]
            public string Name { get; set; }
        }

        [DataContract]
        public class WindowsLiveAuthorizationCode
        {
            [DataMember(Name = "access_token")]
            public string AccessToken { get; set; }

            [DataMember(Name = "refresh_token")]
            public string RefreshToken { get; set; }

            [DataMember(Name = "scope")]
            public string Scope { get; set; }

            [DataMember(Name = "token_type")]
            public string TokenType { get; set; }

            [DataMember(Name = "expires_in")]
            public string ExpiresIn { get; set; }
        }

        private void RefreshTokenClick(object sender, RoutedEventArgs e)
        {

            var uriParams = new Dictionary<string, string>()
                                {
                                    {"client_id", "<your_client_id>"},
                                    {"client_secret", "<your_client_secret>"},
                                    {"redirect_uri", "https://oauth.live.com/desktop"},
                                    {"refresh_token", RefreshToken},
                                    {"grant_type", "refresh_token"}
                                };
            StringBuilder urlBuilder = new StringBuilder();
            foreach (var current in uriParams)
            {
                if (urlBuilder.Length > 0)
                {
                    urlBuilder.Append("&");
                }
                var encoded = HttpUtility.UrlEncode(current.Value);
                urlBuilder.AppendFormat("{0}={1}", current.Key, encoded);
            }
            var tokenUri = "https://oauth.live.com/token?" + urlBuilder.ToString();

            var request = HttpWebRequest.CreateHttp(tokenUri);
            request.BeginGetResponse(result =>
                                         {
                                             var req = result.AsyncState as HttpWebRequest;
                                             using (var resp = req.EndGetResponse(result))

                                             using (var strm = resp.GetResponseStream())
                                             {
                                                 var serializer =
                                                     new DataContractJsonSerializer(
                                                         typeof (WindowsLiveAuthorizationCode));
                                                 var authorization =
                                                     serializer.ReadObject(strm) as WindowsLiveAuthorizationCode;
                                                 AccessToken = authorization.AccessToken;
                                                 RefreshToken = authorization.RefreshToken;

                                                 this.Dispatcher.BeginInvoke(() => MessageBox.Show(
                                                     "Token refreshed"));
                                             }
                                         }, request);
        }
    }
}

Windows Phone Mango Push Notification Changes

The basic concept of push notifications for Windows Phone doesn’t change for Mango. There are still three types (Push Notifications in Windows Phone), tile, toast and raw, and your application still needs to register with the Microsoft Push Notification Service in order to make use of this feature. The differences are that there are extensions to the service, which both plug holes in the initial implementation and provide support for multiple tiles and the back of tiles. Let’s go through the different types of notifications and I’ll point out some of the differences.

Toast Notifications

One of the issues with toast notifications in WP7 was that when the user clicked on the toast they were taken into the application as if they’d clicked on the application from the apps list. There was no arguments or information passed into the application to indicate where it had been launched from. This made it rather painful to do anything useful with toast notifications, other than trying to encourage users back into the application.

In Mango there is an additional (optional) Param element that can be specified in the toast message payload. This is essentially a navigation uri, or a query string, that is passed into the application. The payload message structure looks similar to the following:

string toastMessage = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
                                              "<wp:Notification xmlns:wp=\"WPNotification\">" + 
                                                  "<wp:Toast>" +
                                                      "<wp:Text1>First String</wp:Text1>" +
                                                      "<wp:Text2>Second String</wp:Text2>" + 
                                                      "<wp:Param>/PageTwo.xaml</wp:Param>" + 
 
                                                 "</wp:Toast>" + 
                                              "</wp:Notification>";

The bold line illustrates the new Param element. In this case if the user taps on this toast, they will be taken directly to PageTwo.xaml. Note that PageTwo.xaml will be the first page in the back stack, bypassing the normal entry point for the application.

The Param element can include a query string either in addition to, or instead of, a navigation uri. For example:

     /PageTwo.xaml?query1=value1
     ?query2=value2

In both cases the query key-value pairs can be extracted via the NavigationContext for the page that is navigated to. In the first case, this would be PageTwo.xaml, whereas in the second (where there is no page defined in the Param element) the page would be the default launch page for the application.

 

Tile Notifications

Live tiles get a major uplift in Mango. You still of course have the front tile which consists of the background image, a badge/count in the top right corner and the title. With Mango you can use the back of the tile as well. The back of the tile also has a background image and a title but also has a content attribute which can be used to display more text content (you can’t modify the font size or layout though). If that wasn’t enough, Mango also gives you the ability to pin multiple tiles for your application to the Start (in much the same way as web pages and contacts can be pinned to the Start today).

The new message structure for sending a tile notification is:

string tileMessage =     "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
                                          "<wp:Notification xmlns:wp=\"WPNotification\">" +
                                              "<wp:Tile Id=\"{0}\">" +
                                                  "<wp:BackgroundImage>Background.png</wp:BackgroundImage>" +
                                                  "<wp:Count>6</wp:Count>" + 
                                                  "<wp:Title>My App Title</wp:Title>" + 
                                                  "<wp:BackTitle>Back Tile Title</wp:BackTitle>" + 
                                                  "<wp:BackContent>Some additional content to be displayed</wp:BackContent>" + 
                                                  "<wp:BackBackgroundImage>BackOfTileImage.png</wp:BackBackgroundImage>" +
                                              "</wp:Tile> " +
                                         "</wp:Notification>";

The new elements are:

BackTitle – The title to be displayed on the back of the tile

BackContent – The additional content to be displayed on back of the tile

BackBackgroundImage – The image 173x173 to use on the back of the tile. Can be local (as in this example) or from a remote server, assuming you specify a url that is on one of the permitted domains (see setup of push notifications)

Id – The Id attribute of the Tile element is used to identify tiles in the case where there are multiple tiles pinned to the Start for a given app. The default tile (which is created when the user pins the app from the apps list, as per current version of wp7) has an Id of “” or you can omit this attribute. The Id of a tile also determines the page, and corresponding query string, to be navigated to when the user clicks on the tile.

Raw Notifications

I’m not aware of any changes to raw notifications themselves. However, the service that is used to send notifications can register for a callback when the device becomes inactive – particularly if you are sending large numbers of raw messages out to a phone. More information is available via MSDN on Setting up a Callback Registration Request

Build Mobile: Windows Phone Push Notifications

The fourth part of a series on Windows Phone Push Notifications has been posted on Build Mobile. If you’re interested, check out the direct links below:

- Push Notifications in Windows Phone
- WP7 Push Notifications Part 2

In the Mobile Corner at the Visual Studio Magazine my latest article on using some of the system styles in Windows Phone has been published:

Style Your Application with Windows Phone 7 System Resources

A full listing of articles on both Build Mobile and Visual Studio Magazine is available here

Windows Phone Developer Training: Are You Interested?

We’re looking to run Windows Phone developer training….. but need to know whether you’re interested! Complete the super-quick survey http://bit.ly/remixwp7 to let us know what you want. The quicker you respond, the quicker we’ll make a decision on when, where and how to run developer training.

Note: We’ve purposely dropped the “7” from the Windows Phone title in light of the announcement/SDK for Mango. If you’re skilled with WP7 but want to learn the ins and outs of Mango then make sure you add this to the comments so we can focus on that.

Facelift for the Windows Phone 7 Social Viewer Template

I’ve just checked in the latest Social Viewer template to http://socialviewer.codeplex.com which among a number of bug fixes (including the fix to get Twitter auth working again) also includes a significant facelift.

Previously you defined a number of sources (RSS, Atom, Facebook, Twitter or your own) then grouped them into lists. These lists would then appear in a panorama. This sort of worked for a small number of lists, say 2-4, but you ended up with list after list after list – probably a pivot would be better suited to displaying all the lists.

I’m not a big fan of using a pivot as the starting point for an application so I wanted to craft a better experience that demonstrated the use of both the panorama and pivot controls, as well as using more of the features of the social viewer template itself. What we ended up with is a template that is broken into a main panorama which shows highlights, a more detailed pivot showing a number of on-demand lists and then of course the reading page. Let’s walk through them.

Main Panorama

The main panorama is essentially the launching point for the application. The first pane includes a vertical list of items that is entitled “what’s new” in keeping with the what’s new lists across the core platform. This is a simple list allowing you to easily scan the list for items of interest. Items appear dimmed/greyed to indicate it has been read.

Next we have the recent panorama item where we introduce a bit of a change in pace – you’ll again notice this across the core platform, where you’ll see the panorama broken up into different styles of panes. Here we’re including items that have got images/enclosures to add some life to the panorama.

Lastly we have a pane that is sort of a menu in that it links to different parts of the application. As the template can take advantage of trial mode, there is also a Purchase menu item that is not visible here, linking the user off to the Marketplace link for the application to be purchased.

image image image image

On-Demand Pivot

Clicking on the Developers link on the main panorama navigates the user to a page which contains the pivot control. The control is data bound to a collection of lists. As the user flicks between the lists, the corresponding feeds are downloaded and processed on-demand (as you can see in the second image with the progress bar still visible).

image image image image

Reading

Clicking on any of the items from any of the lists on the Main Panorama or the On-Demand Pivot will navigate the user to the reading page. Here the full post is available, along with any links (see second image) that the user may want to navigate to. The user can also opt to share the post via Facebook, email the post or tweet a reference to the post.

image image image

Settings and About

The last two pages of the template are the Settings and About pages. These are provided out of the box to allow the user to manage their Facebook and Twitter credentials, and to list relevant information about the sources of the data for the application. The About page also provides a mechanism whereby the user can review (via Marketplace) or provide feedback (via email) on the application.

image image

I would love feedback on the latest version of the social viewer template – http://socialviewer.codeplex.com (the updated version is still on the source code tab until I finish testing the updates)

Display PDFs in your Windows Phone 7 application

I just downloaded and was experimenting with the CTP of ComponentOne Studio for Windows Phone. Normally I don’t give these third party control libraries much interest as they’re usually expensive and generally just add another dependency to your application that you have no control over. This is particularly true with mobile applications where performance is so critical.

Anyhow, the one thing that caught my eye in this control library is that there is a PDF Viewer control. There is full documentation available online, including details of this control. What interested me was the following:

View and Save PDF Files

The C1PdfViewer control can be used to view and save PDF files on the Windows Phone device. C1PdfViewer has no external dependency on Adobe Reader to view or save files. Content is parsed and rendered as native XAML elements.

That it awesome that they’re rendering the PDF as native XAML.

After downloading the CTP I was a little lost to start with as I couldn’t see the controls appear within Visual Studio. However they ship a cool Sample Explorer which I was able to use to play around with their samples.

image

After taking a look at the sample I decided to see how easy it was to create a simple application that displays a PDF. Rather than loading the PDF from a resource within the application which is what the sample demonstrates, I decided to load a test PDF located at  http://www.blhr.org/media/documents/test.pdf

The XAML for MainPage is:

<phone:PhoneApplicationPage
    x:Class="PDFViewer.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
    xmlns:c1Pdf="clr-namespace:C1.Phone.PdfViewer;assembly=C1.Phone.PdfViewer"
    Loaded="MainPageLoaded">

    <Grid>
            <c1Pdf:C1PdfViewer x:Name="pdfViewer"
                               ViewMode="FitWidth"
                               Visibility="Collapsed" />
    </Grid>
</phone:PhoneApplicationPage>

And the code to load the PDF is quite simple:

public partial class MainPage : PhoneApplicationPage {
    public MainPage() {
        InitializeComponent();
    }
    private WebClient wc = new WebClient();
    private void MainPageLoaded(object sender, RoutedEventArgs e) {
        wc.OpenReadCompleted += WcOpenReadCompleted;
        wc.OpenReadAsync(new Uri(http://www.blhr.org/media/documents/test.pdf));
    }
    void WcOpenReadCompleted(object sender, OpenReadCompletedEventArgs e) {
        pdfViewer.LoadDocument(e.Result);
        pdfViewer.Visibility = Visibility.Visible;
    }
}

Running this displays the pdf in the application:

image

Warning: There are some definite limitations with this control that are outlined both on the website and within the documentation. For example my first test PDF didn’t render (http://www.education.gov.yk.ca/pdf/pdf-test.pdf) throwing an exception relating to do with the compression format. The guidance is currently to only use this control for rendering PDFs that you have control over.

 

Windows Phone 7 Social Viewer Template v2 Published

If you want to jump start your Windows Phone application development, why not download the Social Viewer template available at http://socialviewer.codeplex.com. You can use this to simplify the creation of apps that read data from Facebook, Twitter, Blogs and any other data feed you might have.

The template integrates directly into Visual Studio 2010 (which you’ll need to do Windows Phone 7 development – http://create.msdn.com) and appears in the New Project dialog.

image

Like most Visual Studio 2010, once you’ve created a new project you can simply hit F5 to run it in the emulator or on a device. Pan left-right to see the different lists. Select an item to read the full item.

image  image  image  image

You can easily change the feeds and the lists that are displayed to the user in the configuration.xaml file. Add api keys for Facebook, Twitter and AdGACto allow the user to post to Facebook or Twitter, and to integrate Ads into your application.

Get the Social Viewer Template v2 from http://socialviewer.codeplex.com today and get building your WP7 applications.

Fix: Calling WCF Methods with Parameters Synchronously on Windows Phone 7

In my previous post, Tidying up Windows Phone 7 + WCF Synchronous Programming Model I proposed a base class called SyncClientBase which would make it much easier to call WCF services from a background thread in a synchronous fashion. Unfortunately, whilst this works well for methods that don’t take any arguments, it completely fails when trying to call methods which take parameters. The first step in the Invoke method was to pull apart the Expression parameter in order to determine the async method that was to be invoked and the corresponding event that would be raised.  ie:

    public TResult Invoke<TResult>(Expression<Action> asyncMethod) 
                          where TResult : AsyncCompletedEventArgs {
        var memberExpression = asyncMethod.Body as MethodCallExpression;
        var method = memberExpression.Method;
        var eventName = method.Name.Replace("Async","Completed");
        var evt = Proxy.GetType().GetEvent(eventName);

 

This works, however, when it comes to actually invoking the async method I was passing in an empty object array – clearly not correct when the method takes parameters. On the desktop we could pull the Expression apart even more and actually pull out the arguments that were supplied in the expression tree. However, after playing around a bit I couldn’t work out how to do this without the .NET CF raising a FieldAccessException or two.

I decided to rework the Invoke method a little: Instead of accepting an Action Expression, it now takes a Func<Delegate> Expression (ie a function that returns the method we want to invoke). It also accepts an array of objects which will be the parameters to the async method to be invoked. The full Invoke method looks like:

public TResult Invoke<TResult>(Expression<Func<Delegate>> asyncMethod, params object[] args) where TResult : AsyncCompletedEventArgs
{     var body = asyncMethod.Body as UnaryExpression;     var operand = body.Operand as MethodCallExpression;     var arg = operand.Arguments[2] as ConstantExpression;     var method = arg.Value as MethodInfo;     var eventName = method.Name.Replace("Async", "Completed");     var evt = Proxy.GetType().GetEvent(eventName);     lock (downloadLock)     {         TResult data = default(TResult);         EventHandler<TResult> handler = (s, e) =>         {             data = e;             downloadWait.Set();         };         evt.AddEventHandler(Proxy, handler);         method.Invoke(Proxy, args);         downloadWait.WaitOne();         evt.RemoveEventHandler(Proxy, handler);         if (data.Error != null)         {             throw data.Error;         }         return data;     }
}
 

The proxy class structure still looks very similar. The only difference is that instead of a method call eg Proxy.Step1Async() we’re passing a delegate eg (Action)Proxy.Step1Async. For methods that require a parameter (eg Step3) the parameters are passed in as additional parameters to the Invoke method.

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

The only issue with this structure is that there is not validation that the correct number and type of parameters are passed into the Invoke method. Other than that, it’s still quite an elegant wrapper.

Tidying up Windows Phone 7 + WCF Synchronous Programming Model

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

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

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

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

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

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

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

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

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

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

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

There are some points to note about this proxy:

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

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

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

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

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

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

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

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