A solution that uses multiple Document Types that feed data to one another often requires one form to be filled out before another. However, the user might not realize this requirement until he or she has already started filling out the second form.
One example is when you have two Document Types: Customer and Timecard. The Customer Document Type is a qForm that is only opened whenever customers need to be edited or added. The Timecard form pulls from the Customer Document Type to populate the drop-down for assigning hours to a Customer’s Accounts Payable registry. If a user begins to fill out the Timecard form and the customer is not in the drop-down, it is much easier to add the new customer directly from within the Timecard form than having to open the separate Customer form.
Figure 1. A catalog form populating the drop-down for another form.
In this task we will look at the steps necessary to solve this problem.
Add a Connection to SubmitDocument
1. In InfoPath Design mode, open the Data Connections dialog, and then click Add.
2. Add a connection that will Receive data. In the following screen, select Web Service and click Next.
3. Type the URL to the DbxlDocumentService.asmx web service that corresponds to your DBXL installation.
4. Select the SubmitDocument web method, and then click Next.
5. For the docTypeName parameter, type the name of the Document Type that you will be adding documents to, but leave the rest blank. Click Next.
6. Make sure the option to Store a copy of the data in the form template is unchecked, and then click Next.
7. Name the data connection something descriptive, deselect the option to Automatically retrieve data when the form is opened, and then click Finish.

Figure 2. The data source for the SubmitDocument web method.
Add Controls to Input Necessary Data
In the example of adding new Customers from the Timecard form, you will need a control on the view to collect all of the information you need to create a new Customer. You can bind these controls to nodes on the Main DOM, but it is best practice to create a secondary data connection based off an XML document to collect the necessary data.
Get a sample XML document to be added as a secondary data connection
1. Open the target form (in this example, the Customer form) as if you were ready to input a new Customer.
a. If the form is a Catalog form with qForm, click the Add Document button.
2. From the InfoPath File menu, select Save As.
3. Save the XML document to your desktop.
Now you have an empty XML document that embodies what DBXL is going to receive when adding a new document to the Document Type. In the next step we’ll add that XML Document to the Timecard Document Type to allow input of data.
Add the sample XML document to the host form template
1. In the InfoPath Designer, open the Data Connections dialog, and click to Add a new Data Connection.
2. Select to add a new connection to Receive data.
3. Select to retrieve data from an XML Document.
4. Browse to and select the XML document saved to your desktop that was created in the previous section.
5. Select to Include the data as a resource file, and then click Next.
6. Name the data connection something significant, deselect the option to Automatically retrieve data when the form is opened, and click Finish.
Now that the data connection has been added, create the controls to allow entry of the data on the view. Your design might look something like the Figure 3.
Figure 3. Adding controls to collect document information.
Codeless versus Coded Implementation Techniques
This task may be accomplished by using rules to construct the necessary XML structure and then submit that XML to the web service. Using rules instead of code can be a quick and easy way to implement this feature for simple forms, but will quickly become too cumbersome for forms that have numerous fields. In the case of adding more complicated documents, you should use the coded implementation.
Adding Rules to Submit the New Document
After all controls have been added, you are ready to add the rules to the Upload button that will upload a new document. To construct the XML needed to submit to DBXL with Rules you must piece it together from one long string using the values that are stored in the secondary data source.
Breaking the XML Document into manageable pieces
1. Open the XML Document saved to your desktop in a text editor, such as Notepad.
2. Separate the document into pieces that you will concatenate together with the values of the secondary data connection. This process is shown in Figure 4.
3. Eliminate the Qdabra DBXL PI node, which will look like this: <?QdabraDBXL docid="" doctype="Customer" name="" author="" description="" ?>
Figure 4. Breaking up the XML.
Add the rules to the Upload button
1. Add a rule to the Upload button that will set the value of the /myFields/dataFields/SubmitDocument/xml node, as seen in Figure 5.
2. For the value, click the fx button to add a new formula.
3. Select the option to edit the XPath directly, and type the following:
concat(‘XML Fragment 1’, XPath_to_FullName, ‘XML Fragment 2’, XPath_to_PhoneNum, ‘XML Fragment 3’, XPath_to_Email, ‘XML Fragment 4’)
4. Be sure to replace the XML Fragment strings with the appropriate XML that you segmented in the previous step.
5. For the XPaths to the various nodes, you can click on the Insert Field or Value button in the expression builder to graphically find the node.
6. Click Ok until you are back to the Rules dialog box for the Upload button.
At this point, you will have a button that creates the necessary XML on the secondary DOM, so now you must add the rules to query the appropriate data connections.
Add rules to query the data connections
1. Click to add a new rule, select the Query Web Service action, and specify the SubmitNewDocument data connection. Make sure this rule executes after the rule that creates and sets the XML string.
2. Add another rule to query the data connection that pulls the Customer list from the database, and then close all dialog boxes.
Figure 5. The completed rules.
Coded Implementation
Implementing this feature using managed code is much simpler and allows for easier manipulation of the XML fragments. Below is an example of creating the necessary XML, loading it into the xml parameter, querying the web service, and then updating the view to reflect the new data.
[InfoPathEventHandler(MatchPath="btnUploadNewCustomer", EventType=InfoPathEventType.OnClick)]
public void btnUploadNewCustomer_OnClick(DocActionEvent e)
{
IXMLDOMNode nNewCustomerNode = builtInLogic.GetNode(domNewCustomer, "/my:QdCatalog");
// Set the query DOM with everything needed to query
string name = builtInLogic.GetNodeValue(domNewCustomer, "/my:QdCatalog/my:QdForm/@my:name");
string author = builtInLogic.GetNodeValue(domNewCustomer, "/my:QdCatalog/my:QdForm/@my:author");
string description = builtInLogic.GetNodeValue(domNewCustomer, "/my:QdCatalog/my:QdForm/@my:description");
builtInLogic.SetNodeValue(domSubmitNewCustomer, "/dfs:myFields/dfs:queryFields/tns:SubmitDocument/tns:name", name);
builtInLogic.SetNodeValue(domSubmitNewCustomer, "/dfs:myFields/dfs:queryFields/tns:SubmitDocument/tns:author", author);
builtInLogic.SetNodeValue(domSubmitNewCustomer, "/dfs:myFields/dfs:queryFields/tns:SubmitDocument/tns:description", description);
builtInLogic.SetNodeValue(domSubmitNewCustomer, "/dfs:myFields/dfs:queryFields/tns:SubmitDocument/tns:xml", nNewCustomerNode.xml);
// Upload the new customer
((WebServiceAdapter2)thisXDocument.DataAdapters["SubmitNewCustomer"]).Query();
// Enumerate from the DB to pick up the latest customer
((WebServiceAdapter2)thisXDocument.DataAdapters["EnumCustomer"]).Query();
// Determine the last one added in the list, assume sort by DocId is default
string sLastCustomerDocId = builtInLogic.GetNodeValue(domCustomer, "/dfs:myFields/dfs:dataFields/ns1:GetColumnsForRows2bResponse/ns1:GetColumnsForRows2bResult/Rows/row[last()]/DocId");
// Set the value of the drop-down to the most recently added customer
builtInLogic.SetNodeValue(String.Format("/my:QdCatalog/my:QdForm[ @my:docId = '{0}' ]/my:Estimate/my:Customer/my:CustomerDocId", builtInLogic.DocIdToView), sLastCustomerDocId);
}