3
votes

I have a working Azure App Service connected to a Notification Hub configured with GCM and APNS. It has been working perfectly for months with on both platforms.

I have now turned on authentication in the app service and configured google and facebook. These also work perfectly, and the correct access is honoured for the easy tables.

However, device registration from the mobile app now fails since the authentication has been turned on.

The following is the error I am getting on the app service (NodeJS):

System.NullReferenceException: Object reference not set to an instance of an object.
  at Microsoft.Azure.AppService.Push.PushRequestHandler.<HandleCreateOrUpdateInstallationAsync>d__14.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
 at  System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.Azure.AppService.Push.PushRequestHandler.<HandlePushRequestAsync>d__f.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.Azure.AppService.Push.PushModule.<OnPostAuthenticateRequestAsync>d__0.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.Azure.AppService.Authentication.HttpModuleDispatcher.<DispatchAsync>d__13.MoveNext()
2016-11-14T09:43:00  PID[7348] Information Sending response: 500.79 Internal Server Error
2016-11-14T09:43:00  PID[7348] Critical    System.ComponentModel.Win32Exception (0x80004005): An operation was attempted on a nonexistent network connection
at CHttpRequest.ReadEntityBody(Byte[] buffer, Int32 maxLength, Boolean allowAsync, Int32& bytesReceived, Int32& bytesRemaining, Boolean& completionPending)
at Microsoft.Azure.AppService.Authentication.HttpRequestBase.AsyncReadHelper.Read()
at Microsoft.Azure.AppService.Authentication.HttpRequestBase.AsyncReadHelper..ctor(HttpRequestBase request, Int32 maxLength)
at Microsoft.Azure.AppService.Authentication.HttpRequestBase.<ReadRequestContentAsync>d__8.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.Azure.AppService.Push.PushRequestHandler.<HandleCreateOrUpdateInstallationAsync>d__14.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.Azure.AppService.Push.PushRequestHandler.<HandlePushRequestAsync>d__f.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.Azure.AppService.Push.PushModule.<OnPostAuthenticateRequestAsync>d__0.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.Azure.AppService.Authentication.HttpModuleDispatcher.<DispatchAsync>d__13.MoveNext()
2016-11-14T09:43:00  PID[7348] Information Sending response: 500.79 Internal Server Error

I am able to send notifications (using test send and via my server push code) to existing registrations, I am just not able to create new registrations.

When I turn the authentication off, it all works normally again.

Do I need to manually create the registrations in the notification hub in this authentication scenario?

I am at a loss as to where I am going wrong, so any help would be greatly appreciated.

3
What does your App Service Configuration look like? Specifically, the Push menu option?Adrian Hall
Hey Adrian, thanks for replying. My App Service Push menu is simply connected to the hub, no tags, no other setup. Are you asking for a config file or will a screenshot of the actual portal suffice?Rys
We've identified an issue with the push registration process. We are getting a patch produced right now. Once we've pushed out the fix, it will magically start working again. Apologies for the inconvenience here.Adrian Hall

3 Answers

3
votes

As an alternative to the RegisterAsync that is causing the problem; you can use a HttpClient call to PUT a Notification Hub installation. The following code will set up the installation on Android, for example:

public async Task RegisterForPushNotifications(MobileServiceClient client)
{
    if (GcmClient.IsRegistered(RootView))
    {
        try
        {
            var registrationId = GcmClient.GetRegistrationId(RootView);
            //var push = client.GetPush();
            //await push.RegisterAsync(registrationId);

            var installation = new DeviceInstallation
            {
                InstallationId = client.InstallationId,
                Platform = "gcm",
                PushChannel = registrationId
            };
            // Set up tags to request
            installation.Tags.Add("topic:Sports");
            // Set up templates to request
            PushTemplate genericTemplate = new PushTemplate
            {
                Body = "{\"data\":{\"message\":\"$(messageParam)\"}}"
            };
            // Register with NH
            var response = await client.InvokeApiAsync<DeviceInstallation, DeviceInstallation>(
                $"/push/installations/{client.InstallationId}",
                installation,
                HttpMethod.Put,
                new Dictionary<string, string>());
        }
        catch (Exception ex)
        {
            Log.Error("DroidPlatformProvider", $"Could not register with NH: {ex.Message}");
        }
    }
    else
    {
        Log.Error("DroidPlatformProvider", $"Not registered with GCM");
    }
}

The DeviceInstallation class looks like this:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;

namespace TaskList.Abstractions
{
    public class DeviceInstallation
    {
        public DeviceInstallation()
        {
            Tags = new List<string>();
            Templates = new Dictionary<string, PushTemplate>();
        }

        [JsonProperty(PropertyName = "installationId")]
        public string InstallationId { get; set; }

        [JsonProperty(PropertyName = "platform")]
        public string Platform { get; set; }

        [JsonProperty(PropertyName = "pushChannel")]
        public string PushChannel { get; set; }

        [JsonProperty(PropertyName = "tags")]
        public List<string> Tags { get; set; }

        [JsonProperty(PropertyName = "templates")]
        public Dictionary<string, PushTemplate> Templates { get; set; }
    }

    public class PushTemplate
    {
        public PushTemplate()
        {
            Tags = new List<string>();
            Headers = new Dictionary<string, string>();
        }

        [JsonProperty(PropertyName = "body")]
        public string Body { get; set; }

        [JsonProperty(PropertyName = "tags")]
        public List<string> Tags { get; set; }

        [JsonProperty(PropertyName = "headers")]
        public Dictionary<string, string> Headers { get; set; }
    }
}

Place the RegisterForPushNotifications() method in your platform-specific code. The DeviceInstallation can be in a PCL.

1
votes

This is an issue with the push blade, and not something you can solve by yourself. I've reached out via email so that we can support you directly.