Was sind Event Handler?
Event Handler sind eine der nützlichsten Dinge, die es in WSS gibt. Es gibt sehr viele Events, auf die man einen Handler setzen kann, um dann bestimmte Aufgaben automatisiert erledigen zu können.
Beispielsweise können mit einem Event Handler beim Erzeugen eines neuen Elements in einer Liste bestimmte Attribute gesetzt werden oder das Element an einen anderen Ort kopiert werden. Oder, wie ich es in letzter Zeit häufig benötigte, können auch Berechtigungen gesetzt werden. Doch hier muss man dann sehr aufpassen, wie in einem späteren Kapitel noch erklärt werden wird.
Für folgende Ereignisse können Event Handler registriert werden:
Microsoft.SharePoint.SPWebEventReceiver : "Site Level"
- SiteDeleted
- SiteDeleting
- WebDeleted
- WebDeleting
- WebMoved
- WebMoving
Microsoft.SharePoint.SPListEventReceiver : "List Level"
- FieldAdded
- FieldAdding
- FieldDeleted
- FieldDeleting
- FieldUpdated
- FieldUpdating
Microsoft.SharePoint.SPItemEventReceiver : "List Item Level"
- ItemAdded
- ItemAdding
- ItemAttachmentAdded
- ItemAttachmentAdding
- ItemAttachmentDeleted
- ItemAttachmentDeleting
- ItemCheckedIn
- ItemCheckedOut
- ItemCheckingIn
- ItemCheckingOut
- ItemDeleted
- ItemDeleting
- ItemFileConverted
- ItemFileMoved
- ItemFileMoving
- ItemUncheckedOut
- ItemUncheckingOut
- ItemUpdated
- ItemUpdating
Einen Event Handler kann man auf zwei Arten im System registrieren:
- Über eine Feature-Definition, die mit Hilfe von stsadm.exe installiert (und aktiviert) wird
- Über das kostenlose Tool Event Handler Explorer, mit dem Klassen über eine GUI als Event Handler registriert werden können, ohne ein eigenes Feature dafür schreiben zu müssen
Event Handler werden im Kontext des Benutzers ausgeführt
Das Wichtigste, das ein Entwickler von Event Handlern wissen sollte ist, dass Event Handler im Kontext des Benutzers ablaufen. Dies kann durchaus zu Problemen oder unerwünschten Ergebnissen führen.
Beispiel 1: Sie möchten einen Event Handler dazu nutzen, in einer Liste doppelte Einträge in einem bestimmten Feld zu vermeiden, auf die einzelnen Datensätze werden aber eigene Berechtigungen gesetzt.
Wenn Sie die Liste nun durchgehen, erhalten Sie automatisch nur diejenigen Elemente, auf die Sie mindestens Leserechte haben, alle anderen bleiben verborgen.
Effekt: Es können trotzdem doppelte Datensätze vorhanden sein!
Beispiel 2: Sie möchten automatische Berechtigungen setzen lassen, wenn ein Element hinzugefügt oder geändert wird. Dazu brechen Sie die Vererbung auf, und löschen alle bisherigen RoleAssignments aus der Collection, um ganz sicher zu gehen.
Effekt: Sobald Sie Ihre eigene RoleAssignment gelöscht haben, verschwindet der Datensatz für Sie im Nirvana, da die Änderungen sofort greifen.
Lösung: Sie müssen die Änderungen in einem anderen Benutzerkontext, am Besten aus dem des Systems vornehmen. Dieses besitzt alle Berechtigungen, ungeachtet von vorhandenen RoleAssignments oder Beschränkungen.
Mit folgendem Code können Sie beispielsweise alle Rechte von einem Element löschen, ohne Beeinträchigungen. Natürlich sollten Sie danach auch wieder bestimmten Benutzern Rechte geben ;)
public override void ItemAdded(SPItemEventProperties properties) { this.DisableEventFiring(); base.ItemAdded(properties); Guid webId = properties.OpenWeb().ID; SPSecurity.RunWithElevatedPrivileges(delegate() { { SPWeb web = site.OpenWeb(webId); SPList list = web.Lists[properties.ListId]; SPListItem item = list.Items.GetItemById(properties.ListItemId); //Rechte entfernen item.BreakRoleInheritance(false); //Ab hier können Sie mit dem Element trotzdem weiter arbeiten //[...] } }); this.EnableEventFiring(); }
After-, BeforeProperties und ListItem
Der Parameter properties jedes EventHandlers beinhaltet alle Daten, die man für den EventHandler benötigt. Leider sind manche davon nicht ganz so einfach zu handhaben.
Die Eigenschaft AfterProperties (SPItemEventDataCollection) enthält beispielsweise alle Eigenschaften, die das Element nach dem Update haben wird. Dies ist insbesondere bei den beiden Events ItemUpdating und ItemAdding notwendig. Das ListItem selbst reflektiert den aktuellen Status, im Falle der synchronen EventHandler (ItemAdding, ItemUpdating,...) also den Status des Elements vor dem Event und im Falle asynchronen (ItemAdded, ItemUpdated, ...) nach dem Event.
Die Eigenschaft BeforeProperties kann man gleich wieder vergessen, genauso wie die Eigenschaften ChangedProperties innerhalb der SPItemEventDataCollection-Klasse, diese werden überhaupt nicht befüllt.
Um also feststellen zu können, was sich beispielsweise nach dem Event ItemUpdating ändern wird muss Feld um Feld zwischen ListItem und AfterProperties verglichen werden. Das funktioniert sehr gut, bis auf eine Ausnahme: Lookup-Felder! Wie immer, sind diese Felder besonders zu behandeln, ganz besonders im Falle von ListItem und AfterProperties.
SPListItem enthält die Daten als NameValueCollection, in der Form [Key];#[Displaywert], im Falle eines Benutzerfeldes (ja, auch das sind Lookup-Felder!) z.B. 45;#Hans Wurst. Dashat nun natürlich einen gravierenden Nachteil für Vergleiche, hierfür muss man von der Eigenschaft in ListItem nur den Key nehmen und diesen mit dem Inhalt des Feldes in AfterProperties vergleichen.