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.

Designziel. Die native SharePoint-Alert-Funktion wurde von Microsoft eingestellt. SP Notify besitzt jeden Abonnement-, Zustell- und Protokolldatensatz vollständig — und gibt Teams vollständige Kontrolle über Formatierung, Häufigkeit und Kanal-Routing, die das eingestellte System nie geboten hat.

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.

1
Benutzer öffnet SharePoint-ListenseiteSharePoint lädt die SPFx ListViewCommandSet-Erweiterung und rendert den "My Notifications"-Symbolleistenbefehl.
2
SPFx fordert ein Zugriffstoken anDie Erweiterung ruft AadHttpClient auf, der SharePoints Token-Brokering verwendet, um ein JWT für api://<client-id> von Azure AD anzufordern. Keine Weiterleitung oder Popup erforderlich.
3
Azure AD gibt ein signiertes JWT zurückDas Zugriffstoken ist auf die registrierte Anwendung beschränkt und enthält die Identitäts-Claims des Benutzers.
4
SPFx ruft das Backend mit zwei erforderlichen Headern aufAuthorization: Bearer <token> enthält das JWT. SPTenantID: <tenant-guid> identifiziert den aufrufenden Mandanten, damit das Backend den korrekten OIDC-Metadaten-Endpunkt auflösen kann.
5
Backend ruft OIDC-Signierungsschlüssel ab (gecacht)Das Backend verwendet TokenValidatorCache, um die OpenID Connect-Metadaten und Signierungsschlüssel des Mandanten abzurufen und zu cachen, wodurch wiederholte Anfragen bei nachfolgenden Requests vermieden werden.
6
JWT-Signatur und Laufzeit werden validiertDas Backend validiert die Token-Signatur gegen die gecachten Signierungsschlüssel und prüft den Ablauf. Bei Erfolg fährt die Funktion fort; bei Fehler gibt sie 401 zurück.
Der 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

[DS.SP.Notify.TenantConfiguration]
TenantId // Primärschlüssel — Azure AD Mandanten-GUID
ClientId // Entra App-Registrierungs-Client-ID
ClientSecret // Client-Secret oder Zertifikat-Thumbprint
Certificate // X.509-Zertifikat für MSAL
SiteUrl // SharePoint-Websitesammlungs-URL
WebhookNotificationUrl // Öffentliche HTTPS-URL für SP-Webhook-Zustellung
EMailFrom // Lizenziertes Postfach für Graph sendMail
TeamsBotAppID // Bot Framework App-ID
TeamsBotPassword // Bot Framework App-Passwort
TeamsTrafficManagerServiceUrl // Bot Connector-Endpunkt

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.
  • TokenValidatorCache pflegt separate OIDC-Validierungsparameter pro Mandant (Signierungsschlüssel, Aussteller-URI).
  • SchedulerNotification iteriert alle registrierten Mandanten unabhängig und instanziiert pro Ausführung einen separaten ChangeManager und Credential-Satz pro Mandant.
  • Alle SQL-Abfragen enthalten ein TenantID-Prädikat — es gibt keine mandantenübergreifenden Abfragen.

Onboarding eines neuen Mandanten

1
Entra-App registrierenErstellen Sie eine App-Registrierung im Azure AD des Zielmandanten. Erteilen Sie die erforderlichen Graph- und SharePoint-Berechtigungen. Laden Sie ein Zertifikat für die MSAL-Authentifizierung hoch.
2
SPFx-Paket deployenLaden Sie das .sppkg-Bundle in den SharePoint App Catalog des Mandanten hoch und genehmigen Sie die API-Berechtigungen, damit die Erweiterung Token erwerben kann.
3
Mandanten-Datensatz erstellenVerwenden Sie das 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.

Phase 1

Alert erstellen

  1. Benutzer klickt auf "My Notifications" in der SharePoint-Listen-Symbolleiste.
  2. SPFx lädt AlertFormPanel und ruft GET /api/alerts4list/{listId} auf, um bestehende Alerts vorab zu laden (auf den Benutzer beschränkt).
  3. Benutzer füllt das Alert-Formular aus und klickt auf OK.
  4. SPFx ruft POST /api/alertmngr/create mit dem vollständigen IAlertInfo-Payload einschließlich des über PnPjs erfassten LastChangedToken auf.
  5. Backend validiert das Bearer-Token, schreibt AlertInfo in SQL und prüft auf bestehende Webhook-Abonnements über DBWebHookEntriesManager.
  6. Wenn kein Webhook vorhanden ist, erwirbt es ein OBO-Token und ruft WebhookService.RegisterWebhookAsync() mit clientState = "AlertID-{id}" auf.
  7. Gibt 201 Created mit dem gespeicherten AlertInfo einschließlich Datenbank-ID und SubscriptionID zurück.
