Uso di Hub di notifica di Azure per inviare notifiche agli utenti con back-end.NET

Panoramica

Il supporto per le notifiche push in Azure consente di accedere a un'infrastruttura push facile da usare, multipiattaforma e con scalabilità orizzontale, che semplifica considerevolmente l'implementazione delle notifiche push sia per le applicazioni consumer sia per quelle aziendali per piattaforme mobili. In questa esercitazione viene illustrato come usare Hub di notifica di Azure per inviare notifiche push a un utente specifico dell'app su un dispositivo specifico. Un back-end WebAPI ASP.NET viene usato per autenticare i client. Usando l’utente client autenticato, un tag viene aggiunto automaticamente dal back-end per la registrazione delle notifiche. Questo tag viene usato per l’invio tramite il back-end per generare notifiche per un utente specifico. Per altre informazioni sulla registrazione per le notifiche tramite il back-end di un'app, vedere l'argomento della guida Registrazione dal back-end dell'app. Questa esercitazione si basa sull'hub di notifica e sul progetto creato nell'esercitazione Introduzione ad Hub di notifica .

È inoltre propedeutica all'esercitazione Push sicuro . Dopo avere eseguito i passaggi indicati in questa esercitazione, è possibile passare all'esercitazione Push sicuro , che illustra come modificare il codice in questa esercitazione per inviare una notifica push in modo sicuro.

Prima di iniziare

I commenti e suggerimenti inviati seriamente verranno presi in considerazione. Se si riscontrano difficoltà nel completare questo argomento o si hanno suggerimenti per migliorarne il contenuto, è possibile lasciare un commento nella parte inferiore della pagina.

Il codice completo per questa esercitazione è disponibile su GitHub qui.

Prerequisiti

Prima di iniziare questa esercitazione, è necessario aver già completato queste esercitazioni su Servizi mobili:

Nota

Se si usano app per dispositivi mobili nel servizio app di Azure, vedere la versione per App per dispositivi mobili di questa esercitazione.

 

Creare il progetto WebAPI

Le sezioni successive illustrano la creazione di un nuovo back-end WebAPI ASP.NET. Questo processo ha tre obiettivi principali:

  • Autenticare i client: si aggiungerà un gestore di messaggi per autenticare le richieste client e associare l'utente alla richiesta.

  • Eseguire la registrazione per le notifiche usando il back-end WebAPI: si aggiungerà un controller per gestire le nuove registrazioni e consentire a un dispositivo client di ricevere le notifiche. Il nome utente autenticato verrà aggiunto automaticamente alla registrazione come tag.

  • Inviare notifiche ai client: si aggiungerà anche un controller per consentire agli utenti di attivare un push sicuro per i dispositivi e i client associati al tag.

Creare un nuovo back-end WebAPI ASP.NET seguendo questa procedura:

Importante

Se si usa Visual Studio 2015 o una versione precedente, prima di procedere con l'esercitazione verificare di avere installato la versione più recente di Gestione pacchetti NuGet per Visual Studio.

A questo scopo, avviare Visual Studio. Scegliere Estensioni e aggiornamenti dal menu Strumenti. Cercare Gestione pacchetti NuGet nella versione di Visual Studio e verificare che sia installata la versione più recente. Se la versione installata non è la più recente, disinstallarla e reinstallare Gestione pacchetti NuGet.

Nota

Assicurarsi che sia installato Visual Studio Azure SDK per la distribuzione del sito Web.

  1. Avviare Visual Studio o Visual Studio Express.

  2. Selezionare Esplora server e accedere all'account Azure. Per creare le risorse del sito Web nell'account è necessario eseguire l'accesso.

  3. In Visual Studio selezionare File > Nuovo > Progetto, espandere Modelli, espandere Visual C# e quindi selezionare Web e Applicazione Web ASP.NET.

  4. Nella casella Nome digitare AppBackend e quindi selezionare OK.

    Finestra Nuovo progetto

  5. Nella finestra Nuovo progetto ASP.NET selezionare la casella di controllo API Web e quindi selezionare OK.

    Finestra Nuovo progetto ASP.NET

  6. Selezionare una sottoscrizione nella finestra Configura app Web di Microsoft Azure e nell'elenco Piano di Servizio app eseguire una di queste operazioni:

    • Selezionare un piano di servizio app creato in precedenza.
    • Selezionare Crea un nuovo piano di servizio app e quindi creare un piano.

    Per questa esercitazione non è necessario disporre di un database. Dopo aver selezionato il piano di servizio app, fare clic su OK per creare il progetto.

    Finestra Configura app Web di Microsoft Azure

