Document DB v8.0 Interceptors, Temporal Support, Telemetry Collection, All Calculations, String Based APIs, & Orleans Storage Providers! Feed The Machine Here
Push (Server)
Server-side push notification dispatch for .NET. A provider-agnostic core with a direct APNs transport
(token-based .p8 / ES256 over HTTP/2 — no FCM dependency for Apple), pluggable persistence
(Shiny.DocumentDb), structured targeting, an interceptor pipeline, automatic dead-token pruning, multi-app
keyed registration, and System.Diagnostics.Metrics telemetry. The whole library is AOT/trim-safe.
Frameworks
.NET
ASP.NET
| Core | |
| APNs | |
| DocumentDb |
Features
Section titled “Features”- Provider-agnostic core — one
IPushManager; transports plug in asIPushProvider - Direct APNs — HTTP/2, token-based
.p8/ ES256 JWT auth, per-registration sandbox/production - Structured, AOT-safe targeting — send to a user, tags/segments, explicit tokens, or broadcast
- Rich payloads — title/body, badge, sound, deep link, collapse id, TTL, silent/background pushes, plus
per-platform escape hatches (
ApplePushOptions,AndroidPushOptions,WebPushOptions) - Automatic token hygiene — expired/invalid tokens are pruned; rotated tokens are applied back
- Interceptors — localize, personalize, or suppress per device
- Batching / FCM multicast — batch-capable transports deliver many devices per call (FCM: up to 500 per
/batchrequest); on by default viaIPushBatchProvider - Multi-app — keyed registrations serve several apps from one server
- Metrics — counters + latency histogram via
System.Diagnostics.Metrics(OpenTelemetry-ready) - Pluggable persistence — in-memory out of the box, or Shiny.DocumentDb on any backend
Getting Started
Section titled “Getting Started”Install the core plus the transport and (optionally) a persistence package:
dotnet add package Shiny.Extensions.Pushdotnet add package Shiny.Extensions.Push.Apnsdotnet add package Shiny.Extensions.Push.DocumentDb # optional; defaults to in-memoryRegister the service:
using Shiny.Extensions.Push;using Shiny.Extensions.Push.Apns;using Shiny.Extensions.Push.DocumentDb;using Shiny.DocumentDb.Sqlite;
builder.Services.AddPushNotifications(push =>{ push.AddApns(o => { o.TeamId = "ABCDE12345"; o.KeyId = "KEY1234567"; o.BundleId = "com.example.app"; o.PrivateKeyPath = "AuthKey_KEY1234567.p8"; // or o.PrivateKey = "<PEM contents>" });
// Persistence (omit to use the in-memory repository) push.UseDocumentDb(o => o.DatabaseProvider = new SqliteDatabaseProvider("Data Source=push.db"));});Register a device when your app reports its token:
await pushManager.RegisterDevice(new DeviceRegistration{ DeviceToken = "<apns-device-token>", Platform = DevicePlatform.iOS, DeviceId = "install-guid", // stable identity across token rotation UserIdentifier = "user-42", Tags = ["beta", "sports"], Environment = PushEnvironment.Production // APNs tokens are environment-specific});Send:
var result = await pushManager.SendToUser("user-42", new PushNotification{ Title = "Goal!", Message = "Your team just scored", Badge = 1, DeepLink = "app://match/123"});// result.BatchId, result.Sent, result.Failed, result.TokensRemoved, result.SkippedNext: Sending, APNs, Persistence, Metrics.