Windows Phone 7 Environment.DeviceType = Un-Blendable code

Windows Phone 7 Environment.DeviceType = Un-Blendable code

So, you’ve decided to be really inventive and build some helper classes that work around the limitations of the Windows Phone 7 emulator (eg inability to simulate network connectivity, accelerometer, location, actually anything that isn’t in Silverlgiht for the desktop). Of course you don’t want this code to be used when the application runs on a real device so you have some code that looks like:

if (System.Environment.DeviceType == DeviceType.Device)
{
    // Device code
}
else
{
    // Emulator code
}

This compiles and runs fine when working in Visual Studio and Blend. However, if this code is invoked as part of building the UI to be displayed in the designer (remember that both Visual Studio and Blend run a bit of code in the background to make sure things are created properly and that data contexts are created to facilitate data binding), you will likely see a message similar to the following.

image

“Method not found: ‘System.DeviceType System.Environment.get_DeviceType()’.

Right, you think, simple enough to fix, I just need to wrap this in a check to see whether it’s running in the designer or not:

if (!DesignerProperties.IsInDesignTool && System.Environment.DeviceType == DeviceType.Device)
{
    // Device code
}
else
{
    // Emulator code
}

Unfortunately you’d be horrified to note that this does NOT get the error to disappear. The error is actually an error raised by the JIT compiler when it goes off looking for DeviceType property. Unfortunately there is no such property on the desktop so it throws an error. Typically JIT compilation is done on an “as required” and “method-level” basis which means that the whole method you are working in will be JITted together, resulting in the error even if the code will never be executed. The workaround…. just move the erroneous  code to a method that won’t get JITted:

 if (!DesignerProperties.IsInDesignTool )
{
    DoRuntimeCode();
}
else
{
    // Designer code
}

private static void DoRuntimeCode()
{
    if (System.Environment.DeviceType == DeviceType.Device)
    {
        // Device code
    }
    else
    {
        // Emulator code
    }
}

Problem fixed…. happy coding.

(FWIW this is a trick that Windows Mobile developers have used for years to build libraries that work across both .NET Framework and .NET Compact Framework where there are features on either platform that aren’t available on the other)

Apple’s WWDC Failure was both Technical and Architectural

Apple’s WWDC Failure was both Technical and Architectural

Ok, I’ve resisted for as long as I could before posting this: Looks like Microsoft isn’t the only large organisation that suffers from technology failures during their presentations. I often criticise Microsoft, particularly here in Australia, of not being thorough enough in their rehearsals for keynotes, leading to demos not working. This time it was Steve Jobs who looked like an idiot on stage when he could access a website on Safari due to a network failure. Clearly there was a major oversight here when it came to making sure there was a backup network in the case of something going wrong.

image

I guess what made me smile was that this demo strengthens my argument against all those web developers out  there that believe the answer to the world’s problems is another mobile website, or worse a RIA application. Current RIA thoughts, be they Ajax or Silverlight, just don’t get mobility and what it means to build an offline capable application. Having built for mobile on a number of platforms for countless year I believe that for your mobile application to be awesome, it must be offline capable. Yes, this means either packaging data with your application, or better, syncing with a server somewhere.

Unfortunately, do you think that Microsoft gets this – not a chance. Actually there are several teams within Microsoft that do understand this (eg Sync Services, Sql Compact, Merge replication and even Live Mesh). However, it appears none of them are currently able to influence the decisions to release Windows Phone 7 without either database or sync support.

Back to the demo failure at WWDC: Clearly they were going to show the rich capabilities of Safari…. My point is that if you are building a “rich” mobile website you’ve messed up your architecture somewhere along the line. Build rich applications using a rich technology designed for the platform. If you want reach, then build a mobile website that is light, fast, easy to navigate and gives the user what they want without chewing through their data plan. Yes, this means NO flash and NO silverlight on the page (not that either of these will render in Safari on iPhone/iPad/iPods)

Windows Phone 7 Applications Running Under the Locked Screen

Windows Phone 7 Applications Running Under the Locked Screen

The new Application Certification Requirements document for Windows Phone 7 Marketplace has been published by Microsoft and includes a couple of interesting points:

Firstly, Microsoft, like Apple, have a stupid clause in their Application Policies to the effect that you can’t charge a subscription basis for access to your application. Well, you could it Marketplace gave you the ability to charge a subscription – they don’t, and since 2.1 forbids you from using an external payment gateway (eg PayPal), you can’t do it.

image

The second and more interesting item is that Windows Phone 7 applications can continue to run even after the Lock screen has appeared.  Apparently there will be (and I say will be as it’s not in the current SDK bits) a method called Microsoft.Phone.Shell.PhoneApplicationService.ApplicationIdleDetectionMode which has to be invoked to allow the application to continue to run.

image

iPhone User Experience Fail

iPhone User Experience Fail

This afternoon I planned to go play in the AppStore. Since everyone’s been raving on about all the cool apps in there I figured I must be missing something – Don’t get me wrong I’ve been in there before but I’m not really an apps person. I use the built in phone capabilities and the occasional app to get the odd job or two done.

Turns out that since the last time I turned on my iphone the beta of iphone OS 4 has expired so my iphone is just sitting there blinking at me indicating that I need to connect to iTunes. I connected to my PC and opened up iTunes (I could almost feel the groan from my computer when I did this). It then comes up with a message saying the iphone software has expired – great, so update it for me. No chance! Restore…. Fail, Check for Updates….. none available, you’re running v4.0 which is the latest and greatest…. not!

Thinking that of course my PC is stupid and what would it know I powered up my Mac. Same deal. I went to the iphone developer website in order to get the v4.0 update and ran into two issues:

– I’ve got two developer profiles with Apple for the companies that I work with. This means that when you sign in they ask you which profile you want to connect to. Do you think I could select one and proceed? Not a hope!

– Once I finally restarted my browser, cleared the cache etc I went back to the iphone dev centre it came up with a message saying it was being updated and to come back soon…. FAIL – you mean I have to sit here with a iphone that doesn’t work?

The work around was simple enough – back to the PC, open the iphone dev centre (which for some reason still works on my PC), download the update, copy update to mac (so I can update my iphone), update iphone from iTunes (on the Mac).

Honestly, that they have the nerve to accuse other companies of a poor user experience…..

Windows Phone 7 Data: Json WCF Data Service with IIS 7 Compression

Windows Phone 7 Data: Json WCF Data Service with IIS 7 Compression

Today I was thinking about the way I consume data within my Windows Phone 7 applications, specifically how I can get a large amount of data into my application. Attempting to send 100Mb worth of uncompressed data across the wire when I could send the same thing compressed at around 25Mb wasn’t really appealing to me. This got me thinking…. “how did I do this on Windows Mobile?”…. surprisingly the answer is blindingly obvious: IIS  compression. In this post I’ll walk you through exposing your data via a WCF Data Service, enabling IIS compression (for IIS 7) and then how you can leverage this on the client side.

Let’s start by creating a simple WCF Data Service to consume:

WCF Data Service

In an ASP.NET project, create a new ADO.NET Entity Data Model, mine is called YoLoModel.edmx (YoLo stands for You only Live once, which was the name of the sample application I built as part of my Remix Australia presentation last week).

image

Next add a new WCF Data Service, and fill in the blanks with the name of your data context (In my case it’s YouOnlyLiveOnceEntities) and enable read access – you should come back later and tighten security!!

using System.Data.Services;

namespace CompressedService
{
    public class YoLoData : DataService<YouOnlyLiveOnceEntities>
    {
        public static void InitializeService(IDataServiceConfiguration config)
        {
             config.SetEntitySetAccessRule("*", EntitySetRights.AllRead);
        }
    }
}

At this point you should run up your ASP.NET project to make sure you get data when you view the data service. You should also make sure that your project is running on IIS, rather than using the Visual Studio Development Server. To do this go to Web tab of the project properties and change to “Use Local IIS Web server” (you need to hit the Create Virtual Directory to create the virtual directory so your application will run on IIS, and don’t forget to save the project properties). In my case IIS is running on port 8080 – this has no bearing on being able to use compression, just happens to be how I have IIS configured on my development machine.

image

Test this using either the browser or Fiddler.

image

IIS Compression

Setting up IIS 7 Compression isn’t that difficult once you know what to do. Start by using either the Web Platform Installer  or Programs and Features. Locate and check the box next to Dynamic Content Compression and hit Install – this adds the module to support dynamic compression into IIS.

image

Next, open up IIS Manager and locate your ASP.NET application. From the Feature View select Compression and then ensure both static and dynamic compression is enabled.

image

Next you have to enable dynamic compression for specific mime-types. Make sure you have the Server node (not your virtual directory or the web site nodes) selected and then select the Configuration Editor from the Feature View.

image

Locate the webServer/httpCompression node and find the dynamicTypes list.

image

Add any missing mime-types to cover SOAP, ATOM, JSON etc (you might as well enable them whilst you’re there). Whilst there is a trade off between performance and compression, dynamic compression only happens when the client requests it, so I’d turn it on for these mime-types and then make sure the clients only use compression appropriately (it’s up to you how you do this).

image

Don’t forget to hit the Apply button!!!

Don’t forget to RESTART IIS, make sure all your web processes restart otherwise you won’t see compressed output.

image

Now, go to Fiddler and use the Request Builder tab to create a GET request. I this case I’m requesting the url http://nickwp7dev:8080/CompressedService/YoLoData.svc/Patients. You need to specify the following headers:

Accept: application/json       -       This will cause WCF Data Services to give you the output in json format which is much trimmer than the bloated xml it usually generates. If you do want to work with xml then you can omit this header.

Accept-Encoding: gzip, deflate       -       This is what tells IIS to generate compressed data.

When you Execute this request you should see that Fiddler detects compressed data – If you don’t then go back and make sure you’ve hit Apply and restarted IIS as this seems to be the problem I came up against when experimenting with this.

image

If you click the yellow bar, Fiddler is kind enough to decompress the data so you can see the json output (or xml if you’ve omitted the Accept header).

image

Windows Phone

Right, so that’s the server side done. Now you need to implement decompression on the client. Unfortunately, unlike true rich client technologies such as WPF or WinForms, Silverlight and Windows Phone are somewhat crippled when it comes to dealing with data. However, with a little help you can work with the data quite easily.

In order to decompress the data coming from IIS I use SharpZipLib. Well actually I used a slightly hacked together version of it. Essentially there are things that need to be updated to be compatible with Silverlight/Windows Phone.

Hacked SharpZipLib for Windows Phone available here

Once you have SharpZipLib, decompressing the data is relatively straight forward:

using System;
using System.IO;
using System.Net;
using System.Windows;
using ICSharpCode.SharpZipLib.GZip;
using Microsoft.Phone.Controls;

namespace WindowsPhoneApplication1
{
    public partial class MainPage : PhoneApplicationPage
    {
        public MainPage()
        {
            InitializeComponent();

            SupportedOrientations = SupportedPageOrientation.Portrait | 
                                     SupportedPageOrientation.Landscape;
        }

        private void DisplayDataButton_Click(object sender, RoutedEventArgs e)
        {
            var request = HttpWebRequest.Create("http://nickwp7dev:8080/CompressedService/YoLoData.svc/Patients");
            request.Headers["Accept"] = "application/json";
            request.Headers["Accept-Encoding"] = "gzip, deflate";
            request.BeginGetResponse(RequestCallback, request);
        }

        void RequestCallback(IAsyncResult response)
        {
            var request = response.AsyncState as HttpWebRequest;
            var resp = request.EndGetResponse(response);
            var strm = resp.GetResponseStream();

            string data;
            using (var gzip = new GZipInputStream(strm))
            using(var reader = new StreamReader(gzip))
            {
                data = reader.ReadToEnd();
            }

            this.Dispatcher.BeginInvoke(()=>{
                this.DataText.Text = data;
            });
        }
    }
}

Run this, an there you go – compressed data from IIS 7 to Windows Phone!

image

Don’t forget you can use the json deserializer to then parse this into objects.