Kurz: Zasílání oznámení konkrétním uživatelům službou Azure Notification Hubs

Přehled

Tento kurz popisuje, jak používat Azure Notification Hubs k odesílání nabízených oznámení konkrétnímu uživateli aplikace na konkrétním zařízení. K ověřování klientů se používá back-end ASP.NET WebAPI. Když back-end ověří uživatele klientské aplikace, automaticky přidá značku k registraci oznámení. Back-end tuto značku používá k posílání oznámení konkrétnímu uživateli.

Poznámka

Dokončený kód pro tento kurz najdete na GitHubu.

V tomto kurzu provedete následující kroky:

  • Vytvoření projektu WebAPI
  • Ověřování klientů v back-endu WebAPI
  • Registrace k oznámením pomocí back-endu WebAPI
  • Odesílání oznámení z back-endu WebAPI
  • Publikování nového back-endu WebAPI
  • Aktualizace kódu klientského projektu
  • Testování aplikace

Požadavky

V tomto kurzu se používá centrum oznámení a projekt sady Visual Studio, které jste vytvořili v kurzu Zasílání oznámení do aplikací pro Univerzální platformu Windows službou Azure Notification Hubs. Proto ho dokončete před zahájením tohoto kurzu.

Poznámka

Pokud jako back-endovou službu používáte Mobile Apps ve službě Azure App Service, prostudujte si část Verze Mobile Apps tohoto kurzu.

Vytvoření projektu WebAPI

Následující části popisují vytvoření nového back-endu ASP.NET WebAPI. Tento proces má tři hlavní účely:

  • Ověřování klientů: Přidáte popisovač zprávy, který bude ověřovat požadavky klientů a přiřazovat uživatele k požadavkům.
  • Registrace k oznámením pomocí back-endu WebAPI: Přidáte kontroler, který bude zpracovávat nové registrace klientských zařízení k přijímání oznámení. Ověřené uživatelské jméno se automaticky přidá do registrace jako značka.
  • Odesílání oznámení klientům: Přidáte kontroler, který uživatelům umožní aktivovat zabezpečené nabízení do zařízení a klientů přidružených ke značce.

Pomocí následujících akcí vytvořte nový back-end webového rozhraní API ASP.NET Core 6.0:

Pokud to chcete zkontrolovat, spusťte sadu Visual Studio. V nabídce Nástroje vyberte Rozšíření a aktualizace. Vyhledejte Správce balíčků NuGet ve vaší verzi sady Visual Studio a ujistěte se, že máte nejnovější verzi. Pokud vaše verze není nejnovější verzí, odinstalujte ji a pak znovu nainstalujte Správce balíčků NuGet.

Snímek obrazovky s dialogovým oknem Rozšíření a Aktualizace se zvýrazněnou možností Spravovat balíček NuGet pro balíček Visual Studios

Poznámka

Ujistěte se, že jste nainstalovali sadu Visual Studio Azure SDK pro nasazení webu.

  1. Spusťte sadu Visual Studio nebo Visual Studio Express.

  2. Vyberte Průzkumník serveru a přihlaste se ke svému účtu Azure. Abyste mohli vytvářet prostředky webu, musíte být přihlášení.

  3. V nabídce Soubor sady Visual Studio vyberte Nový>projekt.

  4. Do vyhledávacího pole zadejte Webové rozhraní API .

  5. Vyberte šablonu projektu webového rozhraní API ASP.NET Core a vyberte Další.

  6. V dialogovém okně Konfigurace nového projektu pojmenujte projekt AppBackend a vyberte Další.

  7. V dialogovém okně Další informace :

    • Ověřte, že je rozhraní .NET 6.0 (dlouhodobá podpora).
    • Ověřte, že je zaškrtnuté políčko Používat kontrolery (zrušte zaškrtnutí, pokud chcete použít minimální počet rozhraní API).
    • Zrušte zaškrtnutí políčka Povolit podporu OpenAPI.
    • Vyberte Vytvořit.

