Você está na página 1de 7

Building Event Receivers

E vent Receivers (formerly known as event handlers) are yet another tool in the arsenal
for working with and extending SharePoint. Event Receivers are code assemblies that
you can attach to a given list or library type and that allow you to respond to a given
event, such as an item being changed. Receivers provide a way to extend SharePoint both
internally and externally, because receivers are not bound to SharePoint. They are started and
run by SharePoint and have complete access to the SharePoint object model (and subsequently
any lists, libraries, sites, and so on, within it), but as a .NET assembly, they can call web
services, access databases, and they can even send e-mail.
Event Receivers apply to all items within SharePoint including lists and libraries. When
an event occurs—such as a file move, a document upload, or similar—the receiver is notified
about the event that occurred, as well as about what the item (and columns) looked like
before and after the event. This also includes some trapping; for example, a file delete can
be prevented before it occurs.
The mechanics of an Event Receiver are the same as for Features or web parts; Feature
definition files are used to define the assembly and also to define the type of list/library (and
the events in that list) that the receiver will listen for. Multiple receivers can also work on the
same list type (like a workflow). Like a Feature, they can be enabled or disabled by site.
What Receivers Are For
Event Receivers give you the ability to react to a list or library event within SharePoint,
which includes adding, updating, and deleting any item. For example, a Receiver might
trigger when a Task Item is created and in turn, create a Calendar Item on another site.
One receiver can react to any number of events.
You might be asking yourself why you would use Event Receivers when you have alerts
and built-in workflows. The answer is simple: there are times when a workflow is too much
or not enough; for example, if you want to send an e-mail message to a third party (like an
auditor) when a certain document type is published. If you’re not a member of the site, you
can’t use alerts. You could create a very simple workflow, but you would have to add it
everywhere. An Event Receiver is tied to a list type, can run on all sites, and can easily
handle such one-off or otherwise unique activities.
Event Receivers are really good for handling integrity, one-off situations, and for extending
SharePoint beyond what workflows can do and into other systems like Microsoft BizTalk
and CRM. On the integrity side, Event Receivers can be used to ensure that items are

correctly entered or that certain conditions are met before permitting a change. Event
Receivers provide before and after methods, which permit you to catch what’s changing
before it changes. To extend SharePoint, Event Receivers can call web services, update
databases, provide input to backend systems, and so on
While it’s tempting, receivers shouldn’t be used to create user workflows. They are only
tied to a list type, and any processing between different receivers, lists, and sites must be
managed by the developer. As code, they cannot be changed easily and are not accessible to
the users except to turn them on and off. As well, they have some quirks (as you’ll read later
in the chapter) that require double-checking statuses and other tasks that make them unusable
for some situations.

Anatomy of Event Receivers


Event Receivers are simply .NET classes that inherit from the SPItemEventReceiver class
in the same way that web parts inherit the WebPart class (though SPItemEventReciever is
a SharePoint namespace, not .NET). This class gives you all of the methods that could be
invoked, both in response to an event and within the properties of the event, which includes
the event type, the site it is in, the list, the list item that triggered the event, and so on. It also
provides functions such as Cancel, which enables you to stop an event.
You can consider an Event Receiver a broad brush when working with events. Unlike
a workflow attached to a specific list, receivers are installed at the site level and are based
on listening to a specific type of list. The type of list the receiver looks for is found by the
template ID of the list (for example, an Events List Type is 106). Any list of the specified
type will cause the receiver to fire (regardless of name/page).
The methods are fairly self explanatory. ItemAdding, for example, indicates that an item
is about to be added. For most event types, there are two parts: ItemAdding, followed by
ItemAdded, which gives you a two-state view of the event, before it happens and after the
event has completed. However, you should note that this is threaded and that you can
manage both states, but you cannot pass between them. For example, if you were to process
something during the ItemUpdating event, you can’t carry it over to the ItemUpdated
event, because it runs as a separate instance. In short, each individual event step runs in
its own instance of the Event Receiver.
Any particular method(s) you want to use within an Event Receiver are overridden using
the standard override method, and you only need to specify the methods you want to use.
You can access ItemUpdated only, for example, if that is the only event you are concerned
with. The override statement in the code also includes the SharePoint Object Model
SPItemEventProperties object, which provides you access to the event details (who fired
it, data within it, and so on). The statement looks like this:
public override void ItemUpdated(SPItemEventProperties properties)
{
base.ItemUpdated(properties);
}
Notice that I’ve also included the base.ItemUpdated line; this ensures that the SPItemEvent
inherited code is run before your custom code is. This isn’t mandatory, but I do it as a best
practice. The complete list of methods is as follows:
• ContextEvent This fires at the start of any event but is not accessible.
• ItemAdded This means that an item has been added.

• ItemAdding This means that an item is about to be added.


