SharePoint 2010: Event Receivers Part 2- Create Event Receiver for Content Types


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.

  1. When we had added the EventReceiver it created a feature to deploy “MyCustomEventReceiver”. See below and we would remove the “MyCustomEventReceiver” from the feature1

    image

  2. Now instead we will use a feature receiver to deploy our custom event receiver.

    image

  3. 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)
    {
    }

    }
}
About these ads

12 Comments on “SharePoint 2010: Event Receivers Part 2- Create Event Receiver for Content Types”

  1. Shankar December 15, 2010 at 10:41 am #

    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.

    • atulchhoda December 15, 2010 at 5:51 pm #

      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

  2. David January 6, 2011 at 12:51 am #

    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

    • atulchhoda January 6, 2011 at 3:21 am #

      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.

      • David January 6, 2011 at 3:42 am #

        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?

      • David January 6, 2011 at 5:16 am #

        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);
        }
        }

        }
        }

      • David January 7, 2011 at 1:36 am #

        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);
        }
        }

        }
        }

  3. atulchhoda January 18, 2011 at 9:47 pm #

    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.

  4. Golu Singh December 20, 2011 at 10:31 am #

    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

    • Tulajaram February 28, 2012 at 2:04 am #

      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.

  5. Matt December 17, 2012 at 4:11 pm #

    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

Trackbacks/Pingbacks

  1. SharePoint – How to create an event receiver for a content type | j5423 - January 9, 2013

    [...] http://sharepointx-men.com/2010/07/09/sharepoint-2010-event-receivers-part-2-create-event-receiver-f… [...]

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 81 other followers

%d bloggers like this: