Hello Folks from the Part 1 I left you all with the GUID to indentify how we would register the Event Receiver with a content type. I will keep this short and crisp.
- When we had added the EventReceiver it created a feature to deploy “MyCustomEventReceiver”. See below and we would remove the “MyCustomEventReceiver” from the feature1
- Now instead we will use a feature receiver to deploy our custom event receiver.
- Before we write any code we would need to go Feature1.Template.xml and add the replaceable parameters, make sure the GUID is LOWER CASE and is from the class file of your custom event receiver.
<?xmlversion="1.0" encoding="utf-8" ?>
<Featurexmlns="http://schemas.microsoft.com/sharepoint/">
<Properties>
<PropertyKey="GloballyAvailable" Value="true" />
<Property
Key="AssemblyQualifiedName"
Value=
"$SharePoint.Type.db9b8706-8d95-40ff-9e93-1a7335af7a3b.AssemblyQualifiedName$"/>
<Property
Key="AssemblyFullName"
Value="$SharePoint.Project.AssemblyFullName$"/>
</Properties>
</Feature>
Okay here is the code which would register your event handler to the content type on "FeatureActivated" and un-register on "FeatureDeactivating" .
using System; using System.Runtime.InteropServices; using System.Security.Permissions; using Microsoft.SharePoint; using Microsoft.SharePoint.Security; using System.Collections.Specialized; using Microsoft.SharePoint.Administration; using System.Collections; namespace MyCustomEventReceiver.Features.Feature1 { /// <summary> /// This class handles events raised during feature activation, deactivation, installation, uninstallation, and upgrade. /// </summary> /// <remarks> /// The GUID attached to this class may be used during packaging and should not be modified. /// </remarks> /// [Guid("f9df7585-b533-4706-a28e-5bcdb732c8f0")] public class Feature1EventReceiver : SPFeatureReceiver { // Uncomment the method below to handle the event raised after a feature has been activated. string asmblyFullNm = string.Empty; string clsNm = string.Empty; public override void FeatureActivated(SPFeatureReceiverProperties properties) { try { SPWeb web = properties.Feature.Parent as SPWeb; ReplaceParameters(properties.Feature.Properties); SPListCollection lstCollection = web.Lists; foreach (SPList lstToUpdate in lstCollection) { if (lstToUpdate.ContentTypes["MyCustomCalendarContentType"] != null) { SPEventReceiverDefinitionCollection defColl = lstToUpdate.EventReceivers; SPEventReceiverDefinition defToDelete = null; bool found = false; for (int k = 0; k < defColl.Count; ++k) { defToDelete = defColl[k]; if (defToDelete.Type == SPEventReceiverType.ItemAdded) { found = true; break; } } if (found) { defToDelete.Delete(); } defColl = lstToUpdate.EventReceivers; found = false; for (int k = 0; k < defColl.Count; ++k) { defToDelete = defColl[k]; if (defToDelete.Type == SPEventReceiverType.ItemUpdated) { found = true; break; } } if (found) { defToDelete.Delete(); } defColl = lstToUpdate.EventReceivers; found = false; for (int k = 0; k < defColl.Count; ++k) { defToDelete = defColl[k]; if (defToDelete.Type == SPEventReceiverType.ItemUpdating) { found = true; break; } } if (found) { defToDelete.Delete(); } defColl = lstToUpdate.EventReceivers; found = false; for (int k = 0; k < defColl.Count; ++k) { defToDelete = defColl[k]; if (defToDelete.Type == SPEventReceiverType.ItemDeleted) { found = true; break; } } if (found) { defToDelete.Delete(); } defColl = lstToUpdate.EventReceivers; found = false; for (int k = 0; k < defColl.Count; ++k) { defToDelete = defColl[k]; if (defToDelete.Type == SPEventReceiverType.ItemAdded) { found = true; break; } } if (found) { defToDelete.Delete(); } SPEventReceiverDefinition def = lstToUpdate.EventReceivers.Add(); string[] classNames = clsNm.Split(','); string className = classNames[0]; def.Assembly = asmblyFullNm; def.Class = className; def.Name = "ItemAddedMyCustomEventReceiver"; def.Type = SPEventReceiverType.ItemAdded; def.SequenceNumber = 1000; def.Synchronization = SPEventReceiverSynchronization.Asynchronous; def.Update(); def = lstToUpdate.EventReceivers.Add(); classNames = clsNm.Split(','); className = classNames[0]; def.Assembly = asmblyFullNm; def.Class = className; def.Name = "ItemUpdatedMyCustomEventReceiver"; def.Type = SPEventReceiverType.ItemUpdated; def.SequenceNumber = 1000; def.Synchronization = SPEventReceiverSynchronization.Asynchronous; def.Update(); def = lstToUpdate.EventReceivers.Add(); classNames = clsNm.Split(','); className = classNames[0]; def.Assembly = asmblyFullNm; def.Class = className; def.Name = "ItemUpdatingMyCustomEventReceiver"; def.Type = SPEventReceiverType.ItemUpdating; def.SequenceNumber = 1000; def.Synchronization = SPEventReceiverSynchronization.Synchronous; def.Update(); def = lstToUpdate.EventReceivers.Add(); classNames = clsNm.Split(','); className = classNames[0]; def.Assembly = asmblyFullNm; def.Class = className; def.Name = "ItemDeletedMyCustomEventReceiver"; def.Type = SPEventReceiverType.ItemDeleted; def.SequenceNumber = 1000; def.Synchronization = SPEventReceiverSynchronization.Asynchronous; def.Update(); } } } catch (Exception eEX) { SPDiagnosticsService.Local.WriteTrace(0, new SPDiagnosticsCategory("MyCustomFeatureReceiver", TraceSeverity.Unexpected, EventSeverity.Error), TraceSeverity.Unexpected, eEX.Message, eEX.StackTrace); } } private void ReplaceParameters(SPFeaturePropertyCollection properties) { clsNm = properties["AssemblyQualifiedName"].Value; asmblyFullNm = properties["AssemblyFullName"].Value; } // Uncomment the method below to handle the event raised before a feature is deactivated. public override void FeatureDeactivating(SPFeatureReceiverProperties properties) { } } }


Hi,
Thanks for a nice article. Can you tell me How to write an ItemUpdated event for Content type? Its giving only “SPItemEventProperties”, so not able to find out when someone changes the Content type. Its an very urgent task for me. Please reply ASAP. For a whole day, am seraching on this issue.
Shankar , the example I posted was for ListItem Event Receiver only for the List/Library that would contain a Content Type. If somebody changes the content type added to the list or library you would have to deregister with old content type and register with the new content type. I hope I understood your question correctly if not tell me what exactly you want to implement.
Atul
Hi Atul,
great example and works well. I have noticed an entry in the ULS log with the message “collection was modified; enumeration may not execute.” after a “Feature activated..” entry. All seems to work but I am interested to know if you knew what caused this and what the implications might be.
Cheers
Dave
Dave, In the feature activation we are removing any previous remains of the SPEventReceiverDefinition collection. I am surprised why the “collection modified…” exception is showing up since we break from the loop within the collection after removing the SPEventReceiverDefinition for added, updated and updating definition. Use the SharePoint Manager 2010 from Codeplex to see the list has the right event receivers.
Thanks,
the list is a document library. In the Feature receiver code I had commented out the receivers I wasn’t using. My Event Receiver only uses ItemAdded so I commented out the rest would this be the problem?
Here is the updated code.
using System;
using System.Runtime.InteropServices;
using System.Security.Permissions;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Security;
using System.Collections.Specialized;
using Microsoft.SharePoint.Administration;
using System.Collections;
namespace DocLibER.Features.DDCDocumentClassifier
{
///
/// This class handles events raised during feature activation, deactivation, installation, uninstallation, and upgrade.
///
///
/// The GUID attached to this class may be used during packaging and should not be modified.
///
[Guid("a48986bb-fddb-4e75-8c02-72debaf76fd3")]
public class Feature1EventReceiver : SPFeatureReceiver
{
// Uncomment the method below to handle the event raised after a feature has been activated.
string asmblyFullNm = string.Empty;
string clsNm = string.Empty;
public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
try
{
SPWeb web = properties.Feature.Parent as SPWeb;
ReplaceParameters(properties.Feature.Properties);
SPListCollection lstCollection = web.Lists;
foreach (SPList lstToUpdate in lstCollection)
{
if (lstToUpdate.ContentTypes["DDCDocument"] != null)
{
SPEventReceiverDefinitionCollection defColl =
lstToUpdate.EventReceivers;
SPEventReceiverDefinition defToDelete = null;
bool found = false;
/// ItemAdded
for (int k = 0; k < defColl.Count; ++k)
{
defToDelete = defColl[k];
if (defToDelete.Type == SPEventReceiverType.ItemAdded)
{
found = true;
break;
}
}
if (found)
{
defToDelete.Delete();
}
// Adding new event receiver.
SPEventReceiverDefinition def = lstToUpdate.EventReceivers.Add();
string[] classNames = clsNm.Split(',');
string className = classNames[0];
/// ItemAdded
def.Assembly = asmblyFullNm;
def.Class = className;
def.Name = "ItemAddedDDCDocumentClassifierEventReceiver";
def.Type = SPEventReceiverType.ItemAdded;
def.SequenceNumber = 1000;
// def.Synchronization = SPEventReceiverSynchronization.Asynchronous;
// changed to sync from default async
// to fix problem with old title information being presented to user to save.
def.Synchronization = SPEventReceiverSynchronization.Synchronous;
def.Update();
}
}
}
catch (Exception eEX)
{
SPDiagnosticsService.Local.WriteTrace(0,
new SPDiagnosticsCategory("DDCDocumentClassifierFeatureReceiver",
TraceSeverity.Unexpected, EventSeverity.Error),
TraceSeverity.Unexpected,
eEX.Message,
eEX.StackTrace);
}
}
private void ReplaceParameters(SPFeaturePropertyCollection properties)
{
clsNm = properties["AssemblyQualifiedName"].Value;
asmblyFullNm = properties["AssemblyFullName"].Value;
}
// Uncomment the method below to handle the event raised before a feature is deactivated.
public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
{
try
{
SPWeb web = properties.Feature.Parent as SPWeb;
ReplaceParameters(properties.Feature.Properties);
SPListCollection lstCollection = web.Lists;
foreach (SPList lstToUpdate in lstCollection)
{
if (lstToUpdate.ContentTypes["DDCDocument"] != null)
{
SPEventReceiverDefinitionCollection defColl =
lstToUpdate.EventReceivers;
SPEventReceiverDefinition defToDelete = null;
bool found = false;
/// ItemAdded
for (int k = 0; k < defColl.Count; ++k)
{
defToDelete = defColl[k];
if (defToDelete.Type == SPEventReceiverType.ItemAdded)
{
found = true;
break;
}
}
if (found)
{
defToDelete.Delete();
}
}
}
}
catch (Exception eEX)
{
SPDiagnosticsService.Local.WriteTrace(0,
new SPDiagnosticsCategory("DDCDocumentClassifierFeatureReceiver",
TraceSeverity.Unexpected, EventSeverity.Error),
TraceSeverity.Unexpected,
eEX.Message,
eEX.StackTrace);
}
}
}
}
Hi Atul,
I found the issue. When debugging the code you can see that the issue is in the “foreach (SPList lstToUpdate in lstCollection)” section. After the first list is found with the desired content type and the eventreceiver collection is updated the collection of lists is invalid and exception occurs when the foreach loop starts again looking for the next list.
The solution (I found in a number of articles including http://graycloud.com/sharepoint/how-find-the-eventhandlers-active-for-each-list-and-disab-t48991.html) is to write the lists to be updated into an array and work from the array and not the collection of lists.
Works a treat. Here is my version of your original example.
Cheers
Dave
using System;
using System.Runtime.InteropServices;
using System.Security.Permissions;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Security;
using System.Collections.Specialized;
using Microsoft.SharePoint.Administration;
using System.Collections;
namespace DocLibER.Features.DDCDocumentClassifier
{
///
/// This class handles events raised during feature activation, deactivation, installation, uninstallation, and upgrade.
///
///
/// The GUID attached to this class may be used during packaging and should not be modified.
///
[Guid("a48986bb-fddb-4e75-8c02-72debaf76fd3")]
public class Feature1EventReceiver : SPFeatureReceiver
{
// Uncomment the method below to handle the event raised after a feature has been activated.
string asmblyFullNm = string.Empty;
string clsNm = string.Empty;
public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
try
{
SPWeb web = properties.Feature.Parent as SPWeb;
// Get the details for the eventreceiver to register
ReplaceParameters(properties.Feature.Properties);
// Get the collection of lists to check for our content type.
SPListCollection lstCollection = web.Lists;
// Define a new array to collect the lists that have our content type.
ArrayList listsWithContentType = new ArrayList();
// Look through the collection of lists and add lists to update to array.
foreach (SPList lstToUpdate in lstCollection)
{
if (lstToUpdate.ContentTypes["DDCDocument"] != null)
{
listsWithContentType.Add(lstToUpdate);
}
}
// For each list in the array update the collection of event receivers.
foreach (SPList listwithContentType in listsWithContentType)
{
SPEventReceiverDefinitionCollection defColl =
listwithContentType.EventReceivers;
SPEventReceiverDefinition defToDelete = null;
bool found = false;
/// ItemAdded
for (int k = 0; k < defColl.Count; ++k)
{
defToDelete = defColl[k];
if (defToDelete.Type == SPEventReceiverType.ItemAdded)
{
found = true;
break;
}
}
if (found)
{
defToDelete.Delete();
}
// Adding new event receiver.
SPEventReceiverDefinition def = listwithContentType.EventReceivers.Add();
string[] classNames = clsNm.Split(',');
string className = classNames[0];
/// ItemAdded
def.Assembly = asmblyFullNm;
def.Class = className;
def.Name = "ItemAddedDDCDocumentClassifierEventReceiver";
def.Type = SPEventReceiverType.ItemAdded;
def.SequenceNumber = 1000;
// def.Synchronization = SPEventReceiverSynchronization.Asynchronous;
// changed to sync from default async
// to fix problem with old title information being presented to user to save.
def.Synchronization = SPEventReceiverSynchronization.Synchronous;
def.Update();
}
}
catch (Exception eEX)
{
SPDiagnosticsService.Local.WriteTrace(0,
new SPDiagnosticsCategory("DDCDocumentClassifierFeatureReceiver",
TraceSeverity.Unexpected, EventSeverity.Error),
TraceSeverity.Unexpected,
eEX.Message,
eEX.StackTrace);
}
}
private void ReplaceParameters(SPFeaturePropertyCollection properties)
{
clsNm = properties["AssemblyQualifiedName"].Value;
asmblyFullNm = properties["AssemblyFullName"].Value;
}
// Uncomment the method below to handle the event raised before a feature is deactivated.
public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
{
try
{
SPWeb web = properties.Feature.Parent as SPWeb;
ReplaceParameters(properties.Feature.Properties);
SPListCollection lstCollection = web.Lists;
ArrayList listsWithContentType = new ArrayList();
foreach (SPList lstToUpdate in lstCollection)
{
if (lstToUpdate.ContentTypes["DDCDocument"] != null)
{
listsWithContentType.Add(lstToUpdate);
}
}
foreach (SPList listwithContentType in listsWithContentType)
{
SPEventReceiverDefinitionCollection defColl =
listwithContentType.EventReceivers;
SPEventReceiverDefinition defToDelete = null;
bool found = false;
/// ItemAdded
for (int k = 0; k < defColl.Count; ++k)
{
defToDelete = defColl[k];
if (defToDelete.Type == SPEventReceiverType.ItemAdded)
{
found = true;
break;
}
}
if (found)
{
defToDelete.Delete();
}
}
}
catch (Exception eEX)
{
SPDiagnosticsService.Local.WriteTrace(0,
new SPDiagnosticsCategory("DDCDocumentClassifierFeatureReceiver",
TraceSeverity.Unexpected, EventSeverity.Error),
TraceSeverity.Unexpected,
eEX.Message,
eEX.StackTrace);
}
}
}
}
David, I thought I did it in the actual code of my project. This one was a dummy but good catch anyways. I hope its working well for you.
This article gave me an insight into SharePoint from scratch.Its Simple to Understand and complete.I Enjoyed learning. Thanks for sharing with us. Its really helpful for beginner as well as developer. Check out this link too its also helped me to complete my task….
http://mindstick.com/Articles/05f028f6-0d22-48e5-88bc-31f7be85c0ea/?Event%20Receiver%20in%20SharePoint%202010
Thanks
Hi Atul,
i have a concern here, please can you help me.
i have a event receiver built but have some issues, here is the issue:
i have column in the parent list: column 1 : choice column
once the value of this column is changed the event receiver will be triggered and an item in child list should be created.
i am using Item Updated method, but i am unable to get the before properties for the changed item,
here is the code:
string orgvalue = properties.BeforeProperties["Initiative Status"].ToString();—– error null value
string current = properties.ListItem["Initiative Status"].ToString();
if (orgvalue!=current)
{
//some code
}
i am getting the null value for the orgvalue line.
please can you help.
Hey Atul,
I tried your solution and it works when I run it in debug mode (ie, it adds the event receivers to my library), but when I package the solution and deploy it to my farm the event receivers do not get added. Do you have any insight?
Thanks,
- Matt