Tutoriel : Envoyer des notifications à des utilisateurs spécifiques avec Azure Notification Hubs

Vue d’ensemble

Ce tutoriel explique comment utiliser Azure Notification Hubs pour envoyer des notifications Push à un utilisateur d’une application sur un appareil spécifique. Un serveur principal WebAPI ASP.NET est utilisé pour authentifier les clients. Lorsque le serveur principal authentifie un utilisateur de l’application client, il ajoute automatiquement une balise à l’enregistrement des notifications. Le serveur principal utilise cette balise pour envoyer des notifications à l’utilisateur spécifique.

Notes

Le code complet de ce didacticiel est disponible sur GitHub.

Dans ce tutoriel, vous effectuez les étapes suivantes :

  • Création du projet WebAPI
  • Authentification des clients sur le serveur principal WebAPI
  • Inscription aux notifications à l’aide du serveur principal WebAPI
  • Envoyer des notifications depuis le serveur principal WebAPI
  • Publication du nouveau serveur principal WebAPI
  • Mise à jour du code pour le projet client
  • Test de l’application

Prérequis

Ce tutoriel fait intervenir le hub de notification et le projet Visual Studio que vous avez créés dans le Tutoriel : Envoyer des notifications vers des applications de plateforme Windows universelle avec Azure Notification Hubs. Par conséquent, terminez-le avant de démarrer ce didacticiel.

Notes

Si vous utilisez Mobile Apps dans Azure App Service comme service principal, consultez la version Mobile Apps de ce didacticiel.

Création du projet WebAPI

Les sections suivantes traitent de la création d’un serveur principal WebAPI ASP.NET. Ce processus a trois objectifs principaux :

  • Authentification des clients : ajoutez un gestionnaire de messages pour authentifier les demandes des clients et associer l’utilisateur à la demande.
  • Inscriptions aux notifications à l’aide du serveur principal WebAPI : ajoutez un contrôleur pour gérer les nouvelles inscriptions afin qu’un appareil client puisse recevoir des notifications. Le nom d’utilisateur authentifié est automatiquement ajouté à l’inscription en tant que balise.
  • Envoi de notifications aux clients : ajoutez un contrôleur permettant aux utilisateurs de déclencher une notification push sécurisée pour les appareils et les clients associés à la balise.

Pour créer le serveur principal ASP.NET Core 6.0, procédez comme suit :

Pour ce faire, lancez Visual Studio. Dans le menu Outils, sélectionnez Extensions et mises à jour. Recherchez Gestionnaire de package NuGet pour votre version de Visual Studio et vérifiez que vous disposez de la dernière version. Si vous ne disposez pas de la version la plus récente, désinstallez votre version actuelle et réinstallez le Gestionnaire de package NuGet.

Capture d’écran de la boîte de dialogue Extensions et mises à jour avec le package Gestionnaire de package NuGet pour Visual Studio mis en évidence.

Notes

Assurez-vous que le Kit de développement logiciel (SDK) Azure Visual Studio est installé, pour le déploiement du site web.

  1. Démarrez Visual Studio ou Visual Studio Express.

  2. Sélectionnez Explorateur de serveurs et connectez-vous à votre compte Azure. Pour créer les ressources du site web sur votre compte, vous devez être connecté.

  3. Dans Visual Studio, dans le menu Fichier, sélectionnez Nouveau>Projet.

  4. Entrez API web dans le champ de recherche.

  5. Sélectionnez le modèle de projet API web ASP.NET Core, puis Suivant.

  6. Dans la boîte de dialogue Configurer votre nouveau projet, nommez le projet AppBackend, puis sélectionnez Suivant.

  7. Dans la boîte de dialogue Informations supplémentaires :

    • Vérifiez que le framework est .NET 6.0 (prise en charge à long terme).
    • Vérifiez que la case à cocher Utiliser des contrôleurs (décocher pour utiliser les API minimales) est cochée.
    • Décochez Activer la prise en charge d’OpenAPI.
    • Sélectionnez Create (Créer).

Supprimer les fichiers de modèle WeatherForecast

  1. Supprimez les fichiers d’exemple WeatherForecast.cs et Controllers/WeatherForecastController.cs du nouveau projet AppBackend.
  2. Ouvrez Properties\launchSettings.json.
  3. Modifiez les propriétés launchUrl de weatherforcast en appbackend.

