Windows Push Notification Server Side Helper Library

Windows Push Notification Server Side Helper Library

  • Comments 14
  • Likes

This post is a preview of the Recipe for the Push Notification Server Side Helper Library. The library provides an easy way for sending all three kinds of push notification messages currently supported by Microsoft Push Notification Services (MPNS): Tile, Toast, and Raw. Our main goal here is to extract any complexity for sending push notification (PN) messages from your website (or web service) to a Windows Phone. This library helps developers to send push messages using only a few lines of code.

We are not going to cover what push notifications are, or how they work. If you are not familiar with push notifications please be sure to read the previous posts: Understanding Microsoft Push Notifications for Windows Phones part 1 and part 2, as well as Using Push Notification from Your Windows Phone Application, or refer to the Push Notifications documentation on MSDN.

In a push notification scenario, the server side piece is as important as the Windows Phone client application. For a complete end-to-end push-enabled scenario to work, you need your server side to be able to receive incoming phone messages, as well as send push requests to Microsoft Push Notification Services as illustrated in the following diagram

image

As we said before, the Push Notification Server Side Helper Library helps you send push notification requests from your cloud application (web service) to MPNS, and manage (understand) the return values received from MPNS in response.

This post provides some background and an example of what you will find in greater detail in the Recipe. To start with, the recipe includes four projects, from which the library is the WindowsPhone.Recipes.Push.Messages assembly. The projects are:

  • WindowsPhone.Recipes.Push.Messages – The Push Notification Server Side Helper Library
  • WindowsPhone.Recipes.Push.Client – A Windows Phone client application the helps illustrate the push scenarios
  • WindowsPhone.Recipes.Push.Server – A WPF application that acts as a local server side application mimicking your real web service (we use a local WCF client as a local web service to simplify the deployment and testing of the helper library; however rest assured that the entire scenario works end-to-end)
  • Libraries –A few supporting libraries we are using in the Recipe

Since we are using WCF service to open a channel for incoming communications, you need to run the entire Visual Studio solution in “Admin mode” or else you will hit an exception when you try to run the WPF “server” application. But before we jump ahead, let’s understand how to use the helper library

PushNotificationMessage Base Class and Sub-Classes

In order to send a PN message to your Windows Phone application, you need to post that message to MPNS. Therefore, it makes sense to abstract the sending functionality and create a PushNotificationMessage base class. This base class handles the majority of the logic and heavy lifting for sending the message to MPNS.

The main public functions that the PushNotificationMessage base class exposes are two send methods:

  • Send, for sending the PN message synchronously – blocking the current thread
  • SendAsync, for sending the PN message asynchronously using the .NET thread pool.

Both methods have a callback for returning the MPNS response codes, and can throw an exception if something goes wrong. A separate sub-class represents each of the different PN message types, as illustrated in the following class diagram.

image

The three supported PN message sub-classes are:

  • RawPushNotificationMessage – Represents sending raw bytes to the Windows Phone application while it is running
  • TilePushNotificationMessage –Represents sending tile updates to the Windows Phone when your application tile is pinned to the phone’s Start screen
  • ToastPushNotificationMessage –Represents sending toast “alert” messages to the Windows Phone

The difference between the three types of messages is the way each one encapsulates the push message format and exposes it with regular .NET properties. Using any of these classes to send a message is relatively easy as shown in the following code samples".

var tile = new TilePushNotificationMessage
{
   BackgroundImageUri = tileImageUri, // Remote or phone-local tile image uri.
   Count = tileCount, // Counter between 1 to 99 should be displayed on the tile.
   Title = “Tile Title” // Title to be displayed on the tile.
};
// Send the message synchronously.
Var sendResult = tile.Send(phoneChannelUri);
 
// Send the message asynchronously.
tile.SendAsync(
phoneChannelUri,
   result => {/* Check the send result */},
   exception => {/* Log the error */});

When sending asynchronously, you need to provide delegates as callback handlers for the return values from MPNS and to log any exceptions.

Similarly, you can send toast and raw notifications, by simply instantiating new instances of ToastPushNotificationMessage and RawPushNotificationMessage, respectively.

Push Notification Server-Side Common Patterns

