Руководство по Отправка уведомлений определенным пользователям с помощью службы "Центры уведомлений Azure"Tutorial: Send notifications to specific users by using Azure Notification Hubs

ОбзорOverview

В этом учебнике показано, как использовать концентраторы уведомлений Azure для отправки push-уведомлений пользователю определенного приложения на конкретном устройстве.This tutorial shows you how to use Azure Notification Hubs to send push notifications to a specific app user on a specific device. Для проверки подлинности клиентов используется серверная часть веб-API ASP.NET.An ASP.NET WebAPI backend is used to authenticate clients. Когда серверная часть проверяет подлинность пользователя клиентского приложения, к регистрации уведомления автоматически добавляется тег.When the backend authenticates a client application user, it automatically adds a tag to the notification registration. Серверная часть использует этот тег для отправки уведомлений определенному пользователю.The backend uses this tag to send notifications to the specific user.

Примечание

Полный код для этого руководства можно найти на GitHub.The completed code for this tutorial can be found on GitHub.

При работе с этим руководством вы выполните следующие задачи:In this tutorial, you take the following steps:

  • Создание проекта веб-APICreate the WebAPI project
  • Аутентификация клиентов в серверной части веб-API.Authenticate clients to the WebAPI backend
  • Регистрация для получения уведомлений с помощью серверной части веб-API.Register for notifications by using the WebAPI backend
  • Отправка уведомлений из серверной части веб-API.Send notifications from the WebAPI backend
  • Публикация новой серверной части веб-API.Publish the new WebAPI backend
  • Обновите код для клиентского проектаUpdate the code for the client project
  • Тестирование приложенияTest the application

Предварительные требованияPrerequisites

В этом руководстве используется центр уведомлений и проект Visual Studio, который вы создали при работе с руководством по отправке уведомлений в приложения универсальной платформы Windows с использованием Центров уведомлений Azure.This tutorial builds on the notification hub and Visual Studio project that you created in the Tutorial: Send notifications to Universal Windows Platform apps by using Azure Notification Hubs tutorial. Выполните инструкции в том руководстве, прежде чем приступать к текущему.Therefore, complete it before starting on this tutorial.

Примечание

Если вы используете мобильные приложения в службе приложений Azure в качестве внутренней службы, то перейдите к версии этого учебника для мобильных приложений.If you are using Mobile Apps in Azure App Service as your backend service, see the Mobile Apps version of this tutorial.

Создание проекта веб-APICreate the WebAPI project

В этой статье описывается создание серверной части веб-API ASP.NET.The following sections discuss the creation of a new ASP.NET WebAPI backend. Этот процесс состоит из трех главных задач.This process has three main purposes:

  • Аутентификация клиентов. Вы добавите обработчик сообщений для аутентификации клиентских запросов и связывания пользователя с запросом.Authenticate clients: You add a message handler to authenticate client requests and associate the user with the request.
  • Регистрация для получения уведомлений с помощью серверной части веб-API. Вы добавите контроллер для обработки новых регистраций клиентских устройств для получения уведомлений.Register for notifications by using the WebAPI backend: You add a controller to handle new registrations for a client device to receive notifications. Имя пользователя, прошедшего аутентификацию, автоматически добавляется в регистрацию как тег.The authenticated username is automatically added to the registration as a tag.
  • Отправка уведомлений клиентам. Вы также добавите контроллер, который позволит активировать безопасную отправку push-уведомлений устройствам и клиентам, связанным с тегом.Send notifications to clients: You add a controller to provide a way for users to trigger a secure push to devices and clients associated with the tag.

Чтобы создать серверную часть веб-API ASP.NET, сделайте следующее:Create the new ASP.NET WebAPI backend by doing the following actions:

Важно!

Если вы используете Visual Studio 2015 или более ранние версии, перед работой с этим руководством установите последнюю версию диспетчера пакетов NuGet для Visual Studio.If you are using Visual Studio 2015 or earlier, before starting this tutorial, ensure that you have installed the latest version of NuGet Package Manager for Visual Studio.

