public
Created

Sample code for OAuth and push notification handling for Windows Store applications

  • Download Gist
WNSHelper.cs
C#
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
/*
Copyright (c) Microsoft
All rights reserved.
Licensed under the Microsoft Limited Public License (the “License”); you may not
use this file except in compliance with the License.
You may obtain a copy of the License at http://msdn.microsoft.com/en-us/cc300389.
 
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS
OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT.
win
See the Microsoft Limited Public License (Ms-LPL) for specific language governing
permissions and limitations under the License.
*/
 
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
 
namespace Utilities
{
public static class WNSHelper
{
static String _token = null;
 
private static async Task RefreshTokenAsync()
{
// set the required name/value pair for the POST
var parms = new List<KeyValuePair<String,String>>();
parms.Add(new KeyValuePair<String, String>("grant_type", "client_credentials"));
parms.Add(new KeyValuePair<String, String>("scope", "notify.windows.com"));
parms.Add(new KeyValuePair<String, String>("client_id", ConfigurationManager.AppSettings["WNSPackageId"]));
parms.Add(new KeyValuePair<String, String>("client_secret", ConfigurationManager.AppSettings["WNSSecret"]));
 
// POST OAuth token request
var client = new HttpClient();
HttpResponseMessage response = await client.PostAsync(
"https://login.live.com/accesstoken.srf",
new FormUrlEncodedContent(parms));
// throw if there's a problem
response.EnsureSuccessStatusCode();
 
// get response (JSON)
String jsonContent = await response.Content.ReadAsStringAsync();
var tokenResponse =
JsonConvert.DeserializeObject<TokenPayload>(jsonContent);
 
// set the token
_token = tokenResponse.access_token;
}
 
public static async Task<NotificationResult> PushNotificationAsync(String uri, String template)
{
// make sure there's a token
if (_token == null) await RefreshTokenAsync();
 
var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", String.Format("Bearer {0}", _token));
client.DefaultRequestHeaders.Add("X-WNS-Type", "wns/toast");
client.DefaultRequestHeaders.Add("X-WNS-RequestForStatus", "true");
 
HttpResponseMessage response = await client.PostAsync(uri, SetContent(template));
var notificationResult = new NotificationResult(response);
 
if (notificationResult.RequiresTokenRefresh())
{
await RefreshTokenAsync();
 
response = await client.PostAsync(uri, WNSHelper.SetContent(template));
notificationResult = new NotificationResult(response);
}
 
return notificationResult;
}
 
private static StringContent SetContent(String template)
{
var requestContent = new StringContent(template);
requestContent.Headers.ContentType = new MediaTypeHeaderValue("text/xml");
requestContent.Headers.ContentLength = template.Length;
 
return requestContent;
}
 
// OAuth response (see http://tools.ietf.org/html/draft-ietf-oauth-v2-23)
private class TokenPayload
{
public String token_type;
public String access_token;
public String expires_in;
}
}
 
public class NotificationResult
{
public HttpStatusCode HttpCode { get; private set; }
public String ErrorDescription { get; private set; }
public String NotificationStatus { get; private set; }
public String DeviceStatus { get; private set; }
public String DebugTrace { get; private set; }
public String MessageId { get; private set; }
 
public NotificationResult(HttpResponseMessage m)
{
HttpCode = m.StatusCode;
NotificationStatus = ParseHeaderValue(m.Headers, "X-WNS-NOTIFICATIONSTATUS");
ErrorDescription = ParseHeaderValue(m.Headers, "X-WNS-ERROR-DESCRIPTION");
DeviceStatus = ParseHeaderValue(m.Headers, "X-WNS-DEVICECONNECTIONSTATUS");
DebugTrace = ParseHeaderValue(m.Headers, "X-WNS-DEBUGTRACE");
MessageId = ParseHeaderValue(m.Headers, "X-WNS-MSG-ID");
}
 
public Boolean RequiresTokenRefresh()
{
return this.HttpCode == HttpStatusCode.Unauthorized;
}
 
public Boolean RequiresChannelUpdate()
{
return (this.HttpCode == HttpStatusCode.NotFound) ||
(this.HttpCode == HttpStatusCode.Gone);
}
 
public Boolean WasSuccessful()
{
return (this.HttpCode == HttpStatusCode.OK);
}
 
public override string ToString()
{
return String.Format("Notification Result: {1}{0}Message Id: {2}{0}Notification Status: {3}{0}Device Status: {4}{0}{5}",
Environment.NewLine + " ",
HttpCode, MessageId, NotificationStatus, DeviceStatus,
(ErrorDescription != String.Empty) ? String.Format("Error Description: {0}", ErrorDescription) : String.Empty);
 
}
 
private String ParseHeaderValue(HttpResponseHeaders headers, String name)
{
var headerValue = headers.Where(h => h.Key.Equals(name, StringComparison.OrdinalIgnoreCase)).FirstOrDefault().Value;
return (headerValue == null) ? String.Empty : headerValue.FirstOrDefault();
}
}
}

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.