• ItemAttachmentAdding This means that a file attachment is being added.
• ItemAttachmentAdded This means that a file attachment has been added.
• ItemAttachmentDeleting This means that a file attachment is about to
be deleted.
• ItemAttachmentDeleted This means that a file attachment has been deleted.
• ItemCheckingIn This means that an item is about to be checked in.
• ItemCheckedIn This means that an item is checked in.
• ItemCheckingOut This means that an item is about to be checked out.
• ItemCheckedOut This means that an item is checked out.
• ItemDeleting This means that an item is about to be deleted.
• ItemDeleted This means that an item has been deleted.
• ItemFileMoving This means that a file is about to move.
• ItemFileMoved This means that a file move is complete.
• ItemFileTransformed This means that a file exists but cannot be overridden;
actual use of this is not documented.
• ItemUncheckingOut This means that an item is about to be unchecked out.
• ItemUncheckedOut This means that an item has been unchecked out.
• ItemUpdating This means that the item is about to be updated.
• ItemUpdated This means that an item has been updated.

Within an Event Receiver, you can expose any or all of the events you need, based on
the way they fire and, of course, what you want to do. Since you have complete access (in
most cases) to what caused the event, you also can make decisions like “Only react to the
event if the list name is X” or “Only update the status if the status in another list is set.” The
basic event firing pattern is shown in Table 19-1.
As you can see, the naming of the methods matches the way that they fire, although you
have to watch out for those that fire additional events (such as an Add with an Attachment).
One thing to be aware of is how Event Receivers are executed within SharePoint. While
invoked by an event, you are running alongside the SharePoint process, and you’re not part
of it like a web part is. This means that your logic is based on background functionality, and
you cannot interact with the User Interface, prompt users for information, and so on. Also,
you don’t have a web context like you do in a web part; you must use the Properties object
in order to determine things such as the site you are running in. Basically, it’s like a standalone
application that simply uses SharePoint to start it up.

Creating an Event Receiver


Creating a new Event Receiver is a fairly straightforward process. Once the shell has been
created, you simply add the necessary logic to the methods you choose. Packaging it up
for SharePoint is done the same way as for any Feature, although the Elements Manifest
definitions are unique for Event Receivers (they are used to tie a receiver to a list type). Of
course, before you build one, you should balance it against the other tools available, since
they don’t offer the kind of flexibility that a web part (with properties) or a workflow does.
I like to use them for background-type activities like dealing with events that don’t really
need a workflow and don’t need an interface like a web part. They can also be used to handle
things that might otherwise need a timer job and can prevent things from happening (such
as a delete).

Unlike other features where you identify what is


available in the Elements file, for receivers this file is used to indicate which type of
list and what kind of events to fire on (remember this means every list of that type in
the site!). For each list type (the List Template ID from the ONET.XML file definitions;
the SDK has the complete list), there is a section for each type of event to be triggered,
which includes the name of the assembly (in this example, DocStatusEventHandler),
the event type, a sequence number (receivers can run in a sequential format), and the
assembly and data information that would be included in a normal Elements file. For
this example, you need to define a receiver for a Document Library Type (type 102)
and two events: ItemUpdated and ItemDeleting. To create the Elements file, you’ll
also need the PublicKeyToken of the class you’ve just built (after it has been signed).
To get this key, select Start | All Programs | Microsoft Visual Studio 2005 | Visual
Studio Tools | Visual Studio 2005 Command Prompt (using the VS command prompt
includes the path needed to the sn.exe file used here). From the command prompt,
change your directory to the debug directory in your project.

Enter the command SN -T DocStatusEventHandler.dll (the -T must be capitalized)


and record the 16-character string returned. This is the public key token for the
assembly.

Deploying the Event Receiver


Deploying Event Receivers is a little easier than deploying a web part because you only
need the DLL and the Feature Definition files to deploy it. You should note, however, that
Event Receivers must be installed in the Global Assembly Cache (GAC) to operate. Typically,
you would set up a package to deploy it like a regular feature; however, you can manually
deploy it as well

A Sample List Event Receiver Class

using System;
using System.IO;
using System.Collections.Generic;
using System.Text;
using Microsoft.SharePoint;
namespace ListMetaLogger
{
public class ListMetaLogger : SPListEventReceiver
{
public override void FieldAdded(SPListEventProperties properties)
{
LogEvent(properties, “FieldAdded”);
}
public override void FieldAdding(SPListEventProperties properties)
{
LogEvent(properties, “FieldAdding”);
}
public override void FieldDeleting(SPListEventProperties properties)
{
LogEvent(properties, “FieldDeleting”);
}
public override void FieldDeleted(SPListEventProperties properties)
{
LogEvent(properties, “FieldDeleted”);
}
public override void FieldUpdated(SPListEventProperties properties)
{
LogEvent(properties, “FieldUpdated”);
72 CHAPTER 7 Handling List Events
}
public override void FieldUpdating(SPListEventProperties properties)
{
LogEvent(properties, “FieldUpdating”);
}
private void LogEvent(SPListEventProperties properties, string eventName)
{
StreamWriter sw = File.AppendText(@”C:\listeventlog.txt”);
StringBuilder sb = new StringBuilder();
sb.AppendFormat(“[{0}] {1} Event Occurred:\n”,
DateTime.Now.ToString(), eventName);
sb.AppendFormat(“\tList : {0}”, properties.ListTitle);
sb.AppendFormat(“\t{0} - Field {1}”,
properties.EventType.ToString(), properties.FieldName);
sw.WriteLine(sb.ToString());
sw.Close();
}
}
}