Autenticare client con il back-end WebAPI

In questa sezione si creerà una nuova classe del gestore di messaggi denominata AuthenticationTestHandler per il nuovo back-end. Questa classe deriva da DelegatingHandler e viene aggiunta come gestore di messaggi per poter elaborare tutte le richieste in arrivo nel back-end.

  1. In Esplora soluzioni fare clic con il pulsante destro del mouse sul progetto AppBackend, scegliere Aggiungi e quindi selezionare Classe.

  2. Assegnare alla nuova classe il nome AuthenticationTestHandler.cs e fare clic su Aggiungi per generarla. Questa classe autentica gli utenti tramite l'autenticazione di base. L'app può usare qualsiasi schema di autenticazione.

  3. In AuthenticationTestHandler.cs aggiungere le istruzioni using seguenti:

     using System.Net.Http;
     using System.Threading;
     using System.Security.Principal;
     using System.Net;
     using System.Text;
     using System.Threading.Tasks;
    
  4. In AuthenticationTestHandler.cs sostituire la definizione di classe AuthenticationTestHandler con il codice seguente:

    Questo gestore autorizza la richiesta quando le tre condizioni seguenti sono vere:

    • La richiesta include un'intestazione di autorizzazione.
    • La richiesta usa l'autenticazione di base .
    • La stringa del nome utente corrisponde alla stringa della password.

    In caso contrario, la richiesta verrà rifiutata. Non si tratta di un vero approccio di autenticazione e autorizzazione. È solo un esempio molto semplice per questa esercitazione.

    Se il messaggio di richiesta viene autenticato e autorizzato da AuthenticationTestHandler, l'utente dell'autenticazione di base viene associato alla richiesta corrente in HttpContext. Le informazioni utente in HttpContext verranno usate da un altro controller (RegisterController) in un secondo momento per aggiungere un tag alla richiesta di registrazione per le notifiche.

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

    Nota

    Nota sulla sicurezza: la classe AuthenticationTestHandler non fornisce un'effettiva autenticazione. Viene usata solo per imitare l'autenticazione di base e non è sicura. È necessario implementare un meccanismo di autenticazione sicuro nelle applicazioni e nei servizi di produzione.

  5. Per registrare il gestore di messaggi aggiungere il codice seguente alla fine del metodo Register nella classe App_Start/WebApiConfig.cs:

     config.MessageHandlers.Add(new AuthenticationTestHandler());
    
  6. Salvare le modifiche.

Eseguire la registrazione per le notifiche tramite il back-end WebAPI