Чтобы проверить, запустите Visual Studio.To check, start Visual Studio. Откройте меню Средства и выберите пункт Расширения и обновления.On the Tools menu, select Extensions and Updates. Найдите диспетчер пакетов NuGet в своей версии Visual Studio и убедитесь, что у вас установлена последняя версия.Search for NuGet Package Manager in your version of Visual Studio, and make sure you have the latest version. Если вы используете не последнюю версию, удалите ее, а затем переустановите диспетчер пакетов NuGet.If your version is not the latest version, uninstall it, and then reinstall the NuGet Package Manager.

Примечание

Убедитесь, что вы установили пакет SDK для Azure для Visual Studio, используемый для развертывания веб-сайта.Make sure you have installed the Visual Studio Azure SDK for website deployment.

  1. Запустите Visual Studio или Visual Studio Express.Start Visual Studio or Visual Studio Express.

  2. Щелкните Обозреватель серверов и войдите в свою учетную запись Azure.Select Server Explorer, and sign in to your Azure account. Чтобы создать ресурсы веб-сайта в своей учетной записи, вы должны войти.To create the web site resources on your account, you must be signed in.

  3. В Visual Studio щелкните правой кнопкой мыши решение Visual Studio и последовательно выберите Добавить и Новый проект.In Visual Studio, right-click Visual Studio solution, point to Add, and click New Project.

  4. Разверните узел Visual C# , выберите Веб и щелкните Веб-приложение ASP.NET.Expand Visual C#, select Web, and click ASP.NET Web Application.

  5. В поле Имя введите AppBackend, а затем нажмите кнопку ОК.In the Name box, type AppBackend, and then select OK.

    Окно создания проекта

  6. В окне Создание проекта ASP.NET установите флажок Веб-API, а затем нажмите кнопку ОК.In the New ASP.NET Project window, select the Web API check box, and then select OK.

    Окно создания проекта ASP.NET

  7. В окне Настройка веб-приложения Microsoft Azure выберите подписку, а затем в списке План службы приложений выполните одно из следующих действий:In the Configure Microsoft Azure Web App window, select a subscription and then, in the App Service plan list, do either of the following actions:

    • Выберите план службы приложений, который вы уже создали.Select an app service plan that you've already created.
    • Выберите Создать план служб приложений, а затем создайте его.Select Create a new app service plan, and then create one.

    База данных для этого руководства не требуется.You do not need a database for this tutorial. Выбрав план служб приложений, нажмите кнопку ОК, чтобы создать проект.After you have selected your app service plan, select OK to create the project.

    Диалоговое окно "Настройка веб-приложения Microsoft Azure"

    Если вы не видите эту страницу для настройки плана службы приложений, продолжайте выполнять руководство.If you don't see this page for configure app service plan, continue with the tutorial. Его можно настроить позднее при публикации приложения.You can configure it while publishing the app later.

Аутентификация клиентов в серверной части веб-API.Authenticate clients to the WebAPI backend

