Microsoft InfoPath 2010
The official blog of the Microsoft InfoPath team

"Design Once" and the new InfoPath 2007 Object Model

"Design Once" and the new InfoPath 2007 Object Model

  • Comments 18
One of the main design principles for InfoPath 2007 and Forms Services 2007 is that you can create your form once, write code for it once, build and publish it once, and then have it work in both the browser and the client. We call this Design Once.
 
To make this possible for form templates with code, we created a new object model that works on both the client and the server, so that the exact same assembly can work in both places. This is similar to what the Compact .NET Framework provides for mobile devices, where you can write a WinForm app that works on both the desktop and a Windows Mobile smartphone. Using the InfoPath object model you can write code for your form that will run the same way both on client, when opened in InfoPath, and on the server, when opened in the browser.
 
Getting started with System.Xml
If you've written code for InfoPath 2003, then you're used to writing code against the MSXML-based object model. For example, you might read and write a field's value like this in C# with the old object model:
 
string xpath = "/my:myFields/my:field1";
IXMLDOMNode field1 = thisXDocument.DOM.selectSingleNode(xpath);
string oldValue = field1.text; // Read
field1.text = "New Value";     // Write
 
Here's how to do the same thing using the new object model:
 
string xpath = "/my:myFields/my:field1";
XPathNavigator field1 = MainDataSource.CreateNavigator().SelectSingleNode(xpath, NamespaceManager);
string oldValue = field1.Value; // Read
field1.SetValue(“New Value”);   // Write
 
If we break that down, we see the following mappings:
 
InfoPath 2003 OM
InfoPath 2007 OM
thisXDocument.DOM
this.MainDataSource
IXMLDOMNode
XPathNavigator
Read field1.text
Read field1.Value
Set field1.text
Set using field1.SetValue()
 
Compatibility: Using the old OM in InfoPath 2007
InfoPath continues to open forms that used the old object model, so you don't have to upgrade them just to use InfoPath 2007. That said, if you want a form to work in the browser, you will need to upgrade to the new object model. If you upgrade the code, InfoPath will automatically update the project format and rebind all your events, but you will need to convert your custom functions to the new OM.
 
Compatibility: Using the new OM in InfoPath 2003
The new object model won't work in InfoPath 2003, so we also allow you to create forms that use the old object model in InfoPath 2007. You can choose which version of the object model you want to use in Form Options in the Programmability category. 
 
Enjoy!
Ned
Leave a Comment
  • Please add 7 and 4 and type the answer here:
  • Post
  • What would be a way to Custom Submit Form using new Object Model in InfoPath 2007
  • Thanks for starting to clarify the compatability matrix between IP 2003 and 2007.  

    I'd like to hear more about IP2003 consuming forms developed in IP2007.  For example, I like the web interface, but our desktops will use 2003 for some time.  Can I use 2007 for the browser clients, and 2003 for windows clients to populate the same forms library?
  • Using new Object Model how would I set a view to be default view dynamically.

    For example in the old Object Model I could access ViewInfos[] collection and set particular ViewInfo like so:

    string view = thisXDocument.DOM.selectSingleNode("//mstns:D_VIEW").text;
    thisXDocument.ViewInfos.IsDefault = true;

    In the new object model isDefault pproperty is not exposed.

    Is there something that I should add.
  • PingBack from http://blogs.msdn.com/infopath/archive/2006/06/08/622340.aspx
  • bkleynbok, the equivalent of your View-setting code in the new object model is:

    string viewName = MainDataSource.CreateNavigator().SelectSingleNode("//mstns:D_VIEW", NamespaceManager).Value;
    e.SetDefaultView(viewName);

    - Ned

    (Thanks for correcting an original version of this comment, I've deleted your correction and updated this to make it easier to read for future comers)

  • bkleynbok, the way to submit through code in the new object model is:

    DataConnections("NAME AS ENTERED IN THE DATA CONNECTION WIZARD").Execute();

    If you have a connection that can be used for both submit and query, then you can cast it to the appropirate type first to control what Execute does. For example, the following will submit a database connection:

    ((AdoSubmitConnection)DataConnections("NAME")).Execute();

    - Ned

  • I am working on Validation of the InfoPath 2007 form.

    I would like to know how validation works using events and FormErrorCollection.

    All help greatly appreciated.
  • This blog has been very helpful.  Because of this I can now submit in either the smart client or office forms server (DataConnections("NAME AS ENTERED IN THE DATA CONNECTION WIZARD").Execute(); ).  

    However I set some fields in FormEvents_Submit and FormEvents_Loading that work in the smart client but not in the web rendering:

    public void FormEvents_Loading(object sender, LoadingEventArgs e)
           {
               XPathNavigator root = this.MainDataSource.CreateNavigator();
               XPathNavigator RequestStatusNode = root.SelectSingleNode("//my:RequestStatus", this.NamespaceManager);
               if (RequestStatusNode.Value == "0")
                   RequestStatusNode.SetValue("None");
           }

    public void FormEvents_Submit(object sender, SubmitEventArgs e)
           {
               XPathNavigator root = this.MainDataSource.CreateNavigator();
               XPathNavigator RequestStatusNode = root.SelectSingleNode("//my:RequestStatus", this.NamespaceManager);
               XPathNavigator ErrorNode = root.SelectSingleNode("//my:Error", this.NamespaceManager);
               try
               {
                   switch (RequestStatusNode.Value)
                   {
                       case "None":
                           RequestStatusNode.SetValue("Pending Management Approval");
                           break;
                       case "Pending Management Approval":
                           RequestStatusNode.SetValue("Pending Advance Approval");
                           break;
                       case "Pending Advance Approval":
                           RequestStatusNode.SetValue("Pending Accounting Approval");
                           break;
                       case "Pending Accounting Approval":
                           RequestStatusNode.SetValue("Approved");
                           break;
                   }
                   this.DataConnections["SharePoint Library Submit"].Execute();
                   e.CancelableArgs.Cancel = false;
               }
               catch (Exception ex)
               {
                   e.CancelableArgs.Cancel = true;
                   e.CancelableArgs.MessageDetails = "Error:" + ex.ToString();
               }
               
           }

    Am I missing something there?

  • Sorry never mind.  Today that code just works.  Strange...
  • This posting is provided "AS IS" with no warranties, and confers no rights. Use of included script samples

  • Any way to specify a form template to use for rich client and different template to use for the browser?

  • To BobC: you can't do different templates for rich client vs browser easily. However, you can create different views within the same form template, and switch to an appropriate view depending on whether you're using a rich client or browser.

    - Alex

  • I've tried to call this.Submit() method from code when the Form Submit is set to Custom Code

  • Hi,

    I have a question regarding connecting two infopaths.

    How can we connect two infopaths through a common column?

    I have an infopath with CustID1 and this infopath contains another file

    attachment(infopath) and I have to popup the second infopath with the same

    CustID1.

    I tried the following code in the OnLoad event.

    try

               {

                   string strCustID = e.InputParameters["CustID"];

                   DataSource dsCustomers = this.DataSources["GetCustID"];

                   XmlNamespaceManager ns = this.NamespaceManager;

                   XPathNavigator xnCustomer = dsCustomers.CreateNavigator();

                   XPathNavigator xnCustomer = xnCustomer.SelectSingleNode("/dfs:myFields/dfs:queryFields/tns:Customers/tns:CustomerID");

                   xnCustomer.SetValue(CustomerID);

                   dsCustomer.QueryConnection.Execute();

               }

               catch (exception e)

               {

                   messagebox.show(e.message,"Error");

               }

    but encountered the following error:

    System.Collections.Generic.KeyNotFoundException was unhandled by user code

     Message="The given key was not present in the dictionary."

     Source="mscorlib"

     StackTrace:

          at System.ThrowHelper.ThrowKeyNotFoundException()

          at System.Collections.Generic.Dictionary`2.get_Item(TKey key)

          at Microsoft.Office.InfoPath.Internal.ReadOnlyDictionary`2.System.Collections.Generic.IDictionary<K,V>.get_Item(K key)

          at Customer_Checklist.FormCode.FormEvents_Loading(Object sender, LoadingEventArgs e)

          at Microsoft.Office.InfoPath.Internal.FormEventsHost.OnLoad(DocReturnEvent pEvent)

          at Microsoft.Office.Interop.InfoPath.SemiTrust._XDocumentEventSink2_SinkHelper.OnLoad(DocReturnEvent pEvent)

    Is this the process for transferring the value of a field from one infopath to another infopath.  

    Thanks in Advance

  • Hi,

    I have an issue in updating db table.

    I tried the code given by tronn.

    (DataConnections("NAME AS ENTERED IN THE DATA CONNECTION WIZARD").Execute(); ).  

    but I am unable to update my database table.

    Any clues for this????

Page 1 of 2 (18 items) 12