Partager via


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

Votre serveur cloud peut envoyer une notification Push à votre application via windows Push Notification Services (WNS). Cette procédure s’applique aux notifications Push brutes, toast, badge et vignette.

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 fourni, vous aurez 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 ces références d’espace de noms :

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

Il existe quatre en-têtes obligatoires qui 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.
  • Le type de contenu est défini en fonction de la valeur du type X-WNS.
  • La longueur du contenu donne la taille de la charge utile de notification incluse.
  • L’en-tête d’autorisation 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 d’autorisation 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 les 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 exemple, aucune vérification n’est effectuée pour que le code XML corresponde à la spécification X-WNS-Type. Le contenu est spécifié en tant que charge utile XML et ici est ajouté à la requête en tant que flux d’octets.

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

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

Remarque

Vous ne recevrez jamais de confirmation de remise pour une notification, juste un accusé de réception reçu 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 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 à obtenir cette réponse à partir 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 lance votre application, demandez un nouveau canal WNS. Votre application doit détecter que son canal a changé, ce qui doit déclencher l’application pour envoyer le 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 la quantité de notifications envoyées afin d’empêcher la limitation. En outre, repensez les scénarios qui entraînent la limitation de vos notifications. Vous fournirez une expérience utilisateur plus riche en limitant les notifications que vous envoyez à celles qui ajoutent de la 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. Journaliser ce code pour faciliter le débogage. Consultez les en-têtes de demande et de réponse du service de notification Push pour obtenir la liste complète des codes de réponse 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. Encapsuler le code dans une seule fonction

L’exemple suivant empaquette le code donné dans les étapes précédentes dans une fonction unique. 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 Push brutes, de vignettes, de badges ou toast. Vous pouvez utiliser cette fonction dans le cadre de votre code de serveur cloud.

Notez que la gestion des erreurs dans cette fonction inclut la situation dans laquelle le jeton d’accès a expiré. Dans ce cas, il appelle une autre fonction de serveur cloud qui s’authentifie à nouveau avec 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 de contenu 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>

L’exemple de réponse HTTP ci-dessous est envoyé 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.