• Skip to main content
  • Skip to primary sidebar

Technical Notes Of
Ehi Kioya

Technical Notes Of Ehi Kioya

  • About
  • Contact
MENUMENU
  • Blog Home
  • AWS, Azure, Cloud
  • Backend (Server-Side)
  • Frontend (Client-Side)
  • SharePoint
  • Tools & Resources
    • CM/IN Ruler
    • URL Decoder
    • Text Hasher
    • Word Count
    • IP Lookup
  • Linux & Servers
  • Zero Code Tech
  • WordPress
  • Musings
  • More
    Categories
    • Cloud
    • Server-Side
    • Front-End
    • SharePoint
    • Tools
    • Linux
    • Zero Code
    • WordPress
    • Musings
Home » Backend (Server-Side) » Add Event Receiver To Specific List Instance In SharePoint

Add Event Receiver To Specific List Instance In SharePoint

By Ehi Kioya 7 Comments

When binding SharePoint event receivers to lists and libraries, the generic method involves using the ListTemplateId element. The problem with this method is that it adds the event receiver to all lists with a matching ListTemplateId. However, in many cases, we only want our event receivers attached to specific list instances.

This article explains how to dynamically add event receivers to lists with specific names across an entire site and its sub sites. The event receivers are bound to the lists in Feature events using C# code instead of the conventional XML method which uses the Elements.xml file.

NOTE: You could also bind an event receiver to a specific list instance using XML by replacing the ListTemplateID element with ListUrl. But you would need to manually activate the Web scoped feature for every site that has the list you’re targeting.

With the method described here, you only need to activate the feature on the root site and the code will recursively search for all matching list instances (using the internal name of the list) and automatically attach the event receivers we want.

Setting Up The Project In Visual Studio

Create an empty SharePoint project. Fill in any desired properties and click on OK.

Event Receiver Project

Specify the site where you want the feature to be activated. Since the feature will be a web scoped feature, it will be available on the Site Features page of all websites. However, you will only need to activate it in the parent site that contains the sub webs with the list(s) we’re interested in.

When asked to specify a trust level, choose “Farm Solution”.

Event Receiver Project Site And Trust Level

When you press Finish, an empty SharePoint project will be created.

Right-click on the project and press Add >> New Item. Select Event Receiver and give the event receiver an appropriate name.

Add Event Receiver to Project

You will be asked to select the type of event receiver. Choose “List Item Events”. You will also need to select the event source. You can choose any value you like here (say Custom List). The value you select here doesn’t matter because we will bypass/override it using code.

You will also need to select the events you want to handle. For this example, I will handle these events:

  • An item was added (ItemAdded)
  • An item was updated (ItemUpdated)
  • An item is being updated (ItemUpdating)

RELATED READING: BeforeProperties and AfterProperties of the SPItemEventReceiver

Event Receiver Events SharePoint

When you click Finish, Visual Studio will add the event receiver using the conventional method involving ListTemplateId and the Elements.xml file. A feature will be created with a reference to the containing project. Inside this project an Elements.xml file and a code file will be created. The Elements.xml file holds the settings of the event receiver. The code file holds the code that will be executed.

If you want to add more events to be captured, select the event receiver from the solution explorer and look at the properties window. Here you will see options to enable or disable events that have to be captured.

NOTE: When you disable an already enabled event, the code inside the code file will not be removed.

Now we need to remove the existing connection between the feature and the event receiver.

Bypassing The Elements.xml File Of Our Event Receiver

To remove the binding between our feature and the Elements.xml file of the event receiver, we need to completely exclude the event receiver from the feature. We will however keep the event receiver as part of the assembly because we will use it programmatically later.

Double click on the feature file. In the “Items in the feature” list, select the event receiver and click on the back arrow (<) to remove the event receiver from the feature. This effectively gives you an empty feature.

Removing Event Receiver From Feature

Save the changes to the feature.

Add The Event Receiver Programmatically

Right-click the feature and add a feature event receiver.

Add Feature Event Receiver

In the newly created feature event receiver class, un-comment both the FeatureActivated and FeatureDeactivating code blocks. The code to add/remove our event receivers to specific lists will be added inside of these blocks.

At the top of the class file, create the event receiver constants that you need. Like this:

