App Part, public partial class MainPage : PhoneApplicationPage { private Guid _deviceId; private HttpNotificationChannel _channel; private const string ChannelName = "Notifications.Phone.NotificationChannel"; // Constructor public MainPage() { InitializeComponent(); if (DesignerProperties.IsInDesignTool) return; // Initialize the DeviceID if (IsolatedStorageSettings.ApplicationSettings.Contains("DeviceId")) _deviceId = (Guid)IsolatedStorageSettings.ApplicationSettings["DeviceId"]; else { _deviceId = Guid.NewGuid(); IsolatedStorageSettings.ApplicationSettings["DeviceId"] = _deviceId; } // Set up Channle SetupNotificationChannel(); } private void SetupNotificationChannel() { _channel = HttpNotificationChannel.Find(ChannelName); if (_channel == null) { _channel = new HttpNotificationChannel(ChannelName); // This event will be fired when the channel is openned. // Maybe will be fired in other cases NEED TO Investigate. _channel.ChannelUriUpdated += (s, e) => { _channel = HttpNotificationChannel.Find(ChannelName); // tell the phone what to do when the app is not running and Tile Notification arrives if (!_channel.IsShellTileBound) { // you can register the phone application to recieve tile images from remote servers [this is optional] //var uris = new Collection<Uri> { new Uri("http://www.thisisfanzoo.com") }; _channel.BindToShellTile(); } // tell the phone what to do when the app is not running and Toast Notification arrives if (!_channel.IsShellToastBound) _channel.BindToShellToast(); RegisterForNotifications(); }; _channel.ErrorOccurred += (s, e) => Deployment.Current.Dispatcher.BeginInvoke(() => ErrorOccurred(e)); _channel.Open(); } else { RegisterForNotifications(); } } private void RegisterForNotifications() { RegisterWithNotificationService(); _channel.ShellToastNotificationReceived += (s, e) => Deployment.Current.Dispatcher.BeginInvoke(() => ToastReceived(e)); _channel.HttpNotificationReceived += (s, e) => Deployment.Current.Dispatcher.BeginInvoke(() => HttpNotificationReceived(e)); _channel.ErrorOccurred += (s, e) => Deployment.Current.Dispatcher.BeginInvoke(() => ErrorOccurred(e)); } private void RegisterWithNotificationService() { var svc = new MyWPNService.WPNServiceClient(); svc.SubscribeCompleted += (s, e) => { if (e.Error != null) { //Debug.WriteLine("Error registering with notification service"); } }; svc.SubscribeAsync(_deviceId, _channel.ChannelUri.ToString()); } private void HttpNotificationReceived(HttpNotificationEventArgs e) { var reader = new StreamReader(e.Notification.Body); var message = reader.ReadToEnd(); //Debug.WriteLine(string.Format("Raw notification received: {0}", message)); lblMessage.Text = "Raw Message Received"; txtMessage.Text = message; reader.Close(); } private void ToastReceived(NotificationEventArgs e) { lblMessage.Text = "Toast Message Received"; txtMessage.Text = string.Format("Title:{0}/nMessage:{1}", e.Collection["wp:Text1"], e.Collection["wp:Text2"]); //Debug.WriteLine("Toast Recevied:" + e.Collection["wp:Text1"] + ", " + e.Collection["wp:Text2"]); } private void ErrorOccurred(NotificationChannelErrorEventArgs e) { lblMessage.Text = "Error Received"; txtMessage.Text = e.Message; //Debug.WriteLine("ERROR:" + e.Message); } } Service part, public enum NotificationType { Tile = 1, Toast = 2, Raw = 3 } public enum BatchingInterval { TileImmediately = 1, ToastImmediately = 2, RawImmediately = 3, TileWait450 = 11, ToastWait450 = 12, RawWait450 = 13, TileWait900 = 21, ToastWait900 = 22, RawWait900 = 23 } public class WPNService : IWPNService { private static Dictionary<Guid, Uri> _clientUris = new Dictionary<Guid, Uri>(); #region IWPNService Members public void Subscribe(Guid clientID, string uri) { if (_clientUris.ContainsKey(clientID)) _clientUris[clientID] = new Uri(uri); else _clientUris.Add(clientID, new Uri(uri)); } public void SendToast(string title, string message) { var toastMessage = "<?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>"; toastMessage = string.Format(toastMessage, title, message); var messageBytes = System.Text.Encoding.UTF8.GetBytes(toastMessage); foreach (var uri in _clientUris.Values) { SendMessage(uri, messageBytes, NotificationType.Toast); } } public void SendTileUpdate(string title, int count, string imageUrl) { var tileMessage = "<?xml version=/"1.0/" encoding=/"utf-8/"?>" + "<wp:Notification xmlns:wp=/"WPNotification/">" + "<wp:Tile>" + "<wp:BackgroundImage>{0}</wp:BackgroundImage>" + "<wp:Count>{1}</wp:Count>" + "<wp:Title>{2}</wp:Title>" + "</wp:Tile> " + "</wp:Notification>"; tileMessage = string.Format(tileMessage, imageUrl, count, title); var messageBytes = System.Text.Encoding.UTF8.GetBytes(tileMessage); foreach (var uri in _clientUris.Values) { SendMessage(uri, messageBytes, NotificationType.Tile); } } public void SendRawNotification(string message) { var messageBytes = Encoding.UTF8.GetBytes(message); foreach (var uri in _clientUris.Values) { SendMessage(uri, messageBytes, NotificationType.Raw); } } private static void SendMessage(Uri uri, byte[] message, NotificationType notificationType) { var request = (HttpWebRequest)WebRequest.Create(uri); request.Method = WebRequestMethods.Http.Post; request.ContentType = "text/xml"; request.ContentLength = message.Length; request.Headers.Add("X-MessageID", Guid.NewGuid().ToString()); switch (notificationType) { case NotificationType.Toast: request.Headers["X-WindowsPhone-Target"] = "toast"; request.Headers.Add("X-NotificationClass", ((int)BatchingInterval.ToastImmediately).ToString()); break; case NotificationType.Tile: request.Headers["X-WindowsPhone-Target"] = "token"; request.Headers.Add("X-NotificationClass", ((int)BatchingInterval.TileImmediately).ToString()); break; default: request.Headers.Add("X-NotificationClass", ((int)BatchingInterval.RawImmediately).ToString()); break; } using (var requestStream = request.GetRequestStream()) { requestStream.Write(message, 0, message.Length); } try { var response = (HttpWebResponse)request.GetResponse(); var notificationStatus = response.Headers["X-NotificationStatus"]; var subscriptionStatus = response.Headers["X-SubscriptionStatus"]; var deviceConnectionStatus = response.Headers["X-DeviceConnectionStatus"]; Debug.WriteLine(string.Format("Device Connection Status: {0}", deviceConnectionStatus)); Debug.WriteLine(string.Format("Notification Status: {0}", notificationStatus)); Debug.WriteLine(string.Format("Subscription Status: {0}", subscriptionStatus)); } catch (WebException ex) { Debug.WriteLine(string.Format("ERROR: {0}", ex.Message)); } } #endregion }