WinRT and Windows Phone 8 Code-Sharing Pitfalls

One of the things Microsoft promised and touted highly prior to and during BUILD 2012 was that it would be possible to share reams of code between your Windows Store and Windows Phone 8 applications.

From MSDN’s “Windows Phone API Reference” here’s what Microsoft made available, taken directly from the article:

 

The Relationship between WinRT and Windows Phone 8 APIs

The diagram has three distinct areas and these are described as follows:

  1. The set of Windows Runtime API not supported on Windows Phone 8. The API surface area of Windows Runtime is very large, with over 11,000 members. We’ve adopted a subset for Windows Phone 8 that allows you to build compelling phone scenarios. Area 1 in the diagram above represents the APIs that are not available on Windows Phone 8.

  2. The set of Windows Runtime API adopted for Windows Phone 8. This is represented by area 2 in the above diagram and consists of approximately 2,800 members. For some types, we have not implemented certain members. For others we have added additional members to support phone-only features. In both cases, these differences are noted in the API reference documentation.

  3. We’ve added key APIs needed to build great apps for the phone. These are represented by area 3 in the diagram and total about 600 members. For example, we have brand-new APIs for speech synthesis and recognition, VOIP, and other features. Creating these as Windows Runtime style APIs means you can use them regardless of the programming language you use for your app.

Naturally there are portions of code that can’t be shared easily, such as device-specific / sensor capabilities and user interface.

However, Microsoft promised that a significant number of WinRT APIs would be made available on WP8 and for a long time touted that “copy and paste” portability would be achievable.

MarkedUp’s SDK technology doesn’t interact directly with the UI or sensors on either WinRT or Windows Phone 8, so the majority of the APIs we use are ones you’d expect to work with both platforms, such as:

  • File system and storage;
  • Serialization;
  • Networking;
  • Globalization;
  • the Windows Store APIs;
  • Licensing;
  • Async and multi-threading; and
  • Unit testing with MSTest.