To illustrate the use of the Push Notification Server Side Helper Library, we’ve create a WPF application that acts like a web service, mimicking a third-party server. To enable this, the WPF application has a WCF service that lets the Windows Phone application register and communicate with MPNS. The WPF has tabs, each of which represents a specific Push Pattern that we wish to illustrate.

Push Patterns are a generalization of a common use of PN in an end-to-end solution that includes specific Windows Phone and server-side logic. The current application has five patterns:

  • One-time Push – Simple one-time send of any or all three push notification message types
  • Push Counter Resets upon Logon – Each time you send a push message, a counter value increments and displays on the tile (assuming the application’s tile is pinned to the Start screen), resetting the next time the user runs the application
  • Ask to Pin Application Tile –The phone application “asks” the user to pin the application’s tile to the phone Start screen up on sending request from the WPF application
  • Create Custom Server-side Image – Tile notification can update the application’s tile on the Start screen, and this scenario illustrate that you can create a complete new tile as image
  • Scheduled Tile Updates –Schedule tile updates (note this requires a testing period of 60 min)

Please note: The server-side patterns are provided as a samples and only to demonstrate the specific pattern usage; they are NOT best practices for server-side or web programming. The goal is to explain the patterns and server-side requirements. To keep the examples simple, we DO NOT use server-side authentication, a database, or any complex setups that would be included in actual scenarios.

As an example, let’s examine the Ask to Pin Application Tile scenario as it explained in the Recipe.

Ask To Pin Application

If a given application sends a tile PN message and that application’s tile is not pinned to the phone Start screen, the PN message will not be delivered to the phone, and the third-party server side will be notified that the application tile is not pinned. Since in Windows Phone, only end users can pin an application’s tile to the phone Start Screen, applications need a way to “ask” the user to pin the application’s tile. This pattern illustrates how an application can do that by sending a specific message to the phone. The pattern implementation includes both server-side and Windows Phone client-side code.

Implementation

  1. The server side maintains a list of the last tile message data sent per registered user.
  2. Upon client registration the server side application knows that the Windows Phone client application is running.
  3. The server side sends a tile message with the most updated tile data.
  4. Based on the response to this message from MPNS, the application knows if the Windows Phone application’s tile is pinned to the Start screen or not:
  1. If the device is connected, the subscription is active, and the notification is received, we know that the application’s tile is pinned to the Start screen.
  2. If not, the server side sends a custom raw PN message to the Windows Phone client application asking it to display the “Ask to Pin” message to the user.
  • Log message-send error or message-send success

Demonstration

  1. Run only the WindowsPhone.Recipes.Push.Server project and make sure that the “Ask to Pin” tab is selected.
  2. Run the WindowsPhone.Recipes.Push.Client (Windows Phone application), and make sure that the application’s tile is not pinned to the Start Menu.
  3. Accept existing push messages and log on with any user name.
  4. A message box should pop up asking to pin the application. Click OK.
  5. On the server UI, click Send to update the tile.
  6. A message box should pop up asking to pin the application. Click OK.
  7. image image
  8. Close the application, pin it to the Start Page, and run the application again. The previous ”Ask to Pin” message should be gone.
  9. On the server UI, click Send to update the tile. The previous ”Ask to Pin” message should be gone and the tile number should be updated.

Note –This pattern can be adjusted to make the Windows Phone client application display the “Ask to Pin” message upon logon.

Code [Implemented as part of the AskToPinPushPatternViewModel.cs file in the WPF application]

The pattern starts when a client first registers to the server. In order to check if the application is pinned or not, the OnSubscribed method below sends a tile notification message to the relevant subscriber (based on the Windows Phone client application URI and username). The data used with the message is new for first time subscriptions or from previously stored data for re-subscriptions. Using stored data prevents updating the tile for no reason.

protected override void OnSubscribed(SubscriptionEventArgs args)
{
    // Asynchronously try to send Tile message to the relevant subscriber
    // with data already sent before so the tile won't change.
    var tileMsg = GetOrCreateMessage(args.Subscription.UserName, false);
 
    tileMsg.SendAsync(
        args.Subscription.ChannelUri,
        result =>
        {
            Log(result);
            OnMessageSent(args.Subscription.UserName, result);
        },
        Log);
}