Odebrání souborů šablon WeatherForecast

  1. Z nového projektu AppBackend odeberte ukázkové soubory WeatherForecast.cs a Controllers/WeatherForecastController.cs.
  2. Otevřete Properties\launchSettings.json.
  3. Změňte vlastnosti launchUrl z weatherforcast na appbackend.

V okně Konfigurovat webovou aplikaci Microsoft Azure vyberte předplatné a pak v seznamu Plán služby App Service proveďte jednu z následujících akcí:

  • Vyberte plán Azure App Service, který jste už vytvořili.
  • Vyberte možnost Vytvořit nový plán App Service a pak tento plán vytvořte.

Pro účely tohoto kurzu nepotřebujete databázi. Jakmile vyberete plán služby App Service, výběrem OK vytvořte projekt.

Okno Konfigurovat webovou aplikaci Microsoft Azure

Pokud tuto stránku pro konfiguraci plánu služby App Service nevidíte, pokračujte kurzem. Můžete ho nakonfigurovat při pozdějším publikování aplikace.

Ověřování klientů v back-endu WebAPI

V této části vytvoříte pro nový back-end novou třídu popisovače zprávy AuthenticationTestHandler. Tato třída je odvozená od třídy DelegatingHandler a přidaná jako popisovač zprávy, aby mohla zpracovávat všechny požadavky přicházející na back-end.

  1. V Průzkumníku řešení klikněte pravým tlačítkem na projekt AppBackend, vyberte Přidat a pak vyberte Třída.

  2. Pojmenujte novou třídu AuthenticationTestHandler.cs a pak ji výběrem Přidat vygenerujte. Tato třída bude pro zjednodušení ověřovat uživatele pomocí základního ověřování. Vaše aplikace může používat jakékoli schéma ověřování.

  3. V souboru AuthenticationTestHandler.cs přidejte následující příkazy using:

    using System.Net.Http;
    using System.Threading;
    using System.Security.Principal;
    using System.Net;
    using System.Text;
    using System.Threading.Tasks;
    
  4. V souboru AuthenticationTestHandler.cs nahraďte definici třídy AuthenticationTestHandler následujícím kódem:

    Tato obslužná rutina ověří požadavek při splnění těchto tří podmínek:

    • Požadavek obsahuje autorizační hlavičku.
    • Požadavek používá základní ověřování.
    • Řetězce uživatelského jména a hesla jsou stejné.

    Jinak bude požadavek zamítnut. Při tomto ověření se nepoužívá správný přístup k ověřování a autorizaci. Je to jenom jednoduchý příklad pro účely tohoto kurzu.

    Pokud třída AuthenticationTestHandler ověří a autorizuje zprávu požadavku, uživatel základního ověřování se připojí k aktuálnímu požadavku v objektu HttpContext. Informace o uživateli v objektu HttpContext později použije jiný kontroler (RegisterController) pro přidání značky do požadavku na registraci oznámení.

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

    Poznámka

    Poznámka k zabezpečení: Třída AuthenticationTestHandler nezajišťuje skutečné ověřování. Používá se pouze k napodobení základního ověřování a není bezpečná. Ve svých produkčních aplikacích a službách musíte implementovat mechanismus zabezpečeného ověřování.

  5. Pokud chcete zaregistrovat obslužnou rutinu zprávy, přidejte do souboru Program.cs na konec Register metody následující kód:

    config.MessageHandlers.Add(new AuthenticationTestHandler());
    
  6. Uložte provedené změny.

Registrace k oznámením pomocí back-endu WebAPI

V této části přidáte do back-endu WebAPI nový kontroler, který bude zpracovávat požadavky na registraci uživatele a zařízení k oznámením pomocí klientské knihovny pro centra oznámení. Kontroler přidá značku uživatele pro uživatele, který byl ověřen a připojen k objektu HttpContext třídou AuthenticationTestHandler. Značka bude mít formát řetězce "username:<actual username>".

  1. V Průzkumníku řešení klikněte pravým tlačítkem na projekt AppBackend a pak vyberte Spravovat balíčky NuGet.

  2. V levém podokně vyberte Online a pak do pole Hledat zadejte Microsoft.Azure.NotificationHubs.

  3. V seznamu výsledků vyberte Microsoft Azure Notification Hubs a pak vyberte Nainstalovat. Dokončete instalaci a pak zavřete okno Správce balíčků NuGet.

    Tato akce přidá referenci na sadu SDK služby Azure Notification Hubs pomocí balíčku NuGet Microsoft.Azure.Notification Hubs.

  4. Vytvořte nový soubor třídy, která představuje propojení s centrem událostí sloužícím k odesílání oznámení. V Průzkumníku řešení klikněte pravým tlačítkem na složku Modely, vyberte Přidat a pak vyberte Třída. Pojmenujte novou třídu Notifications.cs a pak ji výběrem Přidat vygenerujte.

    Okno Přidat novou položku

  5. Na začátek souboru Notifications.cs přidejte následující příkaz using:

    using Microsoft.Azure.NotificationHubs;
    
  6. Nahraďte definici třídy Notifications následujícím kódem a nahraďte dva zástupné symboly připojovacím řetězcem (pro úplný přístup) vašeho centra událostí a názvem centra (najdete ho na webu Azure Portal):

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

    Důležité

    Než budete pokračovat, zadejte název a defaultFullSharedAccessSignature vašeho centra.

  7. Dále vytvořte nový kontroler RegisterController. V Průzkumníku řešení klikněte pravým tlačítkem na složku Kontrolery, vyberte Přidat a pak vyberte Kontroler.

  8. Vyberte Kontroler rozhraní API – prázdný a pak vyberte Přidat.

  9. Do pole Název kontroleru zadejte RegisterController a pojmenujte tak novou třídu, pak vyberte Přidat.

    Okno Přidat kontroler

  10. V souboru RegisterController.cs přidejte následující příkazy using:

    using Microsoft.Azure.NotificationHubs;
    using Microsoft.Azure.NotificationHubs.Messaging;
    using AppBackend.Models;
    using System.Threading.Tasks;
    using System.Web;
    
  11. Do definice třídy RegisterController přidejte následující kód. V tomto kódu přidáváte značku uživatele pro uživatele, který je připojený k objektu HttpContext. Tento uživatel byl ověřen a připojen k objektu HttpContext filtrem zpráv AuthenticationTestHandler, který jste vytvořili. Můžete také přidat volitelné kontroly pro ověření, že uživatel má práva pro registraci k požadovaným značkám.

    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. Uložte provedené změny.

Odesílání oznámení z back-endu WebAPI

V této části přidáte nový kontroler, který zveřejňuje způsob odesílání oznámení klientskými zařízeními. Oznámení je založené na značce uživatelského jména, kterou používá knihovna .NET Notification Hubs v back-endu ASP.NET WebAPI.

  1. Vytvořte další nový kontroler NotificationsController stejným způsobem, kterým jste v předchozí části vytvořili RegisterController.

  2. V souboru NotificationsController.cs přidejte následující příkazy using:

    using AppBackend.Models;
    using System.Threading.Tasks;
    using System.Web;
    
  3. Do třídy NotificationsController přidejte následující metodu:

    Tento kód odesílá typ oznámení na základě parametru pns systému oznámení platformy. Hodnota to_tag slouží k nastavení značky username (uživatelské jméno) pro zprávu. Tato značka musí odpovídat značce uživatelského jména aktivní registrace k centru událostí. Zpráva oznámení se přetáhne z textu požadavku POST a naformátuje se pro cílový systém oznámení platformy.

    V závislosti na systému oznámení platformy, který vaše zařízení používá k přijímání oznámení, jsou podporována oznámení v různých formátech. Například na zařízeních s Windows byste mohli použít informační zprávu pomocí Služby nabízených oznámení Windows, kterou ostatní systémy oznámení platformy přímo nepodporují. V takovém případě musí váš back-end formátovat oznámení na podporované oznámení pro systémy oznámení platformy zařízení, která chcete podporovat. Ve třídě NotificationHubClient pak použijte vhodné rozhraní API pro odesílání.

    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. Stisknutím klávesy F5 aplikaci spusťte a ověřte, že jste zatím postupovali správně. Aplikace otevře webový prohlížeč a zobrazí se na domovské stránce ASP.NET.

