How to use a SharePoint ItemAdded event handler and the object model to submit data from an InfoPath form to a SharePoint list
This article explains how you can use an ItemAdded event handler on a Form Library to extract data from an InfoPath form that was submitted to the form library and use this data to add a new item to a custom SharePoint list.
Problem
You want to save the data that is entered into an InfoPath form to a SharePoint list, but InfoPath does not allow you to submit data to a SharePoint list.
Solution
You could use one of the following 5 methods:
- Use the SharePoint Lists web service together with a CAML batch update to add an item to a SharePoint list.
- Use a SharePoint Designer workflow to get data from the InfoPath form and create a SharePoint list item.
- When using an InfoPath browser form, call directly into the SharePoint object model from within the InfoPath form to add an item to the SharePoint list.
- Use a SharePoint event handler feature to make calls directly into the SharePoint object model to add an item to the SharePoint list when an InfoPath form is added to a Form Library on which the event handler has been activated.
- Use a custom Visual Studio workflow to add an item to the SharePoint list when an InfoPath form is added to a Form Library on which the workflow has been set to run.
This article discusses method 4.
Discussion
In the following example, an InfoPath form with one text field is used to submit data to a custom SharePoint list named Fruits that exists on the same site as where the form library to which the InfoPath form is submitted is located, and populate the Title column of the list with the data from the text box in InfoPath.
The following technique enables you to kick off a SharePoint event handler whenever an InfoPath form is submitted to a form library. In addition, it enables you to retrieve data from the InfoPath form that was submitted and then do whatever you like to do with that data, in this case, use the data from the InfoPath form to create a new item in a SharePoint list.
- In InfoPath, create a new Blank browser-compatible form template.
- Add a Text Box control (field1) and a Button control to the InfoPath form template.
- Double-click the button to open its Properties dialog box.
- On the Button Properties dialog box, click Rules.
- On the Rules dialog box, click Add.
- On the Rule dialog box, click Add Action.
- On the Action dialog box, select Submit using a data connection from the Action drop-down list box, and click Add.
- On the Data Connection Wizard dialog box, select Create a new connection to, and click Next.
- On the Data Connection Wizard dialog box, select To a document library on a SharePoint site, and click Next.
- On the Data Connection Wizard dialog box, type in the location for the Document library (in the format http://Server/Site/FormLibrary/), and click the button behind the File name text box.
- On the Insert Formula dialog box, type now(), and click OK.
- On the Data Connection Wizard dialog box, select the Allow overwrite if file exists check box, and click Next.
- On the Data Connection Wizard dialog box, click Finish.
- Click OK on all open dialog boxes to close them.
- Open Microsoft Visual Studio and follow the instructions on MSDN to create an event handler feature, but override the ItemAdded method instead of the ItemDeleting method.
- Add using or Imports statements to the following namespaces:
- System.Xml
- System.Xml.XPath
- System.IO
Add the following C# code to the ItemAdded event handler:
// Retrieve the InfoPath form that was just added
byte[] xmlFormData = null;
SPFile file = properties.ListItem.File;
xmlFormData = file.OpenBinary();
XPathDocument ipForm = null;
if (xmlFormData != null)
{
using (MemoryStream ms = new MemoryStream(xmlFormData))
{
ipForm = new XPathDocument(ms);
ms.Close();
}
}
// Populate a namespace manager with the namespaces
// for the InfoPath form
XPathNavigator ipFormNav = ipForm.CreateNavigator();
ipFormNav.MoveToFollowing(XPathNodeType.Element);
XmlNamespaceManager nsManager =
new XmlNamespaceManager(new NameTable());
foreach (KeyValuePair<string, string> ns
in ipFormNav.GetNamespacesInScope(XmlNamespaceScope.All))
{
if (ns.Key == String.Empty)
{
nsManager.AddNamespace("def", ns.Value);
}
else
{
nsManager.AddNamespace(ns.Key, ns.Value);
}
}
// Retrieve the value of the field in the InfoPath form
XPathNavigator nodeNav = ipFormNav.SelectSingleNode(
"//my:field1", nsManager);
string ipFieldValue = string.Empty;
if (nodeNav != null)
{
ipFieldValue = nodeNav.Value;
// Add an item to a list and use the value of the field
// as the title for the new item
if (!String.IsNullOrEmpty(ipFieldValue))
{
using (SPSite site = new SPSite(properties.SiteId))
{
using (SPWeb web = site.OpenWeb(
properties.RelativeWebUrl))
{
SPList list = web.GetList(
properties.RelativeWebUrl +
"/Lists/Fruits");
if (list != null)
{
SPListItem item = list.Items.Add();
item["Title"] = ipFieldValue;
item.Update();
}
web.Close();
}
site.Close();
}
}
}
If you are writing Visual Basic code, the complete code for the class would look something like the following:
Imports Microsoft.SharePoint
Imports System.Xml
Imports System.Xml.XPath
Imports System.IO
Public Class AddedActionVB
Inherits SPItemEventReceiver
Public Overrides Sub ItemAdded( _
ByVal properties As Microsoft.SharePoint.SPItemEventProperties)
MyBase.ItemAdded(properties)
' Retrieve the InfoPath form that was just added
Dim xmlFormData As Byte() = Nothing
Dim file As SPFile = properties.ListItem.File
xmlFormData = file.OpenBinary()
Dim ipForm As XPathDocument = Nothing
If xmlFormData IsNot Nothing Then
Using ms As MemoryStream = New MemoryStream(xmlFormData)
ipForm = New XPathDocument(ms)
ms.Close()
End Using
End If
' Populate a namespace manager with the namespaces
' for the InfoPath form
Dim ipFormNav As XPathNavigator = ipForm.CreateNavigator()
ipFormNav.MoveToFollowing(XPathNodeType.Element)
Dim nsManager As XmlNamespaceManager = _
New XmlNamespaceManager(New NameTable())
For Each ns As KeyValuePair(Of String, String) _
In ipFormNav.GetNamespacesInScope(XmlNamespaceScope.All)
If ns.Key = String.Empty Then
nsManager.AddNamespace("def", ns.Value)
Else
nsManager.AddNamespace(ns.Key, ns.Value)
End If
Next
' Retrieve the value of the field in the InfoPath form
Dim nodeNav As XPathNavigator = ipFormNav.SelectSingleNode( _
"//my:field1", nsManager)
Dim ipFieldValue As String = String.Empty
If nodeNav IsNot Nothing Then
ipFieldValue = nodeNav.Value
' Add an item to a list and use the value of the field
' as the title for the new item
If Not String.IsNullOrEmpty(ipFieldValue) Then
Using site As SPSite = New SPSite(properties.SiteId)
Using web As SPWeb = site.OpenWeb( _
properties.RelativeWebUrl)
Dim list As SPList = web.GetList( _
properties.RelativeWebUrl & _
"/Lists/Fruits")
If list IsNot Nothing Then
Dim item As SPListItem = list.Items.Add()
item("Title") = ipFieldValue
item.Update()
End If
web.Close()
End Using
site.Close()
End Using
End If
End If
End Sub
End Class
Build the project, deploy the event handler feature, and activate the feature to the site where the form library is located.
Note: You can use a ListTemplateId of 115 in the Elements.xml file to have the event handler feature run on an XML Form Library.
Contents of the Feature.xml file:
<Feature Scope="Web"
Title="ItemAdded Event Handler VB"
Id="C082C073-D797-4277-8595-8D57B5A306C4"
xmlns="http://schemas.microsoft.com/sharepoint/">
<ElementManifests>
<ElementManifest Location="Elements.xml"/>
</ElementManifests>
</Feature>
Contents of the Elements.xml file:
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
<Receivers ListTemplateId="115">
<Receiver>
<Name>ItemAddedEventHandlerVB</Name>
<Type>ItemAdded</Type>
<SequenceNumber>10000</SequenceNumber>
<Assembly>ItemAddedEventHandlerVB, Version=1.0.0.0, Culture=neutral, PublicKeyToken=3470b8ecafe2f4d7</Assembly>
<Class>ItemAddedEventHandlerVB.AddedActionVB</Class>
<Data></Data>
<Filter></Filter>
</Receiver>
</Receivers>
</Elements>
Contents of an install.bat batch file to install and activate the event handler feature:
"C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\BIN\stsadm.exe" -o installfeature -filename ItemAddedEventHandlerVB\Feature.xml
"C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\BIN\stsadm.exe" -o activatefeature -filename ItemAddedEventHandlerVB\Feature.xml -url http://Server/Site
iisreset
You should now have a fully functional solution so that when you fill out the InfoPath form and click the button, the form is submitted to the form library, and then the event handler is kicked off to add a new item to the SharePoint list with a Title that is the same as the text that you entered into the text box on the InfoPath form.
This technique can be used with any code you would like to execute once an InfoPath form has been submitted to the form library. You do not have to limit yourself to adding items to SharePoint lists, but could for example use the data stored within the InfoPath form to send out an email, call a web service, or add a row to a database table. The possibilities are endless.
Related InfoPath Articles:
- Automatically add a new item to a SharePoint list using InfoPath 2007 and a custom workflow
- How to submit the rows of a repeating table in InfoPath to a SharePoint list
- How to use the SharePoint object model to submit data from an InfoPath browser form to a SharePoint list
- Programmatically add an item/event to a SharePoint 2007 calendar using InfoPath 2007 and .NET code
- How to use a Visual Studio workflow to submit data from an InfoPath form to a SharePoint list
