Asynchronous Image download on Windows Phone 7

When running your solution on local and setting the Source property of the System.Windows.Controls.Image it is not visually apparent that the Image may take some period of time to download simplifying the code the following the original image swap out whereby i was using an arbitrary Uri to an image in Azure Blob Storage that would change at a predefined interval.

imgContent.Source = new BitmapImage(new Uri(arbitraryImageUriThatKeepsChanging));

As soon as the image is available from Azure Blob Storage – or any other hosting provider for that matter if you are not using a CDN and are a long way from your host then or the image is of a large size then it is likely that as soon as the image is set the image content becomes empty until the image is downloaded – i found this to be 10 to 30 seconds over the slow bandwidth of my phone.  To have an empty Image control on the screen was not acceptable so the simple solution is to pull down the image asynchronously using a WebClient then once downloaded update the Image.Source as follows:

Starting the Async download of the image:

WebClient wc = new WebClient();
wc.OpenReadCompleted += new OpenReadCompletedEventHandler(wc_OpenReadCompleted);
wc.OpenReadAsync(new Uri(arbitraryImageUriThatKeepsChanging), wc);

Handling the completed download and updating the image source – note: have intentionally removed the MVVM implementation here to minimise code in post if using MVVM setup the binding on the Image.Source property to the model Source.

void wc_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
   if (e.Error == null && !e.Cancelled)
  {
      try
      {
         BitmapImage image = new BitmapImage();
         image.SetSource(e.Result);
         imgContent.Source = image;
      }
      catch (Exception ex)
      {
          //Exception handle appropriately for your app
      }
  }
  else
  {
      //Either cancelled or error handle appropriately for your app
  }

Async download of Images from Azure to windows phone.

Note: WebClient executes on the UI thread if you wish to do this on a background thread and then later update the UI you should use HttpWebRequest and then Dispatcher within your response to update the UI thread.

Note: It would be interesting to configure the Azure CDN to see the improved performance once the node is distributed from a CDN node that is geographically close.

Nick

Monetize your Windows Phone 7 application with Microsft Advertising SDK

This post covers basic test Ads only.

1. Download the SDK – link can be found here http://advertising.microsoft.com/mobile-apps
2. Add a reference to the Microsoft.Advertising.Mobile.UI.dll
3. Add a reference in your XAML
 

xmlns:ad="clr-namespace:Microsoft.Advertising.Mobile.UI;assembly=Microsoft.Advertising.Mobile.UI"

4. Use one of the following three variants to display ads

<ad:AdControl AdModel="Contextual" ApplicationId="test_client" AdUnitId="Image300_50" />

<ad:AdControl AdModel="Contextual" ApplicationId="test_client" AdUnitId="Image480_80" />

<ad:AdControl AdModel="Contextual" ApplicationId="test_client" AdUnitId="TextAd" />

5. Job done:

Microsoft Advertising

Microsoft Advertising

Note: currently documentation seems to indicate only available to people with US tax identification number with aps targeted for the US market – more details here: http://advertising.microsoft.com/WWDocs/User/en-us/ForPublishers/Ads-in-Windows-Phone-7-Apps-FAQs.pdf

Those of you interested in a similar service for Australia please email me nicholas dot ian dot harris @ hotmail dot com or reply to this post with your contact details – i will keep the comments private.

Kind Regards,

Nick

How to place a Phone Call on Windows Phone 7 using PhoneCallTask

This describes the straightforward task of how to place a Phone Call on Windows Phone 7 using PhoneCallTask.

  1. Add using statement to the Tasks namespace
  2. using Microsoft.Phone.Tasks;
    
  3. Create an instance of PhoneCallTask set the DisplayName and PhoneNumber properties then call Show:
  4.             PhoneCallTask pct = new PhoneCallTask();
                pct.DisplayName = "Nick Harris";
                pct.PhoneNumber = "+61000000000";
                pct.Show();
    
  5. Result
  6. PhoneCallTask

    PhoneCallTask

  7. Press Call
  8. PhoneCallTask

    PhoneCallTask

  9. After a bit of fiddling it appears you can do conference calls which is pretty neat.
  10. Press the Down Arrow
    Press the dial button from the ApplicationBar
    Enter your number and press Call
    Then press merge call and you got yourself a conference call.

    Conference Call

    Conference Call

    It would be cool if the PhoneCallTask allowed for a collection of Display Name and Phone Numbers to be supplied for programmatic conference call initiation.

Nick

How to SMS using the SmsComposeTask for Windows Phone 7

Unlike Windows Mobile with Windows Phone 7 we are currently unable to directly send an SMS from within an application unless we show the composer screen using SMSComposerTask.  This does suck a little bit as we now Aps cant send SMS’s direct or intercept them at all for that matter.  So what does WP7 offer – well to send an SMS you can use SMSComposerTask and to intercept an SMS – nothing, you will need to re-think your application architecture

To send an SMS using the composer in Windows Phone 7 you need to do the following:   

  1. Add using statement to Tasks namespace
  2. using Microsoft.Phone.Tasks;
    
  3. Create an instance of SMSComposerTask set the To field and body then call Show:
  4. SmsComposeTask sms = new SmsComposeTask();
    sms.To = "0123456789";
    sms.Body = "Some prefilled text...";
    sms.Show();
    
  5. Result
  6. SmsComposerTask Windows Phone 7

    SmsComposerTask Windows Phone 7

If your application really can’t live without direct access to send and intercept an SMS without any user interaction in the composer:   

  1. Then you can wait and they may add it in future releases although I am unsure if this will ever occur and I would not rely on it
  2. Or you may be able to rework your architecture to replace SMS with Push Notifications, a WCF service and Database or XML as your storage. The obvious downside to this is that you loose the telcos serverside infrastructure and have to replace it yourself. This adds a lot more code and cost to the developer for implementation and continual subscription costs for hosting which then means your cool free App idea may become too costly.