Publikování nového back-endu WebAPI

Dále tuto aplikaci nasadíte na web Azure, aby byla přístupná ze všech zařízení.

  1. Klikněte pravým tlačítkem na projekt AppBackend a vyberte Publikovat.

  2. Jako cíl publikování vyberte Microsoft Azure App Service a pak vyberte \*\*Publikovat. Otevře se okno Vytvořit plán App Service. Tady můžete vytvořit všechny prostředky Azure, které jsou potřeba ke spuštění webové aplikace ASP.NET v Azure.

    Dlaždice Microsoft Azure App Service

  3. V okně Vytvořit plán App Service vyberte váš účet Azure. Vyberte Změnit typ>webové aplikace. Ponechejte výchozí Název webové aplikace a vyberte Předplatné, Skupinu prostředků a Plán služby App Service.

  4. Vyberte Vytvořit.

  5. Poznamenejte si vlastnost Adresa URL webu v části Souhrn. Tato adresa URL je váš koncový bod back-endu, který použijete později v tomto kurzu.

  6. Vyberte Publikovat.

Průvodce po dokončení publikuje webovou aplikaci ASP.NET do Azure a pak tuto aplikaci otevře ve výchozím prohlížeči. Vaši aplikaci bude možné zobrazit ve službě Azure App Service.

Adresa URL používá název webové aplikace, který jste zadali dříve, ve formátu http://< app_name.azurewebsites.net>.

Aktualizace kódu pro klienta UPW