Phase 2

Änderungserkennung über SharePoint-Webhook

  1. Ein Listenelement wird in SharePoint hinzugefügt, aktualisiert oder gelöscht.
  2. SharePoint sendet POST /api/webhook mit einem SpNotificationPayload mit der Abonnement-ID, clientState, Listen-GUID, Mandanten-ID, Website-URL und Web-ID.
  3. SharePointWebhookReceiver überprüft, ob clientState mit "AlertID-" beginnt, und speichert dann einen TriggerEvent in SQL (fire-and-forget).
  4. Bei der ersten Webhook-Bestätigung wird SubscriptionID im AlertInfo-Datensatz aktualisiert.
  5. Gibt sofort 200 OK zurück — SharePoint erfordert eine Antwort innerhalb weniger Sekunden.
Phase 3

Geplante Benachrichtigungsverarbeitung

  1. SchedulerNotification wird alle 5 Minuten ausgelöst.
  2. Ruft alle aktiven AlertInfo-Datensätze und unverarbeiteten TriggerEvents pro Mandant ab.
  3. Ereignisse werden vor der Verarbeitung nach Listen-GUID dedupliziert.
  4. Für jedes AlertInfo mit einem passenden TriggerEvent wird ChangeManager.ProcessNotification() ausgeführt: SharePoint-Zugriffstoken über MSAL mit Zertifikat-Credentials erwerben; geänderte Elemente aus SharePoint über CSOM abrufen und LastChangedToken als Delta-Cursor verwenden; ChangeType- und AlertType-Filter anwenden; Benachrichtigung versenden.
  5. Verarbeitete TriggerEvents werden als abgeschlossen markiert und gelöscht.
Phase 4

Protokollansicht

  1. Benutzer öffnet "My Notifications" → Registerkarte "Log entries".
  2. SPFx ruft GET /api/alertlog/{alertId} auf; Backend gibt ISPNotifyLog[] zurück.
  3. Eine DetailsList zeigt Kanaltyp, Empfänger, Elementanzahl und Zeitstempel an.
  4. 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/createPOSTAlertService.createAlert()IAlertInfo201
/api/alertmngr/updatePOSTAlertService.updateAlert()IAlertInfo200
/api/alertmngr/deletePOSTAlertService.deleteAlert(){ ID, ListId }204
/api/alerts4list/{listGuid}GETAlertService.getAlerts()200
/api/alerts/{id}GETAlertService.getAlert()200
/api/alertlog/{alertId}GETAlertService.getAlertLogs()200
/api/configmngr/createPOSTConfigurationService.createConfiguration()ITenantConfiguration201
/api/configmngr/updatePOSTConfigurationService.updateConfiguration()ITenantConfiguration200
/api/configmngr/deletePOSTConfigurationService.deleteConfiguration(){ ID }204
/api/configmngr/tenant/{tenantId}GETConfigurationService.getConfiguration()200
Hinweis zum Webhook-Endpunkt. 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
IDIDnumber / long
AlertTitleAlertTitlestring
SendAlertsToSendAlertsTostring[] / List<string>
DeliveryMethodDeliveryMethodDeliveryMethod-Enum
AlertTypeAlertTypeAlertType-Enum
ChangeTypeChangeTypeChangeType-Enum
FilterViewIdFilterViewIdstring?
AlertFrequencyAlertFrequencyAlertFrequency-Enum
SummaryDaySummaryDaynumber? / int?
SummaryTimeSummaryTimestring?
ExpirationDateExpirationDateDate? / DateTime?
IsAlertActiveIsAlertActiveboolean / bool
TeamsIDTeamsIDstring?
ChannelIDChannelIDstring?
ListIdListIdstring (GUID)
ListNameListNamestring
SiteNameSiteNamestring
SPSiteUrlSPSiteUrlstring?
TenantIDTenantIDstring? (GUID)
UserIDUserIDstring?
SubscriptionIDSubscriptionIDstring? (GUID)
LastChangedTokenLastChangedTokenstring?
LastNotificationProcessedLastNotificationProcessedDate? / DateTime?
NextNotificationToProcessNextNotificationToProcessDate? / 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.

DeliveryMethod
0Email
1SMS
2Teams
3WhatsApp
AlertType
0All
1Updated
2Added
3Removed
AlertFrequency
0Immediate
1Daily summary
2Weekly summary
ChangeType
0Anything changes
1Someone else changes
2Someone else changes (created by me)
3Someone else changes (modified by me)
4Item in view changes

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.

💬 SMS
Zustellung HTTP POST an einen konfigurierten SMS-Gateway-Endpunkt in 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.
🟣 Teams
Zustellung Teams Bot Connector mit 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.
🟢 WhatsApp
Zustellung HTTP POST an den WhatsApp Business API-Endpunkt in 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.