Dans la fenêtre Configurer l’application web Microsoft Azure, sélectionnez l’abonnement puis effectuez l’une des actions suivantes dans la liste Plan App Service :

  • Sélectionnez un plan Azure App Service que vous avez déjà créé.
  • Sélectionnez Créer un plan App Service, et créez-en un.

Vous n'avez pas besoin de base de données pour ce didacticiel. Une fois que vous avez sélectionné votre plan App Service, sélectionnez OK pour créer le projet.

Fenêtre Configurer l’application web Microsoft Azure

Si vous ne voyez pas la page Configurer le plan App Service, poursuivez le tutoriel. Vous pourrez le configurer plus tard, lors de la publication de l’application.

Authentification des clients sur le serveur principal WebAPI

Dans cette section, vous créez une classe de gestionnaire de messages nommée AuthenticationTestHandler pour le nouveau serveur principal. Cette classe est dérivée de DelegatingHandler et ajoutée comme gestionnaire de messages afin de pouvoir traiter toutes les demandes entrantes dans le serveur principal.

  1. Dans l’Explorateur de solutions, cliquez avec le bouton droit sur le projet AppBackend, puis sélectionnez Ajouter et Classe.

  2. Nommez la nouvelle classe AuthenticationTestHandler.cs, puis sélectionnez Ajouter pour générer la classe. Par souci de simplification, cette classe permet d’authentifier les utilisateurs via l’ Authentification de base . Votre application peut utiliser n’importe quel schéma d’authentification.

  3. Dans AuthenticationTestHandler.cs, ajoutez les instructions using suivantes :

    using System.Net.Http;
    using System.Threading;
    using System.Security.Principal;
    using System.Net;
    using System.Text;
    using System.Threading.Tasks;
    
  4. Dans AuthenticationTestHandler.cs, remplacez la définition de classe AuthenticationTestHandler par le code suivant :

    Ce gestionnaire autorise la demande lorsque les trois conditions suivantes sont vraies :

    • La demande comprenait un en-tête d’autorisation.
    • La demande utilise l’authentification de base .
    • Les chaînes du nom d’utilisateur et du mot de passe sont identiques.

    Sinon, la demande est rejetée. Cette authentification ne répond pas à une véritable approche d’authentification et d’autorisation. Il s’agit uniquement d’un exemple très simple pour ce didacticiel.

    Si le message de la demande est authentifié et autorisé par AuthenticationTestHandler, l’utilisateur de l’authentification de base est attaché à la demande actuelle sur HttpContext. Les informations utilisateur dans HttpContext sont utilisées ultérieurement par un autre contrôleur (RegisterController) pour ajouter une balise à la demande d’inscription aux notifications.

    public class AuthenticationTestHandler : DelegatingHandler
    {
        protected override Task<HttpResponseMessage> SendAsync(
        HttpRequestMessage request, CancellationToken cancellationToken)
        {
            var authorizationHeader = request.Headers.GetValues("Authorization").First();
    
            if (authorizationHeader != null && authorizationHeader
                .StartsWith("Basic ", StringComparison.InvariantCultureIgnoreCase))
            {
                string authorizationUserAndPwdBase64 =
                    authorizationHeader.Substring("Basic ".Length);
                string authorizationUserAndPwd = Encoding.Default
                    .GetString(Convert.FromBase64String(authorizationUserAndPwdBase64));
                string user = authorizationUserAndPwd.Split(':')[0];
                string password = authorizationUserAndPwd.Split(':')[1];
    
                if (VerifyUserAndPwd(user, password))
                {
                    // Attach the new principal object to the current HttpContext object
                    HttpContext.Current.User =
                        new GenericPrincipal(new GenericIdentity(user), new string[0]);
                    System.Threading.Thread.CurrentPrincipal =
                        System.Web.HttpContext.Current.User;
                }
                else return Unauthorized();
            }
            else return Unauthorized();
    
            return base.SendAsync(request, cancellationToken);
        }
    
        private bool VerifyUserAndPwd(string user, string password)
        {
            // This is not a real authentication scheme.
            return user == password;
        }
    
        private Task<HttpResponseMessage> Unauthorized()
        {
            var response = new HttpResponseMessage(HttpStatusCode.Forbidden);
            var tsc = new TaskCompletionSource<HttpResponseMessage>();
            tsc.SetResult(response);
            return tsc.Task;
        }
    }
    

    Notes

    Note de sécurité : la classe AuthenticationTestHandler n’offre pas de véritable authentification. Elle sert uniquement à simuler l’authentification de base et n’est pas sécurisée. Vous devez mettre en œuvre un mécanisme d’authentification sécurisé dans vos applications de production et vos services.

  5. Pour enregistrer le gestionnaire de messages, ajoutez le code suivant à la fin de la méthode Register dans le fichier Program.cs :

    config.MessageHandlers.Add(new AuthenticationTestHandler());
    
  6. Enregistrez vos modifications.

