快速入門:傳送推播通知 (XAML)
您的雲端伺服器可以透過 Windows 推播通知服務 (WNS) 將推播通知傳送至您的應用程式。 此程式適用於磚、快顯、徽章和原始推播通知。
目標:建立並傳送磚、快顯、徽章或原始推播通知。
必要條件
為了解本主題或使用主題中提供的程式碼,您需要:
- 熟悉 HTTP 通訊。
- 已驗證的雲端伺服器。 如需詳細資訊,請參閱如何使用 Windows 推播通知服務 (WNS) 進行驗證。
- 已註冊的通道,您的雲端伺服器可以透過此通道與您的應用程式進行通訊。 如需詳細資訊,請參閱如何要求、建立和儲存通知通道。
- 應用程式現有的磚 (在應用程式的資訊清單中定義),用來接收通知 (除非您是傳送原始通知)。 如需詳細資訊,請參閱快速入門:使用 Microsoft Visual Studio 資訊清單編輯器建立預設磚。
- 透過文件物件模型 (DOM) API 熟悉 XML 及其操作。
- 若是原始通知,您的應用程式必須設定為接收原始通知。 如需詳細資訊,請參閱快速入門:攔截執行中應用程式的推播通知和快速入門:建立和註冊原始通知背景工作。
指示
1. 包含必要的命名空間參考
本主題中提供的範例可直接使用,但您的程式碼必須包含下列命名空間參考:
using System.Net;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using System.Web;
using System.Text;
2. 建立 HTTP POST 要求
uri
參數是應用程式所要求的通道統一資源識別元 (URI),並且會傳遞至雲端伺服器。 如需詳細資訊,請參閱如何要求、建立和儲存通知通道。
HttpWebRequest request = HttpWebRequest.Create(uri) as HttpWebRequest;
request.Method = "POST";
3. 新增必要的標頭
所有推播通知都必須包含四個必要的標頭:X-WNS-Type、Content-Type、Content-Length, 和 Authorization。
- X-WNS-Type 標頭會指定這是磚、快顯、徽章或原始通知。
- Content-Type 是根據 X-WNS-Type 的值設定。
- Content-Length 會提供所包含通知承載的大小。
- Authorization 標頭會指定驗證認證,可讓您透過此通道將推播通知傳送給此使用者。
Authorization 標頭的 accessToken 參數會指定伺服器上儲存的存取權仗,這是在雲端伺服器要求驗證時,從 WNS 收到的存取權杖。 若沒有存取權杖,您的通知將會遭到拒絕。
如需可能標頭的完整清單,請參閱推播通知服務要求和回應標頭。
request.Headers.Add("X-WNS-Type", notificationType);
request.ContentType = contentType;
request.Headers.Add("Authorization", String.Format("Bearer {0}", accessToken.AccessToken));
4. 新增準備好的內容
就 HTTP 要求而言,通知的 XML 內容是要求本文中的資料 Blob。 例如,XML 符合 X-WNS-Type 規格時,不會進行驗證。 內容會指定為 XML 承載,並且在這裡會做為位元組串流新增至要求。
byte[] contentInBytes = Encoding.UTF8.GetBytes(xml);
using (Stream requestStream = request.GetRequestStream())
requestStream.Write(contentInBytes, 0, contentInBytes.Length);
5. 接聽來自 WNS 的回應,以確認收到通知
注意
您永遠不會收到通知的傳遞確認,只會確認 WNS 已收到通知。
using (HttpWebResponse webResponse = (HttpWebResponse)request.GetResponse())
return webResponse.StatusCode.ToString();
6. 處理 WNS 回應碼
您的應用程式服務傳送通知時,可以接收許多回應碼。 當中有些回應碼較為常見,且可以在 catch 區塊中輕鬆處理。
catch (WebException webException)
{
HttpStatusCode status = ((HttpWebResponse)webException.Response).StatusCode;
HttpStatusCode.Unauthorized:您提供的存取權杖已過期。 取得新的存取權杖,然後再次嘗試傳送通知。 由於快取的存取權杖會在 24 小時後過期,因此您可以預期每天至少會收到一次來自 WNS 的此回應。 建議您實作重試原則上限。
if (status == HttpStatusCode.Unauthorized)
{
GetAccessToken(secret, sid);
return PostToWns(uri, xml, secret, sid, notificationType, contentType);
}
HttpStatusCode.Gone/HttpStatusCode.NotFound:通道 URI 已失效。 從資料庫移除此通道,避免後續嘗試傳送通知至該通道。 此使用者下次啟動您的應用程式時,請要求新的 WNS 通道。 您的應用程式應偵測到其通道已變更,此時應該會觸發應用程式,將新的通道 URI 傳送至您的應用程式伺服器。 如需詳細資訊,請參閱如何要求、建立和儲存通知通道。
else if (status == HttpStatusCode.Gone || status == HttpStatusCode.NotFound)
{
return "";
}
HttpStatusCode.NotAcceptable:WNS 正在節流此通道。 實作重試策略,以大幅減少傳送的通知數量,防止再次節流。 此外,重新思考導致通知受到節流處理的案例。 您將限制傳送至新增 true 值的通知,藉此提供更豐富的使用者體驗。
else if (status == HttpStatusCode.NotAcceptable)
{
return "";
}
其他回應碼:WNS 回應較不常見的回應碼。 記錄此回應碼以協助進行偵錯。 如需 WNS 回應碼的完整清單,請參閱推播通知服務要求和回應標頭。
else
{
string[] debugOutput = {
status.ToString(),
webException.Response.Headers["X-WNS-Debug-Trace"],
webException.Response.Headers["X-WNS-Error-Description"],
webException.Response.Headers["X-WNS-Msg-ID"],
webException.Response.Headers["X-WNS-Status"]
};
return string.Join(" | ", debugOutput);
}
7. 將程式碼封裝成單一函式
下列範例會將上述步驟中所提供的程式碼封裝成單一函式。 此函式會撰寫 HTTP POST 要求,其中包含要傳送至 WNS 的通知。 藉由變更 type 參數的值並調整其他標頭,此程式碼就可用於快顯、磚、徽章或原始推播通知。 您可以在雲端伺服器程式碼中使用此函式。
請注意,此函式中的錯誤處理包含存取權杖已過期的情況。 在此情況下,它會呼叫另一個雲端伺服器函式以使用 WNS 重新驗證,進而取得新的存取權杖。 然後它會對原始函式進行新的呼叫。
// Post to WNS
public string PostToWns(string secret, string sid, string uri, string xml, string notificationType, string contentType)
{
try
{
// You should cache this access token.
var accessToken = GetAccessToken(secret, sid);
byte[] contentInBytes = Encoding.UTF8.GetBytes(xml);
HttpWebRequest request = HttpWebRequest.Create(uri) as HttpWebRequest;
request.Method = "POST";
request.Headers.Add("X-WNS-Type", notificationType);
request.ContentType = contentType;
request.Headers.Add("Authorization", String.Format("Bearer {0}", accessToken.AccessToken));
using (Stream requestStream = request.GetRequestStream())
requestStream.Write(contentInBytes, 0, contentInBytes.Length);
using (HttpWebResponse webResponse = (HttpWebResponse)request.GetResponse())
return webResponse.StatusCode.ToString();
}
catch (WebException webException)
{
HttpStatusCode status = ((HttpWebResponse)webException.Response).StatusCode;
if (status == HttpStatusCode.Unauthorized)
{
// The access token you presented has expired. Get a new one and then try sending
// your notification again.
// Because your cached access token expires after 24 hours, you can expect to get
// this response from WNS at least once a day.
GetAccessToken(secret, sid);
// We recommend that you implement a maximum retry policy.
return PostToWns(uri, xml, secret, sid, notificationType, contentType);
}
else if (status == HttpStatusCode.Gone || status == HttpStatusCode.NotFound)
{
// The channel URI is no longer valid.
// Remove this channel from your database to prevent further attempts
// to send notifications to it.
// The next time that this user launches your app, request a new WNS channel.
// Your app should detect that its channel has changed, which should trigger
// the app to send the new channel URI to your app server.
return "";
}
else if (status == HttpStatusCode.NotAcceptable)
{
// This channel is being throttled by WNS.
// Implement a retry strategy that exponentially reduces the amount of
// notifications being sent in order to prevent being throttled again.
// Also, consider the scenarios that are causing your notifications to be throttled.
// You will provide a richer user experience by limiting the notifications you send
// to those that add true value.
return "";
}
else
{
// WNS responded with a less common error. Log this error to assist in debugging.
// You can see a full list of WNS response codes here:
// https://msdn.microsoft.com/library/windows/apps/hh868245.aspx#wnsresponsecodes
string[] debugOutput = {
status.ToString(),
webException.Response.Headers["X-WNS-Debug-Trace"],
webException.Response.Headers["X-WNS-Error-Description"],
webException.Response.Headers["X-WNS-Msg-ID"],
webException.Response.Headers["X-WNS-Status"]
};
return string.Join(" | ", debugOutput);
}
}
catch (Exception ex)
{
return "EXCEPTION: " + ex.Message;
}
}
// Authorization
[DataContract]
public class OAuthToken
{
[DataMember(Name = "access_token")]
public string AccessToken { get; set; }
[DataMember(Name = "token_type")]
public string TokenType { get; set; }
}
private OAuthToken GetOAuthTokenFromJson(string jsonString)
{
using (var ms = new MemoryStream(Encoding.Unicode.GetBytes(jsonString)))
{
var ser = new DataContractJsonSerializer(typeof(OAuthToken));
var oAuthToken = (OAuthToken)ser.ReadObject(ms);
return oAuthToken;
}
}
protected OAuthToken GetAccessToken(string secret, string sid)
{
var urlEncodedSecret = HttpUtility.UrlEncode(secret);
var urlEncodedSid = HttpUtility.UrlEncode(sid);
var body = String.Format("grant_type=client_credentials&client_id={0}&client_secret={1}&scope=notify.windows.com",
urlEncodedSid,
urlEncodedSecret);
string response;
using (var client = new WebClient())
{
client.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
response = client.UploadString("https://login.live.com/accesstoken.srf", body);
}
return GetOAuthTokenFromJson(response);
}
下列顯示快顯推播通知的 HTTP POST 要求內容範例。
POST https://db3.notify.windows.com/?token=AgUAAADCQmTg7OMlCg%2fK0K8rBPcBqHuy%2b1rTSNPMuIzF6BtvpRdT7DM4j%2fs%2bNNm8z5l1QKZMtyjByKW5uXqb9V7hIAeA3i8FoKR%2f49ZnGgyUkAhzix%2fuSuasL3jalk7562F4Bpw%3d HTTP/1.1
Authorization: Bearer EgAaAQMAAAAEgAAACoAAPzCGedIbQb9vRfPF2Lxy3K//QZB79mLTgK
X-WNS-RequestForStatus: true
X-WNS-Type: wns/toast
Content-Type: text/xml
Host: db3.notify.windows.com
Content-Length: 196
<toast launch="">
<visual lang="en-US">
<binding template="ToastImageAndText01">
<image id="1" src="World" />
<text id="1">Hello</text>
</binding>
</visual>
</toast>
以下顯示的範例 HTTP 回應會由 WNS 傳送至雲端伺服器,以回應 HTTP POST 要求。
HTTP/1.1 200 OK
Content-Length: 0
X-WNS-DEVICECONNECTIONSTATUS: connected
X-WNS-STATUS: received
X-WNS-MSG-ID: 3CE38FF109E03A74
X-WNS-DEBUG-TRACE: DB3WNS4011534
摘要
在本快速入門中,您撰寫了要傳送至 WNS 的 HTTP POST 要求。 接著 WNS 會將通知傳遞至您的應用程式。 至此,您已註冊您的應用程式、使用 WNS 驗證您的雲端伺服器、建立 XML 內容來定義您的通知,並將該通知從您的伺服器傳送至您的應用程式。