В этом разделе вы создадите класс обработчика сообщений с именем AuthenticationTestHandler для новой серверной части.In this section, you create a new message-handler class named AuthenticationTestHandler for the new backend. Этот класс является производным от DelegatingHandler. Он добавляется в качестве обработчика сообщений, чтобы обрабатывать все запросы, поступающие в серверную часть.This class is derived from DelegatingHandler and added as a message handler so that it can process all requests that come into the backend.

  1. В обозревателе решений щелкните правой кнопкой мыши проект AppBackend, выберите Добавить, а затем щелкните Класс.In Solution Explorer, right-click the AppBackend project, select Add, and then select Class.

  2. Присвойте новому классу имя AuthenticationTestHandler.cs и нажмите кнопку Добавить, чтобы создать класс.Name the new class AuthenticationTestHandler.cs, and then select Add to generate the class. Этот класс используется для аутентификации пользователей с помощью обычной проверки подлинности для простоты.This class authenticates users by using Basic Authentication for simplicity. Ваше приложение может использовать любую схему аутентификации.Your app can use any authentication scheme.

  3. В AuthenticationTestHandler.cs добавьте следующие операторы using :In AuthenticationTestHandler.cs, add the following using statements:

    using System.Net.Http;
    using System.Threading;
    using System.Security.Principal;
    using System.Net;
    using System.Text;
    using System.Threading.Tasks;
    
  4. В классе AuthenticationTestHandler.cs замените определение AuthenticationTestHandler следующим кодом:In AuthenticationTestHandler.cs, replace the AuthenticationTestHandler class definition with the following code:

    Обработчик авторизует запрос, если выполнены все три следующих условия:The handler authorizes the request when the following three conditions are true:

    • Запрос включен в заголовок авторизации.The request includes an Authorization header.
    • Запрос использует обычную проверку подлинности.The request uses basic authentication.
    • Строка имени пользователя и строка пароля являются одной стройкой.The user name string and the password string are the same string.

    В противном случае запрос отклоняется.Otherwise, the request is rejected. Этот способ аутентификации нельзя назвать настоящим методом аутентификации и авторизации.This authentication is not a true authentication and authorization approach. Это простой пример для этого руководства.It is only a simple example for this tutorial.

    Если сообщение запроса аутентифицируется и авторизуется AuthenticationTestHandler, пользователь обычной проверки подлинности подключается к текущему запросу в HttpContext.If the request message is authenticated and authorized by AuthenticationTestHandler, the basic authentication user is attached to the current request on HttpContext. Позднее информацию о пользователе в HttpContext будет использовать другой контроллер (RegisterController), чтобы добавить тег в запрос на регистрацию для получения уведомлений.User information in HttpContext will be used by another controller (RegisterController) later to add a tag to the notification registration request.

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

    Примечание

    Примечание о безопасности. Класс AuthenticationTestHandler не обеспечивает настоящую аутентификацию.Security note: The AuthenticationTestHandler class does not provide true authentication. Этот класс используется лишь для имитации базовой проверки подлинности и не является безопасным.It is used only to mimic basic authentication and is not secure. В реальных приложениях и службах необходимо реализовать безопасный механизм проверки подлинности.You must implement a secure authentication mechanism in your production applications and services.

  5. Чтобы зарегистрировать обработчик событий, добавьте в конец метода Register в классе App_Start/WebApiConfig.cs следующий код:To register the message handler, add the following code at the end of the Register method in the App_Start/WebApiConfig.cs class:

    config.MessageHandlers.Add(new AuthenticationTestHandler());
    
  6. Сохраните изменения.Save your changes.

Регистрация для получения уведомлений с помощью серверной части веб-API.Register for notifications by using the WebAPI backend

