Sharepoint Document Event Handlers

Over the last couple of days I’ve been putting together a prototype of a data intake and approval process using InfoPath and WSS Form Libraries.  Basically, I wanted to use InfoPath to be the front end and collect data that is stored in a Form Library.  As a result of the InfoPath Form being filled out and saved to the library, I wanted to utilize a custom Sharepoint Document Event Handler that would perform processing on the server.  For example, when the Form is inserted, I wanted to insert data into the Form (or XML file) on the server, and save it back into the Form Library.  The architecture from a high-level would look something like this:



  1. User clicks “Fill out Form” in the Sharepoint site to download the InfoPath Form template and fill it out.  After filling out the form, the user saves the completed form (XML file) to the Form Library. 
  2. Sharepoint then executes my custom event handler that opens up the XML Form file, de-serializes it into a set of objects, and performs processing using the data.
  3. The event handler updates data in the objects, serializes the objects to XML, and saves the updated XML file back to the Sharepoint Form Library.

So you might be thinking that’s pretty straight-forward.  Normally, developing Sharepoint Event Handlers and using them to process InfoPath Forms is straight-forward.  However, this situation represented a challenge because of step #3.  Specifically, when Sharepoint saves a file to a Form Library it will put a lock on the file and assign it a CheckedOutStatus of “short-term” (SPCheckOutStatus = ShortTerm).  Consequently, it was not possible for my Event Handler to update the form and save it back into the library.  One workaround would be to save the updated file with a different file name, but then I would need an application or process (manual or automated) to remove the original files that are saved in step #1.  Another workaround would be to use a queuing technology like MSMQ to queue the updates to the Form Library or use something like BizTalk 2004 and the BizTalk Adapter for Sharepoint to pull the file out of the library and insert it back later.  In this case BizTalk’s built-in support for configuring Send Port retries would provide me the ability to retry the save until the file lock is removed.  However, neither MSMQ nor BizTalk Server was an option in this situation due to other (non-technical) factors. 


Jan Tielens describes this problem and yet another, simpler workaround in his blog by forcing the current thread in the event handler to sleep until the file is no longer locked.  My concern with this approach was the reliability of the solution.  Should IIS be reset or the application pool recycled while an event handler was still executing, then the InfoPath form would never be saved by the event handler and the changes would be lost. 


In my opinion, this issue significant limits the useability of event handlers for Form Libraries.  I can think of several scenarios where you would want an event handler to be able to perform server side processing and update an InfoPath form.  Argh.


So I had to completely abandon the event handler approach and look into a different solution.  Instead of having the file saved back directly to Sharepoint, I configured the InfoPath template to submit the data to a custom Web Service. 



In this case, the custom WS would receive a complex type (set of serializable classes on the .NET side) that would contain the XML data for the Form.  The WS can then serialize the data to XML and use the Sharepoint .NET managed APIs to insert a new Form into the Forms Library. 


I’ve created a simple example based on the Service Request sample InfoPath Form that demonstrates this approach.  In this example, the Service Request form has been modified to submit data to a custom web service.  The custom web service modifies the received Service Request data and saves the data into a Form Library.  This example demonstrates the following:


  1. Submitting an InfoPath form to a custom Web Service
  2. Serializing & de-serializing an InfoPath Form to/from .NET classes
  3. Appending the XML processing instructions required by InfoPath to an XML document.
  4. Saving an XML document to a Sharepoint Forms Library using the WSS managed API.   

Download the sample and let me know your thoughts. 



