Mulai cepat: Mengirim pemberitahuan push (XAML)

Server cloud Anda dapat mengirim pemberitahuan push ke aplikasi Anda melalui Windows Push Notification Services (WNS). Prosedur ini berlaku untuk pemberitahuan ubin, roti panggang, lencana, dan push mentah.

Tujuan: Untuk membuat dan mengirim petak peta, toast, lencana, atau pemberitahuan push mentah.

Prasyarat

Untuk memahami topik ini atau menggunakan kode yang disediakannya, Anda memerlukan:

Petunjuk

1. Sertakan referensi namespace yang diperlukan

Contoh yang diberikan dalam topik ini dapat digunakan apa adanya, tetapi mengharuskan kode Anda menyertakan referensi namespace layanan ini:

using System.Net;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using System.Web;
using System.Text;

2. Buat permintaan HTTP POST

Parameternya uri adalah saluran Pengidentifikasi Sumber Daya Seragam (URI) yang diminta oleh aplikasi dan diteruskan ke server cloud. Untuk informasi selengkapnya, lihat Cara meminta, membuat, dan menyimpan saluran pemberitahuan.

HttpWebRequest request = HttpWebRequest.Create(uri) as HttpWebRequest;
request.Method = "POST";

3. Tambahkan header yang diperlukan

Ada empat header yang diperlukan yang harus disertakan dalam semua pemberitahuan push: X-WNS-Type, Content-Type, Content-Length, dan Authorization.

  • Header X-WNS-Type menentukan apakah ini petak peta, toast, lencana, atau pemberitahuan mentah.
  • Jenis Konten diatur tergantung pada nilai X-WNS-Type.
  • Panjang Konten memberikan ukuran payload pemberitahuan yang disertakan.
  • Header Otorisasi menentukan kredensial autentikasi yang memungkinkan Anda mengirim pemberitahuan push kepada pengguna ini melalui saluran ini.

Parameter accessToken header Otorisasi menentukan token akses, yang disimpan di server, yang diterima dari WNS saat server cloud meminta autentikasi. Tanpa token akses, pemberitahuan Anda akan ditolak.

Untuk daftar lengkap header yang mungkin, lihat Permintaan layanan pemberitahuan push dan header respons.

request.Headers.Add("X-WNS-Type", notificationType);
request.ContentType = contentType;
request.Headers.Add("Authorization", String.Format("Bearer {0}", accessToken.AccessToken));

4. Tambahkan konten yang disiapkan

Sejauh menyangkut permintaan HTTP, konten XML pemberitahuan adalah blob data dalam isi permintaan. Misalnya, tidak ada verifikasi yang dibuat bahwa XML cocok dengan spesifikasi X-WNS-Type. Konten ditentukan sebagai payload XML dan di sini ditambahkan ke permintaan sebagai aliran byte.

byte[] contentInBytes = Encoding.UTF8.GetBytes(xml);
                        
using (Stream requestStream = request.GetRequestStream())
    requestStream.Write(contentInBytes, 0, contentInBytes.Length);

5. Dengarkan respons dari WNS yang mengakui penerimaan pemberitahuan

Catatan

Anda tidak akan pernah menerima konfirmasi pengiriman untuk pemberitahuan, hanya pengakuan bahwa itu diterima oleh WNS.

using (HttpWebResponse webResponse = (HttpWebResponse)request.GetResponse())
    return webResponse.StatusCode.ToString();

6. Menangani kode respons WNS

Ada banyak kode respons yang dapat diterima layanan aplikasi Anda saat mengirim pemberitahuan. Beberapa kode respons ini lebih umum daripada yang lain dan dapat dengan mudah ditangani dalam blok tangkapan.

catch (WebException webException)
{
    HttpStatusCode status = ((HttpWebResponse)webException.Response).StatusCode;

HttpStatusCode.Unauthorized: Token akses yang Anda sajikan telah kedaluwarsa. Dapatkan yang baru lalu coba kirim pemberitahuan Anda lagi. Karena token akses cache Anda kedaluwarsa setelah 24 jam, Anda bisa mengharapkan untuk mendapatkan respons ini dari WNS setidaknya sekali sehari. Kami menyarankan agar Anda menerapkan kebijakan percobaan kembali maksimum.

    if (status == HttpStatusCode.Unauthorized)
    {
        GetAccessToken(secret, sid);
        return PostToWns(uri, xml, secret, sid, notificationType, contentType);
    }

HttpStatusCode.Gone / HttpStatusCode.NotFound: URI saluran tidak lagi valid. Hapus saluran ini dari database Anda untuk mencegah upaya lebih lanjut untuk mengirim pemberitahuan ke dalamnya. Lain kali pengguna ini meluncurkan aplikasi Anda, minta saluran WNS baru. Aplikasi Anda harus mendeteksi bahwa salurannya telah berubah, yang akan memicu aplikasi untuk mengirim URI saluran baru ke server aplikasi Anda. Untuk informasi selengkapnya, lihat Cara meminta, membuat, dan menyimpan saluran pemberitahuan.

    else if (status == HttpStatusCode.Gone || status == HttpStatusCode.NotFound)
    {
        return "";
    }

HttpStatusCode.NotAcceptable: Saluran ini sedang dibatasi oleh WNS. Terapkan strategi coba lagi yang secara eksponensial mengurangi jumlah pemberitahuan yang dikirim untuk mencegah pembatasan lagi. Selain itu, tinjau kembali skenario yang menyebabkan notificaiton Anda dibatasi. Anda akan memberikan pengalaman pengguna yang lebih kaya dengan membatasi pemberitahuan yang Anda kirimkan kepada mereka yang menambahkan nilai sebenarnya.

    else if (status == HttpStatusCode.NotAcceptable)
    {
        return "";
    }

Kode respons lainnya: WNS merespons dengan kode respons yang kurang umum. Catat kode ini untuk membantu penelusuran kesalahan. Lihat Permintaan layanan pemberitahuan push dan header respons untuk daftar lengkap kode respons 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. Merangkum kode ke dalam satu fungsi

Contoh berikut mengemas kode yang diberikan dalam langkah-langkah sebelumnya ke dalam satu fungsi. Fungsi ini menyusun permintaan HTTP POST yang berisi pemberitahuan yang akan dikirim ke WNS. Dengan mengubah nilai parameter jenis dan menyesuaikan header tambahan, kode ini dapat digunakan untuk toast, ubin, lencana, atau pemberitahuan push mentah. Anda dapat menggunakan fungsi ini sebagai bagian dari kode server cloud Anda.

Perhatikan bahwa penanganan kesalahan dalam fungsi ini mencakup situasi di mana token akses telah kedaluwarsa. Dalam hal ini, ia memanggil fungsi server cloud lain yang mengautentikasi ulang dengan WNS untuk mendapatkan token akses baru. Kemudian melakukan panggilan baru ke fungsi asli.

// 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);
}

Berikut ini memperlihatkan contoh konten untuk permintaan HTTP POST untuk pemberitahuan push toast.

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>

Berikut ini menunjukkan contoh respons HTTP, yang dikirim ke server cloud oleh WNS sebagai respons terhadap permintaan 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

Ringkasan

Dalam Mulai Cepat ini, Anda menyusun permintaan HTTP POST untuk dikirim ke WNS. WNS, pada gilirannya, mengirimkan pemberitahuan ke aplikasi Anda. Pada titik ini, Anda telah mendaftarkan aplikasi Anda, mengautentikasi server cloud Anda dengan WNS, membuat konten XML untuk menentukan pemberitahuan Anda, dan mengirim pemberitahuan tersebut dari server Anda ke aplikasi Anda.