Our experience in porting our code from WinRT (C#) to Windows Phone 8 (C#) was largely good, although we found some nasty pitfalls along that way. In light of BUILD 2013 and all of the new features coming to Windows Phone and Windows 8.1, we thought it would be a good time to share these.

Networking

System.Net.HttpClient – By far the biggest and most vociferous WinRT & WP8 compatibility issue echoed from the development community is the fact that System.Net.HttpClient, Microsoft’s modern HTTP client that is built from the group up to work with async, advanced media types, RESTful APIs, and so forth. HttpClient is a huge boon to our productivity in the course of working with WinRT.

For reasons that I am not privy to, Microsoft did not include HttpClient in the core framework for Windows Phone 8, so MarkedUp uses System.Net.WebRequest wraps it with the appropriate async and error-handling decorators.

One of the major pitfalls of WebRequest is that it throws an exception whenever you receive an HTTP code that isn’t in the 200 (“Success) category. Trying to handle these exceptions asynchronously complicates things considerably, but it can be done.

It should be noted that HttpClient for Windows Phone 8 is available as a separate NuGet package. We can’t use any third party dependencies in our SDK but you are certainly free to use these inside your apps.

System.Net.WebRequest APIs are different across .NET 4.5 / Windows Phone 8 and WinRT – One strategy for dealing with the lack of HttpClient availability on Windows Phone 8 is just to use System.Net.WebRequest everywhere, including WinRT. This is something we tested since standardizing on a single HTTP layer helps reduce our QA overhead.

Our experience was that while vanilla .NET 4.5 and Windows Phone 8 have 100% reuse and compatibility when it comes to WebRequest, this is not the case with WinRT.

For instance, WebRequest does not have any directly settable ContentLength or UserAgent properties in WinRT; WebRequest has a different interface altogether for forming HTTP request bodies in WinRT. Additionally, the System.Net.WebException enum implementation in WinRT is missing a number of options that make it difficult to perform error-handling consistently across platforms.

We ultimately determined that it was less expensive to maintain two different network stack implementations for Windows Phone and WinRT than to try to work around all of the incompatibilities and different behaviors with WebRequest in WinRT.

File System

Windows.Storage.Search is not fully implemented on Windows Phone 8 – For most WinRT developers, Windows.Storage.Search is probably used for one specific purpose inside any given app: determining whether or not a file exists.

Since there isn’t an equivalent to File.Exists in the Windows.Storage namespace, most developers (us included) have to resort to something like this:

One issue that we ran into early on in our QA for Windows Phone is that not all search options which use a Windows.Storage.Search.CommonFileQuery enumeration are implemented in Windows Phone 8. For instance, CommonFileQuery.OrderByName will throw a NotImplemented exception.

However, you can work around most of these issues by just using CommonFileQuery.DefaultQuery if the ordering of the files returned isn’t particularly important.

Licensing

CurrentApp.LicenseInformation doesn’t actually tell you if your Windows Phone 8 app is running as a trial or not – WinRT developers rely on CurrentApp as the single source of truth for all things Windows Store and licensing on Windows 8, and the class is available on Windows Phone 8 and is what developers use for executing in-app purchases.

However, for reasons unknown, the data returned from CurrentApp.LicenseInformation doesn’t have the IsTrial flag set in accordance with the actual licensing status on Windows Phone. Instead, you have to use the legacy API from Windows Phone 7, new Microsoft.Phone.Marketplace.LicenseInformation().IsTrial(), to get that information.

In order to make things more tenable for our x-platform development with WP8 and WinRT, we wrapped CurrentApp into a class called CurrentAppProxy and have it call the appropriate WP8-specific method when inferring licensing information.

Commerce

CurrentAppSimulator does not exist for Windows Phone 8, thus there’s no built-in way to test in-app purchases – We depend on CurrentAppSimulator when testing anything that touches a trial conversion or in-app purchases, so we were a little shocked when we discovered that it isn’t included in Windows Phone 8.

Microsoft subsequently shipped their own mock in-app purchase library for Windows Phone 8, but since we have a shared testbed between WinRT and WP8 and can’t use any third party dependencies anywhere in our SDK we ended up writing our own. We will likely open source it on Github eventually.

No ListingInformation.CurrentMarket – One of the really handy features of ListingInformation in WinRT is the ability for it to tell you the current marketplace of any given user right off the bat using ListingInformation.CurrentMarket; this is important from an analytics point of view and really important if you manage your own commerce engine and want to localize prices in different currencies.

In Windows Phone 8, this method throws a NotImplemented exception. So how do you look up this information on WP8? Thanks to some smarties at StackOverflow, it turns out that System.Globalization.RegionInfo.CurrentRegion can’t be changed by the end user and is the culture reported by the phone to the store for any in-app purchases.

Globalization

RegionInfo uses different constructor arguments on WinRT and Windows Phone 8 – in WinRT, you can construct a new RegionInfo object by passing along the two-character ISO country code that you might receive from a marketplace method. This works great particularly when coupled with CurrentApp.

In Windows Phone 8, you’ll get an ArgumentException every time – in WP8 RegionInfo only accepts the culture name itself, i.e. “en-US,” as the constructor argument, not the region name.

GlobalizationPreferences.HomeGeographicRegion does not exist in Windows Phone 8
when try to establish the local time and culture for a user in WinRT, GlobalizationPreferences.HomeGeographicRegion makes this a breeze if you need to account for local time or any other globalization preference. This API does not exist in Windows Phone 8, but because a user can’t change their region settings you just just use RegionInfo.CurrentRegion.

Serialization

DataContractJsonSerializer doesn’t actually respond to EmitTypeInformation flags – one of the lesser-used features of DataContractJsonSerializer is its ability to control whether or not it includes type information in its outbound JSON payloads via the EmitTypeInformation property; this feature is really useful if you’re sending data to an ASP.NET MVC service and want to disable type hints so the model binder doesn’t fail.

Unfortunately, in Windows Phone 8 they never implemented the control flow that responds to this flag, so you get type information always whether you want it or not. Ultimately, we had to parse out type information using a regular expression upon serialization in order to resolve this issue for Windows Phone 8.

We hope this has been information – let us know if you have any feedback in the comments!

How to Install and Run the Windows 8.1 Preview in Hyper-V

The big announcement from //BUILD 2013 is the pending arrival of Windows 8.1, aka “Windows Blue,” and Microsoft made Windows 8.1 available for download immediately following the //BUILD keynote on Wednesday.

Like many developers, the MarkedUp Analytics team is naturally excited to try new things; that being said – we also don’t like having to wipe a dev machine and re-image it in the event that a beta release of Windows isn’t compatible with tools we use for doing our jobs every day.

So, we use Hyper-V or VirtualBox and run Windows 8.1 in a VM until it’s released to market.

Here’s how to get Windows 8.1 running in Hyper-V:

1. Download the Windows 8.1 Preview ISO

Download any of the Windows 8.1 Preview ISO images here. Pick whichever one best suits your needs. I’m going to use the English 64-bit .ISO.

2. Open Hyper-V and create a new virtual machine

If you’re running Windows 8 already, Hyper-V comes built into the operating system. Once the Windows 8.1 preview ISO is finished downloading you’ll want to create a new VM.

step1 - new VM

We’ll name our VM “Windows 8.1 Preview” and use the default storage location.

step2 - name VM

Windows 8 needs at least 2GB of RAM on a 64-bit system; I’m going to give this VM 4GB since I plan on running Visual Studio and some other RAM-intensive software on it later.

step3 - allocate RAM to VM

For now we’re going to leave the VM’s network as “Not Connected” – we’ll create a Virtual Network Adapter for it later.

If you already have a Hyper-V virtual network adapter that can share Internet connectivity with the host machine, use it here. Otherwise we’ll add one later after the OS installation on the VM is complete.

step4 - set VM network to not connected

Windows 8 needs at least 20GB of disk space on a 64-bit system. I’m going to give this VM 40GB and I’m going to use a dynamically expanding disk.

Dynamically expanding disks will be slow initially, but it saves room on the host machine in the event that you don’t occupy the entire VHD volume immediately.

If speed is an issue, you can create a fixed-size disk up front.

step5 - set VHD creation options for VM

3. Install Windows 8.1 Preview from ISO

Now we’re going to use the Windows 8.1 Preview .ISO file we downloaded earlier to install the operating system while we finalize our VM.

stp6 - install OS via Windows 8.1 ISO

This option will have you complete the Windows 8.1 Preview installation the first time the VM boots, using the .ISO file you downloaded earlier as the bootable media.

With all of those steps complete, you should now see the “Windows 8.1 Preview” VM on your Hyper-V list:

step7 - verify that Windows 8.1 VM is available in Hyper-V

Select the Windows 8.1 Preview VM and start it, and you should see the first “Install Windows” screen after a few seconds:

step8 - start the Windows 8.1 VM and install the OS

Click next.

You’ll need to enter in a product key for Windows 8.1 Preview during the first part of the installation process.

The product key for Windows 8.1 Preview is NTTX3-RV7VB-T7X7F-WQYYY-9Y92F, according to Microsoft’s official Windows 8.1 Preview installation instructions.

step9 - enter product key for Windows 8.1 Preview

If you see the following message and it asks you to choose between an upgrade and a custom installation, Select “Custom: Install Windows only.”

step10 - select custom install for Windows 8.1 Preview

Install Windows 8.1 on the VHD that we created earlier.

step11 - install Windows 8.1 preview on VHD created earlier

Let the Windows 8.1 Preview installation run to completion. And after 30 minutes or so you should be able to create a local Windows account and log in.

step12 - verify Windows 8.1 installation

4. If you don’t have one already, create a Virtual Network Adapter for Windows 8.1

If you didn’t have a Virtual Network Adapter ready during step 2, we’ll create one now.

First, shut down your Windows 8.1 Preview VM and turn it off – we’re about to make some changes to it.

step13 - shut off Windows 8.1 VM

Open up the Hyper-V manager and go to “Virtual Switch Manager.”

step14 - go Virtual Switch Manager in Hyper-V

Select “New virtual network switch.” Give the switch a name and make it an External Network. If you have multiple physical network adapters (i.e. ethernet and WiFi), use whichever one you use most often. Check the “allow management operating system to share this network adapter” box.

step15 - create new Virtual Adapter in HyperV

Apply changes.

Go back to your VMs and right click on the “Windows 8.1 Preview” VM you created – select “Settings,” then select “Network Adapter.”

step16 - Windows 8.1 VM network adapter settings

Change the Virtual switch to the new switch you just created; mine is called “Magical Switch.”

step17 - set virtual switch on Windows 8.1 Preview VM

Apply changes. Before we try starting the VM, let’s make sure that our switch was set up correctly – I often have trouble getting Hyper-V’s network adapters to behave properly the first time around.

Go to Control Panel and then to View Network Connections. Right click on the new switch you just created and select Properties.

step18 - verify virtual switch properties

Only the following properties should be set:

  • Client for Microsoft Networks
  • QoS Packet Scheduler
  • File and Printer Sharing for Microsoft Networks
  • Microsoft LLDP Protocol Driver
  • Link-layer Topology Discovery Mapper I/O Driver
  • Link-layer Topology Discovery Responder
  • Internet Protocol Version 6 (TCP/IPv6) and
  • Internet Protocol Version 4 (TCP/IPv4)

You will likely need to reboot your host machine in order to get the Internet working again. Go ahead and do that now.

5. Start Windows 8.1 Preview; Profit

You now should be able to start your Windows 8.1 VM in Hyper-V and connect to the Internet.

Install complete

Please give this guide a try and let us know if you run into any trouble!