Partager via


Démarrage rapide : Envoi d’une notification Push (XAML)

Votre serveur cloud peut envoyer une notification Push à votre application par le biais de Windows Push Notification Services (WNS). Cette procédure s’applique aux notifications Push par vignette, toast, badge et raw.

Objectif: Pour créer et envoyer une vignette, un toast, un badge ou une notification Push brute.

Prérequis

Pour comprendre cette rubrique ou utiliser le code qu’elle fournit, vous avez besoin des éléments suivants :

Instructions

1. Inclure les références d’espace de noms nécessaires

Les exemples fournis dans cette rubrique peuvent être utilisés en l’état, mais nécessitent que votre code inclue les références d’espace de noms suivantes :

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

2. Créer une requête HTTP POST

Le uri paramètre est l’URI (Uniform Resource Identifier) du canal demandé par l’application et transmis au serveur cloud. Pour plus d’informations, consultez Comment demander, créer et enregistrer un canal de notification.

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

3. Ajouter les en-têtes requis

Quatre en-têtes doivent être inclus dans toutes les notifications Push : X-WNS-Type, Content-Type, Content-Length et Authorization.

  • L’en-tête X-WNS-Type spécifie s’il s’agit d’une vignette, d’un toast, d’un badge ou d’une notification brute.
  • Content-Type est défini en fonction de la valeur de X-WNS-Type.
  • Content-Length indique la taille de la charge utile de notification incluse.
  • L’en-tête Authorization spécifie les informations d’identification d’authentification qui vous permettent d’envoyer une notification Push à cet utilisateur via ce canal.

Le paramètre accessToken de l’en-tête Authorization spécifie le jeton d’accès, stocké sur le serveur, qui a été reçu de WNS lorsque le serveur cloud a demandé l’authentification. Sans le jeton d’accès, votre notification sera rejetée.

Pour obtenir la liste complète des en-têtes possibles, consultez En-têtes de demande et de réponse du service de notification Push.

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

4. Ajouter le contenu préparé

En ce qui concerne la requête HTTP, le contenu XML de la notification est un objet blob de données dans le corps de la requête. Par instance, aucune vérification n’est effectuée que le XML correspond à la spécification X-WNS-Type. Le contenu est spécifié en tant que charge utile XML et est ajouté ici à la requête sous la forme d’un flux d’octets.

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

5. Écouter une réponse de WNS qui accuse réception de la notification

Notes

Vous ne recevrez jamais de confirmation de livraison pour une notification, juste un accusé de réception par WNS.

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

6. Gérer les codes de réponse WNS

Il existe de nombreux codes de réponse que votre service d’application peut recevoir lorsqu’il envoie une notification. Certains de ces codes de réponse sont plus courants que d’autres et peuvent être facilement traités dans un bloc catch.

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

HttpStatusCode.Unauthorized : le jeton d’accès que vous avez présenté a expiré. Obtenez-en un nouveau, puis réessayez d’envoyer votre notification. Étant donné que votre jeton d’accès mis en cache expire après 24 heures, vous pouvez vous attendre à recevoir cette réponse de WNS au moins une fois par jour. Nous vous recommandons d’implémenter une stratégie de nouvelle tentative maximale.

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

HttpStatusCode.Gone / HttpStatusCode.NotFound : l’URI du canal n’est plus valide. Supprimez ce canal de votre base de données pour empêcher d’autres tentatives d’envoi de notification. La prochaine fois que cet utilisateur lancera votre application, demandez un nouveau canal WNS. Votre application doit détecter que son canal a changé, ce qui doit déclencher l’envoi du nouvel URI de canal à votre serveur d’applications. Pour plus d’informations, consultez Comment demander, créer et enregistrer un canal de notification.

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

HttpStatusCode.NotAcceptable : ce canal est limité par WNS. Implémentez une stratégie de nouvelle tentative qui réduit de façon exponentielle le nombre de notifications envoyées afin d’éviter une nouvelle limitation. En outre, repensez les scénarios qui entraînent la limitation de vos notificaitons. Vous fournirez une expérience utilisateur plus riche en limitant les notifications que vous envoyez à ceux qui ajoutent une valeur réelle.

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

Autres codes de réponse : WNS a répondu avec un code de réponse moins courant. Consignez ce code pour faciliter le débogage. Pour obtenir la liste complète des codes de réponse WNS, consultez En-têtes de demande et de réponse du service de notification Push .

    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. Encapsuler le code dans une seule fonction

L’exemple suivant empaquette le code fourni dans les étapes précédentes dans une seule fonction. Cette fonction compose la requête HTTP POST qui contient une notification à envoyer à WNS. En modifiant la valeur du paramètre de type et en ajustant des en-têtes supplémentaires, ce code peut être utilisé pour les notifications toast, vignette, badge ou push brutes. Vous pouvez utiliser cette fonction dans le code de votre serveur cloud.

Notez que la gestion des erreurs dans cette fonction inclut la situation où le jeton d’accès a expiré. Dans ce cas, elle appelle une autre fonction de serveur cloud qui s’authentifie à nouveau auprès de WNS pour obtenir un nouveau jeton d’accès. Il effectue ensuite un nouvel appel à la fonction d’origine.

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

L’exemple suivant montre un exemple de contenu pour une requête HTTP POST pour une notification 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>

Voici un exemple de réponse HTTP, envoyée au serveur cloud par WNS en réponse à la requête 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

Résumé

Dans ce guide de démarrage rapide, vous avez composé une requête HTTP POST à envoyer à WNS. WNS, à son tour, remet la notification à votre application. À ce stade, vous avez inscrit votre application, authentifié votre serveur cloud avec WNS, créé du contenu XML pour définir votre notification et envoyé cette notification de votre serveur à votre application.