Karine Bosch’s Blog

On SharePoint

Walkthrough 5 – Developing an Event Receiver for a Document Content Type


Developing an event receiver for a document library content type is almost the same as developing a content type for a custom list.

You can read more about it here.

Step 1 – Create the site columns

I use the same site columns as in Walkthrough 3.

<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <!--Site Columns-->
  <Field
    ID="{C2A8588A-F8A2-4324-BE39-4962E2E75895}"
    Name="NumberOfMoons"
    DisplayName="Number of Moons"
    Description="The number of moons that turn around the planet."
    Type="Number"
    Group="Universe Site Columns"
    />
  <Field
    ID="{85F781F8-0AB3-433e-B828-DC0DD39AE695}"
    Name="Distance"
    DisplayName="Distance (in km)"
    Description="The distance from the sun."
    Type="Number"
    Group="Universe Site Columns"
    />
  <Field
    ID="{0E273391-2749-4c17-BCFD-009E2DC98F2F}"
    Name="OrbitalPeriod"
    DisplayName="Orbital Period (in earth days)"
    Description="The time necessary to turn around the sun calculated in earth days."
    Type="Number"
    Group="Universe Site Columns"
    />
  <Field
    ID="{7A86784F-65B3-4b48-8EAF-C77FFED7BB61}"
    Name="MinimumTemperature"
    DisplayName="Minimum temperature (in °C)"
    Description="Minimum temperature in °C at the surface of the planet."
    Type="Number"
    Group="Universe Site Columns"
    />
  <Field
    ID="{9677F5F2-4CA6-4d88-9DE1-3518DE4E2A01}"
    Name="MaximumTemperature"
    DisplayName="Maximum temperature (in °C)"
    Description="Maximum temperature in °C at the surface of the planet."
    Type="Number"
    Group="Universe Site Columns"
    />
</Elements>

Step 2 – Create the content type

The content type definition is a bit different from the content type in walkthrough 3. The content type id reflects its inheritance: in this walkthrough the content type inherits from the Document item. Together with the content type, a specific document template will be deployed. This document template is defined in the <DocumentTemplate> element within the <ContentType> element.

To bind an event handler to a content type, you have to add a <XmlDocuments> element into the <ContentType> element. This <XmlDocuments> element can contain 1 or more <XmlDocument> elements. The <Receivers> element is added as a child element to the <Document> element.

<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <!--Content Types-->
  <ContentType
    ID="0x010100B9DF8CEC5E11482E8ECB368D6395230F"
    Group="Universe Content Types"
    Name="Planet Document"
    >
    <FieldRefs>
      <FieldRef ID="{fa564e0f-0c70-4ab9-b863-0177e6ddd247}" DisplayName="Planet" />
      <FieldRef ID="{C2A8588A-F8A2-4324-BE39-4962E2E75895}" />
      <FieldRef ID="{85F781F8-0AB3-433e-B828-DC0DD39AE695}" />
      <FieldRef ID="{0E273391-2749-4c17-BCFD-009E2DC98F2F}" />
      <FieldRef ID="{7A86784F-65B3-4b48-8EAF-C77FFED7BB61}" />
      <FieldRef ID="{9677F5F2-4CA6-4d88-9DE1-3518DE4E2A01}" />
    </FieldRefs>
    <DocumentTemplate TargetName="PlanetTemplate.docx"/>
    <XmlDocuments>
      <XmlDocument NamespaceURI="http://schemas.microsoft.com/sharepoint/events">
        <Receivers xmlns:spe="http://schemas.microsoft.com/sharepoint/events">
          <Receiver>
            <Name>PlanetDocEventHandler</Name>
            <Type>ItemAdded</Type>
            <SequenceNumber>10000</SequenceNumber>
            <Assembly>UniverseEventHandlers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=841f382b41c47c60</Assembly>
            <Class>UniverseEventHandlers.PlanetDocumentEventReceiver</Class>
            <Data></Data>
            <Filter></Filter>
          </Receiver>
        </Receivers>
      </XmlDocument>
    </XmlDocuments>
  </ContentType>
</Elements>

Step 3 – Create the event receiver

 When a document is created containing information about a certain planet, the event handler will check if the planet has moons. In that case the event receiver will create a task for the creator of the document to gather information about the moons.

The code for the event receiver looks as follows:

    public class PlanetDocumentEventReceiver:  SPItemEventReceiver
    {
        public override void ItemAdded(SPItemEventProperties properties)
        {
            // when a document is uploaded a task must be created to discover the moons
            string numberOfMoons = properties.ListItem["NumberOfMoons"].ToString();
            int moons;
            int.TryParse(numberOfMoons, out moons);
            if (moons > 0)
            {
                // get the name of the planet that needs to be saved
                string planet = properties.ListItem["Planet"].ToString();

                using (SPWeb web = properties.OpenWeb())
                {
                    SPList taskList = web.Lists["Tasks"];
                    SPListItem task = taskList.Items.Add();
                    task["Title"] = string.Format("Discover {0} moons for planet {1}.",
                        numberOfMoons, planet);
                    task["Priority"] = "(2) Normal";
                    task["AssignedTo"] = web.CurrentUser.LoginName;
                    task["Description"] = string.Format("A document for planet {0} is created. Please, add the necessary documentation for the {1} moons.",
                        planet, numberOfMoons);

                    task.Update();
                }
            }
        }
    }