The PN message is sent asynchronously, and the OnMessageSent callback is called when the tile PN message is sent. At that point, the server side can check if the application is pinned to the Start screen by checking the response returned by MPNS. If the tile is pinned, do nothing. However, if the application’s tile is not pinned, the Windows Phone client application will “ask” the user to pin the application’s tile by sending a raw message with custom data, in our case the “Ask to Pin” message. This raw message is received by the phone client and displays a message to the user.

/// <summary>
/// Once tile update sent, check if handled by the phone.
/// In case that the application is not pinned, ask to pin.
/// </summary>
private void OnMessageSent(string userName, MessageSendResult result)
{
    if (!CheckIfPinned(result))
    {
        AskUserToPin(result.ChannelUri);
    }
}

The same logic repeats in cases where the server wants to send a tile update to one or more clients. This time the message is newly created.

/// <summary>
/// Send a tile notification to all relevant subscribers.
/// </summary>
protected override void OnSend()
{            
    // Asynchronously try to send this message to all relevant subscribers.
    foreach (var subscriber in PushService.Subscribers)
    {
        // Create a tile message to send an update.
        var tileMsg = GetOrCreateMessage(subscriber.UserName);
 
        tileMsg.SendAsync(
            subscriber.ChannelUri,
            result =>
            {
                Log(result);
                OnMessageSent(subscriber.UserName, result);
            },
            Log);
    }
}

The CheckIfPinned method below checks if the application is pinned to the Start screen by observing the three previously described flags.

private bool CheckIfPinned(MessageSendResult result)
{
    // We known if the application is pinned by checking the following send result flags:
    return result.DeviceConnectionStatus == DeviceConnectionStatus.Connected &&
           result.SubscriptionStatus == SubscriptionStatus.Active &&
           result.NotificationStatus == NotificationStatus.Received;
}

The AskUserToPin method below sends a raw message with the custom “Ask to Pin” data, which is intercepted by the phone.

/// <summary>
/// Just in case that the application is running, send a raw message, asking
/// the user to pin the application. This raw message has to be handled in client side.
/// </summary>
private void AskUserToPin(Uri uri)
{
    new RawPushNotificationMessage
    {
        RawData = Encoding.ASCII.GetBytes(RawMessage)
 
    }.SendAsync(uri);
}

Conclusion

The Push Notification Server Side Helper Library is a simple library that lets you focus on your web service logic rather than on the technicality of sending push messages.

The actual Recipe contains detailed documentation and full code implementation. The above example is just one of 5 scenarios, each with full details.

Download the Recipe and its documentation

