SharePoint: Writing a Custom Event Receiver

Posted by: Sumit Maitra , on 2/9/2011, in Category SharePoint
Views: 97144
Abstract: In this article we will see how to create a Custom Event Receiver in Sharepoint and tie it up to a site as a SharePoint Feature.

In my previous articles I have discussed how we can use custom content types and custom page layouts to define document structure in SharePoint. It did not involve any coding or customization. In this article we’ll continue where we left off and see how we can add a hook in SharePoint and enhance the content creation and approval process to make it more valuable to end users.

Business Case

If we look at our example of creating a custom Content Type for “Functional Specifications”, we could extrapolate it to many different types of documents typically used in an enterprise, e.g. Policy documents, Functional Specs, Technical Specs, Time Sheets, Work-Orders etc. Custom Content types help us with defining the data-structure while layouts help us define the presentation. What if these documents were to require review and approval? SharePoint as most us know, has built in workflow capabilities. In SP 2010, workflows have been made pretty obvious. In fact our custom Pages will not be visible to everyone if we don’t actually publish them and the only way to do that is to start the approval workflow. Okay fine, workflows are still out of box, what are we doing new in that? Well nothing directly.

Imagine what would happen after a document (like our Functional Spec) is approved? A team would start using it. Development cycle would start. Ten days into development new requirements would come in and the spec would have to be re-visited and re-routed for approval. Until the document is approved again it would no longer be in ‘Published’ state. To view the previous state would be slightly messy. Instead of using the out of box revision history, if we built a capability where after every “Publish” the content is converted into a read-only format (like HTML/doc/pdf) and kept in a different location, it would solve our problem. If that location is a version controlled document library, then each version of the complete document would be available for anytime reference! Sounds good, how do we do it?

Hello, SharePoint “Event Receivers”

SharePoint has this infrastructure built in where certain SP objects raise events that can be handled by custom code. The event of interest to us is the ItemUpdated event fired by any SPList. This event is fired every time you make a change and save your list item. If you have a hook in place you can view the entire content and its current values in Event Receiver. So, enough of theory, let’s get hands on and build our own Event Receiver feature for SharePoint 2010.

Building a SharePoint Event Receiver Feature

Visual Studio 2010 makes development for SharePoint really painless. The following steps will help us setup and build an Event Receiver in no time.

Step 1: Start off with a new project and select the “SharePoint 2010” template. Select “Event Receiver” project type. I’ve given the Project name as “CustomContentPublishFeature”. Click OK.

Sharepoint Event Receiver

Step 2 The SharePoint Customization Wizard will come up as shown below. It gives you two deployment options for your feature, one is Sandboxed and other is Farm deployment. I selected Sandboxed because I want the feature to be limited to the site collection where I am publishing only.

sharepoint sandbox

Click next to get to the “Event Receiver Settings” page.

Step 3: As seen below we’ve selected our “Type of event receiver” to be “List Item Events” and “Event Source” to be the “Pages Library” because that’s the library use has the pages that have our custom content type.

sharepoint customization wizard

From the list of events that can be handled, select “An item was updated”. You can add more events later too.

Step 4: Click Finish and wait for Visual Studio to do the skeleton work for you. In VS 2008 you have to do most of the skeleton work yourself, but in VS 2010 it’s all setup for you. Once VS finishes processing, you will have a solution structure similar to the below image.

Step 5: The event receiver class will be called EventReciever1. I’ve renamed it to PublishingsPageEventReceiver. I had to rename the class file and the CS file manually.

publishings page event receiver

You will notice as a part of the EventReceiver you’ve a cs file and an xml file called Elements.xml. The Elements file is a kind of glue that binds your code to SP Event framework. Let’s explore it in a little more details.

elements xml

The <Receivers> node has the collection of custom event receivers that you are packing in this feature. They apply to List Types (indicated by ListTemplateId=850).
The <receiver> node describes each receiver class you have.
<Name> Event Receiver name used by SharePoint in admin screens. You can modify this to anything you want
<Type> refers to the event. Don’t modify this unless you are modifying the corresponding override method in the receiver’s .cs file.
<Assembly> element is a placeholder for the full assembly name. This is auto updated by Visual Studio tooling before deployment. It needs to have the fully qualified assembly name. Note you have a key.snk file so your dll is going to be a signed DLL.
<Class> refers to the fully qualified name of the class that has the event handler method.
<SequenceNumber> if you have multiple event receivers for the same event you can sequence them using the sequence number.

Step 6: Next if you expand the Feature node you’ll see an element called Feature1. I have renamed it to CustomContentPublishFeature. Double click on it bring up the Feature properties editor. There isn’t much for us to do here other than giving it a more meaningful Title and Description. You can also change the deployment scope here from Web to farm etc. We’ll keep it the default - Web.

custom content publish feature

Close the feature editor.

We are almost done and if you notice we still haven’t written any ‘custom’ code yet. That’s the next part.

Step 7: Right click on the “PublishPagesEventReceiver” and select Add->Class. Name the class ConvertContentTypeToHtml.cs. This class will encapsulate our ‘logic’ to generate HTML from our list item. It just has a single method called GetHtml(…) that has only one input parameter the item that is being updated/published. The included code has the column names hardcoded. In an ideal world we would use an xsl transformation to convert the item’s xml into html. I’ll cover xsl transforms and more customizations in a future article. For now we’ll use the quick-and-dirty ‘code transformation’.

Step 8: Now Right click on the “PublishPagesEventReceiver” and select Add->Class again. Name the class SharePointFileHelper.cs. This class will save our transformed html as a file into a given sharepoint library. This class also has a single method SaveFileToLibrary that takes the site url, library name, html content and file name as parameters.

Step 9: Last step is to tie things up. Open the PublishPagesEventReciever.cs file. Below the base.ItemUpdated(properties) method call add the following code:

publish pages event reciever code

In the above code, we do the following:

  1. Retrieve the list item from the properties parameter.
  2. Retrieve the file from the list item
  3. Check if the file status is published. If it’s not published we don’t need to do anything
  4. If it is published, gets the html from the item using our custom ConvertContentTypeToHtml class.
  5. Then user the SharePoint helper class to save the file.

a. The Site URL is easily obtained from the list item itself.

b. We want to publish it to the default document library that’s called “Documents”. If you want the published file to go to a different library just give the correct qualified name.

c. Html – is the html content that needs to be saved.

d. And the file name that we’ve derived from the item’s title.

Debugging Custom Event Receivers

I mentioned earlier also how easy it is to develop for SP 2010 using VS 2010. After you’ve done all the above steps, all you need to do it hit F5 and sit back. If you want to see what VS 2010 is doing behind the scenes you can peek into the ‘Output’ window. A sample view would be something like follows.

sharepoint deployment

Essentially VS is taking care of all the plumbing work needed to deploy and register your feature with SharePoint. All this was possible through the excellent WSP builder tool in VS 2008 too, but you still needed to attach the debugger to the process manually. In VS 2010 you don’t even have to do that. VS will start an IE instance and load the required site up and attach the debugger to the process for you. You just provide your credentials and log in.

To verify everything is correct follow the steps below

Step 1: Put a breakpoint in the first line of ItemUpdated(…) method.

Step 2: Hit F5 to run the application. Let VS start IE and if you are asked credentials for the site provide credentials for the site.

Step 3: Navigate to the Pages library

Step 4: Click on the ‘Contoso Mobile Functional Spec’ that we had created in our previous article.

Step 5: Go to Site Actions->Edit Page

Step 6: Update some values and click on “Save and Close” button. If everything was setup right, the debugger will kick in and you should now hit the break point.

debug breakpoint

Step 7: Setup another breakpoint inside the if(…) condition. Hit F5 to continue. Don’t be surprised when this breakpoint is not hit. If you inspected the file.Level property value you would notice it’s still Draft hence the ‘if’ condition is not satisfied and no publish happened. If you have come this far thing are moving in the right direction. Remove the breakpoint outside the ‘if’ condition and go back to IE.

sharepoint if breakpoint

Step 8: Select the ‘Publish’ tab on the ribbon and click on ‘Submit’ button.

publish tab

Step 9: Provide submission comments and click OK. The following screen will come up. This screen initiates the default approval workflow. Provide some details in the Request field and click on Start.

start button

Step 10: If you are wondering who the approval went to, by default it goes to the users in the default group called ‘Approvers’. If you don’t have any users in that group the workflow will still start but you’ll see a couple of errors regarding failure to send mail (even if you have outgoing email setup correctly).

Step 11: If you have a user in the Approver group login as that user and navigate to the page. Select the Publish tab and click on Approve. Provide approval comments and wait for debugger to kick in.

If you don’t have a user in the Approver group just go to Publish tab and click on the ‘Status’ button.

status button

It will navigate to a page that looks as follows:

approval button

Click on the ‘Please approve Contoso Mobile-Functional Specification’ link to bring up the approval comments window.

workflow comments

See how the comments that were put in the workflow start have come up here. Click on Approve. Give it a few moments before you hit the debugger in Visual Studio

vs debugger

I’ve put in a dummy check to verify the return value. If the return value is true, everything went fine. Hit F5 and let the session continue.

But wait a second, why did we hit the breakpoint now? That’s because as soon as the workflow was approved, SharePoint internally marked the page as Published. That changed the file.Level property’s value to ‘Published’ and this kicked off the ‘Updated’ event handler. This time the ‘if’ condition was satisfied and we thus hit the breakpoint.