In questa sezione si aggiungerà un nuovo controller al back-end WebAPI per gestire le richieste di registrazione di un utente e un dispositivo per le notifiche tramite la libreria client per gli hub di notifica. Il controller aggiunge un tag user per l'utente che è stato autenticato e collegato a HttpContext da AuthenticationTestHandler. Il tag avrà il formato della stringa, "username:<actual username>".

  1. In Esplora soluzioni fare clic con il pulsante destro del mouse sul progetto AppBackend e quindi scegliere Gestisci pacchetti NuGet.

  2. Nel riquadro sinistro selezionare Online e nella casella Cerca digitare Microsoft.Azure.NotificationHubs.

  3. Nell'elenco dei risultati fare clic su Hub di notifica di Microsoft Azure e quindi selezionare Installa. Completare l'installazione e quindi chiudere la finestra di Gestione pacchetti NuGet.

    Questa azione aggiunge un riferimento ad Azure Notification Hubs SDK usando il pacchetto NuGet Microsoft.Azure.NotificationHubs.

  4. Creare un nuovo file di classe che rappresenta la connessione con l'hub di notifica usato per inviare le notifiche. In Esplora soluzioni fare clic con il pulsante destro del mouse sulla cartella Modelli, scegliere Aggiungi e quindi fare clic su Classe. Assegnare alla nuova classe il nome Notifications.cs e quindi selezionare Aggiungi per generarla.

    Finestra Aggiungi nuovo elemento

  5. In Notifications.cs aggiungere l'istruzione using seguente all'inizio del file:

     using Microsoft.Azure.NotificationHubs;
    
  6. Sostituire la definizione di classe Notifications con il codice seguente e sostituire i due segnaposto con la stringa di connessione (con accesso completo) per l'hub di notifica e con il nome dell'hub disponibile nel portale di Azure classico:

     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>");
         }
     }
    
  7. Creare quindi un nuovo controller denominato RegisterController. In Esplora soluzioni fare clic con il pulsante destro del mouse sulla cartella Controller, scegliere Aggiungi e quindi fare clic su Controller.

  8. Fare clic su Controller Web API 2 - Vuoto e selezionare Aggiungi.

    Finestra Aggiungi scaffolding

  9. Nella casella Nome controller digitare RegisterController per assegnare un nome alla nuova classe, quindi selezionare Aggiungi.

    Finestra Aggiungi controller

  10. In RegisterController.cs aggiungere le istruzioni using seguenti:

    using Microsoft.Azure.NotificationHubs;
    using Microsoft.Azure.NotificationHubs.Messaging;
    using AppBackend.Models;
    using System.Threading.Tasks;
    using System.Web;
    
  11. Aggiungere il codice seguente all'interno della definizione di classe RegisterController . Si noti che in questo codice viene aggiunto un tag user per l'utente associato a HttpContext. L'utente è stato autenticato e associato a HttpContext dal filtro messaggi aggiunto, AuthenticationTestHandler. È anche possibile aggiungere controlli facoltativi per verificare che l'utente disponga dei diritti per la registrazione per i tag richiesti.

    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 "gcm":
                registration = new GcmRegistrationDescription(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. Salvare le modifiche.

Inviare notifiche dal back-end WebAPI

In questa sezione si aggiunge un nuovo controller che consente ai dispositivi client di inviare una notifica. La notifica si basa sul tag username che usa la libreria di gestione del servizio Hub di notifica di Azure nel back-end WebAPI ASP.NET.

  1. Creare un altro nuovo controller denominato NotificationsController seguendo la stessa procedura usata per creare RegisterController nella sezione precedente.

  2. In NotificationsController.cs aggiungere le istruzioni using seguenti:

     using AppBackend.Models;
     using System.Threading.Tasks;
     using System.Web;
    
  3. Aggiungere il metodo seguente alla classe NotificationsController:

    Questo codice invia un tipo di notifica basato sul parametro pns del servizio di notifica della piattaforma (PNS). Il valore to_tag viene usato per impostare il tag username nel messaggio. Questo tag deve corrispondere a un tag username di una registrazione dell'hub di notifica attiva. Il messaggio di notifica viene estratto dal corpo della richiesta POST ed è formattato per il PNS di destinazione.

    A seconda del servizio di notifica della piattaforma (PNS) usato dai dispositivi supportati per ricevere le notifiche, sono supportate notifiche in una serie di formati. Nei dispositivi Windows è ad esempio possibile usare una notifica di tipo avviso popup con WNS che non è supportata direttamente da un altro PNS. In tal caso, il back-end deve formattare la notifica come notifica supportata per il PNS dei dispositivi che si intende supportare. Usare quindi l'API di invio appropriata per 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 "gcm":
                 // Android
                 var notif = "{ \"data\" : {\"message\":\"" + "From " + user + ": " + message + "\"}}";
                 outcome = await Notifications.Instance.Hub.SendGcmNativeNotificationAsync(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. Premere F5 per eseguire l'applicazione e verificare l'accuratezza del lavoro svolto sinora. L'app apre un Web browser e viene visualizzata nella home page di ASP.NET.

Pubblicare il nuovo back-end WebAPI

L'app verrà ora distribuita in un sito Web Azure per renderla accessibile da tutti i dispositivi.

  1. Fare clic con il pulsante destro del mouse sul progetto AppBackend e scegliere Pubblica.

  2. Selezionare Servizio app di Microsoft Azure come destinazione di pubblicazione e quindi fare clic su Pubblica.
    Verrà visualizzata la finestra Crea servizio app. Qui è possibile creare tutte le risorse di Azure necessarie per eseguire l'app Web ASP.NET in Azure.

    Riquadro Servizio app di Microsoft Azure

  3. Nella finestra Crea servizio app selezionare l'account Azure. Selezionare Modifica tipo > App Web. Mantenere il valore di Nome app Web predefinito e selezionare la sottoscrizione, il gruppo di risorse e il piano di servizio app.

  4. Selezionare Crea.

  5. Prendere nota della proprietà URL sito nella scheda Riepilogo. Questo URL sarà l'endpoint back-end più avanti nell'esercitazione.

  6. Selezionare Pubblica.

Al termine della procedura guidata, l'app Web ASP.NET viene pubblicata in Azure e aperta nel browser predefinito. L'applicazione sarà visibile in Servizi app di Azure.

L'URL usa il nome dell'app Web specificato in precedenza, con il formato http://<nome_app>.azurewebsites.net.

Aggiornare il codice per il progetto client

In questa sezione viene aggiornato il codice nel progetto completato per l’esercitazione Introduzione ad Hub di notifica . Il codice dovrebbe essere già associato allo store e configurato per l'hub di notifica. In questa sezione si aggiungerà il codice per chiamare il nuovo back-end WebAPI e si userà tale codice per la registrazione e l'invio di notifiche.

  1. In Visual Studio, aprire la soluzione creata per l’esercitazione Introduzione ad Hub di notifica .
  2. In Esplora soluzioni fare clic con il pulsante destro del mouse sul progetto (Windows 8.1), quindi scegliere Gestisci pacchetti NuGet.
  3. Sul lato sinistro fare clic su Online.
  4. Nella casella di ricerca digitare Client Http.
  5. Nell'elenco dei risultati fare clic su Librerie client HTTP Microsoft e quindi su Installa. Completare l'installazione.
  6. Di nuovo nella casella di ricerca di NuGet digitare Json.net. Installare il pacchetto Json.NET , quindi chiudere la finestra di Gestione pacchetti NuGet.
  7. Ripetere i passaggi precedenti per il progetto (Windows Phone 8.1) al fine di installare il pacchetto NuGet JSON.NET per il progetto Windows Phone.
  8. In Esplora soluzioni, nel progetto (Windows 8.1), fare doppio clic su MainPage.xaml per aprirlo nell'editor di Visual Studio.
  9. Nel codice XML MainPage.xaml sostituire la sezione <Grid> con il codice seguente. Questo codice consente di aggiungere una casella di testo con nome utente e password con cui l'utente eseguirà l'autenticazione. Consente inoltre di aggiungere caselle di testo per il messaggio di notifica e il tag del nome utente che deve ricevere la notifica:

     <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="toggleGCM" Grid.Row="5" Grid.Column="1" HorizontalAlignment="Center" Content="GCM" />
                 <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>
    
  10. In Esplora soluzioni, nel progetto (Windows Phone 8.1), aprire MainPage.xaml e sostituire la sezione <Grid> di Windows Phone 8.1 con lo stesso codice riportato in precedenza. L’interfaccia dovrebbe essere simile a quanto illustrato nella figura seguente.

  11. In Esplora soluzioni aprire il file MainPage.xaml.cs per i progetti (Windows 8.1) e (Windows Phone 8.1). Aggiungere le istruzioni using seguenti all'inizio del file:

    using System.Net.Http;
    using Windows.Storage;
    using System.Net.Http.Headers;
    using Windows.Networking.PushNotifications;
    using Windows.UI.Popups;
    using System.Threading.Tasks;
    
  12. In MainPage.xaml.cs, per i progetti (Windows 8.1) e (Windows Phone 8.1), aggiungere il seguente membro alla classe MainPage. Assicurarsi di sostituire <Enter Your Backend Endpoint> con l'endpoint back-end effettivo ottenuto in precedenza: ad esempio http://mybackend.azurewebsites.net.

    private static string BACKEND_ENDPOINT = "<Enter Your Backend Endpoint>";
    
  13. Aggiungere il codice seguente alla classe MainPage in MainPage.xaml.cs per i progetti (Windows 8.1) e (Windows Phone 8.1).

    Il metodo PushClick è il gestore di clic per il pulsante Send Push . Chiama il back-end per attivare una notifica a tutti i dispositivi con un tag di nome utente corrispondente al parametro to_tag . Il messaggio di notifica viene inviato come contenuto JSON nel corpo della richiesta.

    Il metodo LoginAndRegisterClick è il gestore di clic per il pulsante Log in and register . Tale metodo memorizza il token di autenticazione di base nell'archivio locale (si noti che rappresenta qualsiasi token usato dallo schema di autenticazione), quindi usa RegisterClient per la registrazione per le notifiche tramite il back-end.

    private async void PushClick(object sender, RoutedEventArgs e)
    {
        if (toggleWNS.IsChecked.Value)
        {
            await sendPush("wns", ToUserTagTextBox.Text, this.NotificationMessageTextBox.Text);
        }
        if (toggleGCM.IsChecked.Value)
        {
            await sendPush("gcm", 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 will be 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;
    }
    
  14. In Esplora soluzioni, nel progetto Condiviso, aprire il file App.xaml.cs. Individuare la chiamata a InitNotificationsAsync() in the OnLaunched() . Impostare come commento o eliminare la chiamata a InitNotificationsAsync(). Il gestore del pulsante aggiunto in precedenza inizializzerà le registrazioni delle notifiche.

     protected override void OnLaunched(LaunchActivatedEventArgs e)
     {
         //InitNotificationsAsync();
    
  15. In Esplora soluzioni fare clic con il pulsante destro del mouse sul progetto Condiviso, quindi scegliere Aggiungi e infine Classe. Assegnare alla classe il nome RegisterClient.cs, quindi fare clic su OK per generare la classe.

    Questa classe conclude le chiamate REST necessarie per contattare il back-end dell'app allo scopo di effettuare la registrazione per le notifiche push. Archivia inoltre in locale i registrationId creati dall'hub di notifica, come illustrato in Registrazione dal back-end dell'app. Si noti che usa un token di autorizzazione memorizzato nell'archivio locale quando si fa clic sul pulsante Esegui accesso e registrazione .

  16. Aggiungere le seguenti istruzioni using all'inizio del file 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;
    
  17. Aggiungere il codice seguente all'interno della definizione di 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)
        {
            // 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"];
    
    }
    
  18. Salvare tutte le modifiche.

Test dell'applicazione

  1. Avviare l'applicazione in Windows 8.1 e Windows Phone 8.1. Per Windows Phone 8.1 è possibile eseguire l'istanza nell'emulatore o in un dispositivo reale.
  2. Nell'istanza di Windows 8.1 dell'app immettere un Nome utente e una Password come illustrato nella schermata riportata di seguito. È consigliabile immettere un nome utente e una password diversi dal nome utente e dalla password immessi in Windows Phone.
  3. Fare clic su Log in and register e verificare nella relativa finestra di dialogo di avere effettuato l'accesso. In questo modo anche il pulsante Send Push verrà abilitato.

  4. Nell'istanza di Windows Phone 8.1 immettere la stringa di un nome utente nei campi Nome utente e Password quini fare clic su Log in and register.
  5. Quindi nel campo relativo al tag del nome utente del destinatario immettere il nome utente registrato in Windows 8.1. Immettere un messaggio di notifica e fare clic su Send Push.

  6. Solo i dispositivi registrati con il tag del nome utente del destinatario riceveranno il messaggio di notifica.

Passaggi successivi