V této části aktualizujete kód v projektu, který jste vytvořili v kurzu Zasílání oznámení do aplikací pro Univerzální platformu Windows službou Azure Notification Hubs. Projekt už by měl být přidružený k Windows Storu. Také už by měl být nakonfigurovaný tak, aby používal vaše centrum oznámení. V této části přidáte kód, který volá nový back-end WebAPI a používá ho k registraci a zasílání oznámení.

  1. V sadě Visual Studio otevřete řešení, které jste vytvořili v rámci kurzu Zasílání oznámení do aplikací pro Univerzální platformu Windows službou Azure Notification Hubs.

  2. V Průzkumník řešení klikněte pravým tlačítkem na projekt Univerzální platforma Windows (UPW) a pak klikněte na Spravovat balíčky NuGet.

  3. Na levé straně vyberte Procházet.

  4. Do pole Hledat zadejte Http Client.

  5. V seznamu výsledků klikněte na System.Net.Http a pak klikněte na Nainstalovat. Dokončete instalaci.

  6. Vraťte se do pole Hledat pro balíčky NuGet a zadejte Json.net. Nainstalujte balíček Newtonsoft.json a pak zavřete okno Správce balíčků NuGet.

  7. V Průzkumníku řešení v projektu WindowsApp dvakrát klikněte na soubor MainPage.xaml a otevřete ho v editoru Visual Studio.

  8. MainPage.xaml V souboru nahraďte <Grid> oddíl následujícím kódem: Tento kód přidá textové pole pro uživatelské jméno a heslo, pomocí kterého se uživatel ověřuje. Přidá také textová pole pro zprávu s oznámením a značku uživatelského jména, která by měla oznámení obdržet:

    <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. V Průzkumník řešení otevřete MainPage.xaml.cs soubor pro projekty (Windows 8.1) a (Windows Phone 8.1). Na začátek obou souborů přidejte následující příkazy using:

    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. V MainPage.xaml.cs projektu WindowsApp přidejte do třídy následující člena MainPage . Nezapomeňte nahradit <Enter Your Backend Endpoint> skutečným koncovým bodem vašeho back-endu, který jste předtím získali. Například, http://mybackend.azurewebsites.net.

    private static string BACKEND_ENDPOINT = "<Enter Your Backend Endpoint>";
    
  11. Přidejte následující kód do třídy MainPage v MainPage.xaml.cs pro projekty (Windows 8.1) a (Windows Phone 8.1).

    Metoda PushClick je obslužná rutina události kliknutí pro tlačítko Send Push (Odeslat nabízené oznámení). Metoda volá back-end za účelem aktivace odeslání oznámení do všech zařízení, jejichž značka uživatelského jména odpovídá parametru to_tag. Zpráva oznámení se odešle jako obsah JSON v textu požadavku.

    Metoda LoginAndRegisterClick je obslužná rutina události kliknutí pro tlačítko Login and register (Přihlášení a registrace). Metoda do místního úložiště uloží základní autorizační token (reprezentuje jakýkoli token, který používá vaše schéma autorizace) a pak pomocí metody RegisterClient provede registraci oznámení v back-endu.

    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. Otevřete App.xaml.cs a vyhledejte volání InitNotificationsAsync() v obslužné rutině OnLaunched() události. Okomentujte nebo odstraňte volání metody InitNotificationsAsync(). Obslužná rutina tlačítka inicializuje registrace oznámení:

    protected override void OnLaunched(LaunchActivatedEventArgs e)
    {
        //InitNotificationsAsync();
    
  13. Klikněte pravým tlačítkem na projekt WindowsApp, Přidat a potom na Třída. Pojmenujte třídu RegisterClient.csa potom kliknutím na OK vygenerujte třídu.

    Tato třída zabalí potřebná volání REST ke kontaktování back-endu aplikace za účelem registrace nabízených oznámení. Kromě toho místně ukládá ID registrací vytvořená centrem oznámení, jak je podrobně popsáno v tématu popisujícím registraci z back-endu aplikace. Po kliknutí na tlačítko Login and register (Přihlášení a registrace) použije autorizační token uložený v místním úložišti.

  14. Na začátek souboru RegisterClient.cs přidejte následující příkazy using:

    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. Do definice třídy přidejte následující kód 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. Uložte všechny provedené změny.

Test aplikace

  1. Spusťte aplikaci v obou systémech Windows.

  2. Zadejte Username (Uživatelské jméno) a Password (Heslo), jak je znázorněno na následující obrazovce. Zadané hodnoty by se měly lišit od uživatelského jména a hesla, které jste zadali na Windows Phone.

  3. Klikněte na Login and register (Přihlášení a registrace) a ověřte, že se zobrazí dialogové okno s oznámením o přihlášení. Tento kód také aktivuje tlačítko Send Push (Odeslat nabízené oznámení).

    Snímek obrazovky aplikace Notification Hubs s vyplněným uživatelským jménem a heslem

  4. Dále do pole Recipient Username Tag (Značka uživatelského jména příjemce) zadejte zaregistrované uživatelské jméno. Zadejte zprávu oznámení a klikněte na Send Push (Odeslat nabízené oznámení).

  5. Zprávu oznámení obdrží pouze zařízení, která se zaregistrovala s použitím odpovídající značky uživatelského jména.

    Snímek obrazovky aplikace Notification Hubs zobrazující zprávu, která se odeslala

Další kroky

V tomto kurzu jste zjistili, jak posílat nabízená oznámení konkrétním uživatelům, k jejichž registracím jsou přidružené značky. V dalším kurzu se dozvíte, jak posílat nabízená oznámení na základě polohy: