Introduction To InfoPath Development and The Forms Services Object Model
The InfoPath Forms Services functionality is coupled with a set of powerful class libraries that are broken up into two major namespaces which can be found in
- Program Files
- Microsoft Office Servers
The following section describes each of these namespaces and the components that they provide.
The administration namespace provides the option to develop routines revolving around common administrative tasks, similar to how the SharePoint administrative namespace exposes classes for managing deployments. The most important class in this namespace is arguably the FormsService class. The FormsService class represents the top level for Forms Service in a web farm. The administration namespace contains various other classes that allow administration operations such as managing form templates, InfoPath related SharePoint Features, Universal Data Connections, and other minor functions. Therefore, you could use the administration namespace for pieces such as the FormTemplate object which denotes a form template that has been uploaded to Forms Services, exposing several levels of Form template interaction and manageability.
This namespace provides access to the relevant InfoPath controls. Notably, this namespace must be referenced in order to call the XmlFormView control, which is used for the rendering of the InfoPath control in a web environment as opposed to rendering within the InfoPath Smart client. This namespace also contains other minor classes that deal with utilizing [Author: The word procure and its derivatives seem inappropriate throughout this chapter.] browser based form rendering.
InfoPath Controls Reference Push or Pull Values
An important concept regarding the use of InfoPath 2007 controls when developing forms is the concept of how controls are referenced, which will effect howdata that is pushed and pulled from an arbitrary InfoPath control is manipulated,. One of the most common examples is to take a sample control, such as an InfoPath ListBox or ComboBox control, and passvalues into the control to populate its contents with a dataset InfoPath controls, unlike traditional controls in .NET, are not referenced directly by using control identifiers, They are instead referenced by binding or pulling related values on the XML nodes on an XmlNode object that represents the control. For example, you might have a TextBox control on the Visual Studio design surface that has programmatic name to reference the control in order to identify the object (see Figure 14.4) that you normally could reference by the identifier. This is different when developing against InfoPath since control reference does not occur directly, but rather the controls are referenced by the XmlNode object that represents the control.
Calling Data Out Of an InfoPath Control
Frequently when developing custom InfoPath code you need to call a piece of data out of one of the XML nodes set in the control, in essence selecting a single node from the XMLnode object. In order to pull data out of a control, first call the XPathNavigator (as opposed to using legacy InfoPath 2003 methods such as the XmlDocument class and the SelectNodes method). The XPathNavigator class provides cursor navigation through the provided InfoPath XML node set from the root of the set datasource, so you can perform queries againstdata.. The first task in order to get the data out of an InfoPath control therefore is for you to call the XPathNavigator class by implementing the CreateNavigator() method. The XPathNavigator you should set to the main (primary) data source by using the MainDataSource property to get the DataSource object, which can be set to a variety of secondary datasources if you require it.
Here is the code for setting the DataSource and calling CreateNavigator():
- XPathNavigator sharepointPro2007Nav = this.MainDataSource.CreateNavigator();
In order to query data that resides in the InfoPath control, you can use the SelectSingleNode method in order to build an XPath statement to return a Node object that matches the XPath expression, and the Value method out of XPathNavigator you can then use to return the query of the current node value to return a string result. The NamespaceManager property is used in order to resolve any namespace resolutions that are required. You can use the NamespaceManager property to accomplish more XmlNamespaceManager object actions as well, such as adding or deleting namespaces within a form.
Here is the code for returning a value from an XML node:
- string value = sharepointPro2007Nav.SelectSingleNode
- ("//my:pro2007field", NamespaceManager).Value;
Similarly, to iterate through all the available nodes, XPathNodeIterator and the Select method can be leveraged. Following, the variable housing the results could simply be passed as an argument to a MoveNext method in order to go through the returned values step by step. Taking it a step further, you could use this strategy to extract a single field as demonstrated in the below code using the Current property out of the System.Xml.XPath namespace, then query the value of the current node using the SelectSingleNode method.
Here is the code for a select method to pass to a MoveNext() method:
- XPathNodeIterator pro2007Iteration = nav.Select("// my:pro2007field", NamespaceManager);
- // Start a while loop against the iteration and implement the MoveNext() method
- while (pro2007Iteration.MoveNext())
- // Get a current field using the SelectSingleNode method string
- pro2007String = pro2007Iteration.Current.SelectSingleNode("my:myfield", this.NamespaceManager);
It is also possible for you to set values for an InfoPath control using a switch/case to do minor pattern matching in order to execute an action, such as setting a value by using the SetValue() method.
Here is the code for switch/case setting of node values:
- XPathNavigator sharepointPro2007Nav = this.MainDataSource.CreateNavigator(); XPathNavigator sharepointPro2007Node = sharepointPro2007Nav.SelectSingleNode("//my: sharepointPro2007", this.NamespaceManager);
- switch (sharepointPro2007Node.Value)
- case "ProSharePoint1Case":
- sharepointPro2007Node.SetValue("Pro SharePoint Case Value 1");
- case "ProSharePoint2Case":
- sharepointPro2007Node.SetValue("Pro SharePoint Case Value 2");
Furthermore, you can implement some exception handling that can handle canceling save events by using the CanceableArgs property in order to extinguish an attempt at a save event. Putting exception handling into the custom InfoPath code is important since it will trap form logic errors, provide isolation of errors, and increase the overall reliability of the final form. Use the CancelableArgs property to allow the capture of the Save Event which will allow a user to cancel by setting it to true (which is the default as well). In order to display an error to the user, use MessageDetails allowing a string to be thrown to the user informing them of the error so that they can report the problem to you.
Here is the code for some example exception handling:
- catch (Exception ex)
- e.CancelableArgs.Cancel = true;
- e.CancelableArgs.MessageDetails = "The error is:" + ex.ToString();
Setting the Data of an InfoPath Control
A comparable approach to calling out data is required in order to set the fields in an InfoPath control. The XPathNavigator class will allow a cursor into the XML node set, and XPath expression matching occurs, however pushing a specific piece of data is performed by using the SetValue method out of XPathNavigator in order to set the child nodes with the passed in string argument.
Here is the code for setting a control value:
- XPathNavigator sharepointPro2007Nav = MainDataSource.CreateNavigator(); sharepointPro2007Nav.SelectSingleNode("//my:pro2007field ", NamespaceManager).SetValue("pro2007Value");
Compiling Frequently Used InfoPath Control Queries
It is important to realize that when you are using the XPathNavigator class and the related XPath expressions, the XPath expressions can be precompiled in order to optimize the code being integrated into InfoPath. For example, if a value is constantly being queried it is possible for you to use the Compile method in order to pass in the XPath query in order to return an XPathExpression object to call the same XPath expression string multiple times. Using the Compile method when coding against InfoPath will result in less bloated code and less development time while developing reusable XPath queries. In the code introduced above where we queried the Pro2007field, it could be optimized if being reused multiple times by adjusting it with the Compile method.
Here is the code for compiling an expression:
- XPathNavigator sharepointPro2007Nav = this.MainDataSource.CreateNavigator();
- XPathExpression pro2007Exp = sharepointPro2007Nav.Compile("//my:pro2007field", NamespaceManager).Value;
Afterwards, the XPathExpression object becomes available which will allow the expression you to pass the object into the SelectSingleNode method.
- string value = sharepointPro2007Nav.SelectSingleNode(pro2007Exp).Value; value = sharepointPro2007Nav.SelectSingleNode(pro2007Exp).Value;