Comments (8)

  1. Jan says:

    Nice solution! I haven’t had time to check out your code, but do you need a custom web service for each type of an InfoPath form? Or do you have a more "generic" approach?

    Additionally, can you handle other documents than InfoPath forms with this solution?

  2. jamescon says:

    In this example, the Web Service expects a complex XML data structure that conforms to the same schema as the XSD. So yes, with this approach I would need a custom web service for each different InfoPath Form (assuming the Form used a different schema). The custom web service could easily be consumed by any other client (ASP.NET Web Form, JSP, etc.) to submit a form into the Form Library.

    A more generic approach might be to create an HTTP Handler and change the Submit type for the InfoPath form to HTTP instead of a Web Service. Or you could even change the Submit type to script and post the form’s data to the HTTP Handler in the script using the MSXML.XMLHTTP component. Either way you would be doing a post of the raw XML data on submit to an HTTP end point where you could run your own custom code. This would be a more generic solution because you could use the HTTP Handler with multiple schemas/InfoPath form types.

  3. Building Your First Business Process … shows how easy it is to build a business process using Visual Studio .NET and BizTalk Server 2004, expose that business process as a Web service,

  4. Zeynep says:

    Hi to all,

    I used your code in a web service tries to update a documents existing in the form library on the fly with this code:

    Microsoft.SharePoint.SPSite objSPSite = new Microsoft.SharePoint.SPSite("site");

    Microsoft.SharePoint.SPWeb objSPWeb = objSPSite.OpenWeb();

    Microsoft.SharePoint.SPFolder objSPFolder = objSPWeb.GetFolder("folder");

    ….some code…

    objSPFolder.Files.Add(fileUrl, bytFileContents, true);

    The problem is when it tries to add the file it gives the exception below:

    Microsoft.SharePoint.SPException: Cannot connect to the configuration database. —> System.Runtime.InteropServices.COMException (0x81070555): Cannot connect to the configuration database.

    Do you have any idea about this?


  5. jamescon says:

    Sorry for the delay in following up. I hope you’ve resolved the issue by now. Just in case you haven’t, here are a few things I would check:

    – Verify that you can browse to the site and upload files into the Form Library manually.

    – The custom web service must be running on the Sharepoint server. I have seen this error when trying to connect to a Sharepoint site remotely via the API from a machine that doesn’t have Sharepoint installed.

    – Here is a knowledge base article that might be helpful:;en-us;833183

  6. BRad says:


  7. kent says:

    How do i install this demo

  8. jamescon says:

    The zip file includes an InfoPath template (ServiceRequest.xsn) and a directory (SRWebServices) that contains the .NET Web Service and project files.

    Here’s my attempt at step-by-step instructions for getting this example running:

    1. Create a new virtual directory for the SRWebServices folder. Probably the easiest way to do this is to just drop the SRWebServices folder in you’re default web sites root (c:inetpubwwwroot) by default.

    2. If you have Sharepoint installed on the root of the same web site, you will need to take the SRWebServices virtual directory out of Sharepoint’s managed paths. This can be done from the Define Managed Paths page in the Sharepoint Central Administration site. You can find some more information about managed paths and step-by-step instructions on how to include or exclude paths from this page in the WSS documentation:

    3. If the Web Service is running on a different machine then you’ll be using the InfoPath form (most likely), then the URL for the Web Service in the form needs to be modified. Open up the ServiceRequest.xsn InfoPath Form Template in InfoPath in Design mode. In InfoPath go to the Tools menu and select Submitting Forms. Click on the "Select a Web Service" button in the Submitting Forms dialog. During the wizard, point to the SRService.asmx .NET Web Service by entering the URL to the ASMX file. This URL will be set to the localhost path by default, but might need to be updated based on your setup. You should just use the name of the machine hosting the Web Service instead of localhost.

    4. After modifying the path to the Web Service, publish the new InfoPath Form Template to a new Sharepoint Forms Library. The code assumes that the Form Library is named “Service Requests”, but step #5 describes how to change that. Here’s a link to the documentation that describes how to do this:

    5. Finally, the code for the SRService.asmx Web Service will probably need to be modified to point to the Sharepoint site and Form library. The code in the SRService.asmx.cs file on line 69 contains the URL to the Sharepoint site. Here’s the current code:

    //Get a reference to the SPSite object representing

    //…the current Sharepoint Site

    Microsoft.SharePoint.SPSite objSPSite = new Microsoft.SharePoint.SPSite("http://localhost/sites/InfopathExamples");

    And modify line 75 to make sure you are pointing to the correct Form Library:

    //Get a reference to the SPFolder object representing

    //…the Service Requests Form Library

    Microsoft.SharePoint.SPFolder objSPFolder = objSPWeb.GetFolder("Service Requests");

    Just recompile the web service project and you should be set. Let me know if that helps.