Inscription aux notifications à l’aide du serveur principal WebAPI

Dans cette section, vous ajoutez un nouveau contrôleur au serveur principal WebAPI pour gérer les demandes d’inscription d’un utilisateur et d’un appareil aux notifications à l’aide de la bibliothèque cliente pour les hubs de notification. Le contrôleur ajoute une balise d’utilisateur pour l’utilisateur qui a été authentifié et attaché à HttpContext par AuthenticationTestHandler. La balise a le format de chaîne "username:<actual username>".

  1. Dans l’Explorateur de solutions, cliquez avec le bouton droit sur le projet AppBackend, puis sélectionnez Gérer les packages NuGet.

  2. Dans le volet gauche, sélectionnez En ligne puis tapez Microsoft.Azure.NotificationHubs dans la zone Recherche.

  3. Dans la liste de résultats, sélectionnez Microsoft Azure Notification Hubs, puis Installer. Procédez à l’installation, puis fermez la fenêtre du Gestionnaire de package NuGet.

    Cette action ajoute une référence au Kit de développement logiciel (SDK) Azure Notification Hubs à l’aide du package NuGet Microsoft.Azure.Notification Hubs.

  4. Créez un nouveau fichier de classe qui représente la connexion avec le hub de notification utilisé pour envoyer des notifications. Dans l’Explorateur de solutions, cliquez avec le bouton droit sur le dossier Modèles, sélectionnez Ajouter, puis Classe. Nommez la nouvelle classe Notifications.cs, puis sélectionnez Ajouter pour générer la classe.

    Fenêtre Ajouter un nouvel élément

  5. Dans Notifications.cs, ajoutez l’instruction using suivante en haut du fichier :

    using Microsoft.Azure.NotificationHubs;
    
  6. Remplacez la définition de classe Notifications par le code suivant et les deux espaces réservés par la chaîne de connexion (avec accès complet) de votre centre Notification Hubs et le nom du hub (disponible sur le Portail Azure) :

    public class Notifications
    {
        public static Notifications Instance = new Notifications();
    
        public NotificationHubClient Hub { get; set; }
    
        private Notifications() {
            Hub = NotificationHubClient.CreateClientFromConnectionString("<your hub's DefaultFullSharedAccessSignature>",
                                                                            "<hub name>");
        }
    }
    

    Important

    Entrez le nom et la DefaultFullSharedAccessSignature de votre hub avant de continuer.

  7. Ensuite, créez un contrôleur nommé RegisterController. Dans l’Explorateur de solutions, cliquez avec le bouton droit sur le dossier Contrôleurs, sélectionnez Ajouter, puis Contrôleur.

  8. Sélectionnez Contrôleur API - Vide, puis Ajouter.

  9. Dans la boîte Nom du contrôleur, tapez RegisterController pour nommer la nouvelle classe, puis sélectionnez Ajouter.

    Fenêtre Ajouter un contrôleur.

  10. Dans RegisterController.cs, ajoutez les instructions using suivantes :

    using Microsoft.Azure.NotificationHubs;
    using Microsoft.Azure.NotificationHubs.Messaging;
    using AppBackend.Models;
    using System.Threading.Tasks;
    using System.Web;
    
  11. Ajoutez le code suivant dans la définition de classe RegisterController . Dans ce code, vous ajoutez une balise d’utilisateur pour l’utilisateur attaché à HttpContext. L’utilisateur a été authentifié et attaché à HttpContext par le filtre de messages que vous avez ajouté, AuthenticationTestHandler. Vous pouvez également ajouter des contrôles facultatifs afin de vérifier que l’utilisateur dispose des droits d’inscription nécessaires pour les balises requises.

    private NotificationHubClient hub;
    
    public RegisterController()
    {
        hub = Notifications.Instance.Hub;
    }
    
    public class DeviceRegistration
    {
        public string Platform { get; set; }
        public string Handle { get; set; }
        public string[] Tags { get; set; }
    }
    
    // POST api/register
    // This creates a registration id
    public async Task<string> Post(string handle = null)
    {
        string newRegistrationId = null;
    
        // make sure there are no existing registrations for this push handle (used for iOS and Android)
        if (handle != null)
        {
            var registrations = await hub.GetRegistrationsByChannelAsync(handle, 100);
    
            foreach (RegistrationDescription registration in registrations)
            {
                if (newRegistrationId == null)
                {
                    newRegistrationId = registration.RegistrationId;
                }
                else
                {
                    await hub.DeleteRegistrationAsync(registration);
                }
            }
        }
    
        if (newRegistrationId == null) 
            newRegistrationId = await hub.CreateRegistrationIdAsync();
    
        return newRegistrationId;
    }
    
    // PUT api/register/5
    // This creates or updates a registration (with provided channelURI) at the specified id
    public async Task<HttpResponseMessage> Put(string id, DeviceRegistration deviceUpdate)
    {
        RegistrationDescription registration = null;
        switch (deviceUpdate.Platform)
        {
            case "mpns":
                registration = new MpnsRegistrationDescription(deviceUpdate.Handle);
                break;
            case "wns":
                registration = new WindowsRegistrationDescription(deviceUpdate.Handle);
                break;
            case "apns":
                registration = new AppleRegistrationDescription(deviceUpdate.Handle);
                break;
            case "fcm":
                registration = new FcmRegistrationDescription(deviceUpdate.Handle);
                break;
            default:
                throw new HttpResponseException(HttpStatusCode.BadRequest);
        }
    
        registration.RegistrationId = id;
        var username = HttpContext.Current.User.Identity.Name;
    
        // add check if user is allowed to add these tags
        registration.Tags = new HashSet<string>(deviceUpdate.Tags);
        registration.Tags.Add("username:" + username);
    
        try
        {
            await hub.CreateOrUpdateRegistrationAsync(registration);
        }
        catch (MessagingException e)
        {
            ReturnGoneIfHubResponseIsGone(e);
        }
    
        return Request.CreateResponse(HttpStatusCode.OK);
    }
    
    // DELETE api/register/5
    public async Task<HttpResponseMessage> Delete(string id)
    {
        await hub.DeleteRegistrationAsync(id);
        return Request.CreateResponse(HttpStatusCode.OK);
    }
    
    private static void ReturnGoneIfHubResponseIsGone(MessagingException e)
    {
        var webex = e.InnerException as WebException;
        if (webex.Status == WebExceptionStatus.ProtocolError)
        {
            var response = (HttpWebResponse)webex.Response;
            if (response.StatusCode == HttpStatusCode.Gone)
                throw new HttpRequestException(HttpStatusCode.Gone.ToString());
        }
    }
    
  12. Enregistrez vos modifications.

