0

I have a background service, which sends push notifications. Everything works okay, except the last method.

await pushClient.RequestPushMessageDeliveryAsync(subscription, notification, stoppingToken);

It throws an exception

Object reference not set to an instance of an object

at Lib.Net.Http.WebPush.Internals.UrlBase64Converter.FromUrlBase64String(String input) at Lib.Net.Http.WebPush.PushServiceClient.GetKeyingMaterial(PushSubscription subscription, AsymmetricKeyParameter applicationServerPrivateKey, Byte[] applicationServerPublicKey) at Lib.Net.Http.WebPush.PushServiceClient.SetContent(HttpRequestMessage pushMessageDeliveryRequest, PushSubscription subscription, PushMessage message) at Lib.Net.Http.WebPush.PushServiceClient.PreparePushMessageDeliveryRequest(PushSubscription subscription, PushMessage message, VapidAuthentication authentication, VapidAuthenticationScheme authenticationScheme) at Lib.Net.Http.WebPush.PushServiceClient.d__36.MoveNext() at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)

I assume this may be because I incorrectly instantiate the PushServiceClient. If so, how to do it right?

The full class of the background service:

public class PushNotificationsProducer : BackgroundService
{
    private const int NOTIFICATION_FREQUENCY = 10 * 1000;
    public IOptions<PushNotificationsOptions> Options { get; }
    public IServiceProvider Services { get; }

    public PushNotificationsProducer(IOptions<PushNotificationsOptions> options,
        IServiceProvider services)
    {
        Options = options;
        Services = services;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            await Task.Delay(NOTIFICATION_FREQUENCY, stoppingToken);

            await SendNotifications(stoppingToken);
        }
    }

    private async Task SendNotifications(CancellationToken stoppingToken)
    {
        List<User> users;
        ApplicationDbContext db;
        using (var scope = Services.CreateScope())
        {
            db = scope.ServiceProvider
                    .GetRequiredService<ApplicationDbContext>();

            users = await db.Users.ToListAsync(stoppingToken);

            foreach (var user in users)
            {

                    var subscription = await db.AppPushSubscriptions.Where(x => x.UserId == user.Id).FirstOrDefaultAsync(stoppingToken);

                    // create notif
                    PushMessage notification = new AngularPushNotification
                    {
                        Title = "Some text!",
                        Body = $"Some text.",
                        Icon = "assets/icons/icon-96x96.png"
                    }.ToPushMessage();


                    PushServiceClient pushClient;
                    pushClient = scope.ServiceProvider
                            .GetRequiredService<PushServiceClient>();

                    pushClient.DefaultAuthentication = new VapidAuthentication(Options.Value.PublicKey,
                        Options.Value.PrivateKey)
                    {
                        Subject = "https://example.net"
                    };

                    try
                    {
                        await pushClient.RequestPushMessageDeliveryAsync(subscription, notification, stoppingToken);
                    }
                    catch (Exception e)
                    {
                        throw;
                    }           
            }
        }
    }
}
vulp
  • 1,451
  • 13
  • 32
  • Where does `sub` come from. not finding a declaration – Nkosi Nov 07 '19 at 19:33
  • @Nkosi, updated the code. – vulp Nov 07 '19 at 19:55
  • Have you checked to make sure none of the used variable are null? `FirstOrDefaultAsync` has the potential to return null, so it could very well be the subscription that is null if the user is not subscribed – Nkosi Nov 07 '19 at 19:57
  • @Nkosi, Yes, I have checked that. All variables have values. – vulp Nov 07 '19 at 20:02
  • Found the problem after reading source code of the Lib.Net.Http.WebPush. The library converts enum keys to lowercase for comparison. Fixed it by doing the same. – vulp Nov 07 '19 at 20:46

0 Answers0