Push Notification Service In Windows Runtime Apps

In this article, we will learn how to send push notification to Windows apps (Windows and Windows Phone apps) from our own web application.

Here are the steps:

Step 1:

At first we have to reserve or register our app in Windows Store.

Go to https://dev.windows.com and login with your Microsoft account that is Developer account registered.

Go to Dashboard, and Create new app.

app
Step 2:

Reserve a name of an app. I used ‘PushNotificationService’ for this tutorial.

create

Step 3:

From the left side of the dashboard, Go to Services > Push Notifications section. We can see the Live Service Site link from where we get the Package-SID and Client Secret that is needed for in Web-Service.

Note down those Package-SID and Client Secret.

Push Notifications
Push Notifications
Step 4:

Create a Windows Project. Associate this app with the Windows Store. For that, Right click on Project, Store, Associate App with the Store.

Log in with your Microsoft developer account and associate your app.

store

Step 5:

Next, we will need Channel URI. In the MainPage.xaml, add a Button and a TextBox to get Channel URI of app.

Complete XAML Code:
  1. <Page  
  2.     x:Class="PushNotificationService.MainPage"  
  3.     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
  4.     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
  5.     xmlns:local="using:PushNotificationService"  
  6.     xmlns:d="http://schemas.microsoft.com/expression/blend/2008"  
  7.     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"  
  8.     mc:Ignorable="d">  
  9.   
  10.     <Grid Background="#FF425799">  
  11.         <Button x:Name="PushChannelBtn" Content="Get Channel Uri" FontSize="40" Click="PushChannelBtn_Click" Margin="243,164,0,482" Height="122" Width="429" />  
  12.         <TextBox x:Name="txtChannelURI" FontSize="22" Foreground="Black" TextWrapping="Wrap"   Margin="51,484,53,203" Background="White" />  
  13.     </Grid>  
  14. </Page>  
Step 6:

In the code behind of MainPage.xaml.cs, update your code with the following code snippet i.e. for the Button Click Event. When we run our app, we will get the Channel URI in the TextBox. Note down this Channel Uri, we will need this in Web Service part.
  1. private async void PushChannelBtn_Click(object sender, RoutedEventArgs e)  
  2. {  
  3.     var channel = await PushNotificationChannelManager.CreatePushNotificationChannelForApplicationAsync();  
  4.     txtChannelURI.Text = channel.Uri.ToString();  
  5. }  
Note: We have to enable Toast Capabilities in Package.appxmanifest.

package

Step 7: WEB-SERVICE Part

Now we need a Web Service (Web Application) to send push notification to our registered devices.

For that add a new project. File > Add > New Project > Visual C# > Web > ASP.NET Web Application. Click OK, On Template select Empty. After that Add a new Web Form in your Web Application. Name it SendToast.

project

empty

web form

name
Step 8:

In the SendToast.aspx.cs, we need to implement methods and functions to get the Access Token using Package SID, Client Secret and Channel URI.

Add your Package SID, Client Secret, and Channel URI in the respective places.