const SPEventReceiverType eventTypeAdded = SPEventReceiverType.ItemAdded;
const SPEventReceiverType eventTypeUpdated = SPEventReceiverType.ItemUpdated;
const SPEventReceiverType eventTypeUpdating = SPEventReceiverType.ItemUpdating;

The key lines of code that needs to be added to the FeatureActivated event to add the event receivers will look like this:

ListC.EventReceivers.Add(eventTypeAdded, Assembly.GetExecutingAssembly().FullName, "EventReceiverDemo.DemoEventReceiver.DemoEventReceiver");

That would add the ItemAdded event receiver.

Add more of such lines as appropriate for all the event receiver types you want to add. You will notice that the Assembly namespace is not recognized until you add a using statement for System.Reflection:

using System.Reflection;

The last parameter of the EventReceivers.Add method can be found in the Elements.xml file which we previously excluded from the feature. A relevant section of this file will look like:

<Receiver>
    <Name>DemoEventReceiverItemAdded</Name>
    <Type>ItemAdded</Type>
    <Assembly>$SharePoint.Project.AssemblyFullName$</Assembly>
    <Class>EventReceiverDemo.DemoEventReceiver.DemoEventReceiver</Class>
    <SequenceNumber>10000</SequenceNumber>
</Receiver>

Copy the value of the “Class” xml element and use it as the last parameter of the EventReceivers.Add method. $SharePoint.Project.AssemblyFullName$ is replaced by Assembly.GetExecutingAssembly().FullName in the code.

Putting It All Together

Since you might need to add and remove the event receiver multiple times during development and testing, it makes sense to first confirm that the specific event receiver you’re trying to add to a list is not already added. So you might want to first call the following method before adding the event receiver programmatically:

private static void DeleteEvents(SPList list)
{
    SPEventReceiverDefinitionCollection erdc = list.EventReceivers;
    List<SPEventReceiverDefinition> eventsToDelete = new List<SPEventReceiverDefinition>();

    foreach (SPEventReceiverDefinition erd in erdc)
    {
        if (erd != null)
        {
            try
            {
                eventsToDelete.Add(erd);
            }
            catch (Exception) { }
        }
    }
    foreach (SPEventReceiverDefinition er in eventsToDelete)
    {
        if (er.Type == eventTypeAdded || er.Type == eventTypeUpdated || er.Type == eventTypeUpdating)
        {
            er.Delete();
        }
    }
}

Here’s the full code of my feature event receiver class. Notice the code in the FeatureDeactivating section. This ensures that any events we added are removed when the feature is deactivated:

using System;
using System.Runtime.InteropServices;
using System.Security.Permissions;
using Microsoft.SharePoint;
using System.Reflection;
using System.Collections.Generic;

namespace EventReceiverDemo.Features.DemoFeature
{
    /// <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("5995cad7-361d-4001-9b45-a3aa9553883f")]
    public class DemoFeatureEventReceiver : SPFeatureReceiver
    {
        const SPEventReceiverType eventTypeAdded = SPEventReceiverType.ItemAdded;
        const SPEventReceiverType eventTypeUpdated = SPEventReceiverType.ItemUpdated;
        const SPEventReceiverType eventTypeUpdating = SPEventReceiverType.ItemUpdating;

