Registrace z back-endu aplikace

Jak je uvedeno v předchozích částech, musí zařízení vytvořit jednu nebo více registrací v centru oznámení, aby mohla přijímat nabízená oznámení. Jedním ze způsobů, jak tuto registraci dokončit, je, aby mobilní zařízení kontaktovala centrum oznámení přímo a zadala (nebo aktualizovala) jejich popisovač PNS a jejich značky. Tento přístup má řadu omezení a existují některé scénáře, ve kterých je vhodné při aktualizaci registrace zařízení kontaktovat vlastní back-end vaší aplikace. Back-end pak zavolá centrum oznámení.

Kdy se zaregistrovat z back-endu aplikace

Existují dva scénáře, ve kterých je vhodné směrovat registrace zařízení prostřednictvím back-endu vaší aplikace.

Značky musí být zabezpečené.

Když se zařízení zaregistruje přímo v centru oznámení, může určit libovolnou požadovanou značku. To není problém, pokud jsou značky skupinami veřejného zájmu, které se můžou přihlásit k odběru libovolného zařízení (například informační kanály týkající se sportovních týmů). To ale může být problém, když jsou některé značky dostupné jenom pro některé uživatele.

Aby bylo možné zaregistrovat každého uživatele pouze do povolených značek, musíte operace registrace směrovat prostřednictvím back-endu vaší vlastní aplikace, který může provádět ověřování uživatelů a autorizovat registraci požadovaných značek.

Nejběžnějším příkladem tohoto scénáře je použití značek k reprezentaci ID uživatelů. V takovém případě chcete zařízením zabránit v registraci do značek, které představují jiné uživatele, protože by dostávaly oznámení jiného uživatele.

Značky jsou upraveny back-endem vaší aplikace.

Registrace ze zařízení je pohodlná a umožňuje rychle nastavit nabízená oznámení a bohaté směrování do skupin zájmů. Registrace ze zařízení ale nefunguje velmi dobře, pokud chcete změnit značky v důsledku událostí, ke kterým dochází na jiných zařízeních.

Zvažte dva scénáře: pokud jsou značky na telefonu Alice nastavené jako výsledek událostí, ke kterým dochází na telefonu Alice, je snadné, aby aplikace aktualizovala značky v centru oznámení. Pokud se značky na druhé straně musí v důsledku událostí na jiných zařízeních změnit (například notebook Alice při přihlášení k webu), bude muset zařízení počkat, až se aplikace znovu aktivuje, aby odrážela změny v centru oznámení.

Konkrétním příkladem předchozího scénáře je hudební aplikace, která zahrnuje webové prostředí a mobilní aplikaci. V takovém případě může konkrétní uživatel sledovat novou skupinu prostřednictvím webu a chtít, aby zařízení co nejdříve dostávalo oznámení o nové skupině. Dalším příkladem je, když značky pocházejí z jiných částí back-endu (například CRM), které můžou změnit stav uživatele ze Silver na Gold. Tato změna může vést k nastavení nové značky u všech registrací uživatelů.

Postup registrace z back-endu

Při registraci zařízení musí centrum oznámení rozlišovat mezi různými zařízeními. Toho nelze dosáhnout jen tak, že se podíváte na popisovače PNS, protože jsou přechodné a nejsou jedinečné. Aby bylo možné tento problém vyřešit, služba Notification Hubs generuje ID dlouhodobé registrace, která musí každé zařízení ukládat místně, aby bylo možné odkazovat na vlastní registraci pokaždé, když aktualizuje popisovač, značky nebo šablonu PNS.

Následující obrázek znázorňuje tok registrace pro nativní oznámení:

  1. Pokud se v zařízení neukládá žádné ID registrace místně,

    1. Pokud chcete získat ID registrace, zavolejte back-end aplikace.

    2. Back-endová aplikace volá centra oznámení, aby vytvořila nové ID registrace a pak vrátila ID zpět do zařízení.

    3. Uložte ID registrace v místním úložišti zařízení.

  2. Na zařízení načtěte ID registrace z místního úložiště:

    1. Zavolejte back-end aplikace a zadejte ID registrace, popisovač PNS a značky.

    2. Back-end aplikace vytvoří nebo aktualizuje odpovídající registraci v centru oznámení.

    3. Pokud back-end aplikace vrátí stavový kód 410, je potřeba vytvořit nové ID registrace. Odstraňte ID registrace z místního úložiště a restartujte ho z kroku 1.

Backend Registration

Tok pro oznámení šablony je podobný. Jediné rozdíly jsou následující:

  1. Pokud zařízení používá více šablon, musí na jednu šablonu uložit jedno ID registrace.

  2. Šablony můžete identifikovat pomocí vlastnosti TemplateName registrace.

Následující kód je příkladem back-endových koncových bodů.

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

Všimněte si, že v předchozím kódu musíte přidat logiku, abyste zajistili, že klient volající tento koncový bod má oprávnění k registraci požadovaných značek. Back-end může také přidat samotné značky (například značku userid ).

Následující příklad kódu ukazuje, jak implementovat metodu registrace pro aplikaci Windows Store ze zařízení s předchozími koncovými body:

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"];

        }
    }

Ukládání ID registrace do back-endové databáze

Někdy aplikace chtějí zachovat ID registrace v back-endu aplikace místo v místním úložišti zařízení. K tomu obvykle dochází, když back-end aplikace už má způsob identifikace zařízení (například id instalace) a způsob, jak ukládat informace o zařízení do back-endového úložiště (například při migraci z vlastního nabízeného řešení, ve kterém byly uložené popisovače PNS).

Úprava značek z back-endu

Pokud chcete změnit značky z back-endu, musíte mít způsob, jak back-end identifikovat registrace, které se mají upravit. Obvykle se to provádí pomocí značky.

Předpokládejme například, že existuje hudební aplikace, ve které uživatel přidá novou oblíbenou skupinu z webu a back-end přidá značku do mobilních registrací uživatele v důsledku toho. V tomto případě aplikace používá značku k identifikaci uživatele a pak tuto značku používá k načtení registrací, které se mají aktualizovat, a aktualizovat je.

Následující příklad kódu načte registrace a přidá do nich novou značku.

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

Všimněte si, že pokud v tomto příkladu používáte šablony, předpokládáme, že přidáváte značku do všech šablon.