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