Step 12: Go back to IE instance and click on the ‘Libraries’ link in the left navigation pane

sharepoint libraries

Click on Documents

Step 13: Voila! You see an HTML file with the same name as the title of your functional specification page! Click on the menu button (down arrow that comes up when you hover on the ‘Name’ field) and select ‘Send To->Download a Copy’.

download a copy

Step 14: Save the file and open it. It will show something like the following

html rendering

Okay, that’s not the prettiest HTML rendering, but you get the gist. There are some rough edges like the approved by name has a few characters in front of it. Those can be smoothened out when we use a more advanced xsl transform or you can get as fancy as you want in the ConvertContentToHtml class.

But as of now we have successfully built and tested our own Event Receiver and published it as a SharePoint Feature. Hurray!!!

Note: We have so far seen deployment in a development environment only. I will have a quick follow-up on how to do the deployment in a server environment. It’s nothing but a stsadm command followed by activation steps through the site configurations.

Conclusion

We saw how to create an Event Receiver and tie it up to a site as SharePoint Feature. Event Receivers are handy hooks into SharePoint’s content management flow. They allow you to intercept and manipulate default behavior. You can do custom validations, business rules enforcement and lots of other little customizations that don’t come ‘out of box’ in SharePoint. Overall in this (loosely coupled three part) series I’ve tried to solve a common content management problem in an Enterprise business setup. I will follow up with a couple of more enhancements that will have some more custom development. Till then, have fun!

Appendix

I have the “Feature Extension Runtime” installed through my VS2010 Extensions manager. The attached code was built with this extension enabled. Following is a snapshot of ‘extensions’ I got for my VS 2010 installation. If you haven’t checked out the available extensions so far go to Tools->Extension Manager… and have fun.

feature extension runtime

The source code of this article can be downloaded over here

Give a +1 to this article if you think it was well written. Thanks!
Recommended Articles
Sumit is a .NET consultant and has been working on Microsoft Technologies since his college days. He edits, he codes and he manages content when at work. C# is his first love, but he is often seen flirting with Java and Objective C. You can follow him on twitter at @sumitkm or email him at sumitkm [at] gmail


Page copy protected against web site content infringement by Copyscape


User Feedback
Comment posted by sum IT on Thursday, November 3, 2011 12:21 AM
NICE ARTICLE
Comment posted by sid on Wednesday, May 2, 2012 11:42 AM
very nice article..Thanks You
Comment posted by Manish Singh on Monday, May 14, 2012 9:37 AM
sumit thanks this article it's very good for novice. can you post or mail me the article related to detailed scope or uses of event receiver,various aspects where we can maximize the performance.
Comment posted by Vicky on Tuesday, February 5, 2013 1:39 AM
Hi,
Need your help!
I have a site collection. Have one common library where all documents are hosted(with fields: Document name, Version No., Version Comments).
There are several sub sites with a library in each, which will have links to these documents.(custom content type used)
Problem is I want that whenever a document is updated in common library, the updated fields(Version No., Version Comments etc) are not updated in respective sub sites where link to documents content type is used.
I want the updated version(fields) should appear in links also, whenever the same is updated for any document in the common library.
Any help will be greatly appreciated!!

Is it possible to handle this scenario with event handlers? If yes, can you please share the code?
Comment posted by Vicky on Tuesday, February 5, 2013 4:31 AM
Hi,
Need your help!
I have a site collection. Have one common library where all documents are hosted(with fields: Document name, Version No., Version Comments).
There are several sub sites with a library in each, which will have links to these documents.(custom content type used)
Problem is I want that whenever a document is updated in common library, the updated fields(Version No., Version Comments etc) are not updated in respective sub sites where link to documents content type is used.
I want the updated version(fields) should appear in links also, whenever the same is updated for any document in the common library.
Any help will be greatly appreciated!!

Is it possible to handle this scenario with event handlers? If yes, can you please share the code?
Comment posted by nivi on Wednesday, March 13, 2013 4:18 AM
I have a month column which is a choice column in my document library in the format specified below.. For eg. Jan 2013 I have the following requirements 1. The month dropdown should always have only those months which start from 6 months previous of the current month.For eg.If the current month is March 2013 then only the months starting from oct 2012 to march 2013 should be populated in the dropdown 2.There is another column in my document library called 'date' of date format.It is not to be shown in the default view.The date field should automatically be set as the 1st date of the month selected from the month column.For example. IF the month selected is March 2013 .The date Should b 1/3/2013. Please Help!!Its urgent.. Any Help is welcome...Please Step By Step Exaplanation Is expected Along with the code...Thanks in Advance..

Post your comment
Name:  
E-mail: (Will not be displayed)
Comment:
Insert Cancel