Archive | November, 2014

Adding an event receiver to a content type with CSOM

28 Nov

Problem

CSOM does not provide the method to add an event receiver to a content type. On the SSOM you can just grab the content type object and access the event receivers by the EventReceivers property. Unfortunately this is not possible with the client library.

Solution

Although this is not supported by Microsoft there’s a workaround to this problem. The ContentType object contains a property called SchemaXmlWithResourceTokens. This property stores information about the content type as well the event receivers associated with it, but more importantly – this property is not read only, meaning that we can set its value via CSOM and update the content type! So, the solution to the problem is to manipulate the XML that is stored in this property to add a new event receiver.

Key parts of the XML

The root element of the XML is ContentType. Inside it you should find as one of its children the XmlDocuments element. This element may or may not contain the, what I’m going to call, Events XmlDocument element. <XmlDocument NamespaceURI=”http://schemas.microsoft.com/sharepoint/events”&gt;

If you’re using PowerShell or CSOM to take a look into your content type SchemaXmlWithResourceTokens and you can’t find this element it is because it doesn’t have any event receiver associated with it. This WILL make a difference when you implement your code to add the event receiver. For now consider that this element is going to be there.

Inside the Events XmlDocument we have a base64 encoded XML that contains the definition of the event receivers. Using a base64 decoder you can see that the encoded value is just XML.

The XML tree should look like the structure below where the bolded elements are encoded.

  1. ContentType
    1. XmlDocuments
      1. XmlDocument (Events XmlDocument)
        1. spe:Receivers
          1. Receiver

I have worked the code and was successfully able to add a new event receiver. Unfortunately I’m not able to share the code right now but it shouldn’t be too complicated to implement. The steps I used to add a new event receiver was:

  1. Retrieve the content type with CSOM (Make sure to load the SchemaXmlWithResourceTokens property)
  2. Create a new XmlDocument object.
  3. Find the XmlDocument (Events XmlDocument) with xpath
  4. Decode the child element from base64 to string
  5. Create a new XmlDocument object for the newly decoded string
  6. Add a new Receiver element
  7. Encode the spe:Receivers back to base64
  8. Set the SchemaXmlWithResourceTokens  with the new XML
  9. Update the Content Type

Your code should also take into account if the XmlDocument (Events XmlDocument) doesn’t exist. In this case, you will need to create the XML structure. Make sure to pay attention the the namespaces as they are required for the solution to work.

Please keep in mind that this is a workaround to the problem and although in my tests it proved to work it is not supported. I used this approach to attach a remote event receiver to a content type in the host web of a SharePoint app!

Hopefully in the future Microsoft will add the support for adding event receivers to a content type with CSOM.

Cheers