Take the 2-minute tour ×
SharePoint Stack Exchange is a question and answer site for SharePoint enthusiasts. It's 100% free, no registration required.

I have an event receiver written by someone else. It originally came with events for ItemCheckingIn and ItemCheckedIn, but we needed something to handle simple metadata updates, too. Since those don't necessarily require checkout/checkin in a document library, I added ItemUpdated to the code (I went to the properties of the event receiver thing in the project and selected "true" for that method, which added the empty method to my code, and xml goodies to elements.xml). I then tested this out and it did not work. That is, ItemCheckingIn and ItemCheckedIn still did their thing, but ItemUpdated did not. I then added ItemUpdating and tried that - still no luck.

Is there some step I'm missing here? People say all kinds of things about stuff being registered but seriously isn't that supposed to be handled by all the feature settings and stuff? Can you only add these things when you are first creating the eventreceiver in visual studio? It's not like there's an error or even would be an error - I copied the code from one of the original methods - the event just does not even fire.

Any clues out there?

Thanks,

  • Matt

UPDATE **

After the answer below I got a bug up my rear and went back to my solution in Visual Studio, looking for more clues. It turns out that the "feature" has C# code related to my event reciever (FeatureName.EventReciever.cs). In there, the particular events being handled are assigned to a configurable content type (set in web.config) VIA CODE. Is this normal? Should I RTFM at this point and figure out how this stuff is really done? I thought the Elements.xml for the EventReceiver handled this...

Code for FeatureName.EventReceiver.cs:

    public override void FeatureActivated(SPFeatureReceiverProperties properties)
    {

        try
        {
            SPWeb web = properties.Feature.Parent as SPWeb;

            //di-associate CWTEventReceiver from CWT Print only content type
            DisableCWTEventReceiver(web);


            //associate CWTEventReceiver to content type as defined in configuration <activefields sharepointcontenttypename="CWT Print Only"> 
                FmiMetadataMappingHandler mappingHandler = WebConfigurationManager.OpenWebConfiguration("/", web.Site.WebApplication.Name).GetSection(Utils.GetConfigSectionNameForWeb(web)) as FmiMetadataMappingHandler;
                SPContentType ct = web.ContentTypes[mappingHandler.ActiveFields.SharepointContentTypeName];

                if (ct != null)
                {

                    Assembly assembly = Assembly.GetExecutingAssembly();
                    AssemblyName assName = assembly.GetName();
                   // bind event receiver to ItemCheckingIn Event                                      
                    SPEventReceiverDefinition receiverCheckingIn = ct.EventReceivers.Add();
                    receiverCheckingIn.Name = "CWTEventReceiverItemCheckingIn";
                    receiverCheckingIn.Type = SPEventReceiverType.ItemCheckingIn;
                    receiverCheckingIn.SequenceNumber = 1000;
                    receiverCheckingIn.Assembly = assName.FullName;
                    receiverCheckingIn.Class = EVENT_RECEIVER_CLASS_NAME;
                    receiverCheckingIn.Update();

                    // bind event receiver to ItemCheckedIn Event                                      
                    SPEventReceiverDefinition receiverCheckedIn = ct.EventReceivers.Add();
                    receiverCheckedIn.Name = "CWTEventReceiverItemCheckedIn";
                    receiverCheckedIn.Type = SPEventReceiverType.ItemCheckedIn;
                    receiverCheckedIn.SequenceNumber = 1001;
                    receiverCheckedIn.Assembly = assName.FullName;
                    receiverCheckedIn.Class = EVENT_RECEIVER_CLASS_NAME;
                    receiverCheckedIn.Update();
                    //update content type with event receiver
                    ct.Update(true);
                }

        }
        catch (Exception ex)
        {
            Utils.LogError(ex.Message, ex.StackTrace);
        }

    }
share|improve this question
add comment

2 Answers 2

up vote 2 down vote accepted

Event receivers are generally attached to lists by means of a list definition (which can define event receivers that are attached upon deployment) or programmatically through custom code. Depending on how you're deploying this event receiver, you might not actually be attaching the receiver to your list.

You can use PowerShell to see which event receivers are attached: http://social.msdn.microsoft.com/Forums/en-US/sharepointgeneralprevious/thread/4d006ad1-c055-4095-97b5-52e0f45f6c0f

If the code in that link reveals that the receiver's not attached, you can also use PowerShell to attach an event receiver: http://sharepintblog.com/2011/06/04/adding-event-receivers-with-powershell/