        #region FeatureActivated
        public override void FeatureActivated(SPFeatureReceiverProperties properties)
        {
            SPSecurity.RunWithElevatedPrivileges(delegate()
            {
                SPWeb rootweb = (SPWeb)properties.Feature.Parent;
                foreach (SPWeb web in rootweb.GetSubwebsForCurrentUser())
                {
                    // Add event receivers to Contacts List
                    SPList ListC = null;
                    try
                    {
                        ListC = web.GetList(web.ServerRelativeUrl.TrimEnd('/') + "/Lists/Contacts");
                    }
                    catch (Exception) { }
                    if (null != ListC)
                    {
                        DeleteEvents(ListC);
                        ListC.EventReceivers.Add(eventTypeAdded, Assembly.GetExecutingAssembly().FullName, "EventReceiverDemo.DemoEventReceiver.DemoEventReceiver");
                        ListC.EventReceivers.Add(eventTypeUpdated, Assembly.GetExecutingAssembly().FullName, "EventReceiverDemo.DemoEventReceiver.DemoEventReceiver");
                    }

                    // Add event receivers to Locations List
                    SPList ListL = null;
                    try
                    {
                        ListL = web.GetList(web.ServerRelativeUrl.TrimEnd('/') + "/Lists/Locations");
                    }
                    catch (Exception) { }
                    if (null != ListL)
                    {
                        DeleteEvents(ListL);
                        ListL.EventReceivers.Add(eventTypeAdded, Assembly.GetExecutingAssembly().FullName, "EventReceiverDemo.DemoEventReceiver.DemoEventReceiver");
                        ListL.EventReceivers.Add(eventTypeUpdated, Assembly.GetExecutingAssembly().FullName, "EventReceiverDemo.DemoEventReceiver.DemoEventReceiver");
                    }

                    // Add event receivers to Access List
                    SPList ListA = null;
                    try
                    {
                        ListA = web.GetList(web.ServerRelativeUrl.TrimEnd('/') + "/Lists/Access");
                    }
                    catch (Exception) { }
                    if (null != ListA)
                    {
                        DeleteEvents(ListA);
                        ListA.EventReceivers.Add(eventTypeAdded, Assembly.GetExecutingAssembly().FullName, "EventReceiverDemo.DemoEventReceiver.DemoEventReceiver");
                        ListA.EventReceivers.Add(eventTypeUpdated, Assembly.GetExecutingAssembly().FullName, "EventReceiverDemo.DemoEventReceiver.DemoEventReceiver");
                    }

                    // Add ItemUpdated event receiver to Information List
                    SPList ListI = null;
                    try
                    {
                        ListI = web.GetList(web.ServerRelativeUrl.TrimEnd('/') + "/Lists/Information");
                    }
                    catch (Exception) { }
                    if (null != ListI)
                    {
                        DeleteEvents(ListI);
                        ListI.EventReceivers.Add(eventTypeUpdating, Assembly.GetExecutingAssembly().FullName, "EventReceiverDemo.DemoEventReceiver.DemoEventReceiver");
                    }
                }
            });
        }
        #endregion

        #region FeatureDeactivating
        public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
        {
            SPSecurity.RunWithElevatedPrivileges(delegate()
            {
                SPWeb rootweb = (SPWeb)properties.Feature.Parent;
                foreach (SPWeb web in rootweb.Webs)
                {
                    // Remove event receivers from Contacts List
                    SPList ListC = null;
                    try
                    {
                        ListC = web.GetList(web.ServerRelativeUrl.TrimEnd('/') + "/Lists/Contacts");
                    }
                    catch (Exception) { }
                    if (null != ListC)
                    {
                        DeleteEvents(ListC);
                    }

                    // Remove event receivers from Locations List
                    SPList ListL = null;
                    try
                    {
                        ListL = web.GetList(web.ServerRelativeUrl.TrimEnd('/') + "/Lists/Locations");
                    }
                    catch (Exception) { }
                    if (null != ListL)
                    {
                        DeleteEvents(ListL);
                    }

                    // Remove event receivers from Access List
                    SPList ListA = null;
                    try
                    {
                        ListA = web.GetList(web.ServerRelativeUrl.TrimEnd('/') + "/Lists/Access");
                    }
                    catch (Exception) { }
                    if (null != ListA)
                    {
                        DeleteEvents(ListA);
                    }

                    // Remove event receivers from Information List
                    SPList ListI = null;
                    try
                    {
                        ListI = web.GetList(web.ServerRelativeUrl.TrimEnd('/') + "/Lists/Information");
                    }
                    catch (Exception) { }
                    if (null != ListI)
                    {
                        DeleteEvents(ListI);
                    }
                }
            });
        }
        #endregion

        #region DeleteEvents (Helper method)
        private static void DeleteEvents(SPList list)
        {
            SPEventReceiverDefinitionCollection erdc = list.EventReceivers;
            List<SPEventReceiverDefinition> eventsToDelete = new List<SPEventReceiverDefinition>();

            foreach (SPEventReceiverDefinition erd in erdc)
            {
                if (erd != null)
                {
                    try
                    {
                        eventsToDelete.Add(erd);
                    }
                    catch (Exception) { }
                }
            }
            foreach (SPEventReceiverDefinition er in eventsToDelete)
            {
                if (er.Type == eventTypeAdded || er.Type == eventTypeUpdated || er.Type == eventTypeUpdating)
                {
                    er.Delete();
                }
            }
        }
        #endregion
    }
}

Hope this helps someone. If you have used this method before or found it helpful, please add your comments below.

RELATED READING: Disable SharePoint Item Event Firing When An SPListItem Is Updated

Found this article valuable? Want to show your appreciation? Here are some options:

  1. Spread the word! Use these buttons to share this link on your favorite social media sites.
  2. Help me share this on . . .

    • Facebook
    • Twitter
    • LinkedIn
    • Reddit
    • Tumblr
    • Pinterest
    • Pocket
    • Telegram
    • WhatsApp
    • Skype
  3. Sign up to join my audience and receive email notifications when I publish new content.
  4. Contribute by adding a comment using the comments section below.
  5. Follow me on Twitter, LinkedIn, and Facebook.

Related

Filed Under: Backend (Server-Side), SharePoint Tagged With: CSharp, SharePoint

About Ehi Kioya

I am a Toronto-based Software Engineer. I run this website as part hobby and part business.

To share your thoughts or get help with any of my posts, please drop a comment at the appropriate link.

You can contact me using the form on this page. I'm also on Twitter, LinkedIn, and Facebook.

Reader Interactions

Comments

  1. Angelo says

    March 15, 2017 at 10:34 am

    thanks!

    Reply
  2. Sunil says

    January 5, 2018 at 6:23 am

    Thanks man! This helps a lot.

    Reply
  3. Greg says

    August 31, 2018 at 11:18 am

    Question on the GUID. Right before the “public class DemoFeatureEventReceiver” line you have the GUID. Can you explain on this? Do I need to have this as well? If so, how do I obtain the GUID to use?

    Thanks! This is a great article.

    Reply
  4. Greg says

    August 31, 2018 at 11:22 am

    Disregard my last question. I see the GUID line gets insert automatically when you the new event receiver.

    Thanks again for a great article.

    Reply
    • Ehi Kioya says

      August 31, 2018 at 11:50 am

      Great to know you found it helpful. Best regards.

      Reply
  5. Greg says

    October 10, 2018 at 4:05 pm

    I’ve followed these instructions to create two event receivers: ItemAdded and ItemUpdated. Today that my ItemAdded event receiver isn’t getting removed after the feature has been activated but the ItemUpdated is.

    I used Powershell to delete the rogue ItemAdded receiver. Then re-activated my feature. Both ItemAdded and ItemUpdated are there, but when I de-activate the feature again, only the ItemUpdated is removed.

    Do you have any ideas on this?

    Reply
    • Ehi Kioya says

      October 10, 2018 at 4:36 pm

      Hi Greg,

      You’re probably missing something in your code and you might need to share it here so I can take a quick look. Otherwise, here are a few things you might want to try:

      1. Confirm that you’re not mixing up ItemAdded with ItemAdding events. Check this in the actual event you created and in the conditional check within the DeleteEvents method.

      2. Maybe you have an exception occurring somewhere. If that is the case, you may not get any error messages because if you notice, the catch blocks in my code are empty. To fix this, you may need to debug your FeatureDeactivating event by stepping through the code in Visual Studio. Or you can add an extra line of code to log exceptions to some SharePoint list somewhere – and then you can inspect that list.

      3. And… Are both the ItemAdded event and the ItemUpdated event on the same list?

      Reply

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Primary Sidebar

23,570
Followers
Follow
30,000
Connections
Connect
14,568
Page Fans
Like
  • Recently   Popular   Posts   &   Pages
  • Actual Size Online Ruler Actual Size Online Ruler
    I created this page to measure your screen resolution and produce an online ruler of actual size. It's powered with JavaScript and HTML5.
  • Fix For “Function create_function() is deprecated” In PHP 7.2 Fix For "Function create_function() is deprecated" In PHP 7.2
    As of PHP 7.2 create_function() has been deprecated because it uses eval(). You should replace it with an anonymous function instead.
  • How To Change A SharePoint List Or Library URL How To Change A SharePoint List Or Library URL
    All versions of the SharePoint user interface provide an option to change the title (or display name) of a list or library. Changing SharePoint library URL (or internal name), however, is not exactly very intuitive. We will discuss the process in this article.
  • About
  • Contact

© 2022   ·   Ehi Kioya   ·   All Rights Reserved
Privacy Policy