Compartir a través de


Registro desde el back-end de la aplicación

Como se mencionó en las secciones anteriores, los dispositivos deben crear uno o varios registros en un centro de notificaciones para recibir notificaciones push. Una manera de completar este registro es hacer que los dispositivos móviles se ponga en contacto directamente con el centro de notificaciones para especificar (o actualizar) su identificador de PNS y sus etiquetas. Este enfoque tiene una serie de limitaciones y hay algunos escenarios en los que es aconsejable ponerse en contacto con su propio back-end de la aplicación cuando un dispositivo actualiza su registro. A continuación, el back-end llama al centro de notificaciones.

Cuándo registrarse desde el back-end de la aplicación

Hay dos escenarios en los que es aconsejable enrutar los registros de dispositivos a través del back-end de la aplicación.

Las etiquetas deben estar protegidas

Cuando un dispositivo se registra directamente con un centro de notificaciones, puede especificar cualquier etiqueta que desee. Esto no es un problema si las etiquetas son grupos de interés público a los que cualquier dispositivo puede suscribirse (por ejemplo, fuentes de noticias con respecto a los equipos deportivos). Sin embargo, esto puede ser un problema cuando algunas etiquetas solo están disponibles para algunos usuarios.

Para registrar cada usuario solo en las etiquetas permitidas, debe enrutar las operaciones de registro a través de su propio back-end de la aplicación, que puede realizar la autenticación de usuario y autorizar el registro para las etiquetas necesarias.

El ejemplo más común de este escenario es usar etiquetas para representar identificadores de usuario. En este caso, quiere impedir que los dispositivos se registren en etiquetas que representen a otros usuarios, ya que recibirían las notificaciones de otro usuario.

El back-end de la aplicación modifica las etiquetas.

El registro desde el dispositivo es cómodo y le permite configurar rápidamente las notificaciones push y el enrutamiento enriquecido a grupos de interés. Sin embargo, el registro desde el dispositivo no funciona muy bien si desea cambiar las etiquetas como resultado de eventos que se producen en otros dispositivos.

Considere dos escenarios: si las etiquetas del teléfono de Alice se establecen como resultado de eventos que se producen en el teléfono de Alice, es fácil que la aplicación actualice las etiquetas en el centro de notificaciones. Si, por otro lado, las etiquetas deben cambiar como resultado de eventos que se producen en otros dispositivos (por ejemplo, el portátil de Alice cuando ha iniciado sesión en un sitio web), el dispositivo tendrá que esperar a que la aplicación vuelva a estar activa para reflejar los cambios en el centro de notificaciones.

Un ejemplo específico del escenario anterior es una aplicación de música que incluye una experiencia web y una aplicación móvil. En este caso, un usuario específico podría seguir una nueva banda a través del sitio web y desea que el dispositivo empiece a recibir notificaciones sobre la nueva banda lo antes posible. Otro ejemplo es cuando las etiquetas proceden de otras partes del back-end (un CRM, por ejemplo), que puede cambiar el estado del usuario de Silver a Gold. Este cambio puede dar lugar a que se establezca una nueva etiqueta en todos los registros de los usuarios.

Registro desde el back-end

Al registrar un dispositivo, un centro de notificaciones debe distinguir entre distintos dispositivos. Esto no se puede lograr simplemente examinando los identificadores de PNS, ya que son transitorios y no únicos. Para solucionar este problema, Notification Hubs genera identificadores de registro de larga duración que cada dispositivo debe almacenar localmente para poder hacer referencia a su propio registro cada vez que actualiza su identificador de PNS, etiquetas o plantilla.

En la ilustración siguiente se muestra el flujo de registro para las notificaciones nativas:

  1. En el dispositivo, si no se almacena ningún identificador de registro localmente,

    1. Llame al back-end de la aplicación para obtener el identificador de registro.

    2. El back-end de la aplicación llama a notification hubs para crear un nuevo identificador de registro y, a continuación, devuelve el identificador al dispositivo.

    3. Almacene el identificador de registro en el almacenamiento local del dispositivo.

  2. En el dispositivo, recupere el identificador de registro del almacenamiento local:

    1. Llame al back-end de la aplicación, proporcionando el identificador de registro, el identificador de PNS y las etiquetas.

    2. El back-end de la aplicación crea o actualiza el registro correspondiente en el centro de notificaciones.

    3. Si el back-end de la aplicación devuelve el código de estado 410, se debe crear un nuevo identificador de registro. Elimine el identificador de registro del almacenamiento local y reinicie desde el paso 1.

Backend Registration

El flujo de las notificaciones de plantilla es análogo. Las únicas diferencias son las siguientes:

  1. Si un dispositivo usa varias plantillas, debe almacenar un identificador de registro por plantilla.

  2. Puede identificar las plantillas mediante la propiedad TemplateName del registro.

El código siguiente es un ejemplo de puntos de conexión de back-end.

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

Tenga en cuenta que, en el código anterior, debe agregar la lógica para asegurarse de que el cliente que llama a ese punto de conexión está autorizado para registrarse para las etiquetas solicitadas. Además, el back-end puede agregar las etiquetas en sí (por ejemplo, una etiqueta userid ).

En el ejemplo de código siguiente se muestra cómo implementar el método de registro para una aplicación de Windows Store, desde el dispositivo, con los puntos de conexión anteriores:

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

        }
    }

Almacenamiento de identificadores de registro en una base de datos back-end

A veces, las aplicaciones quieren mantener los identificadores de registro en el back-end de la aplicación en lugar de en el almacenamiento local del dispositivo. Esto suele ocurrir cuando el back-end de la aplicación ya tiene una manera de identificar los dispositivos (por ejemplo, un installationId) y una manera de almacenar información del dispositivo en el almacenamiento back-end (por ejemplo, al migrar desde una solución de inserción personalizada en la que se almacenaron los identificadores de PNS).

Modificación de etiquetas desde el back-end

Si desea modificar etiquetas del back-end, debe tener una manera de que el back-end identifique los registros que se van a modificar. Normalmente, esto se hace mediante una etiqueta .

Por ejemplo, supongamos que hay una aplicación de música en la que un usuario agrega una nueva banda favorita de la Web y el back-end agrega una etiqueta en los registros móviles del usuario como resultado de eso. En este caso, la aplicación usa una etiqueta para identificar al usuario y, a continuación, usa esa etiqueta para recuperar los registros que se van a actualizar y actualizar.

En el ejemplo de código siguiente se recuperan los registros y se agrega una nueva etiqueta a ellos.

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

Tenga en cuenta que, en este ejemplo, si usa plantillas, se supone que va a agregar la etiqueta en todas las plantillas.