В этом разделе вы добавите новый контроллер в серверную часть веб-API, которая будет обрабатывать запросы на регистрацию пользователя и устройства для получения уведомлений с помощью клиентской библиотеки центров уведомлений.In this section, you add a new controller to the WebAPI backend to handle requests to register a user and a device for notifications by using the client library for notification hubs. Контроллер будет добавлять тег пользователя для пользователя, который прошел аутентификацию и подключен к HttpContext с помощью AuthenticationTestHandler.The controller adds a user tag for the user that was authenticated and attached to HttpContext by AuthenticationTestHandler. Тег имеет формат строки: "username:<actual username>".The tag has the string format, "username:<actual username>".

  1. В обозревателе решений щелкните правой кнопкой мыши проект AppBackend и выберите пункт Управление пакетами NuGet.In Solution Explorer, right-click the AppBackend project and then select Manage NuGet Packages.

  2. На панели слева выберите В сети, затем в поле поиска введите Microsoft.Azure.NotificationHubs.In the left pane, select Online and then, in the Search box, type Microsoft.Azure.NotificationHubs.

  3. В списке результатов выберите Центры уведомлений Microsoft Azure, а затем нажмите кнопку Установить.In the results list, select Microsoft Azure Notification Hubs, and then select Install. Завершите установку и закройте окно диспетчера пакетов NuGet.Complete the installation, and then close the NuGet Package Manager window.

    Это действие добавляет ссылку на пакет SDK для Центров уведомлений Azure с помощью пакета NuGet Microsoft.Azure.Notification Hubs.This action adds a reference to the Azure Notification Hubs SDK by using the Microsoft.Azure.Notification Hubs NuGet package.

  4. Создайте файл класса, представляющий подключение к концентратору уведомлений, который используется для отправки уведомлений.Create a new class file that represents the connection with the notification hub that's used to send notifications. В обозревателе решений щелкните правой кнопкой мыши папку Модели, выберите Добавить, а затем щелкните Класс.In Solution Explorer, right-click the Models folder, select Add, and then select Class. Назовите новый класс Notifications.cs и нажмите кнопку Добавить, чтобы создать класс.Name the new class Notifications.cs, and then select Add to generate the class.

    Окно добавления нового элемента

  5. В Notifications.cs добавьте следующий оператор using в начало файла:In Notifications.cs, add the following using statement at the top of the file:

    using Microsoft.Azure.NotificationHubs;
    
  6. Замените определение класса Notifications следующим кодом и замените два заполнителя строкой подключения (с полным доступом) для своего концентратора уведомлений и именем концентратора (доступно на портале Azure):Replace the Notifications class definition with the following code, and replace the two placeholders with the connection string (with full access) for your notification hub and the hub name (available at 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>");
        }
    }
    

    Важно!

    Прежде чем продолжить, введите имя и DefaultFullSharedAccessSignature вашего концентратора.Enter the name and the DefaultFullSharedAccessSignature of your hub before proceeding further.

  7. Теперь создайте новый контроллер с именем RegisterController.Next, create a new controller named RegisterController. В обозревателе решений щелкните правой кнопкой мыши папку Контроллеры, выберите Добавить, а затем щелкните Контроллер.In Solution Explorer, right-click the Controllers folder, select Add, and then select Controller.

  8. Щелкните элемент Контроллер Web API 2 — пустой и нажмите кнопку Добавить.Select Web API 2 Controller - Empty, and then select Add.

    Окно добавления шаблона

  9. В поле Имя контроллера введите имя нового класса RegisterController, а затем нажмите кнопку Добавить.In the Controller name box, type RegisterController to name the new class, and then select Add.

    Окно добавления контроллера

  10. В RegiterController.cs добавьте следующие операторы using :In RegisterController.cs, add the following using statements:

    using Microsoft.Azure.NotificationHubs;
    using Microsoft.Azure.NotificationHubs.Messaging;
    using AppBackend.Models;
    using System.Threading.Tasks;
    using System.Web;
    
  11. Добавьте в определение класса RegisterController следующий код:Add the following code inside the RegisterController class definition. В этом коде вы добавите тег для пользователя, который подключен к HttpContext.In this code, you add a user tag for the user that's attached to HttpContext. Пользователь прошел аутентификацию и подключен к HttpContext с помощью добавленного фильтра сообщений AuthenticationTestHandler.The user was authenticated and attached to HttpContext by the message filter that you added, AuthenticationTestHandler. Вы можете также добавить дополнительные проверки, чтобы убедиться, что у пользователя есть право регистрации запрошенных тегов.You can also add optional checks to verify that the user has rights to register for the requested tags.

    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. Сохраните изменения.Save your changes.

Отправка уведомлений из серверной части веб-API.Send notifications from the WebAPI backend

