public async Task Send(WnsNotification notification) { // Get or renew our access token var accessToken = await AccessTokenManager.GetAccessToken(); //https://cloud.notify.windows.com/?token=..... //Authorization: Bearer {AccessToken} // // Not sure how to do this in httpclient var http = new HttpClient(); http.DefaultRequestHeaders.ExpectContinue = false; //Disable expect-100 to improve latency http.DefaultRequestHeaders.TryAddWithoutValidation("X-WNS-Type", string.Format("wns/{0}", notification.Type.ToString().ToLower())); if (!http.DefaultRequestHeaders.Contains("Authorization")) //prevent double values { http.DefaultRequestHeaders.TryAddWithoutValidation("Authorization", "Bearer " + accessToken); } if (notification.RequestForStatus.HasValue) { http.DefaultRequestHeaders.TryAddWithoutValidation("X-WNS-RequestForStatus", notification.RequestForStatus.Value.ToString().ToLower()); } if (notification.TimeToLive.HasValue) { http.DefaultRequestHeaders.TryAddWithoutValidation("X-WNS-TTL", notification.TimeToLive.Value.ToString()); //Time to live in seconds } if (notification.Type == WnsNotificationType.Tile) { var winTileNot = notification as WnsTileNotification; if (winTileNot != null && winTileNot.CachePolicy.HasValue) { http.DefaultRequestHeaders.Add("X-WNS-Cache-Policy", winTileNot.CachePolicy == WnsNotificationCachePolicyType.Cache ? "cache" : "no-cache"); } if (winTileNot != null && !string.IsNullOrEmpty(winTileNot.NotificationTag)) { http.DefaultRequestHeaders.Add("X-WNS-Tag", winTileNot.NotificationTag); // TILE only } } else if (notification.Type == WnsNotificationType.Badge) { var winTileBadge = notification as WnsBadgeNotification; if (winTileBadge != null && winTileBadge.CachePolicy.HasValue) { http.DefaultRequestHeaders.Add("X-WNS-Cache-Policy", winTileBadge.CachePolicy == WnsNotificationCachePolicyType.Cache ? "cache" : "no-cache"); } } HttpContent content = null; if (notification.Type == WnsNotificationType.Raw) { content = new StreamContent(new MemoryStream(((WnsRawNotification)notification).RawData)); } else { content = new StringContent( notification.Payload.ToString(), // Get XML payload Encoding.UTF8, "text/xml"); } var result = await http.PostAsync(notification.ChannelUri, content); var status = ParseStatus(result, notification); //RESPONSE HEADERS // X-WNS-Debug-Trace string // X-WNS-DeviceConnectionStatus connected | disconnected | tempdisconnected (if RequestForStatus was set to true) // X-WNS-Error-Description string // X-WNS-Msg-ID string (max 16 char) // X-WNS-NotificationStatus received | dropped | channelthrottled // // 200 OK // 400 One or more headers were specified incorrectly or conflict with another header. // 401 The cloud service did not present a valid authentication ticket. The OAuth ticket may be invalid. // 403 The cloud service is not authorized to send a notification to this URI even though they are authenticated. // 404 The channel URI is not valid or is not recognized by WNS. - Raise Expiry // 405 Invalid Method - never will get // 406 The cloud service exceeded its throttle limit. // 410 The channel expired. - Raise Expiry // 413 The notification payload exceeds the 5000 byte size limit. // 500 An internal failure caused notification delivery to fail. // 503 The server is currently unavailable. // OK, everything worked! if (status.HttpStatus == HttpStatusCode.OK && status.NotificationStatus == WnsNotificationSendStatus.Received) { return; } //401 if (status.HttpStatus == HttpStatusCode.Unauthorized) { AccessTokenManager.InvalidateAccessToken(accessToken); throw new RetryAfterException(notification, "Access token expired", DateTime.UtcNow.AddSeconds(5)); } //404 or 410 if (status.HttpStatus == HttpStatusCode.NotFound || status.HttpStatus == HttpStatusCode.Gone) { throw new DeviceSubscriptionExpiredException(notification) { OldSubscriptionId = notification.ChannelUri, ExpiredAt = DateTime.UtcNow }; } // Any other error throw new WnsNotificationException(status); }