Rejestrowanie z zaplecza aplikacji

Jak wspomniano w poprzednich sekcjach, urządzenia muszą utworzyć co najmniej jedną rejestrację w centrum powiadomień, aby otrzymywać powiadomienia wypychane. Jednym ze sposobów ukończenia tej rejestracji jest bezpośrednie skontaktowanie się z centrum powiadomień w celu określenia (lub zaktualizowania) dojścia systemu powiadomień i tagów usługi PNS. Takie podejście ma szereg ograniczeń i istnieje kilka scenariuszy, w których zaleca się skontaktowanie się z zapleczem aplikacji podczas odświeżania rejestracji urządzenia. Następnie zaplecze wywołuje centrum powiadomień.

Kiedy należy zarejestrować się z zaplecza aplikacji

Istnieją dwa scenariusze, w których zaleca się kierowanie rejestracji urządzeń za pośrednictwem zaplecza aplikacji.

Tagi muszą być zabezpieczone

Gdy urządzenie jest rejestrowane bezpośrednio w centrum powiadomień, może określić dowolny tag. Nie jest to problem, jeśli tagi są grupami interesu publicznego, do których każde urządzenie może subskrybować (na przykład kanały informacyjne dotyczące zespołów sportowych). Może to być jednak problem, gdy niektóre tagi są dostępne tylko dla niektórych użytkowników.

Aby zarejestrować każdego użytkownika tylko w dozwolonych tagach, należy kierować operacje rejestracji za pośrednictwem własnego zaplecza aplikacji, które może przeprowadzać uwierzytelnianie użytkownika i autoryzować rejestrację wymaganych tagów.

Najczęstszym przykładem tego scenariusza jest użycie tagów do reprezentowania identyfikatorów użytkowników. W takim przypadku chcesz uniemożliwić rejestrowanie urządzeń w tagach reprezentujących innych użytkowników, ponieważ będą otrzymywać powiadomienia innych użytkowników.

Tagi są modyfikowane przez zaplecze aplikacji

Rejestrowanie z urządzenia jest wygodne i umożliwia szybkie konfigurowanie powiadomień wypychanych i rozbudowany routing do grup zainteresowań. Jednak rejestrowanie z urządzenia nie działa bardzo dobrze, jeśli chcesz zmienić tagi w wyniku zdarzeń występujących na innych urządzeniach.

Rozważmy dwa scenariusze: jeśli tagi na telefonie Alicji są ustawione w wyniku zdarzeń występujących na telefonie Alicji, aplikacja może łatwo zaktualizować tagi w centrum powiadomień. Jeśli z drugiej strony tagi muszą ulec zmianie w wyniku zdarzeń na innych urządzeniach (na przykład laptopa Alicji po zalogowaniu się do witryny internetowej), urządzenie będzie musiało poczekać, aż aplikacja będzie ponownie aktywna, aby odzwierciedlić zmiany w centrum powiadomień.

Konkretnym przykładem poprzedniego scenariusza jest aplikacja muzyczna obejmująca środowisko internetowe i aplikację mobilną. W takim przypadku określony użytkownik może podążać za nowym pasmem za pośrednictwem witryny internetowej i chce, aby urządzenie zaczęło otrzymywać powiadomienia o nowym pasmie tak szybko, jak to możliwe. Innym przykładem jest to, że tagi pochodzą z innych części zaplecza (na przykład CRM), co może zmienić stan użytkownika z Silver na Gold. Ta zmiana może spowodować ustawienie nowego tagu dla rejestracji wszystkich użytkowników.

Jak zarejestrować się z zaplecza

Podczas rejestrowania urządzenia centrum powiadomień musi rozróżniać różne urządzenia. Nie można tego osiągnąć, patrząc na dojścia pns, ponieważ są przejściowe, a nie unikatowe. Aby rozwiązać ten problem, usługa Notification Hubs generuje długotrwałe identyfikatory rejestracji, które każde urządzenie musi przechowywać lokalnie, aby można było odwoływać się do własnej rejestracji za każdym razem, gdy aktualizuje dojście do usługi PNS, tagi lub szablon.

Na poniższej ilustracji przedstawiono przepływ rejestracji dla powiadomień natywnych:

  1. Na urządzeniu, jeśli identyfikator rejestracji nie jest przechowywany lokalnie,

    1. Wywołaj zaplecze aplikacji, aby uzyskać identyfikator rejestracji.

    2. Zaplecze aplikacji wywołuje centra powiadomień, aby utworzyć nowy identyfikator rejestracji, a następnie zwrócić identyfikator z powrotem do urządzenia.

    3. Zapisz identyfikator rejestracji w magazynie lokalnym urządzenia.

  2. Na urządzeniu pobierz identyfikator rejestracji z magazynu lokalnego:

    1. Wywołaj zaplecze aplikacji, podając identyfikator rejestracji, dojście systemu powiadomień platformy i tagi.

    2. Zaplecze aplikacji tworzy lub aktualizuje odpowiednią rejestrację w centrum powiadomień.

    3. Jeśli zaplecze aplikacji zwraca kod stanu 410, należy utworzyć nowy identyfikator rejestracji. Usuń identyfikator rejestracji z magazynu lokalnego i uruchom ponownie z kroku 1.

