Systemübersicht
Der SharePoint Advanced Notification Manager ist der vorgesehene Ersatz für Microsofts eingestellte native SharePoint-Alert-Funktion. Er bietet einen reichhaltigeren, Multi-Kanal-Benachrichtigungsdienst — Benutzer verwalten Alert-Abonnements über eine SPFx-Erweiterung in einer SharePoint-Listen-Symbolleiste. Alert-Daten werden in Azure SQL über ein Azure Functions-Backend gespeichert.
Wenn sich Listenelemente ändern, sendet SharePoint einen Webhook an das Backend, das das Ereignis als TriggerEvent in die Warteschlange einreiht und Benachrichtigungen in einem 5-Minuten-Zeitplan über E-Mail (Microsoft Graph), SMS, Microsoft Teams (Bot Connector) oder WhatsApp (Business API) versendet.
Komponenten
Das System erstreckt sich über vier Infrastrukturschichten. Die Verantwortlichkeiten jeder Schicht sind streng getrennt — das Frontend schreibt nie direkt in SQL, und das Backend gibt nie UI-Schicht-Aufrufe aus.
SharePoint Online
Hostet die Liste und zeigt die SPFx ListViewCommandSet-Erweiterung in der Symbolleiste an. Das NotifyConfigurationWebPart bietet eine Mandanten-Admin-Benutzeroberfläche. SharePoint löst Webhooks bei Elementänderungen aus.
Azure AD / Entra
Hostet die App-Registrierung, die Bearer-Token an die SPFx-Erweiterung ausstellt. Das Backend validiert diese Token über OIDC-Metadaten und erwirbt auch OBO- und Client-Credential-Token für den Graph/SharePoint-Zugriff.
Azure Functions-Backend
Vier interne Dienste als Azure Functions: HTTP Endpoints (die REST API), Webhook Receiver (Änderungsaufnahme, fire-and-forget), Scheduler (5-Minuten-Timer-Trigger) und Change Manager (CSOM-Diff + Benachrichtigungsversand). SQL-Persistenz über AlertInfo-, TriggerEvent-, WebHooks- und Log-Tabellen.
Benachrichtigungskanäle
E-Mail über Microsoft Graph sendMail. SMS per HTTP an einen konfigurierten Anbieter. Microsoft Teams über den Bot Connector mit Adaptive Cards. WhatsApp über die WhatsApp Business API. Kanal pro Alert basierend auf DeliveryMethod ausgewählt.
Authentifizierungsfluss
Die SPFx-Erweiterung verwendet SharePoints integrierten AadHttpClient, um Azure AD Bearer-Token transparent zu erwerben — kein manueller OAuth-Fluss im Frontend-Code. Jede Backend-HTTP-Funktion validiert den Token unabhängig; kein API-Gateway führt eine zentralisierte Validierung durch.
AadHttpClient auf, der SharePoints Token-Brokering verwendet, um ein JWT für api://<client-id> von Azure AD anzufordern. Keine Weiterleitung oder Popup erforderlich.Authorization: Bearer <token> enthält das JWT. SPTenantID: <tenant-guid> identifiziert den aufrufenden Mandanten, damit das Backend den korrekten OIDC-Metadaten-Endpunkt auflösen kann.TokenValidatorCache, um die OpenID Connect-Metadaten und Signierungsschlüssel des Mandanten abzurufen und zu cachen, wodurch wiederholte Anfragen bei nachfolgenden Requests vermieden werden.SPTenantID-Header ist zwingend erforderlich. Ohne ihn kann das Backend nicht bestimmen, welche OIDC-Metadaten des Mandanten geladen werden sollen, und wird die Anfrage ablehnen, selbst wenn das JWT selbst gültig ist.Multi-Tenant-Architektur
Eine einzige Backend-Deployment bedient mehrere SharePoint-Mandanten. Die Isolation wird auf jeder Ebene durchgesetzt — pro Request, in der Datenbank und im Scheduler.
TenantConfiguration-Schema
Isolationsmechanismen
- Jede HTTP-Anfrage enthält den
SPTenantID-Header, den das Backend verwendet, um alle Datenbanklesevorgänge und -schreibvorgänge auf diesen Mandanten zu beschränken. TokenValidatorCachepflegt separate OIDC-Validierungsparameter pro Mandant (Signierungsschlüssel, Aussteller-URI).SchedulerNotificationiteriert alle registrierten Mandanten unabhängig und instanziiert pro Ausführung einen separatenChangeManagerund Credential-Satz pro Mandant.- Alle SQL-Abfragen enthalten ein
TenantID-Prädikat — es gibt keine mandantenübergreifenden Abfragen.
Onboarding eines neuen Mandanten
.sppkg-Bundle in den SharePoint App Catalog des Mandanten hoch und genehmigen Sie die API-Berechtigungen, damit die Erweiterung Token erwerben kann.NotifyConfigurationWebPart, um POST /api/configmngr/create mit den Mandantenanmeldedaten aufzurufen. Das Backend beginnt mit der Verarbeitung dieses Mandanten beim nächsten Scheduler-Zyklus.Alert-Lebenszyklus
Ein Alert durchläuft vier verschiedene Phasen — von der Erstellung über die Änderungserkennung, die geplante Benachrichtigungsübermittlung bis hin zur Protokollansicht. Jede Phase wird von einer anderen Backend-Komponente verarbeitet.
Alert erstellen
- Benutzer klickt auf "My Notifications" in der SharePoint-Listen-Symbolleiste.
- SPFx lädt
AlertFormPanelund ruftGET /api/alerts4list/{listId}auf, um bestehende Alerts vorab zu laden (auf den Benutzer beschränkt). - Benutzer füllt das Alert-Formular aus und klickt auf OK.
- SPFx ruft
POST /api/alertmngr/createmit dem vollständigenIAlertInfo-Payload einschließlich des über PnPjs erfasstenLastChangedTokenauf. - Backend validiert das Bearer-Token, schreibt
AlertInfoin SQL und prüft auf bestehende Webhook-Abonnements überDBWebHookEntriesManager. - Wenn kein Webhook vorhanden ist, erwirbt es ein OBO-Token und ruft
WebhookService.RegisterWebhookAsync()mitclientState = "AlertID-{id}"auf. - Gibt
201 Createdmit dem gespeichertenAlertInfoeinschließlich Datenbank-ID undSubscriptionIDzurück.
Änderungserkennung über SharePoint-Webhook
- Ein Listenelement wird in SharePoint hinzugefügt, aktualisiert oder gelöscht.
- SharePoint sendet
POST /api/webhookmit einemSpNotificationPayloadmit der Abonnement-ID,clientState, Listen-GUID, Mandanten-ID, Website-URL und Web-ID. SharePointWebhookReceiverüberprüft, obclientStatemit"AlertID-"beginnt, und speichert dann einenTriggerEventin SQL (fire-and-forget).- Bei der ersten Webhook-Bestätigung wird
SubscriptionIDimAlertInfo-Datensatz aktualisiert. - Gibt sofort
200 OKzurück — SharePoint erfordert eine Antwort innerhalb weniger Sekunden.
Geplante Benachrichtigungsverarbeitung
SchedulerNotificationwird alle 5 Minuten ausgelöst.- Ruft alle aktiven
AlertInfo-Datensätze und unverarbeitetenTriggerEventspro Mandant ab. - Ereignisse werden vor der Verarbeitung nach Listen-GUID dedupliziert.
- Für jedes
AlertInfomit einem passendenTriggerEventwirdChangeManager.ProcessNotification()ausgeführt: SharePoint-Zugriffstoken über MSAL mit Zertifikat-Credentials erwerben; geänderte Elemente aus SharePoint über CSOM abrufen undLastChangedTokenals Delta-Cursor verwenden;ChangeType- undAlertType-Filter anwenden; Benachrichtigung versenden. - Verarbeitete
TriggerEventswerden als abgeschlossen markiert und gelöscht.
Protokollansicht
- Benutzer öffnet "My Notifications" → Registerkarte "Log entries".
- SPFx ruft
GET /api/alertlog/{alertId}auf; Backend gibtISPNotifyLog[]zurück. - Eine
DetailsListzeigt Kanaltyp, Empfänger, Elementanzahl und Zeitstempel an. - Durch Klicken auf eine Protokollzeile öffnet sich ein Dialog, der den vollständigen HTML-E-Mail-Text rendert.
API-Vertrag
Die gesamte Frontend-zu-Backend-Kommunikation verwendet diese zehn REST-Endpunkte. Jede Anfrage muss ein Bearer-Token und den SPTenantID-Header enthalten.
| Endpunkt | Methode | Frontend-Aufrufer | Request-Body | Antwort |
|---|---|---|---|---|
| /api/alertmngr/create | POST | AlertService.createAlert() | IAlertInfo | 201 |
| /api/alertmngr/update | POST | AlertService.updateAlert() | IAlertInfo | 200 |
| /api/alertmngr/delete | POST | AlertService.deleteAlert() | { ID, ListId } | 204 |
| /api/alerts4list/{listGuid} | GET | AlertService.getAlerts() | — | 200 |
| /api/alerts/{id} | GET | AlertService.getAlert() | — | 200 |
| /api/alertlog/{alertId} | GET | AlertService.getAlertLogs() | — | 200 |
| /api/configmngr/create | POST | ConfigurationService.createConfiguration() | ITenantConfiguration | 201 |
| /api/configmngr/update | POST | ConfigurationService.updateConfiguration() | ITenantConfiguration | 200 |
| /api/configmngr/delete | POST | ConfigurationService.deleteConfiguration() | { ID } | 204 |
| /api/configmngr/tenant/{tenantId} | GET | ConfigurationService.getConfiguration() | — | 200 |
POST /api/webhook wird nicht vom Frontend aufgerufen — er wird direkt von der SharePoint-Abonnement-Infrastruktur aufgerufen. Er validiert clientState anstelle eines Bearer-Tokens.Gemeinsame Datenmodelle
TypeScript-Frontend-Interfaces und C#-Backend-Klassen spiegeln sich genau wider. Enum-Integer-Werte sind in beiden Codebasen identisch — keine Transformationsschicht erforderlich.
IAlertInfo ↔ AlertInfo
| TypeScript (IAlertInfo) | C# (AlertInfo) | Typ |
|---|---|---|
| ID | ID | number / long |
| AlertTitle | AlertTitle | string |
| SendAlertsTo | SendAlertsTo | string[] / List<string> |
| DeliveryMethod | DeliveryMethod | DeliveryMethod-Enum |
| AlertType | AlertType | AlertType-Enum |
| ChangeType | ChangeType | ChangeType-Enum |
| FilterViewId | FilterViewId | string? |
| AlertFrequency | AlertFrequency | AlertFrequency-Enum |
| SummaryDay | SummaryDay | number? / int? |
| SummaryTime | SummaryTime | string? |
| ExpirationDate | ExpirationDate | Date? / DateTime? |
| IsAlertActive | IsAlertActive | boolean / bool |
| TeamsID | TeamsID | string? |
| ChannelID | ChannelID | string? |
| ListId | ListId | string (GUID) |
| ListName | ListName | string |
| SiteName | SiteName | string |
| SPSiteUrl | SPSiteUrl | string? |
| TenantID | TenantID | string? (GUID) |
| UserID | UserID | string? |
| SubscriptionID | SubscriptionID | string? (GUID) |
| LastChangedToken | LastChangedToken | string? |
| LastNotificationProcessed | LastNotificationProcessed | Date? / DateTime? |
| NextNotificationToProcess | NextNotificationToProcess | Date? / DateTime? |
Enumerationen
Alle Enums werden wörtlich zwischen TypeScript und C# geteilt. Integer-Werte werden über die Leitung serialisiert und müssen über Deployments hinweg stabil bleiben.
Benachrichtigungskanäle
Das Backend unterstützt vier ausgehende Zustellungskanäle, die pro Alert basierend auf DeliveryMethod ausgewählt und von ChangeManager.ProcessNotification() ausgeführt werden, nachdem der CSOM-Diff qualifizierende Änderungen bestätigt.
POST /v1.0/users/{sender}/sendMail
Absender EMailFrom muss ein lizenziertes Exchange-Postfach im Mandanten sein.
Inhalt HTML-Body erstellt von MailManager, fasst hinzugefügte/aktualisierte/gelöschte Elemente zusammen.
Empfänger Anzeigenamen werden vor dem Senden über Microsoft Graph aufgelöst.
TenantConfiguration.
Inhalt Nur-Text-Nachricht. SendUrlInSms-Flag fügt die Element-URL an.
Anbieter Anbieterunabhängig — jedes HTTP-basierte Gateway kann pro Mandant konfiguriert werden.
TeamsBotAppID / TeamsBotPassword.
Inhalt TeamsManager formatiert als Adaptive Card, die im Zielkanal gepostet wird.
Ziel TeamsID + ChannelID, die bei der Alert-Erstellung über Graph me/joinedTeams ausgewählt werden.
TenantConfiguration.
Inhalt Nur-Text-Nachricht mit optionaler Element-URL. Zugestellt an das WhatsApp-Konto des Empfängers.
Empfänger Telefonnummer in WhatsAppPhoneNumber am Alert-Abonnement gespeichert.
Anbieter Kompatibel mit jedem WhatsApp Business API-konformen Gateway.