Step 4 – Create a module to deploy the document template

The document template is deployed separately in a <Module> and will be provisioned to the _cts directory, which represents the contents of the Content Types Gallery.

<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <Module Name="PlanetDocs" Url="_cts/Planet Document" RootWebOnly="TRUE">
    <File Url="PlanetTemplate.docx" Name="PlanetTemplate.docx" Type="Ghostable"></File>
  </Module>
</Elements>

Step 5 – Create a List Instance and bind the content type to the list intance

You can deploy the previous CAML to create the site columns and content types. In the user interface of the SharePoint site you can create a custom list and add the content type to it. BUT you can also create a list instance using the CAML element <ListInstance>. To bind a content type to a list instance you have to use the <ContentTypeBinding> element. Add a new XML file with f.e. the name listinstance.xml and add the following CAML to it:

<Elements Id="{76875FAE-7F92-4e32-8A83-04C21AFFBE2E}"
          xmlns="http://schemas.microsoft.com/sharepoint/">
  <ListInstance
       FeatureId="020C02E9-16D9-4aa4-ACEE-26BC4DCA7672"
       Title="Planet Documents"
       Description="List of planets documents based on Planet Document content type."
       Id="10010"
       TemplateType="101"
       OnQuickLaunch = "TRUE"
       Url="Planet Documents">
  </ListInstance>
  <ContentTypeBinding ContentTypeId="0x010100B9DF8CEC5E11482E8ECB368D6395230F" ListUrl="Planet Documents"/>
</Elements>

You can read more about creating list instances in CAML here.

Create the Feature.xml

Your feature.xml will look as follows:

<Feature Id="{020C02E9-16D9-4aa4-ACEE-26BC4DCA7672}"
    Title="Event Handlers - Walkthrough 5"
    Description="This feature demonstrates the use of an event handler on a document library content type."
    Scope="Site"
    Hidden="FALSE"
    xmlns="http://schemas.microsoft.com/sharepoint/">
    <ElementManifests>
       <ElementManifest Location="sitecolumns.xml" />
       <ElementManifest Location="contenttype.xml" />
       <ElementManifest Location="template.xml" />
       <ElementManifest Location="listinstance.xml" />
    </ElementManifests>
</Feature>

Deploy and test the feature

Well, that’s it.  Deploy the feature and navigate to the Planet Documents list. Before creating a document check that you have a Tasks list. If not, create one with the name Tasks. Click the New button to create a new document. Choose Planet Document and fill out information for the planet Mars. Close and save the document. Navigate to the Tasks list to check the task that has been created by the event receiver.

5 Comments »

  1. Hi,
    I have gone through all your posts on event handlers.Thank you for your crisp & clear explanations. In my project now Iam dealing with the following scenario.
    We have a set of infopath forms(.xml not xsn) in a document library. Each form is published with creating a specific content for that. And each content type has a site column as “work flow status” . Now I need to display a Dash Board of these form’s status. My approach to this problem is I will add a feature event handler to the site and each time form added to the library or updated, will track the value of work flow status code in a list and with this list values I will create a grid display in a web part.

    Hope you got my scenario. I wish you to suggest the right approach for my problem. Iam very new to this sharepoint object model.

    Comment by Nimisha | March 22, 2011 | Reply

  2. Hi Nimisha,
    Thanks for reading my posts. Can’t your grid handle the field “workflow status” that you already have in your document library?
    If not, you could use an event receiver to store values in a separate list.
    Karine

    Comment by Karine Bosch | March 23, 2011 | Reply

  3. Thank you once again for your immediate response. Iam using event handler to store status value in a seperate list (exactly as u said).

    Comment by Nimisha | March 23, 2011 | Reply

  4. Hello Karine I need an event receiver to handle when a new document is added to particular library. The event handler must then access 8 different list to check to see which one of these list the document was uploaded too.
    After that the event handler must then check the % complete coloumn and if its 100 % get the next task for that particular list and email the person that its assigned to and let them know that this event is completed and they have a new task.

    The event handler must also check the date and make sure that this event is within the time limint specified by the task.

    Comment by Jermaine | February 29, 2012 | Reply

  5. Jermaine,
    One little remark: why does the event handler has to access 8 different lists to check to which the document is added? By reading the value in properties.ListItem.ParentList you know exactly to which list the document is added.
    I think with the necessary code the rest of the requirements can be handled from within the event handler.

    Comment by Karine Bosch | March 1, 2012 | Reply


Leave a comment