Complete code snippet for SendToast.aspx.cs:
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.IO;  
  4. using System.Linq;  
  5. using System.Net;  
  6. using System.Runtime.Serialization;  
  7. using System.Runtime.Serialization.Json;  
  8. using System.Text;  
  9. using System.Web;  
  10. using System.Web.UI;  
  11. using System.Web.UI.WebControls;  
  12.   
  13. namespace Webservice  
  14. {  
  15.     public partial class SendToast : System.Web.UI.Page  
  16.     {  
  17.         private string packageSID = "Your Package SID";  
  18.         private string clinetSecret = "Your Client Secret";  
  19.         private string channelUri = "Your Channel URI obtained from APP";  
  20.         private string accessToken = string.Empty;  
  21.   
  22.         [DataContract]  
  23.         public class OAuthToken  
  24.         {  
  25.             [DataMember(Name = "access_token")]  
  26.             public string AccessToken { getset; }  
  27.             [DataMember(Name = "token_type")]  
  28.             public string TokenType { getset; }  
  29.         }  
  30.   
  31.         OAuthToken GetOAuthTokenFromJson(string jsonString)  
  32.         {  
  33.             using (var ms = new MemoryStream(Encoding.Unicode.GetBytes(jsonString)))  
  34.             {  
  35.                 var ser = new DataContractJsonSerializer(typeof(OAuthToken));  
  36.                 var oAuthToken = (OAuthToken)ser.ReadObject(ms);  
  37.                 return oAuthToken;  
  38.             }  
  39.         }  
  40.         protected void Page_Load(object sender, EventArgs e)  
  41.         {  
  42.             if (Application["channelUri"] != null)  
  43.             {  
  44.                 Application["channelUri"] = channelUri;  
  45.             }  
  46.             else  
  47.             {  
  48.                 Application.Add("channelUri", channelUri);  
  49.             }  
  50.   
  51.             if (Application["channelUri"] != null)  
  52.             {  
  53.                 string aStrReq = Application["channelUri"as string;  
  54.                 string toast1 = "<?xml version=\"1.0\" encoding=\"utf-8\"?> ";  
  55.                 string toast2 = @"<toast>  
  56.                         <visual>  
  57.                             <binding template=""ToastText01"">  
  58.                                 <text id=""1"">Hello Push Notification Service!!</text>  
  59.                             </binding>  
  60.                         </visual>  
  61.                     </toast>";  
  62.                 string xml = toast1 + toast2;  
  63.   
  64.                 Response.Write("Result: " + PostToCloud(aStrReq, xml));  
  65.             }  
  66.             else  
  67.             {  
  68.                 Response.Write("Application 'channelUri=' has not been set yet");  
  69.             }  
  70.             Response.End();  
  71.         }  
  72.         protected string PostToCloud(string uri, string xml, string type = "wns/toast")  
  73.         {  
  74.             try  
  75.             {  
  76.                 if (accessToken == "")  
  77.                 {  
  78.                     GetAccessToken();  
  79.                 }  
  80.                 byte[] contentInBytes = Encoding.UTF8.GetBytes(xml);  
  81.   
  82.                 WebRequest webRequest = HttpWebRequest.Create(uri);  
  83.                 HttpWebRequest request = webRequest as HttpWebRequest;  
  84.                 webRequest.Method = "POST";  
  85.   
  86.                 webRequest.Headers.Add("X-WNS-Type", type);  
  87.                 webRequest.Headers.Add("Authorization", String.Format("Bearer {0}", accessToken));  
  88.   
  89.                 Stream requestStream = webRequest.GetRequestStream();  
  90.                 requestStream.Write(contentInBytes, 0, contentInBytes.Length);  
  91.                 requestStream.Close();  
  92.   
  93.                 HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse();  
  94.   
  95.                 return webResponse.StatusCode.ToString();  
  96.             }  
  97.             catch (WebException webException)  
  98.             {  
  99.                 string exceptionDetails = webException.Response.Headers["WWW-Authenticate"];  
  100.                 if ((exceptionDetails != null) && exceptionDetails.Contains("Token expired"))  
  101.                 {  
  102.                     GetAccessToken();  
  103.                     return PostToCloud(uri, xml, type);  
  104.                 }  
  105.                 else  
  106.                 {  
  107.                     return "EXCEPTION: " + webException.Message;  
  108.                 }  
  109.             }  
  110.             catch (Exception ex)  
  111.             {  
  112.                 return "EXCEPTION: " + ex.Message;  
  113.             }  
  114.         }  
  115.         public void GetAccessToken()  
  116.         {  
  117.             var urlEncodedSid = HttpUtility.UrlEncode(String.Format("{0}"this.packageSID));  
  118.             var urlEncodedSecret = HttpUtility.UrlEncode(this.clinetSecret);  
  119.   
  120.             var body =  
  121.               String.Format("grant_type=client_credentials&client_id={0}&client_secret={1}&scope=notify.windows.com", urlEncodedSid, urlEncodedSecret);  
  122.   
  123.             var client = new WebClient();  
  124.             client.Headers.Add("Content-Type""application/x-www-form-urlencoded");  
  125.   
  126.             string response = client.UploadString("https://login.live.com/accesstoken.srf", body);  
  127.             var oAuthToken = GetOAuthTokenFromJson(response);  
  128.             this.accessToken = oAuthToken.AccessToken;  
  129.         }  
  130.     }  
  131. }  
Step 9:

Run the windows app first and get the Channel URI and put it in SendToast.aspx.cs. After that run the web application. If all things are set correctly, then you will get ‘Result: OK’ response.

reslt
And you get the notifications in your device.

notifications

result

That’s it!
 
Get the complete project from GitHub.  

Thanks, Happy Coding!

Read more articles on Windows Runtime Apps: