快速入門:傳送推播通知 (XAML)
您的雲端伺服器可以透過 Windows 推播通知服務 (WNS) 將推播通知傳送至您的應用程式。 此程式適用於磚、快顯通知、徽章和原始推播通知。
目標: 建立並傳送磚、快顯通知、徽章或原始推播通知。
必要條件
若要瞭解本主題或使用它所提供的程式代碼,您需要:
- 熟悉 HTTP 通訊。
- 已驗證的雲端伺服器。 如需詳細資訊,請參閱 如何使用 Windows 推播通知服務 (WNS) 進行驗證。
- 已註冊的通道,您的雲端伺服器可以透過此通道與您的應用程式通訊。 如需詳細資訊,請參閱 如何要求、建立和儲存通知通道。
- 應用程式指令清單中定義的應用程式現有圖格,可接收通知(除非您正在傳送原始通知)。 如需詳細資訊,請參閱 快速入門:使用 Microsoft Visual Studio 指令清單編輯器建立預設磚。
- 熟悉 XML 及其透過文件物件模型 (DOM) API 操作。
- 在原始通知的情況下,您的應用程式必須設定為接收原始通知。 如需詳細資訊,請參閱 快速入門:攔截執行應用程式的 推播通知和 快速入門:建立和註冊原始通知背景工作。
指示
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 標頭會指定這是磚、快顯通知、徽章或原始通知。
- 根據 X-WNS-Type 的值 來設定 Content-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 正在節流此通道。 實作重試策略,以指數方式減少傳送的通知數量,以防止再次進行節流。 此外,重新思考導致您未處理的案例。 您將藉由限制傳送給新增真實值的通知,來提供更豐富的用戶體驗。
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 的通知。 藉由變更類型參數的值並調整其他標頭,此程式代碼可用於快顯通知、磚、徽章或原始推播通知。 您可以使用此函式作為雲端伺服器程式代碼的一部分。
請注意,此函式中的錯誤處理包含存取令牌已過期的情況。 在此情況下,它會呼叫另一個雲端伺服器函式,以使用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 內容來定義您的通知,並將該通知從您的伺服器傳送至您的應用程式。
相關主題
意見反應
https://aka.ms/ContentUserFeedback。
即將推出:在 2024 年,我們將隨著內容的意見反應機制逐步淘汰 GitHub 問題,並以新的意見反應系統來取代。 如需詳細資訊,請參閱提交並檢視相關的意見反應