Udostępnij za pośrednictwem


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

  • Anonymous
    May 23, 2004
    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?
  • Anonymous
    May 23, 2004
    The comment has been removed
  • Anonymous
    May 26, 2004
    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,
  • Anonymous
    June 24, 2004
    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?
    thanks...
  • Anonymous
    July 08, 2004
    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: http://support.microsoft.com/default.aspx?scid=kb;en-us;833183

  • Anonymous
    July 28, 2004
    grgdflh
  • Anonymous
    July 28, 2004
    How do i install this demo
  • Anonymous
    July 30, 2004
    The comment has been removed