Envoyer des notifications depuis le serveur principal WebAPI

Dans cette section, vous ajoutez un nouveau contrôleur qui montre aux appareils clients comment envoyer une notification. La notification se base sur la balise du nom d’utilisateur qui utilise la bibliothèque .NET du service d’Azure Notification Hubs dans le serveur principal WebAPI ASP.NET.

  1. Créez un nouveau contrôleur nommé NotificationsController, de la même façon que vous avez créé RegisterController dans la section précédente.

  2. Dans NotificationsController.cs, ajoutez les instructions using suivantes :

    using AppBackend.Models;
    using System.Threading.Tasks;
    using System.Web;
    
  3. Ajoutez la méthode suivante à la classe NotificationsController :

    Ce code envoie un type de notification basé sur le paramètre pns du service de notification de plateforme. La valeur de to_tag permet de définir la balise username sur le message. Cette balise doit correspondre à une balise de nom d’utilisateur d’une inscription de hub de notification active. Le message de notification est extrait du corps de la demande POST et mis en forme pour le PNS cible.

    Selon le service Platform Notification Service (PNS) que vos appareils pris en charge utilisent pour recevoir des notifications, ces dernières sont prises en charge dans plusieurs formats. Par exemple sur des appareils Windows, vous pouvez utiliser une notification toast avec WNS qui n’est pas directement prise en charge par un autre service PNS. Dans une instance de ce type, votre serveur principal doit formater la notification dans un format pris en charge pour le service PNS des appareils que vous envisagez de prendre en charge. Utilisez ensuite l’API d’envoi appropriée sur la classe NotificationHubClient.

    public async Task<HttpResponseMessage> Post(string pns, [FromBody]string message, string to_tag)
    {
        var user = HttpContext.Current.User.Identity.Name;
        string[] userTag = new string[2];
        userTag[0] = "username:" + to_tag;
        userTag[1] = "from:" + user;
    
        Microsoft.Azure.NotificationHubs.NotificationOutcome outcome = null;
        HttpStatusCode ret = HttpStatusCode.InternalServerError;
    
        switch (pns.ToLower())
        {
            case "wns":
                // Windows 8.1 / Windows Phone 8.1
                var toast = @"<toast><visual><binding template=""ToastText01""><text id=""1"">" + 
                            "From " + user + ": " + message + "</text></binding></visual></toast>";
                outcome = await Notifications.Instance.Hub.SendWindowsNativeNotificationAsync(toast, userTag);
                break;
            case "apns":
                // iOS
                var alert = "{\"aps\":{\"alert\":\"" + "From " + user + ": " + message + "\"}}";
                outcome = await Notifications.Instance.Hub.SendAppleNativeNotificationAsync(alert, userTag);
                break;
            case "fcm":
                // Android
                var notif = "{ \"data\" : {\"message\":\"" + "From " + user + ": " + message + "\"}}";
                outcome = await Notifications.Instance.Hub.SendFcmNativeNotificationAsync(notif, userTag);
                break;
        }
    
        if (outcome != null)
        {
            if (!((outcome.State == Microsoft.Azure.NotificationHubs.NotificationOutcomeState.Abandoned) ||
                (outcome.State == Microsoft.Azure.NotificationHubs.NotificationOutcomeState.Unknown)))
            {
                ret = HttpStatusCode.OK;
            }
        }
    
        return Request.CreateResponse(ret);
    }
    
  4. Appuyez sur la touche F5 pour exécuter l’application et vérifier le travail que vous avez accompli jusqu’à présent. L’application ouvre un navigateur web, qui s’affiche sur la page d’accueil ASP.NET.