Backend Registration

Przepływ powiadomień szablonu jest analogiczny. Jedyne różnice są następujące:

  1. Jeśli urządzenie używa wielu szablonów, musi przechowywać jeden identyfikator rejestracji na szablon.

  2. Szablony można zidentyfikować przy użyciu właściwości TemplateName rejestracji.

Poniższy kod jest przykładem punktów końcowych zaplecza.

public class RegisterController : ApiController
    {

        private NotificationHubClient hub;

        public RegisterController()
        {
            hub = NotificationHubClient.CreateClientFromConnectionString("Endpoint=sb://buildhub-ns.servicebus.windows.net/;SharedAccessKeyName=DefaultFullSharedAccessSignature;SharedAccessKey=DuWV4SQ08poV6HZly8O/KQNWv3YRTZlExJxu3pNCjGU=", "build2014_2");
        }
        
        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()
        {
            return await hub.CreateRegistrationIdAsync();
        }

        // PUT api/register/5
        // This creates or updates a registration (with provided PNS handle) at the specified id
        public async void Put(string id, DeviceRegistration deviceUpdate)
        {
            // IMPORTANT: add logic to make sure that caller is allowed to register for the provided tags
            
            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;
            registration.Tags = new HashSet<string>(deviceUpdate.Tags);

            try
            {
                await hub.CreateOrUpdateRegistrationAsync(registration);
            } catch (MessagingException e) {
                ReturnGoneIfHubResponseIsGone(e);
            }
        }

        // DELETE api/register/5
        public async void Delete(string id)
        {
            await hub.DeleteRegistrationAsync(id);
        }


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

Należy pamiętać, że w poprzednim kodzie należy dodać logikę, aby upewnić się, że klient wywołujący ten punkt końcowy jest autoryzowany do rejestrowania w żądanych tagach. Ponadto zaplecze może dodać same tagi (na przykład tag userid ).

Poniższy przykład kodu pokazuje, jak zaimplementować metodę rejestracji dla aplikacji ze sklepu Windows Store na urządzeniu z poprzednimi punktami końcowymi:

class RegisterClient
    {
        private string POST_URL = "{your back-end endpoints}";

        private class DeviceRegistration
        {
            public string Platform { get; set; }
            public string Handle { get; set; }
            public string[] Tags { get; set; }
        }

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

        private async Task<HttpStatusCode> UpdateRegistrationAsync(string regId, DeviceRegistration deviceRegistration)
        {
            using (var httpClient = new HttpClient())
            {
                var putUri = POST_URL + "/" + regId;
                var response = await httpClient.PutAsJsonAsync<DeviceRegistration>(putUri, deviceRegistration);
                return response.StatusCode;
            }
        }

        private async Task<string> RetrieveRegistrationIdOrRequestNewOneAsync()
        {
            var settings = ApplicationData.Current.LocalSettings.Values;
            if (!settings.ContainsKey("__NHRegistrationId"))
            {
                using (var httpClient = new HttpClient())
                {
                    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 Exception();
                    }
                }
            }
            return (string)settings["__NHRegistrationId"];

        }
    }

Przechowywanie identyfikatorów rejestracji w bazie danych zaplecza

Czasami aplikacje chcą przechowywać identyfikatory rejestracji w zapleczu aplikacji zamiast w lokalnym magazynie urządzenia. Zwykle dzieje się tak, gdy zaplecze aplikacji ma już sposób identyfikowania urządzeń (na przykład identyfikatora instalacji) i sposobu przechowywania informacji o urządzeniu w magazynie zaplecza (na przykład podczas migracji z niestandardowego rozwiązania wypychania, w którym są przechowywane dojścia systemu powiadomień platformy powiadomień platformy).

Jak modyfikować tagi z zaplecza

Jeśli chcesz zmodyfikować tagi z zaplecza, musisz mieć możliwość zidentyfikowania rejestracji, które mają zostać zmodyfikowane. Zwykle odbywa się to przy użyciu tagu.

Załóżmy na przykład, że istnieje aplikacja muzyczna, w której użytkownik dodaje nowy ulubiony zespół z Sieci Web, a zaplecze dodaje tag w rejestracjach mobilnych użytkownika w wyniku tego. W takim przypadku aplikacja używa tagu do identyfikowania użytkownika, a następnie używa tego tagu do pobrania rejestracji do zaktualizowania i zaktualizowania ich.

Poniższy przykład kodu pobiera rejestracje i dodaje do nich nowy tag.

var registrations = await hub.GetRegistrationsByTagAsync("{userId}", 10);
            foreach (var reg in registrations)
            {
                reg.Tags.Add("{newBand}");
                await hub.UpdateRegistrationAsync(reg);
            }

Pamiętaj, że w tym przykładzie, jeśli używasz szablonów, zakładamy, że dodasz tag do wszystkich szablonów.