14 Comments
You must be logged in to comment. Sign in or Join Now
  • asWorks
    1 Posts

    Hello, should it be possible to run the pushserver on a different machine ( Internetserver) to make the pushserver available for the windows developer phone and not just for the emulator?

    I tried to copy the pushserver to another machine but wasn´t able to update the service reference of the client.

    I am not shure if this should be possible or if further changes in the code are needed. ( I just changed the ip adress in the clients service reference to match the server.

    Thanks for your efforts. Every help will be appreciated.

    asWorks

  • Help!

    I cant run The server project. I keep getting this for an error:

    Error 1 ClickOnce does not support the request execution level 'requireAdministrator'. WindowsPhone.Recipes.Push.Server

    I am running VS2010 Pro as Administrator. When I first opened the solution I was able to build everything successfully. What am I doing wrong? Here are the steps I took:

    1) Downloaded source, unblocked DLLs.

    2) Opened VS 2010 pro as Administrator and opened the solution.

    3) Build the whole solution (successfully)

    4) Right Clicked on WindowsPhone.Recipies.Push.Server and selected "publish"

    5) I tried both "file system" and also "local IIS"

    I got the aforemention error. Now I can't even rebuild the solution without getting the error

  • @Yochay thanks for this great recipe: it turned out to be very useful. Just wanted to let you know that there is a spelling error in the WindowsPhone.Recipes.Push.Messasges library (should probably be "Messages" instead)

    - Thanks again.

  • andycted
    43 Posts

    As mentioned in other forums related to push notifications, there is still a huge issue with 'TempDisconnected' state.

    There is nothing mentioned in other posts that really solves the situation and even programming exactly as documented reproduces the problem way too ofter to provide live tiles functionality to users.

    This at least with all the combinations I've tried with:

    3 different DSL networks

    3 different wifi routers/ACP

    2 different phone operators

    plugged/unplugged

    lockscreen on/off

    The only thing that works reliably is the emulator.

    I've tried following the directions mentioned here and in other posts, I've tried to build everything from scratch, I've tried many different implementations, all with the same result. NoDo was supposed to fix the issue (at least some support personnel suggested so), but changed anything.

  • Hi,

    I tried the application with given steps.

    But, it's not working on my PC.

    After running server application with "Ask to Pin" tab selected. when I run WP7 Emulator by enable Push Notification, when i clicked on login, it gives me Login screen and doesn't process.

    It is not giving me message box for ask to pin the application.

    please help.

    Thanks,

    Pariksheet

  • Great work - thanks for this. Fantastic to see such a complete example.

    I have one problem though - I get 'TempDisconnected' a lot (device connection status) when using it to send to a real phone (my phone is on and fully connected at the time). It works fine initially but later on that becomes the case. When that happens message delivery is very unreliable (mainly doesn't work at all). Have you any advice on that?

    Thanks!

    Ian

  • Mendoza
    2 Posts

    @Yochay

    Sorry, but link you provided doesn't work.

    The problem is that, our devices stops connecting to MS PNS. I have figure out that we need to reset device to factory settings. After unlocking device and deploying our application we can connect to MS PNS. PNS will be working until we restart device (turn off and turn on). After restart in magic way, application cannot connect to MS PNS again - event ChannelUriUpdate is never called.

    I was checking packets in Wireshark. When we reset device to factory settings, unlock it and deploy our application, then I see packets coming to push.live.net. Connection to MS PNS is working as excepted. However when I restart device then I cannot see any packets comming to push.live.net. It seems that device stops comunicating with MS PNS after restart.

    Some URLs received before this issue starts with http://notify.live-int.com/. However we cannot even ping this address now. It was previously working fine. Now we receive URLs only starting with http://db3.notify.live.net/.

    I have access to 4 different device models from different vendors. I can repeat this issue on every device. What can be the problem?

  • @CodingInsomnia You are right, it should be UTF8 and not ASCII as PN does support UTF8. Fixing as we speak, and thanks for the heads up.

  • @Mendoza - This comment is relevant to the other threads on the forums.create.msdn.com/442290.aspx.

    Basically, the Push Client is responsible for the communication between the phone and the PN servers. Sometime, depends on network coverage and some other factors - like battery life, the push client throttles down the rate of updates between the device and PN services. This can have a significant outcome on the communication between your device and PN, and can result in longer delays from when you open your push channel until you receive and answer. This can even be few minutes.

    When running on the emulator, you’ll see no problems, since your network is excellent and there are no battery issues. However on production phone and in different environment, things can change.

    We’ll soon post some update to the Push Recipes and to the Push Notification blogs to address these issues.

    Hope this help,

    Yochay

  • @dxrdxr Bascially you are correct, I guess we used this name since it is part of the Ask To Pin Pattern... With said, the current CheckIfPinned method checks if the phone is "online" and can receive the tile push notification....

  • Mendoza
    2 Posts

    Unfortunately project for WP7 doesn't work on my devices. HttpNotificationChannel.ChannelUriUpdated is never called. I found that other people have also this problem - forums.create.msdn.com/.../442290.aspx. Is any solution to this issue?

  • I just spiked a version of Entile that uses your helper library and it works really well.

    I did find one bug though. In the ToastPushNotificationMessage class, you use Encoding.ASCII.GetBytes instead of Encoding.UTF8.GetBytes. This means that you can't send toasts with any special characters (such as ÅÄÖ, åäö from the end of the Swedish alphabet). Since you actually say in the XML header that the content is UTF-8, that is what you should use anyway.

  • dxrdxr
    1 Posts

    Wouldn't it be better to have CheckIfPinned() check if NotificationStatus.Surpressed? The existing condition can fail for any number of reasons unrelated to pinning. But a properly setup notification that is just lacking being pinned will cause a surpressed response.

  • Hey, that's funny. I just released a preview of a library that also tries to leviate some of the difficulty in sending Toasts and Tiles. Since I've put much of the focus on the client and the actually registering the client with the server I think this may actually go very well together.

    coding-insomnia.com/.../introducing-entile-notification-framework