Publication du nouveau serveur principal WebAPI

Ensuite, vous déployez l’application sur un site web Azure afin de la rendre accessible à tous les appareils.

  1. Cliquez avec le bouton droit sur le projet AppBackend, puis sélectionnez Publier.

  2. Sélectionnez Microsoft Azure App Service comme cible de publication, puis cliquez sur \*\*Publier. La fenêtre Créer App Service s’ouvre. Vous pouvez créer toutes les ressources Azure nécessaires pour exécuter l’application web ASP.NET dans Azure.

    Vignette Microsoft Azure App Service

  3. Dans la fenêtre Créer App Service, sélectionnez votre compte Azure. Sélectionnez Modifier le type>Application web. Conservez le nom de l’application web par défaut et sélectionnez l’abonnement, le groupe de ressources et le plan App Service.

  4. Sélectionnez Create (Créer).

  5. Notez la valeur de la propriété URL du site dans la section Résumé. Cette URL constitue le point de terminaison de votre serveur principal plus loin dans ce didacticiel.

  6. Sélectionnez Publier.

Après en avoir terminé avec l’Assistant, il publie l’application web ASP.NET dans Azure, puis ouvre l’application dans le navigateur par défaut. Votre application est visible dans Azure App Services.

L’URL utilise le nom de l’application web que vous avez spécifié précédemment, au format http://<app_name>.azurewebsites.net.

Mettre à jour le code pour le client UWP

Dans cette section, vous mettez à jour le code du projet que vous avez terminé pour le Tutoriel : Envoyer des notifications vers des applications de plateforme Windows universelle avec Azure Notification Hubs. Le projet doit déjà être associé au Windows store. Il doit également être configuré pour utiliser votre hub de notification. Dans cette section, vous allez ajouter du code pour appeler le nouveau serveur principal WebAPI et l’utiliser pour l’enregistrement et l’envoi de notifications.

  1. Dans Visual Studio, ouvrez la solution que vous avez créée pour le Tutoriel : Envoyer des notifications vers des applications de plateforme Windows universelle avec Azure Notification Hubs.

  2. Dans l’Explorateur de solutions, cliquez avec le bouton droit sur le projet Plateforme Windows universelle, puis cliquez sur Gérer les packages NuGet.

  3. Sur le côté gauche, sélectionnez Parcourir.

  4. Dans la zone Rechercher, entrez Client Http.

  5. Dans la liste des résultats, cliquez sur System.Net.Http, puis cliquez sur Installer. Terminez l'installation.

  6. De retour dans la zone Recherche NuGet, tapez Json.net. Installez le package Newtonsoft.json , puis fermez la fenêtre du Gestionnaire de package NuGet.

  7. Dans l’Explorateur de solutions, dans le projet WindowsApp, double-cliquez sur MainPage.xaml pour l’ouvrir dans l’éditeur de Visual Studio.

  8. Dans le fichier MainPage.xaml, remplacez la section <Grid> par le code suivant : Ce code ajoute une zone de texte Nom d’utilisateur et Mot de passe pour l’authentification de l’utilisateur. Il ajoute également des zones de texte pour le message de notification et la balise de nom d’utilisateur qui doivent recevoir la notification :

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
    
        <TextBlock Grid.Row="0" Text="Notify Users" HorizontalAlignment="Center" FontSize="48"/>
    
        <StackPanel Grid.Row="1" VerticalAlignment="Center">
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="Auto"/>
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition></ColumnDefinition>
                    <ColumnDefinition></ColumnDefinition>
                    <ColumnDefinition></ColumnDefinition>
                </Grid.ColumnDefinitions>
                <TextBlock Grid.Row="0" Grid.ColumnSpan="3" Text="Username" FontSize="24" Margin="20,0,20,0"/>
                <TextBox Name="UsernameTextBox" Grid.Row="1" Grid.ColumnSpan="3" Margin="20,0,20,0"/>
                <TextBlock Grid.Row="2" Grid.ColumnSpan="3" Text="Password" FontSize="24" Margin="20,0,20,0" />
                <PasswordBox Name="PasswordTextBox" Grid.Row="3" Grid.ColumnSpan="3" Margin="20,0,20,0"/>
    
                <Button Grid.Row="4" Grid.ColumnSpan="3" HorizontalAlignment="Center" VerticalAlignment="Center"
                            Content="1. Login and register" Click="LoginAndRegisterClick" Margin="0,0,0,20"/>
    
                <ToggleButton Name="toggleWNS" Grid.Row="5" Grid.Column="0" HorizontalAlignment="Right" Content="WNS" IsChecked="True" />
                <ToggleButton Name="toggleFCM" Grid.Row="5" Grid.Column="1" HorizontalAlignment="Center" Content="FCM" />
                <ToggleButton Name="toggleAPNS" Grid.Row="5" Grid.Column="2" HorizontalAlignment="Left" Content="APNS" />
    
                <TextBlock Grid.Row="6" Grid.ColumnSpan="3" Text="Username Tag To Send To" FontSize="24" Margin="20,0,20,0"/>
                <TextBox Name="ToUserTagTextBox" Grid.Row="7" Grid.ColumnSpan="3" Margin="20,0,20,0" TextWrapping="Wrap" />
                <TextBlock Grid.Row="8" Grid.ColumnSpan="3" Text="Enter Notification Message" FontSize="24" Margin="20,0,20,0"/>
                <TextBox Name="NotificationMessageTextBox" Grid.Row="9" Grid.ColumnSpan="3" Margin="20,0,20,0" TextWrapping="Wrap" />
                <Button Grid.Row="10" Grid.ColumnSpan="3" HorizontalAlignment="Center" Content="2. Send push" Click="PushClick" Name="SendPushButton" />
            </Grid>
        </StackPanel>
    </Grid>
    
  9. Dans l’Explorateur de solutions, ouvrez le fichier MainPage.xaml.cs pour les projets (Windows 8.1) et (Windows Phone 8.1) . Ajoutez les instructions using suivantes au début des deux fichiers :

    using System.Net.Http;
    using Windows.Storage;
    using System.Net.Http.Headers;
    using Windows.Networking.PushNotifications;
    using Windows.UI.Popups;
    using System.Threading.Tasks;
    
  10. Dans MainPage.xaml.cs pour le projet WindowsApp, ajoutez le membre suivant à la classe MainPage. Remplacez bien <Enter Your Backend Endpoint> par le point de terminaison réel de votre serveur principal, obtenu précédemment. Par exemple : http://mybackend.azurewebsites.net.

    private static string BACKEND_ENDPOINT = "<Enter Your Backend Endpoint>";
    
  11. Ajoutez le code ci-dessous à la classe MainPage dans MainPage.xaml.cs pour les projets (Windows 8.1) et (Windows Phone 8.1) .

    La méthode PushClick correspond au gestionnaire de clic du bouton Envoyer des notifications Push . Elle appelle le serveur principal pour déclencher une notification vers tous les appareils avec une balise de nom d’utilisateur correspondant au paramètre to_tag . Le message de notification est envoyé en tant que contenu JSON dans le corps de la demande.

    La méthode LoginAndRegisterClick correspond au gestionnaire de clic du bouton Se connecter et s’inscrire. Elle stocke le jeton d’authentification de base (représente n’importe quel jeton utilisé par votre système d’authentification) dans un stockage local, puis utilise RegisterClient pour l’inscription aux notifications à l’aide du serveur principal.

    private async void PushClick(object sender, RoutedEventArgs e)
    {
        if (toggleWNS.IsChecked.Value)
        {
            await sendPush("wns", ToUserTagTextBox.Text, this.NotificationMessageTextBox.Text);
        }
        if (toggleFCM.IsChecked.Value)
        {
            await sendPush("fcm", ToUserTagTextBox.Text, this.NotificationMessageTextBox.Text);
        }
        if (toggleAPNS.IsChecked.Value)
        {
            await sendPush("apns", ToUserTagTextBox.Text, this.NotificationMessageTextBox.Text);
    
        }
    }
    
    private async Task sendPush(string pns, string userTag, string message)
    {
        var POST_URL = BACKEND_ENDPOINT + "/api/notifications?pns=" +
            pns + "&to_tag=" + userTag;
    
        using (var httpClient = new HttpClient())
        {
            var settings = ApplicationData.Current.LocalSettings.Values;
            httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", (string)settings["AuthenticationToken"]);
    
            try
            {
                await httpClient.PostAsync(POST_URL, new StringContent("\"" + message + "\"",
                    System.Text.Encoding.UTF8, "application/json"));
            }
            catch (Exception ex)
            {
                MessageDialog alert = new MessageDialog(ex.Message, "Failed to send " + pns + " message");
                alert.ShowAsync();
            }
        }
    }
    
    private async void LoginAndRegisterClick(object sender, RoutedEventArgs e)
    {
        SetAuthenticationTokenInLocalStorage();
    
        var channel = await PushNotificationChannelManager.CreatePushNotificationChannelForApplicationAsync();
    
        // The "username:<user name>" tag gets automatically added by the message handler in the backend.
        // The tag passed here can be whatever other tags you may want to use.
        try
        {
            // The device handle used is different depending on the device and PNS.
            // Windows devices use the channel uri as the PNS handle.
            await new RegisterClient(BACKEND_ENDPOINT).RegisterAsync(channel.Uri, new string[] { "myTag" });
    
            var dialog = new MessageDialog("Registered as: " + UsernameTextBox.Text);
            dialog.Commands.Add(new UICommand("OK"));
            await dialog.ShowAsync();
            SendPushButton.IsEnabled = true;
        }
        catch (Exception ex)
        {
            MessageDialog alert = new MessageDialog(ex.Message, "Failed to register with RegisterClient");
            alert.ShowAsync();
        }
    }
    
    private void SetAuthenticationTokenInLocalStorage()
    {
        string username = UsernameTextBox.Text;
        string password = PasswordTextBox.Password;
    
        var token = Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(username + ":" + password));
        ApplicationData.Current.LocalSettings.Values["AuthenticationToken"] = token;
    }
    
  12. Ouvrez App.xaml.cs et recherchez l’appel vers InitNotificationsAsync() dans le gestionnaire d’événements OnLaunched(). Commentez ou supprimez l’appel vers InitNotificationsAsync(). Le gestionnaire de bouton initialise les inscriptions aux notifications :

    protected override void OnLaunched(LaunchActivatedEventArgs e)
    {
        //InitNotificationsAsync();
    
  13. Cliquez avec le bouton droit sur le projet WindowsApp, cliquez sur Ajouter, puis cliquez sur Classe. Nommez la classe RegisterClient.cs, puis cliquez sur OK pour générer la classe.

    Cette classe encapsule les appels REST nécessaires pour contacter le service principal de l'application et inscrire cette dernière pour les notifications Push. Il enregistre également en local les informations registrationIds créées par le hub de notification, comme expliqué dans la rubrique Inscription auprès du serveur principal de votre application. Il utilise un jeton d'autorisation qui se trouve dans le stockage local lorsque vous cliquez sur le bouton Se connecter et s'inscrire.

  14. Ajoutez les instructions using suivantes au début du fichier RegisterClient.cs :

    using Windows.Storage;
    using System.Net;
    using System.Net.Http;
    using System.Net.Http.Headers;
    using Newtonsoft.Json;
    using System.Threading.Tasks;
    using System.Linq;
    
  15. Ajoutez le code suivant dans la définition de classe RegisterClient :

    private string POST_URL;
    
    private class DeviceRegistration
    {
        public string Platform { get; set; }
        public string Handle { get; set; }
        public string[] Tags { get; set; }
    }
    
    public RegisterClient(string backendEndpoint)
    {
        POST_URL = backendEndpoint + "/api/register";
    }
    
    public async Task RegisterAsync(string handle, IEnumerable<string> tags)
    {
        var regId = await RetrieveRegistrationIdOrRequestNewOneAsync();
    
        var deviceRegistration = new DeviceRegistration
        {
            Platform = "wns",
            Handle = handle,
            Tags = tags.ToArray<string>()
        };
    
        var statusCode = await UpdateRegistrationAsync(regId, deviceRegistration);
    
        if (statusCode == HttpStatusCode.Gone)
        {
            // regId is expired, deleting from local storage & recreating
            var settings = ApplicationData.Current.LocalSettings.Values;
            settings.Remove("__NHRegistrationId");
            regId = await RetrieveRegistrationIdOrRequestNewOneAsync();
            statusCode = await UpdateRegistrationAsync(regId, deviceRegistration);
        }
    
        if (statusCode != HttpStatusCode.Accepted && statusCode != HttpStatusCode.OK)
        {
            // log or throw
            throw new System.Net.WebException(statusCode.ToString());
        }
    }
    
    private async Task<HttpStatusCode> UpdateRegistrationAsync(string regId, DeviceRegistration deviceRegistration)
    {
        using (var httpClient = new HttpClient())
        {
            var settings = ApplicationData.Current.LocalSettings.Values;
            httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", (string) settings["AuthenticationToken"]);
    
            var putUri = POST_URL + "/" + regId;
    
            string json = JsonConvert.SerializeObject(deviceRegistration);
                            var response = await httpClient.PutAsync(putUri, new StringContent(json, Encoding.UTF8, "application/json"));
            return response.StatusCode;
        }
    }
    
    private async Task<string> RetrieveRegistrationIdOrRequestNewOneAsync()
    {
        var settings = ApplicationData.Current.LocalSettings.Values;
        if (!settings.ContainsKey("__NHRegistrationId"))
        {
            using (var httpClient = new HttpClient())
            {
                httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", (string)settings["AuthenticationToken"]);
    
                var response = await httpClient.PostAsync(POST_URL, new StringContent(""));
                if (response.IsSuccessStatusCode)
                {
                    string regId = await response.Content.ReadAsStringAsync();
                    regId = regId.Substring(1, regId.Length - 2);
                    settings.Add("__NHRegistrationId", regId);
                }
                else
                {
                    throw new System.Net.WebException(response.StatusCode.ToString());
                }
            }
        }
        return (string)settings["__NHRegistrationId"];
    
    }
    
  16. Enregistrez toutes vos modifications.

Tester l'application

  1. Lancez l’application sur chaque Windows.

  2. Entrez un Nom d’utilisateur et un Mot de passe, comme indiqué dans l’écran ci-dessous. Ces informations d’identification doivent différer du nom d’utilisateur et du mot de passe entrés sur Windows Phone.

  3. Cliquez sur Se connecter et s’inscrire et vérifiez le contenu de la boîte de dialogue indiquant que vous êtes connecté. Ce code active également le bouton Envoyer des notifications Push.

    Capture d’écran de l’application Notification Hubs montrant le nom d’utilisateur et le mot de passe renseignés.

  4. Puis, dans le champ Balise de nom d’utilisateur, entrez le nom d’utilisateur enregistré. Entrez un message de notification, puis cliquez sur Envoyer des notifications Push.

  5. Seuls les appareils enregistrés avec la balise de nom d’utilisateur correspondant reçoivent le message de notification.

    Capture d’écran de l’application Notification Hubs montrant le message ayant fait l’objet d’un envoi (push).

Étapes suivantes

Dans ce tutoriel, vous avez appris à envoyer des notifications Push à des utilisateurs spécifiques ayant des balises associées à leurs enregistrements. Pour savoir comment envoyer des notifications basées sur l’emplacement, passez au tutoriel suivant :