Deploying Event Receivers


You can deploy event receivers in three different ways:
. Deploying programmatically
. Deploying via Features
. Deploying with Content types
Regardless of how you deploy the event receivers, the class library that you created that
contains the event receiver class must be strongly named (signed with a key) and must
also be installed in the Global Assembly Cache (GAC).
Deploying Event Receivers Programmatically
If you want your event receivers to only be associated with a single instance of a list
rather than with all lists of a certain template ID (Table 7.5 in the next section shows all
the built-in template IDs), you can write some code to manually register your event
receivers with a given list.
The following code snippet shows how to associate an event receiver class and Assembly
with a specific list by calling the Add method on the EventReceivers collection. Once the
new receiver has been created, you need to give it the fully qualified assembly name that
points to the code you have written and deployed as well as provide a sequence number
and indicate the type of event to which the receiver responds.
SPWeb webSite = new SPSite(“http://win2k3r2lab”).OpenWeb();
SPList theList = webSite.Lists[“Tasks”];
SPEventReceiverDefinition newReceiver = theList.EventReceivers.Add();
newReceiver.Class = “Receiver.ReceiverClass”;
newReceiver.Assembly =
“Receiver,Version=1.0.0.0,Culture=neutral,PublicKeyToken=abc123abc123abc”;
newReceiver.Sequence = 5000;
newReceiver.Type = SPEventReceiverType.ItemUpdated;
newReceiver.Update();
Deploying Event Receivers with Features
The problem with deploying event receivers by manually writing code that installs the
receiver against a specific instance of a list is that you don’t get much reuse benefit from
that receiver.
When developing SharePoint Solutions that include code that responds to list events,
those event receivers are often part of a Feature definition. When including an event
receiver in a Feature definition, you can indicate the type of list for which your code will
be listening for events by specifying the list’s template ID in the Feature definition itself.
Deploying Event Receivers 77
7
Listings 7.3 and 7.4 show the Feature.xml and Elements.xml files that configure a
Feature that contains a list item event receiver.
LISTING 7.3 Feature.xml
<Feature Scope=”Web”
Title=”List Item Event Logger”
Id=”{EF0917F4-5ED8-40b1-9A37-585BCDE9DB63}”
xmlns=”http://schemas.microsoft.com/sharepoint/”>
<ElementManifests>
<ElementManifest Location=”Elements.xml”/>
</ElementManifests>
</Feature>
LISTING 7.4 Elements.xml
<Elements xmlns=”http://schemas.microsoft.com/sharepoint/”>
<Receivers ListTemplateId=”107”>
<Receiver>
<Name>EventLogger</Name>
<Type>ItemAdded</Type>
<SequenceNumber>10000</SequenceNumber>
<Assembly>EventLogger, Version=1.0.0.0, Culture=neutral,
➥PublicKeyToken=5d1d751131e0aacf</Assembly>
<Class>EventLogger.ListEventLogger</Class>
<Data></Data>
<Filter></Filter>
</Receiver>
<Receiver>
<Name>EventLogger</Name>
<Type>ItemUpdated</Type>
<SequenceNumber>10000</SequenceNumber>
<Assembly>EventLogger, Version=1.0.0.0, Culture=neutral,
➥PublicKeyToken=5d1d751131e0aacf</Assembly>
<Class>EventLogger.ListEventLogger</Class>
<Data></Data>
<Filter></Filter>
</Receiver>
<Receiver>
<Name>EventLogger</Name>
<Type>ItemDeleted</Type>
<SequenceNumber>10000</SequenceNumber>
<Assembly>EventLogger, Version=1.0.0.0, Culture=neutral,
➥PublicKeyToken=5d1d751131e0aacf</Assembly>
<Class>EventLogger.ListEventLogger</Class>
78 CHAPTER 7 Handling List Events
<Data></Data>
<Filter></Filter>
</Receiver>
</Receivers>
</Elements>
After you have the Feature.xml and Elements.xml files, you can deploy them into your
SharePoint Template\Features directory. After they are in the directory, use the following
stsadm.exe command to install the Feature:
Stsadm –o installfeature –filename FeatureDirectory\Feature.xml
Use the following stsadm.exe command to activate the Feature on your website (make
sure you change the relative directory paths and URLs to match your configuration):
Stsadm –o activatefeature –filename FeatureDirectory\Feature.xml –url
➥“http://server/web site”
After you install and activate the Feature, you must run iisreset for SharePoint to start
making use of the newly registered event receivers.

Deploying Event Receivers with Content Types


Deploying event receivers with content types follows the same pattern as deployment
with Features. First, you must create the strongly named, signed Assembly and place it in
the GAC of the destination server. If you are deploying to a farm, the event receiver
Assembly must be in the GAC of every front-end server. After the Assembly has been
deployed, it is just a matter of creating a content type with a Feature and using the procedure
for Feature-based event receiver deployment discussed in the preceding section.

Você também pode gostar