ItemDeleting events get fired when deleting a Content Type

ItemDeleting events get fired when deleting a Content Type header image

Recently I have been working with ItemEventreceivers to do some more complex tasks like extending the default approval flow. It included using almost all events that where available and it all worked pretty need. However at some point while checking the ULS logs I found out that my event receivers got fired even though I didn’t expect them to.

So first things first; I was using the following receivers (an overview can be found on MSDN):

  • ItemAdding
  • ItemUpdating
  • ItemDeleting
  • ItemAdded
  • ItemUpdated
  • ItemDeleted

According to the documentation all of these EventReceivers will behave as soon as something happens to an item of your choosing. If you attach your EventHandler to a ContentType it will fire for all of the items of that ContentType, but if you use it to attach it to a library it will fire for all items in that specific library.

Now back to my issue I found out that as soon as I attached my EventReceiver to my list the ItemDeleting got triggered as soon as I deleted a ContentType. After debugging for a few minutes I got irritated and decided to check all events I was working with, just to be sure I didn’t screw up anything else. In order to do it quick new project with only one feature and one ItemEventReceiver that would only log to the ULS every time an event is or has been fired.

public class MyFirstEventReceiver : SPItemEventReceiver
{
  public override void ItemAdding(SPItemEventProperties properties)
  {
    Tracer.TraceMessage("ItemAdding", "Patterns and Practices/SharePoint Guidance");
  }

  public override void ItemUpdating(SPItemEventProperties properties)
  {
    Tracer.TraceMessage("ItemUpdating", "Patterns and Practices/SharePoint Guidance");
  }

  public override void ItemDeleting(SPItemEventProperties properties)
  {
    Tracer.TraceMessage("ItemDeleting", "Patterns and Practices/SharePoint Guidance");
  }

  public override void ItemAdded(SPItemEventProperties properties)
  {
    Tracer.TraceMessage("ItemAdded", "Patterns and Practices/SharePoint Guidance");
  }

  public override void ItemUpdated(SPItemEventProperties properties)
  {
    Tracer.TraceMessage("ItemUpdated", "Patterns and Practices/SharePoint Guidance");
  }

  public override void ItemDeleted(SPItemEventProperties properties)
  {
    Tracer.TraceMessage("ItemUpdated", "Patterns and Practices/SharePoint Guidance");
  }
}

Now if you deploy this code and create a new Document Library you should be able to monitor the events. If you enable the Content Type Management you can also add new Content Types and you will see that if you add a new Content Type nothing is triggered. However if you would modify an existing ContentType (or add a new one that you modify) as long as you add a new Document Template the following events are triggered:

ULS ItemAdding

Then if you would delete that new Content Type you will see the following events triggered:

ULS ItemDeleting

Now that wouldn’t make much sense at first but after some discussion with Robin Meure it actually did make some. Every time you create a new Content Type a new folder gets created on the list level, and as soon as you delete the same Content Type that folder gets deleted. Now that would actually made some sense so I dug up IL Spy to do some reflection. My first attempt to check when the new DocumentTemplate is applied stranded due to the fact that it all was private, however when a document gets deleted there is this nice method DeleteFolder:

// Microsoft.SharePoint.SPContentType
internal void DeleteFolder()
{
    string webRelativeUrlFromUrl;
    if (this.List != null)
    {
        webRelativeUrlFromUrl = this.Web.GetWebRelativeUrlFromUrl(this.Scope + "/" + this.FolderPath);
    }
    else
    {
        webRelativeUrlFromUrl = this.Web.GetWebRelativeUrlFromUrl(this.FolderPath);
    }
    if (this.m_folder == null)
    {
        this.m_folder = new SPFolder(this.Web, webRelativeUrlFromUrl);
    }
    if (this.m_folder.Exists)
    {
        this.m_folder.Delete();
    }
}

So it all started to make sense. The events I saw that got triggered actually should be triggered since I scoped my event to trigger on the whole list and anything that would happen there. If you do not want to catch these events you can either bind your receivers to a Content Type, or write some logic that exclude folders the folders.

So many thanks to Robin for helping me understanding it a bit more, and another mistery solved.

Loading comments…