Hope this helps!

* Edit by Matt *

Please see the comments below for a fleshing-out of why this is the answer.

share|improve this answer
    
OK, so that did help. I discovered that my new event handlers are not registered. This is all handled through a WSP solution, though. So how can I make that automatic? As far as I know I did not have to do any powershell stuff to make this work the first time when I installed it with the original two event handlers, and retracting and deploying new versions of the solution has not changed anything either. –  Matt Nov 1 '12 at 20:21
    
What does your solution contain? If it's deploying the list definition, then updating the Receivers part of the schema should work. Edit - so that's what enter does.. Otherwise, you can use a Feature Receiver to attach it automatically: bramnuyts.be/2011/04/01/… –  Ted N. Nov 1 '12 at 20:28
    
see update above. Also in the powershell window I saw each event handler mentioned twice. Is that normal/expected? –  Matt Nov 1 '12 at 20:33
1  
Okay, so this feature is actually attaching the event receiver to the content type programmatically. That's a bit unusual, but if it's been working so far, it's not necessarily a problem. The 'right' way to do it is here: karinebosch.wordpress.com/walkthroughs/…. Does this feature also deploy the content type/lists, or is that separate? In regards to seeing them twice - not really sure. You might want to inspect the content type in powershell and look at its event receivers ($web.ContentTypes["Content Type Name"].EventReceivers) and see what's there. –  Ted N. Nov 1 '12 at 20:41
    
It's only listed once for the web. The feature only deploys the event receivers and attendant code and WCF references. Thanks, I'll look at that link. –  Matt Nov 1 '12 at 20:46
show 2 more comments