В этом разделе вы добавите новый контроллер, который позволяет клиентским устройствам отправлять уведомления.In this section, you add a new controller that exposes a way for client devices to send a notification. Уведомление основано на теге имени пользователя, который использует библиотеку .NET центров уведомлений Azure в серверной части веб-API ASP.NET.The notification is based on the username tag that uses Azure Notification Hubs .NET Library in the ASP.NET WebAPI backend.

  1. Создайте еще один контроллер с именем NotificationsController так же, как вы создали RegisterController в предыдущем разделе.Create another new controller named NotificationsController the same way you created RegisterController in the previous section.

  2. В NotificationsController.cs добавьте следующие операторы using :In NotificationsController.cs, add the following using statements:

    using AppBackend.Models;
    using System.Threading.Tasks;
    using System.Web;
    
  3. Добавьте следующий метод в класс NotificationsController:Add the following method to the NotificationsController class:

    Этот код отправляет тип уведомлений, основанный на параметре pns системы отправки уведомлений платформы (PNS).This code sends a notification type that's based on the Platform Notification Service (PNS) pns parameter. Значение to_tag используется для задания тега имени пользователя в сообщении.The value of to_tag is used to set the username tag on the message. Этот тег должен соответствовать тегу имени пользователя активной регистрации центра уведомлений.This tag must match a username tag of an active notification hub registration. Сообщение уведомления извлекается из текста запроса POST и форматируется для целевого PNS.The notification message is pulled from the body of the POST request and formatted for the target PNS.

    Поддержка форматов уведомлений зависит от того, какую систему PNS используют поддерживаемые устройства.Depending on the PNS that your supported devices use to receive notifications, the notifications are supported by a variety of formats. Например, на устройствах Windows можно использовать всплывающие уведомления с помощью WNS, которые не поддерживает другая система PNS.For example, on Windows devices, you might use a toast notification with WNS that isn't directly supported by another PNS. В этом случае серверная часть решения конвертирует уведомление в формат, соответствующий PNS устройств, которые вы планируете поддерживать.In such an instance, your backend needs to format the notification into a supported notification for the PNS of devices you plan to support. Затем используйте соответствующий API отправки для класса NotificationHubClient.Then use the appropriate send API on the NotificationHubClient class.

    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. Нажмите клавишу F5, чтобы запустить приложение и убедиться, что все правильно работает.To run the application and ensure the accuracy of your work so far, select the F5 key. Приложение откроется в веб-браузере и отобразится на домашней странице ASP.NET.The app opens a web browser, and it is displayed on the ASP.NET home page.

Публикация новой серверной части веб-API.Publish the new WebAPI backend

Теперь разверните приложение на веб-сайте Azure, чтобы сделать его доступным для всех устройств.Next, you deploy the app to an Azure website to make it accessible from all devices.

  1. Щелкните правой кнопкой мыши проект AppBackend и нажмите кнопку Опубликовать.Right-click the AppBackend project, and then select Publish.

  2. Выберите службу приложений Microsoft Azure, в которой вы хотите опубликовать приложение, и нажмите кнопку **Опубликовать.Select Microsoft Azure App Service as your publish target, and then select **Publish. Откроется окно создания службы приложений.The Create App Service window opens. В этом окне можно создать все необходимые ресурсы Azure для запуска веб-приложения ASP.NET в Azure.Here you can create all the necessary Azure resources to run the ASP.NET web app in Azure.

    Плитка службы приложений Microsoft Azure

  3. В окне Создание службы приложений выберите свою учетную запись Azure.In the Create App Service window, select your Azure account. Выберите Изменить тип > Веб-приложение.Select Change Type > Web App. Не изменяйте стандартное имя веб-приложения. Выберите подписку, группу ресурсов и план службы приложений.Keep the default Web App Name, and then select the Subscription, Resource Group, and App Service Plan.

  4. Нажмите кнопку Создать.Select Create.

  5. Запишите свойство URL-адрес сайта в разделе Сводка.Make a note of the Site URL property in the Summary section. Это URL-адрес конечной точки внутренней части.This URL is your back-end endpoint later in the tutorial.

  6. Нажмите кнопку Опубликовать.Select Publish.

Когда мастер завершит работу, веб-приложение ASP.NET будет опубликовано в Azure и откроется в браузере по умолчанию.After you've completed the wizard, it publishes the ASP.NET web app to Azure and then opens the app in the default browser. Приложение также будет отображаться в службах приложений Azure.Your application is viewable in Azure App Services.

В URL-адресе используется имя веб-приложения, указанное ранее, в формате http://<имя_приложения>.azurewebsites.net.The URL uses the web app name that you specified earlier, with the format http://<app_name>.azurewebsites.net.

Обновление кода клиента UWPUpdate the code for the UWP client