If your application can live without SMS interception but needs direct access to send and SMS without any user interaction in the composer:

  1. Then you may be able to use those options listed above
  2. Or, look into SMS providers that provide a web service based API – needless to say if you can’t figure out how to oncharge this to the end user this will also cost you but it may be significantly less then hosting depending on your volume

 Nick   Â
   

Windows Phone 7 OData CTP, nope use REST and JSON

First things first the OData CTP for Windows Phone 7 is exactly that – a CTP - therefore expectations are not high but I did have them set at medium.  Due to the issues I was hitting i ended up having to use REST to consume my WCF data service then write a bunch of code to deserialize the JSON response. So this post will take you through how to do this.

But first, what issues did I encounter – well after being able to successfully to generate the service reference using dataservice util I was able to consume the service successfully and i felt yay big ticks this is awesome.  I then went to implement serverside paging, cool serverside paging out of the box thats pretty neat.  However when I went to then consume the next page from the service the Continuation Token was always null.  This ment that I was unable to navigate to the next page set with the link that should have been returned.  Note:  - if anyone managed to get this working with the CTP please drop me a link and/or some sample code.

Checking out Nicks blog – Windows Phone 7 Data: Json WCF Data Service with IIS 7 Compression I figured out how to construct a REST request using fiddler i tried by application/atom+xml and application/json – both results had the next link :( … With this in mind i really had to narrow down if it was the CTP or not – I created a .NET 4.0 win forms app and generated the service reference  and used the same code to consumed it successfully with the Continuation token being set.  At this point i settled that it is something was from the CTP….

After spending a lot of time trying to get to the bottom of it – using reflector to figure out where the error was coming from because the OData CTP source was not available i finaly decided to cut my losses and just consume the feed using REST.  Funnyly enough, but not so funny at the time, it took less time to write the data contract to deserialize the JSON then I spent fighting the CTP.  To do this I did the following:

Consume your service using REST to see the format of the returned data:

1. Construct request in this case to Posts and add the header accept: application/json then press execute

REST request to WCF Data service

REST request to WCF Data service

2. Take the response and format it using an online formatter to make life easy on yourself

{
   “d”:{
      “results”:[
         {
            "__metadata":{
               "uri":"http://localhost/TestServices/SomeService.svc/Posts(guid'ccb89791-a49b-4224-924d-0e0bc56d8ffb')",
               "type":"Model.Post"
            },
            "Id":"ccb89791-a49b-4224-924d-0e0bc56d8ffb",
            "Title":"some title",
            "Content":"Some long content"
         }
      ],
      “__next”:”http://localhost/TestServices/SomeService.svc/Posts?$skiptoken=guid’ccb89791-a49b-4224-924d-0e0bc56d8ffb’”
   }
}

3. Create your DataContract so that it can consume a response of the format above.  Note the nasty bit about this is the nesting of the above.  I created a generic representation of this so that this can be re-used for your other tables.  So this is what we are building:

Datacontract for JSON deserialization of WCF Data Service

Datacontract for JSON deserialization of WCF Data Service

and the code is as follows: Note the name of the data member maps to the sample JSON for the serialization / deserialization of the JSON content:

using System;
using System.Collections.Generic;
using System.Runtime.Serialization;

namespace JSON.DataContract
{
    [DataContract] //Gets the outer {}
    public class BaseJSONResult<T> where T : BaseMyContent
    {
        [DataMember(Name = "d")] //Gets the d
        public ComposedResult<T> Result { get; set; }
    }

    [DataContract]
    public partial class ComposedResult<T> where T : BaseMyContent
    {
        [DataMember(Name = "results")]
        public List<T> MyContents { get; set; }

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

    [DataContract(Name = "__metadata")]
    public class MetaData
    {
        [DataMember(Name = "uri")]
        public string Uri { get; set; }

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

    [DataContract]
    public abstract class BaseMyContent
    {
        [DataMember(Name = "__metadata")]
        public MetaData MetaData { get; set; }
    }

    public partial class Post : BaseMyContent
    {
        [DataMember]
        public Guid Id { get; set; }
        [DataMember]
        public string Title { get; set; }
        [DataMember]
        public string Content { get; set; }
    }

    [DataContract]
    public partial class SomeOtherClass : BaseMyContent
    {
        [DataMember]
        public Guid Id { get; set; }
        [DataMember]
        public string Name { get; set; }
        [DataMember]
        public string Caption { get; set; }
    }
}

Note: if you have more types you would like to extend the support to just derrive them from BaseMyContent like SomeOtherClass above.
Note: this example does not currently take care of Links between types… but you should easily be able to add support for this.

4. Usage: Use a web request and response and Json serializer to process the results

   HttpWebRequest request = HttpWebRequest.Create("http://localhost/TestServices/SomeService.svc/Posts") as HttpWebRequest;
   request.Accept = "application/json"; //atom+xml";
   request.BeginGetResponse(RequestCallback, request);

The callback where deserialization occurs, post will contain the deserialize content

private void OnRequestCallback(IAsyncResult result)
{
     var request = result.AsyncState as HttpWebRequest;
     var response = request.EndGetResponse(result);
     if (response != null)
     {
          var jsonSerializer = new DataContractJsonSerializer(typeof(BaseJSONResult<Post>)); //Note: DataContractJsonSerializer requires a reference to System.Servicemodel.Web

          BaseJSONResult<Post> post = null;
          using (var stream = response.GetResponseStream())
          {
               post = jsonSerializer.ReadObject(stream) as BaseJSONResult<Post>;
          }

          this.Dispatcher.BeginInvoke(() =>
             PostRetrieved(Post));
     }
}

Now finally you can get at a populated Next link with post.NextLinkUri *wipes teary eyes*

5. If you are having troubles and the deserialization is not working the best tip i can give you is to try serializing your datacontract and cross check it with the data returned from your service. To serialize it do the following:

              Â
var test = new BaseJSONResult<Post>()
{
    // Make sure you set all the properties
};
using (MemoryStream ms = new MemoryStream())
{
    jsonSerializer.WriteObject(ms, test);
    byte[] bytes = ms.ToArray();
    string json = Encoding.UTF8.GetString(bytes, 0, bytes.Length);
    Console.WriteLine(json); //Compare this with your fiddler result
}

I really can’t wait until the CTP comes out full form with the bugs fixed, it will save a lot of time, but for now I am keeping a wide berth with the intention of returning once it is out of CTP.

How to Send Tile Toast and Raw Notifications to the Microsoft Push Notification Service to Windows Phone 7

Note: Code here applies to CTP – I have not yet updated for the RTM.
This post provides the code required to send notifications through the Microsoft Push Notifications Service to a Windows Phone 7 device. I have put this together for the purpose of re-use across projects. Receiving and processing the notification on Windows Phone 7 will be the subject of a later post but I have some screenshots of the result here.

I will keep this breif as you are likely already aware, but for those of you who are not there are three types of notifications you can send to a Windows Phone 7 device:

  • Tile – A tile is a visual, dynamic representation of application specific state within the quick launch area of the phone’s start experience
  • Toast – Displays as an overlay onto the user’s current screen, a bit like an outlook email notification popup that you can press that launches you into the application.
  • Raw – provides the ability for your application service to push data to the application while it is in the foreground without the need for your application to poll the appplication service.

So as a teaser – what do these look like in action:

  • Tile – ability to change the count, background image(using either a local image and remote image) and text, yes E=mc^2 influnced by the first non programming book i am reading in about 10yrs – “A Brief History of Time” by Steven Hawking, ok so still technical. but not programming.
  • Tile Push Notification Before

    Tile Push Notification Before

    Tile Push Notification After

    Tile Push Notification After

  • Toast – See the Orange pop up at the top with the lame joke – well that is a toast, it looks like the above before and after as below.
  • Toast Push Notification After

    Toast Push Notification After

  • Raw – provides the ability for your application service to push data to the application while it is in the foreground without the need for your application to poll the appplication service. Well really with raw there is nothing to show until you implement a handler in your application to do something useful with the data (HttpNotificationChannel.HttpNotificationReceived). Therefore no image until next post.
  • So what exactly are we building a RawNotification, TileNotification and ToastNotification class with a Send method that returns a parsed NotificationResponse – here it is:

    An API for sending Push Notifications Tile, Toast and Raw
    Once you finish implementing this with the code provided in the post you will be able to send a notification as simply as follows:
  • Tile – TileNotification.cs
  • ToastNotification toast = new ToastNotification("Wanted Toast", "But forgot the bread ", new Uri(txtUri.Text), Guid.NewGuid(), 2, null);
    ThreadPool.QueueUserWorkItem((o) => toast.Send(ProcessResponse));
  • Toast – ToastNotification.cs
  • TileNotification tile = new TileNotification(@"/Images/Background1.png", 2, "E = mc^2", new Uri(txtUri.Text), Guid.NewGuid(), 1, null);
    ThreadPool.QueueUserWorkItem((o) => tile.Send(ProcessResponse));
  • Raw – RawNotification.cs
  •             XmlDocument rawData = new XmlDocument();
                string rawContent = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n\r\n" +
    
                                     "<root>\r\n" +
                                        "<foo>c</foo>\r\n" +
                                        "<bar>3000000</bar>\r\n" +
                                     "</root>";
                rawData.LoadXml(rawContent);           
    
                RawNotification raw = new RawNotification(rawData, new Uri(txtUri.Text), Guid.NewGuid(), 3, null);
                ThreadPool.QueueUserWorkItem((o) => raw.Send(ProcessResponse));

    So now you can see how easy it is to use, how is the code for sending the notifications implemented:

    NotificationBase.cs

    using System;
    using System.IO;
    using System.Net;
    using System.Security.Cryptography.X509Certificates;
    
    namespace NickHarris.Net.Notification
    {
        public enum NotificationType { Token, Toast, Raw };   
    
        public abstract class NotificationBase
        {
            private Uri _URI;
            private Guid? _UUID;
            private int? _priority;
            private X509Certificate _certificate;
            private NotificationType _target;
            private byte[] FormattedNotificationMessage { get; set; }
    
            public NotificationBase(Uri uri, Guid? uuid, int? priority, X509Certificate certificate, NotificationType target)
            {
                _URI = uri;
                _UUID = uuid;
                _priority = priority;
                _certificate = certificate;
                _target = target;
            }
    
            protected abstract Byte[] GetTemplateFormatted();
            protected abstract bool IsPriorityValid(int priority);
    
            protected HttpWebRequest CreateRequest(Uri uri, Guid? uuid, int? priority, X509Certificate certificate, NotificationType target)
            {
                 if (priority.HasValue && !IsPriorityValid(priority.Value))
                    throw new ArgumentOutOfRangeException("Priority {0} is not valid for this notification type", priority.ToString());
    
                // The URI that the Push Notification service returns to the Push Client when creating a notification channel.
                HttpWebRequest request = WebRequest.Create(uri) as HttpWebRequest;
                // HTTP POST is the only allowed method to send the notification.
                request.Method = WebRequestMethods.Http.Post;
                request.ContentType = "text/xml; charset=utf-8";
                FormattedNotificationMessage = GetTemplateFormatted();
                request.ContentLength = FormattedNotificationMessage.Length;
                request.Headers = GetHeaders(uuid, priority, target);
    
                // If the cloud service sending this request is authenticated, it needs to send its certificate.
                // Otherwise, this step is not needed.
                if (certificate != null)
                    request.ClientCertificates.Add(certificate);
                return request;
            }
    
            protected WebHeaderCollection GetHeaders(Guid? uuid, int? priority, NotificationType target)
            {
                WebHeaderCollection headers = new WebHeaderCollection();
    
                // The optional custom header X-MessageID uniquely identifies a notification message. If it is present, the same value is returned.
                // in the notification response. It must be a string that contains a UUID.
                if (uuid.HasValue)
                    headers.Add("X-MessageID", uuid.Value.ToString());
    
                if (target != NotificationType.Raw)
                    headers.Add("X-WindowsPhone-Target", target.ToString().ToLower());
    
                // The optional custom header X-NotificationClass sets the notification class for this notification request. The valid value range is
                // from 1-31. If this value is not present, the server defaults to 2
                if (priority.HasValue)
                    headers.Add("X-NotificationClass", priority.Value.ToString());
    
                return headers;
            }
    
            public void Send(Action<NotificationResponse> callback)
            {
                HttpWebRequest request = CreateRequest(_URI, _UUID, _priority, _certificate, _target);
                request.BeginGetRequestStream((x) =>
                {
                    using (Stream requestStream = request.GetRequestStream())
                    {
                        requestStream.Write(FormattedNotificationMessage, 0, FormattedNotificationMessage.Length);
                        requestStream.Close();
                    }
    
                    //Get Async response from push notification service
                    request.BeginGetResponse((asyncResult) =>
                    {
                        using (WebResponse notifyResponse = request.EndGetResponse(asyncResult))
                        {
                            //callback to notify caller of result
                            callback(new NotificationResponse((HttpWebResponse)notifyResponse));
                        }
                    }, null);
                }, null);
            }
        }
    }

    RawNotification.cs

    using System;
    using System.Security.Cryptography.X509Certificates;
    using System.Text;
    using System.Xml;
    
    namespace NickHarris.Net.Notification
    {
        public class RawNotification:NotificationBase
        {
            public XmlDocument Payload { get; set; }
            public RawNotification(XmlDocument payload, Uri subscriptionUri, Guid? uuid, int? priority, X509Certificate certificate)
            : base(subscriptionUri, uuid, priority, certificate, NotificationType.Raw)
            {
                Payload = payload;
            }
    
            protected override byte[] GetTemplateFormatted()
            {
                return Encoding.UTF8.GetBytes(Payload.OuterXml);
            }
    
            protected override bool IsPriorityValid(int priority)
            {
                return    (priority > 2 && priority < 11)  //3-10 – Real Time. The raw notification is delivered as soon as possible.
                       || (priority > 12 && priority < 21) //13-20 – Priority. The raw notification is delivered at a predefined timeout.
                       || (priority > 22 && priority < 32); //23-31 – Regular. The raw notification is delivered at a predefined timeout which is greater than the Priority batching interval.
            }
        }
    }

    TileNotification.cs

    using System;
    using System.Security.Cryptography.X509Certificates;
    using System.Text;
    
    namespace NickHarris.Net.Notification
    {
        public class TileNotification : NotificationBase
        {
            public string BackgroundImage { get; set; }
            public int Count { get; set; }
            public string Title { get; set; }
    
             public TileNotification(string backgroundImage, int count, string title, Uri subscriptionUri, Guid? uuid, int? priority, X509Certificate certificate)
                : base(subscriptionUri, uuid, priority, certificate, NotificationType.Token)
            {
                BackgroundImage = backgroundImage;
                Count = count;
                Title = title;
            }
    
             protected override Byte[] GetTemplateFormatted()
             {
                 string tileMessage = "X-WindowsPhone-Target: token\r\n\r\n" +  //Note: I have left this in line so you can see the format.  Would be better if you add it to a Resource file
                    "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
                    "<wp:Notification xmlns:wp=\"WPNotification\">" +
                       "<wp:Token>" +
                          "<wp:Img>{0}</wp:Img>" +
                          "<wp:Count>{1}</wp:Count>" +
                          "<wp:Title>{2}</wp:Title>" +
                       "</wp:Token> " +
                    "</wp:Notification>";
    
                 //return new UTF8Encoding().GetBytes(string.Format(Properties.Resources.ToastNotificationTemplate, Environment.NewLine, Environment.NewLine, BackgroundImage, Count, Title));
                 return new UTF8Encoding().GetBytes(string.Format(tileMessage,BackgroundImage, Count, Title));
             }
    
             protected override bool IsPriorityValid(int priority)
             {
                 return    priority == 1   // 1 – Real Time. The tile notification is delivered as soon as possible.
                        || priority == 11  //11 – Priority. The tile notification is delivered at a predefined timeout.
                        || priority == 21; //21 – Regular. The tile notification is delivered at a predefined timeout which is greater than the Priority batching interval.
             }
        }
    }

    ToastNotification.cs

    using System;
    using System.Security.Cryptography.X509Certificates;
    using System.Text;
    
    namespace NickHarris.Net.Notification
    {
        public class ToastNotification: NotificationBase
        {
            public string TitleOne { get; set; }
            public string TitleTwo { get; set; }
    
            public ToastNotification(string titleOne, string titleTwo, Uri subscriptionUri, Guid? uuid, int? priority, X509Certificate certificate)
                : base(subscriptionUri, uuid, priority, certificate, NotificationType.Toast)
            {
                TitleOne = titleOne;
                TitleTwo = titleTwo;
            }
    
            protected override Byte[] GetTemplateFormatted()
            {
                string toastTemplate = "X-WindowsPhone-Target: TOAST\r\n\r\n" +                 //Note: I have left this in line so you can see the format.  Would be better if you add it to a Resource file
                                        "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
                                        "<wp:Notification xmlns:wp=\"WPNotification\">" +
                                           "<wp:Toast>" +
                                              "<wp:Text1>{0}</wp:Text1>" +
                                              "<wp:Text2>{1}</wp:Text2>" +
                                           "</wp:Toast>" +
                                        "</wp:Notification>";
    
                return new UTF8Encoding().GetBytes(string.Format(toastTemplate, TitleOne, TitleTwo));
                //return new UTF8Encoding().GetBytes(string.Format(Properties.Resources.ToastNotificationTemplate, Environment.NewLine, Environment.NewLine, TitleOne, TitleTwo));
            }
    
            protected override bool IsPriorityValid(int priority)
            {
                return priority == 2        //2 – Real Time. The toast notification is delivered as soon as possible.
                       || priority == 12    //12 – Priority. The toast notification is delivered at a predefined timeout.
                       || priority == 22;   //22 – Regular. The toast notification is delivered at a predefined timeout which is greater than the Priority batching interval.
    
            }
        }
    }

    NotificationResponse.cs

    using System;
    using System.Net;
    
    namespace NickHarris.Net.Notification
    {
        public enum NotificationStatus { None = 0, Received, QueueFull, Dropped, Unknown }; //N/A mapped to None, Unknown -> unknown will likely occur with updates to the CTP
        public enum DeviceConnectionStatus { None = 0, Connected, TemporarilyDisconnected, Inactive, Unknown };
        public enum SubscriptionStatus { None = 0, Active, Expired, Unknown };
    
        public struct NotificationResponse
        {
            private string _messageID; //keep as string not everyone will be using guids
            private NotificationStatus _notificationStatus;
            private SubscriptionStatus _subscriptionStatus;
            private DeviceConnectionStatus _deviceConnectionStatus;
            private HttpStatusCode _httpStatusCode;
    
            public NotificationResponse(HttpWebResponse response)
            {
                _messageID = response.Headers["X-MessageID"];
                _notificationStatus = GetNotificationStatus(response.Headers["X-NotificationStatus"]);
                _subscriptionStatus = GetSubscriptionStatus(response.Headers["X-SubscriptionStatus"]);
                _deviceConnectionStatus = GetDeviceConnectionStatus(response.Headers["X-DeviceConnectionStatus"]);
                _httpStatusCode = response.StatusCode;
            }
    
            public HttpStatusCode HttpStatusCode
            {
                get { return _httpStatusCode; }
                private set { _httpStatusCode = value; }
            }
    
            public DeviceConnectionStatus DeviceConnectionStatus
            {
                get { return _deviceConnectionStatus; }
                private set { _deviceConnectionStatus = value; }
            }
    
            public SubscriptionStatus SubscriptionStatus
            {
                get { return _subscriptionStatus; }
                private set { _subscriptionStatus = value; }
            }
    
            public NotificationStatus NotificationStatus
            {
                get { return _notificationStatus; }
                private set { _notificationStatus = value; }
            }
    
            public string MessageID
            {
                get { return _messageID; }
                private set { _messageID = value; }
            }
    
            private static NotificationStatus GetNotificationStatus(string notificationStatus)
            {
                NotificationStatus status = NotificationStatus.Unknown;
    
                if (notificationStatus.ToUpper() == "N/A")
                    status = NotificationStatus.None;
                else if (Enum.IsDefined(typeof(NotificationStatus), notificationStatus))
                    status = (NotificationStatus)Enum.Parse(typeof(NotificationStatus), notificationStatus, true);
                else
                {//leave as unknown
                }
    
                return status;
            }
            private static DeviceConnectionStatus GetDeviceConnectionStatus(string deviceConnectionStatus)
            {
                DeviceConnectionStatus status = DeviceConnectionStatus.Unknown;
                deviceConnectionStatus = deviceConnectionStatus.Replace(" ", string.Empty);
    
                if (deviceConnectionStatus.ToUpper() == "N/A")
                    status = DeviceConnectionStatus.None;
                else if (Enum.IsDefined(typeof(DeviceConnectionStatus), deviceConnectionStatus))
                    status = (DeviceConnectionStatus)Enum.Parse(typeof(DeviceConnectionStatus), deviceConnectionStatus, true);
                else
                {//leave as unknown
                }
    
                return status;
            }
            private static SubscriptionStatus GetSubscriptionStatus(string subscriptionStatus)
            {
                SubscriptionStatus status = SubscriptionStatus.Unknown;
    
                if (subscriptionStatus.ToUpper() == "N/A")
                    status = SubscriptionStatus.None;
                else if (Enum.IsDefined(typeof(SubscriptionStatus), subscriptionStatus))
                    status = (SubscriptionStatus)Enum.Parse(typeof(SubscriptionStatus), subscriptionStatus, true);
                else
                {//leave as unknown
                }
    
                return status;
            }       
    
        }
    }

    So now for the disclaimer – Main thing is – it works (apart from remote tile notifications – currently an issue with the CTP as far as I can tell).  This version of the code was created against the requirements of the April CTP so I expect the message format to change although if you put it into your project resource file as the //comments above dictate you should be able to change this as the developer toolkit evolves.

    I will to keep this blog up to date with fixes for any changes as future CTPs are released or bugs I find as I dig deeper so make sure you subscribe to my RSS feed.

    Enjoy the code and the nights you will save not having to write it :)

    Nick

    How to Pin your application in Windows Phone 7 emulator April CTP refresh

    The Windows Phone 7 emulator provides Pin capability within the April CTP refresh. To pin your application perform the following:

    1. Right click on you WP7 app project and select properties.
    2. Set the Title under deployment options to your title name “PinMyApp”
    3. Set the Title under Tile options to “Pin My App” – this is the actual text shown over the tile
    4. Set the background image on the Tile using the dropdown.
    5. Deploy your application
    6. When on the Start screen Press to view your applications
    7. Hold down on your application “PinMyApp” until a context menu appears then select “pin to start”
    8.  

    9. Observe your application is now pinned

    Its important to note that you can use Push notifications to change the text, count and image on your applications tile. This can be achieved by setting up a notification channel using HttpNotificationChannel and binding to the shell entry point BindToShellEntryPoint(); Once you have registered a uri will be returned and you can then send tile notifications using a WebRequest. I am currently working on a blog post for this one, so stay tuned

    Nick

    Upgrading your Windows Phone projects for Windows Phone 7 Developer Tools CTP April refresh

    Upgrading your Windows Phone projects for Windows Phone 7 Developer Tools CTP April refresh 

    Here are a bunch of breaking issues I encountered on installing Upgrading your Windows Phone projects for Windows Phone 7 Developer Tools CTP April refresh 

      For each silverlight for mobile project in your solution you get the following warning (Note: XNA framework apps will not provide a warning but will still require the changes)

    • Issue: WarningYou are using a project created by previous version of Windows Phone Developer Tools CTP. Your application may not run properly. Please edit the WMAppManifest.xml file under Properties node and insert the following <Capability> elements between
      <Capabilities></Capabilities> element as shown below. <Capabilities>
      <Capability Name="ID_CAP_NETWORKING" />
      <Capability Name="ID_CAP_LOCATION" />
      <Capability Name="ID_CAP_SENSORS" />
      <Capability Name="ID_CAP_MICROPHONE" />
      <Capability Name="ID_CAP_MEDIALIB" />
      <Capability Name="ID_CAP_GAMERSERVICES" />
      <Capability Name="ID_CAP_PHONEDIALER" />
      <Capability Name="ID_CAP_PUSH_NOTIFICATION" />
      <Capability Name="ID_CAP_WEBBROWSERCOMPONENT" />
      </Capabilities> 
    • Solution: You can find WMAppManifest.xml in the Properties folderof your project once found add the sections listed above
    • Issue: Push Notifications now require the publisher to be defined
    • Solution: This can be done within the WMAppManifest.xml in the Properties folder.  Update the Publisher on <App> E.g 
    <App xmlns="" ProductID="{1ac9139d-aa7e-6c70-acf9-c6ceb69632a1}" Title="PinMyApp"
    RuntimeType="SilverLight" Version="1.0.0.0" Genre="NormalApp"
    Author="Nick.Harris" Description="Demo"
    Publisher="www.NickHarris.net">
    • Issue: Push Notification payload has been updated
    • Solution: Update notifications as per the specification here  
    • Issue: The property ‘Visible’ does not exist on the type ‘ApplicationBar’ in the XML namespace ‘clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone.Shell’
    • Solution: this has bee renamed to IsVisible
    • Issue: ‘System.Windows.Navigation.NavigationService’ does not contain a definition for ‘TopLevelNavigationService’
    • Solution: change NavigationService.TopLevelNavigationService.Navigate(…) to NavigationService.Navigate(…)  Note: did not find this one in the breaking changes….

    Release notes for other  breaking changes are here

    New Windows Phone 7 Developer Tools CTP April refresh 2010

    Download and install Windows Phone 7 Developer Tools April 2010 Refresh.

    Note as part of this install I had to remove the following components in order:

    • Microsoft Visual Studio 2010  RC       
    • Microsoft Windows Phone Developer Resources         
    • Microsoft Windows Phone Developer Tools
    • Microsoft Silverlight 4.0 SDK
    • Microsoft Visual Studio 2010 Express Prerequisites x64.
    • NET Framework 4 Multi-Targeting Pack
    • Microsoft .NET Framework 4 Extended
    • Microsoft .NET Framework 4 Client Profile
    • VC 10.0 Runtime
    • Microsoft Windows Phone Emulator x64
    • Windows Phone 7 Add-in for Visual Studio 2010 – ENU
    • Microsoft XNA Game Studio 4.0

    Ever had one of those days when your mouse batteries go flat in the middle of a blog post.  Then you swap out one of the batteries from the mouse and switch it with the keyboard to suck the last remaining juice from it.  Ten minutes later both are flat and you got no spares.  Lets just say its one of those days :)

    Anyhow the refresh has new features (-take note of the additions to the emulator ) and breaking changes(download release notes at this link) - take note of the new publisher setting and notification templates.

    Implementing MVVM for the first time on Windows Phone 7 using Silverlight for Mobile

    This post is my first attempt at implementing the MVVM pattern on Windows Phone 7 using Silverlight for Mobile.
    Prior to reading this post you should read Silverlight for Mobile on Windows Phone 7 InkPresenter Fun as a reference point for context and contrast.

    1. The MainPageViewModel is added for MainPage.   Key points to note are:
      • MainPageViewModel inherits from DependencyObject
      • Strokes is a DependencyProperty
      • Functionality from event handlers of MainPage moved into MainPageViewModel
      • No current use of Dispatcher as currently no separate thread attempting to update UI thread.
       public class MainPageViewModel : DependencyObject
          {
              private StrokeCollection _strokes;
              private Stack<Stroke> _removedStrokes = new Stack<Stroke>();
              private Stroke _currentStroke;
               Â
              public MainPageViewModel()
              {
                  Strokes = new StrokeCollection();
              }
           Â
              public StrokeCollection Strokes
              {
                  get { return (StrokeCollection)GetValue(StrokesProperty); }
                  set { SetValue(StrokesProperty, value); }
              }
      
              // Using a DependencyProperty as the backing store for Strokes.  This enables animation, styling, binding, etc...
              public static readonly DependencyProperty StrokesProperty =
                  DependencyProperty.Register("Strokes", typeof(StrokeCollection), typeof(MainPageViewModel), new PropertyMetadata(null));
      
              public void BeginCapture(Point point)
              {
                Â
                  _currentStroke = new Stroke();
                  _currentStroke.StylusPoints.Add(GetStylusPoint(point));
                  _currentStroke.DrawingAttributes.Color = Colors.Blue;
                  this.Dispatcher.BeginInvoke(
                  Strokes.Add(_currentStroke);          Â
              }
      
              public void CaptureStrokePoint(Point point)
              {          Â
                  if (_currentStroke != null)
                      _currentStroke.StylusPoints.Add(GetStylusPoint(point));
              }
      
              public void EndCapture()
              {
                  _currentStroke = null;
              }
      
              private StylusPoint GetStylusPoint(Point position)
              {
                  return new StylusPoint(position.X, position.Y);
              }
      
              public void Undo()
              {
                  if (Strokes != null && Strokes.Count > 0)
                  {
                      _removedStrokes.Push(Strokes.Last());
                      Strokes.RemoveAt(Strokes.Count - 1);
                  }
              }
      
              public void Redo()
              {
                  if (_removedStrokes != null && _removedStrokes.Count > 0)
                  {
                      Strokes.Add(_removedStrokes.Pop());              Â
                  }
              }
          }
      
    2. The MainPage code behind now becomes as follows.  Important points to note are:
      • The Datacontext is now set to an instance of MainPageViewModel i.e _vm; 
      • The _vm is called within each event handler to manipulate the view.
      public partial class MainPage : PhoneApplicationPage
          {
              private MainPageViewModel _vm;
      
              public MainPage()
              {          Â
                  InitializeComponent();
      
                  SupportedOrientations = SupportedPageOrientation.Portrait | SupportedPageOrientation.Landscape;
                Â
                  _vm = new MainPageViewModel();
                  this.DataContext = _vm;
               Â
                  inkTest.MouseMove += new MouseEventHandler(inkTest_MouseMove);
                  inkTest.MouseLeftButtonDown += new MouseButtonEventHandler(inkTest_MouseLeftButtonDown);
                  inkTest.MouseLeftButtonUp += new MouseButtonEventHandler(inkTest_MouseLeftButtonUp);
              }
      
              private void inkTest_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
              {
                  _vm.EndCapture();
                  inkTest.ReleaseMouseCapture();
              }
      
              private void inkTest_MouseMove(object sender, MouseEventArgs e)
              {
                  _vm.CaptureStrokePoint(e.GetPosition(inkTest));
              }
      
              private void inkTest_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
              {
                  _vm.BeginCapture(e.GetPosition(inkTest));
              }
      
              private void btnUndo_Click(object sender, EventArgs e)
              {
                  _vm.Undo();
              }
      
              private void btnRedo_Click(object sender, EventArgs e)
              {
                  _vm.Redo();
              }  Â
          }
      
    3. The MainPage XAML now becomes as follows: Its important to note that:
      • InkPresenter Now binds Strokes
               <Grid x:Name="ContentGrid" Grid.Row="1">
                  <InkPresenter Name="inkTest" Strokes="{Binding Strokes}" Background="White" Height="652" VerticalAlignment="Top" />
              </Grid>
      
          <phoneNavigation:PhoneApplicationPage.ApplicationBar>
              <shell:ApplicationBar Visible="True" IsMenuEnabled="True">
                  <shell:ApplicationBar.Buttons>
                      <shell:ApplicationBarIconButton x:Name="btnUndo" IconUri="/Images/dark/appbar.minus.rest.png" Click="btnUndo_Click"></shell:ApplicationBarIconButton>
                      <shell:ApplicationBarIconButton x:Name="btnRedo" IconUri="/Images/dark/appbar.add.rest.png" Click="btnRedo_Click"></shell:ApplicationBarIconButton>
                  </shell:ApplicationBar.Buttons>
              </shell:ApplicationBar>      Â
          </phoneNavigation:PhoneApplicationPage.ApplicationBar>  Â
      

    This implementation is now easier to write unit tests against then its predecessor.  One thing I am not happy with is the lack of use of Command and ICommand to route all commands to the MainPageViewModel using bindings.  I noticed that although ICommand exists in silverlight for mobile the Button, ApplicationBarIconButton and InkPresenter dont support the command property.  Initial thoughts would be to create a derived class e.g for ApplicationBarIconButton to provide a Command property but it seems like it is a lot of effort for little gain.  Anyone out there know if the Command prop and bindings will be supported on the user controls in Silverlight for Mobile?

    Windows Phone 7 NotificationChannelOpenException with MS Push Notification HttpNotificationChannel.Open

    Issue: Had a NotificationChannelOpenException today when testing out MS Push Notifications  for Windows Phone 7 using code as follows.

                HttpNotificationChannel _channel = new HttpNotificationChannel("NickTest");      �
    ...
                try
                {             �
                    _channel.ChannelUriUpdated += new EventHandler&lt;NotificationChannelUriEventArgs&gt;(channel_ChannelUriUpdated);
                    _channel.HttpNotificationReceived += new EventHandler&lt;HttpNotificationEventArgs&gt;(channel_HttpNotificationReceived);
                    _channel.ShellEntryPointNotificationReceived += new EventHandler&lt;NotificationEventArgs&gt;(channel_ShellEntryPointNotificationReceived);
                    _channel.ShellNotificationReceived += new EventHandler&lt;NotificationEventArgs&gt;(channel_ShellNotificationReceived);
                    _channel.ExceptionOccurred += new EventHandler&lt;NotificationChannelExceptionEventArgs&gt;(channel_ExceptionOccurred);
    
                    _channel.Open(); //Error occurs here
                    //_channel.BindToShellEntryPoint(); // tile�
                    _channel.BindToShellNotification(); // - toast
                }
                catch (NotificationChannelExistsException)
                {
                    _channel = HttpNotificationChannel.Find(_channelName);
                }

    Exception stack dump was as follows when calling Open on the _channel:

    Microsoft.Phone.Notification.NotificationChannelOpenException was unhandled
      Message=NotificationChannelOpenException
      StackTrace:
           at Microsoft.Phone.Notification.SafeNativeMethods.ThrowExceptionFromHResult(Int32 hr, Exception defaultException)
           at Microsoft.Phone.Notification.HttpNotificationChannel.Open()
           at MyStrokes.Provider.NotificationProvider.Subscribe()
           at MyStrokes.App.Application_Startup(Object sender, StartupEventArgs e)
           at System.Windows.CoreInvokeHandler.InvokeEventHandler(Int32 typeIndex, Delegate handlerDelegate, Object sender, Object args)
           at MS.Internal.JoltHelper.FireEvent(IntPtr unmanagedObj, IntPtr unmanagedObjArgs, Int32 argsTypeIndex, String eventName)

    Solution:  If you try to Open a channel almost immediately after you hit Debug when emulator fires up this issue will occur.  The solution is simple – Give the emulator two minutes before making the call. 

    It appears this is a documented issue in the Windows Phone 7 Developer Tools CTP Release Notes:

  • The push client debugging has to wait for two minutes after boot of the emulator (or device) before using the APIs (i.e. Start screen show up).
  • For push notifications, if the emulator host computer is behind a proxy, SOCKS proxy has to be configured on the host computer.You can go to Control Panel > Network and Internet > Internet Options > Connections tab, and then choose the Setting option to set this configuration. //Also thought this was useful
  •  

    Adding a Windows Phone 7 WCF service reference in VS2010 RC

    Issue: You want to add a WCF service reference to a Windows Phone 7 project in Visual Studio 2010 RC Ultimate.  You right click the project to find “Add Service Reference…” option is not available.

    Solution: Assume this will be fixed in the RTM. Until then open up your Windows Phone 7 project in the Visual Studio 2010 Express edition that was installed with the Windows Phone Developer Tools.  The express allows you to “Add Service Reference…” to the WP7 project without issue.  Once done, reload your project in VS 2010 RC Ulitimate.

    Silverlight for Mobile on Windows Phone 7 InkPresenter fun

    After installing the Windows Phone Developer Tools this is a simple test for a bit of fun using Silverlight for Mobile for the first time to capturing user strokes using the InkPresenter.

    1. In Visual Studio 2010 Press File –> New Project –> Silverlight for Windows Phone –> Windows Phone Application
    2. Creating a Silverlight for Mobile Application

      Creating a Silverlight for Mobile Application

    3. Add an InkPresenter and two buttons Undo and Redo to the to the content Grid
    4.  

            <!--ContentGrid is empty. Place new content here-->
              <Grid x:Name="ContentGrid" Grid.Row="1">
                  <InkPresenter  Name="inkTest" Background="White" Margin="0,0,0,62" />
                  <Button Name="btnUndo" Content="Undo" Grid.Row="1" Height="72" HorizontalAlignment="Left" Margin="44,584,0,0" VerticalAlignment="Top" Width="160" Click="btnUndo_Click" Background="#FF933A3A" />
                  <Button Name="btnRedo" Content="Redo" Height="72" HorizontalAlignment="Left" Margin="272,584,0,0" VerticalAlignment="Top" Width="160" Grid.Row="1" Click="btnRedo_Click" Background="#FF933A3A" />
              </Grid>
    5. On the InkPresenter, named inkTest in this example, Add Event handlers for MouseMove, MouseLeftButtonDown, MouseLeftButtonUp to capture the movement from the user
    6.             inkTest.MouseMove += new MouseEventHandler(inkTest_MouseMove);
                  inkTest.MouseLeftButtonDown += new MouseButtonEventHandler(inkTest_MouseLeftButtonDown);
                  inkTest.MouseLeftButtonUp += new MouseButtonEventHandler(inkTest_MouseLeftButtonUp);
    7. To capture the mouse movements and turn them into Strokes on the InkPresenter the corresponding EventHandlers and member variables are as follows
    8. private Stroke _currentStroke;
      
      private void inkTest_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
      {
          _currentStroke = null;
      }
      
      private void inkTest_MouseMove(object sender, MouseEventArgs e)
      {
          if (_currentStroke != null)
              _currentStroke.StylusPoints.Add(GetStylusPoint(e.GetPosition(inkTest)));
      }
      
      private void inkTest_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
      {
          inkTest.CaptureMouse();
          _currentStroke = new Stroke();
          _currentStroke.StylusPoints.Add(GetStylusPoint(e.GetPosition(inkTest)));
          _currentStroke.DrawingAttributes.Color = Colors.Blue;
          inkTest.Strokes.Add(_currentStroke);
      }
      
      private StylusPoint GetStylusPoint(Point position)
      {
          return new StylusPoint(position.X, position.Y);
      }
    9. And since its difficult to draw with a mouse I want to be able to undo and redo some of my Strokes I use a simple Stack so implement the following EventHandlers for the Undo and Redo buttons
    10.         private Stack _removedStrokes = new Stack();
      
              private void btnUndo_Click(object sender, RoutedEventArgs e)
              {
                  if (inkTest.Strokes != null && inkTest.Strokes.Count > 0)
                  {
                      _removedStrokes.Push(inkTest.Strokes.Last());
                      inkTest.Strokes.RemoveAt(inkTest.Strokes.Count - 1);
                  }
              }
      
              private void btnRedo_Click(object sender, RoutedEventArgs e)
              {
                  if (_removedStrokes != null && _removedStrokes.Count > 0)
                  {
                      inkTest.Strokes.Add(_removedStrokes.Pop());
                  }
              }
    11. And the final result is :)
    12. InkPresenter on Windows Phone 7

      InkPresenter on Windows Phone 7

    This demonstrated a simple application that was faster to code then to blog about and that even with an undo button I am still hopeless at drawing :) . Try implementing the same functionality in the .NET Compact Framework :)

    Next posts will look at

    • Reworking this application to use MVVM
    • Using the Microsoft Notification Service

    What a day – dev therapy with tonights downloads + installs

    When you have a bad day there is nothing better then some dev therapy = tonights downloads + installs;

    1. .NET Framework 4 full RC
    2. Visual Studio 2010 Ultimate RC
    3. Visual Studio 2010 remote debugger RC
    4. Windows Phone Developer Tools CTP includes
      • Windows Phone Emulator CTP
      • Silverlight for Windows Phone CTP
      • XNA 4.0 Game Studio CTP
    5. Microsoft Expression Blend 4 Beta
    6. Visual Studio 2010 and .NET Framework 4 Training Kit