Your problem seems to be largely getting troubleshooted (troubleshot?) in the other answer's discussion thread, but to answer the specific question you're asking, there are several ways you can register/unregister event receivers:

  1. Elements.xml (or inline Elements in your Feature.xml as you prefer)
  2. PowerShell
  3. FeatureReceiver code (which is, in and of itself, an event receiver)
  4. A custom solution (SP2007 example: http://spscustomadmin.codeplex.com/ )

How you do it largely depends on your approach to the solution. In other words, if you're developing a code-heavy solution, you'll probably want to do your event receiver registrations in code too, as it gives you the most flexibility and tools for diagnosis for problems such as what you're dealing with above. As an example of something I work with a lot:

Your problem seems to be largely getting troubleshooted (troubleshot?) in the other answer's discussion thread, but to answer the specific question you're asking, there are several ways you can register/unregister event receivers:
  1. Elements.xml (or inline Elements in your Feature.xml as you prefer)
  2. PowerShell
  3. FeatureReceiver code (which is, in and of itself, an event receiver)
  4. A custom solution (SP2007 example: http://spscustomadmin.codeplex.com/ )

How you do it largely depends on your approach to the solution. In other words, if you're developing a code-heavy solution, you'll probably want to do your event receiver registrations in code too, as it gives you the most flexibility and tools for diagnosis for problems such as what you're dealing with above. As an example of something I work with a lot:

using System;
using System.Diagnostics;
using System.Collections.Generic;
using System.Reflection;
using System.Text;

using Microsoft.Office.Server.Diagnostics;

using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;

namespace MyCompany.Tools
{
    public class FeatureReceiver : SPFeatureReceiver
    {
        private String _executingAssembly
        {
            get { return Assembly.GetExecutingAssembly().FullName; }
        }

        String eventAssembly = "MyCompany.Tools.Tool, Version=1.0.0.0, Culture=neutral, PublicKeyToken=35049b4e811be271";
        String eventClass = "MyCompany.Tools.Tool.EventReceiver";
        String targetList = "Receiver List";

        public override void FeatureActivated(SPFeatureReceiverProperties properties)
        {
            String featureProperties = String.Format("{0} ({1})", properties.Feature.Definition.DisplayName, properties.Feature.Definition.Id.ToString());
            String activationProperties = GetScopeAndParent(properties.Definition.Scope, properties.Feature.Parent);
            LogInformation(String.Concat("Feature Activated: ", featureProperties));
            LogInformation(activationProperties);

            try
            {
                using (SPWeb web = (SPWeb)properties.Feature.Parent)
                {
                    SPList list = web.Lists[targetList];

                    list.EventReceivers.Add(SPEventReceiverType.ItemAdded, eventAssembly, eventClass);
                    LogInformation(String.Format("Added {0} receiver to list {1} successfully.", SPEventReceiverType.ItemAdded.ToString(), list.Title));
                }
            }
            catch (Exception ex)
            {
                LogCritical(ex, String.Format("Exception encountered in {0}:", _executingAssembly));
            }
        }

        public override void FeatureInstalled(SPFeatureReceiverProperties properties)
        {
            String featureProperties = String.Empty;
            if (properties.Feature != null)
            {
                featureProperties = String.Format("{0} ({1})", properties.Feature.Definition.DisplayName, properties.Feature.Definition.Id.ToString());
            }
            else
            {
                featureProperties = String.Format("{0} ({1})", properties.Definition.DisplayName, properties.Definition.Id.ToString());
            }
            LogInformation(String.Concat("Feature Installed: ", featureProperties));
            if (properties.Feature != null)
            {
                LogInformation(String.Concat((properties.Feature.Parent.ToString())));
            }
        }

        public override void FeatureUninstalling(SPFeatureReceiverProperties properties)
        {
            String featureProperties = String.Empty;
            if (properties.Feature != null)
            {
                featureProperties = String.Format("{0} ({1})", properties.Feature.Definition.DisplayName, properties.Feature.Definition.Id.ToString());
            }
            else
            {
                featureProperties = String.Format("{0} ({1})", properties.Definition.DisplayName, properties.Definition.Id.ToString());
            }
            LogInformation(String.Concat("Feature Uninstalling: ", featureProperties));
            if (properties.Feature != null)
            {
                LogInformation(String.Concat((properties.Feature.Parent.ToString())));
            }
        }

        public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
        {
            String featureProperties = String.Format("{0} ({1})", properties.Feature.Definition.DisplayName, properties.Feature.Definition.Id.ToString());
            String activationProperties = GetScopeAndParent(properties.Definition.Scope, properties.Feature.Parent);
            LogInformation(String.Concat("Feature Deactivating: ", featureProperties));
            LogInformation(activationProperties);

            using (SPWeb web = properties.Feature.Parent as SPWeb)
            {
                SPList list = null;
                try
                {
                    list = web.Lists[targetList];

                    for (int i = (list.EventReceivers.Count - 1); i >= 0; i--)
                    {
                        if (list.EventReceivers[i].Assembly == eventAssembly)
                        {
                            list.EventReceivers[i].Delete();
                        }
                    }
                }
                catch { } //If the list doesn't exist, then the event receiver is gone too, so just deactivate the feature.
            }
        }

        private String GetScopeAndParent(SPFeatureScope scope, Object parent)
        {
            String returnValue = String.Empty;

            try
            {
                if (scope == SPFeatureScope.Farm)
                {
                    SPFarm farm = (SPFarm)parent;
                    returnValue = String.Format("  Farm: {0} ({1})", farm.Name, farm.Id.ToString());
                }
                else if (scope == SPFeatureScope.WebApplication)
                {
                    SPWebApplication webApp = (SPWebApplication)parent;
                    returnValue = String.Format("  Web Application: {0} ({1})", webApp.Name, webApp.Id.ToString());
                }
                else if (scope == SPFeatureScope.Site)
                {
                    using (SPSite site = (SPSite)parent)
                    {
                        returnValue = String.Format("  Site: {0} ({1})", site.Url, site.ID.ToString());
                    }
                }
                else if (scope == SPFeatureScope.Web)
                {
                    using (SPWeb web = (SPWeb)parent)
                    {
                        returnValue = String.Format("  Web: {0} ({1})", web.Url, web.ID.ToString());
                    }
                }
            }
            catch { }

            return returnValue;
        }

        private void LogInformation(String message)
        {
            Trace.WriteLine(message);
            PortalLog.DebugLogString(PortalLogLevel.Information, message);
        }

        private void LogUnexpected(String message)
        {
            Trace.WriteLine(message);
            PortalLog.DebugLogString(PortalLogLevel.Unexpected, message);
        }

        private void LogCritical(Exception ex, String message)
        {
            Trace.WriteLine(message);
            Trace.WriteLine(ex.Message);
            Trace.WriteLine(ex.StackTrace);

            PortalLog.DebugLogString(PortalLogLevel.Critical, message);
            PortalLog.DebugLogString(PortalLogLevel.Critical, ex.Message);
            PortalLog.DebugLogString(PortalLogLevel.Critical, ex.StackTrace);
        }
    }
}

It doesn't implement FeatureUpdating(), PortalLog is deprecated now, and it's probably not the most efficient way, but it works well enough and you can tailor it as needed.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.