В этом разделе описано, как обновить код в проекте, который вы завершили при работе с руководством по отправке уведомлений в приложения универсальной платформы Windows с использованием Центров уведомлений Azure.In this section, you update the code in the project you completed for the Tutorial: Send notifications to Universal Windows Platform apps by using Azure Notification Hubs tutorial. Проект уже должен быть связан с Магазином Windows.The project should already be associated with the Windows store. Он также должен использовать Центр уведомлений.It also should be configured to use your notification hub. В этом разделе вы добавляете код для вызова нового серверного веб-API и используете его для регистрации и отправки уведомлений.In this section, you add code to call the new WebAPI backend and use it for registering and sending notifications.

  1. Откройте решение Visual Studio, созданное при работе с руководством по отправке уведомлений в приложения универсальной платформы Windows с использованием Центров уведомлений Azure.In Visual Studio, open the solution you created for the Tutorial: Send notifications to Universal Windows Platform apps by using Azure Notification Hubs.

  2. В обозревателе решений щелкните правой кнопкой мыши проект универсальной платформы Windows (UWP) и выберите Управление пакетами NuGet.In Solution Explorer, right-click the Universal Windows Platform (UWP) project and then click Manage NuGet Packages.

  3. В области слева выберите Обзор.On the left-hand side, select Browse.

  4. В текстовом поле Поиск введите Клиент HTTP.In the Search box, type Http Client.

  5. В списке результатов щелкните System.Net.Http и выберите Установить.In the results list, click System.Net.Http, and click Install. Выполните установку.Complete the installation.

  6. Вернитесь к полю NuGet Поиск и введите Json.net.Back in the NuGet Search box, type Json.net. Установите пакет Newtonsoft.json, а затем закройте окно диспетчера пакетов NuGet.Install the Newtonsoft.json package, and then close the NuGet Package Manager window.

  7. В обозревателе решений в проекте WindowsApp дважды щелкните MainPage.xaml, чтобы открыть его в редакторе Visual Studio.In Solution Explorer, in the WindowsApp project, double-click MainPage.xaml to open it in the Visual Studio editor.

  8. В коде XML-файла MainPage.xaml замените раздел <Grid> следующим кодом: Этот код добавляет текстовое поле имени пользователя и пароля, которые будут использоваться для проверки подлинности пользователя.In the MainPage.xaml XML code, replace the <Grid> section with the following code: This code adds a username and password textbox that the user authenticates with. Он также добавляет текстовые поля для сообщения уведомления и тег имени пользователя, который должен получать уведомления:It also adds text boxes for the notification message and the username tag that should receive the 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. В обозревателе решений откройте файл MainPage.xaml.cs для проектов (Windows 8.1) и (Windows Phone 8.1) .In Solution Explorer, open the MainPage.xaml.cs file for the (Windows 8.1) and (Windows Phone 8.1) projects. В верхнюю часть каждого из файлов добавьте такие using операторы:Add the following using statements at the top of both files:

    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. В файле MainPage.xaml.cs для проекта WindowsApp добавьте в класс MainPage следующий элемент.In MainPage.xaml.cs for the WindowsApp project, add the following member to the MainPage class. Обязательно замените <Enter Your Backend Endpoint> фактической конечной точкой серверной части, полученной ранее.Be sure to replace <Enter Your Backend Endpoint> with your actual backend endpoint obtained previously. Например, http://mybackend.azurewebsites.net.For example, http://mybackend.azurewebsites.net.

    private static string BACKEND_ENDPOINT = "<Enter Your Backend Endpoint>";
    
  11. В файле MainPage.xaml.cs для проектов (Windows 8.1) и (Windows Phone 8.1) добавьте в класс MainPage приведенный ниже код.Add the code below to the MainPage class in MainPage.xaml.cs for the (Windows 8.1) and (Windows Phone 8.1) projects.

    Метод PushClick является обработчиком нажатия для кнопки Отправить push-уведомление .The PushClick method is the click handler for the Send Push button. Он обеспечивает отправку серверной частью уведомлений на все устройства с тегом имени пользователя, который соответствует параметру to_tag .It calls the backend to trigger a notification to all devices with a username tag that matches the to_tag parameter. Сообщение уведомления отправляется в виде JSON-содержимого в теле запроса.The notification message is sent as JSON content in the request body.

    Метод LoginAndRegisterClick является обработчиком нажатия для кнопки Вход и регистрация.The LoginAndRegisterClick method is the click handler for the Login and register button. Он сохраняет маркер проверки подлинности (относится к любому маркеру, используемому в данной схеме проверки подлинности) в локальном хранилище, а затем с помощью RegisterClient подписывается на получение уведомлений, используя серверную часть.It stores the basic authentication token (represents any token your authentication scheme uses) in local storage, then uses RegisterClient to register for notifications using the backend.

    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. В обработчике событий InitNotificationsAsync() откройте файл App.xaml.cs и найдите вызов OnLaunched():Open App.xaml.cs and find the call to InitNotificationsAsync() in the OnLaunched() event handler. Закомментируйте или удалите вызов InitNotificationsAsync().Comment out or delete the call to InitNotificationsAsync(). Обработчик кнопки инициализирует регистрации уведомлений.The button handler initializes notification registrations.

    protected override void OnLaunched(LaunchActivatedEventArgs e)
    {
        //InitNotificationsAsync();
    
  13. Щелкните правой кнопкой мыши проект WindowsApp, а затем выберите пункты Добавить и Класс.Right-click the WindowsApp project, click Add, and then click Class. Присвойте классу имя RegisterClient.cs, а затем нажмите кнопку ОК, чтобы создать класс.Name the class RegisterClient.cs, then click OK to generate the class.

    Этот класс инкапсулирует вызовы REST, необходимые для связи с серверной частью приложения с целью регистрации в службе push-уведомлений.This class wraps the REST calls required to contact the app backend, in order to register for push notifications. В данном случае также происходит локальное сохранение идентификаторов registrationId , созданных концентратором уведомлений в соответствии с описанием в разделе Регистрация из серверной части приложения.It also locally stores the registrationIds created by the Notification Hub as detailed in Registering from your app backend. В данном случае используется маркер проверки подлинности, сохраненный в локальном хранилище при нажатии кнопки Вход и регистрация.It uses an authorization token stored in local storage when you click the Login and register button.

  14. Добавьте в начало файла RegisterClient.cs следующие операторы using :Add the following using statements at the top of the RegisterClient.cs file:

    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. Добавьте в определение класса RegisterClient следующий код:Add the following code inside the RegisterClient class definition.

    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. Сохраните изменения.Save all your changes.

Тестирование приложенияTest the Application

  1. Запустите приложение в обоих Windows.Launch the application on both Windows.

  2. Введите Имя пользователя и Пароль, как показано ниже.Enter a Username and Password as shown in the screen below. Они должны отличаться от имени пользователя и пароля, вводимых в Windows Phone.It should differ from the user name and password you enter on Windows Phone.

  3. Щелкните Вход и регистрация и убедитесь, что в диалоговом окне отображается подтверждение выполнения входа.Click Log in and register and verify a dialog shows that you have logged in. Таким образом, будет активирована кнопка Отправить push-уведомление.This code also enables the Send Push button.

  4. Затем в поле Тег имени получателя введите зарегистрированное имя пользователя.Then in the Recipient Username Tag field, enter the user name registered. Введите сообщение уведомления и нажмите кнопку Отправить push-уведомление.Enter a notification message and click Send Push.

  5. Сообщения уведомления могут получать только устройства с зарегистрированным соответствующим тегом имени получателя.Only the devices that have registered with the matching username tag receive the notification message.

Дополнительная информацияNext steps

В этом руководстве вы узнали, как отправлять push-уведомления определенным пользователям, с регистрацией которых связаны теги.In this tutorial, you learned how to push notifications to specific users that have tags associated with their registrations. Чтобы узнать, как отправлять push-уведомления на основе расположения, перейдите к следующему руководству:To learn how to push location-based notifications, advance to the following tutorial: