Microsoft InfoPath 2010
The official blog of the Microsoft InfoPath team

  • Microsoft InfoPath 2010

    Submitting to a SharePoint List

    • 533 Comments

    As you know, submitting to a Microsoft Windows SharePoint form library from an InfoPath form is quite simple: just add a “submit” type of data connection to InfoPath and away you go. However, submitting to a SharePoint List is another matter. In this post, we will take a look at the steps necessary to enable this functionality.

    Step 1: Create the list

    1. Create a new custom list named: MyContacts
    2. From the Settings button choose List Settings
    3. Click Create Column
    4. Add the following columns/data types:

    • FirstName, Single line of text
    • LastName, Single line of text
    • Email, Single line of text
    • Phone, Single line of text

    The next step is to create a Collaborative Application Markup Language (CAML) template that contains the same XML nodes as the columns we added to our list – this will be used as a secondary data connection in the InfoPath Form Template.

    Step 2: Create the CAML template

    1. Launch Notepad (or any text editor)
    2. Copy and paste the following code to the Notepad document:

    <?xml version="1.0" encoding="UTF-8"?>
    <Batch OnError="Continue">
        <Method ID="1" Cmd="New">
            <Field Name='Title'></Field>
            <Field Name="FirstName"></Field>
            <Field Name="LastName"></Field>
            <Field Name="Email"></Field>
            <Field Name="Phone"></Field>
        </Method>
    </Batch>

    3. Save this as: Add List Item Template.xml

     

    Step 3: Create the InfoPath Form Template

    1. Create a new, blank, browser-compatible form template
    2. Add a “Receive” type secondary data connection to the Add List Item Template.xml file created in Step #2. (Make sure the options “Include the data as a resource file in the form template” and “Automatically retrieve data when the form is opened” are enabled.)
    3. Add a “Receive” type secondary data connection to the “MyContacts” SharePoint List created in Step #1 and make sure the option “Automatically retrieve data when the form is opened” is enabled.
    NOTE: Be sure to include the “Title” field along with the custom fields we created.

    Each SharePoint list is created with a unique identifier called a GUID. In order to submit items to a SharePoint list, you must know the unique GUID for that list. These next steps will enable you to identify the GUID for your “MyContacts” list.

    Step 4: Identify the list GUID

    1. Open a browser and navigate to the MyContacts list
    2. From the Settings menu choose List Settings
    3. In the browser’s address bar you will see the URL appended with “List=”

     

    4. Copy everything after the equals sign and paste this into a text editor as we will need this value later on.

    NOTE: We will need the list GUID to be formatted as “{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}”. If your GUID appears as above with the hyphens and braces “escaped” (i.e. %7B for the braces and %2D for the hyphens) then you will need to replace the escaped characters with the braces and hyphens so when we use this GUID later, it will appear as: {1E76517B-2C36-4473-A420-A737D98589BC}

    Step 5: Add controls to the InfoPath Form Template

    1. Open the Data Source Task Pane
    2. From the Data Source dropdown box choose the “MyContacts” connection

    3. Right-click on “MyContacts” and choose Repeating Table – this will add a repeating table bound to that connection to your View
    4. From the Data Source dropdown box choose Main
    5. Add a text box to the “myFields” node named: ListName and set the Default Value property to the GUID value of your list – we will use this node to specify the list when we perform the Submit operation

     

    To update the SharePoint list we will be using the “UpdateListItems” method of the SharePoint “lists.asmx” web service. This web method requires a couple of parameters (the list name and what gets updated) – now that we have added the “ListName” node which contains the GUID and we have the Add List Item Template XML data connection which describes our data structure we have all the necessary information to add the “UpdateListItems” web method!

    Step 6: Add the “lists.asmx” web service

    1. Add a new “Submit” type of web service data connection to the “lists.asmx” web service – this is typically located at: http://servername/_vti_bin/lists.asmx
    2. Select the “UpdateListItems” operation
    3. Double-click the “listname” parameter and assign the “my:ListName” node as the value

    4. Double-click the “updates” parameter, select the “Add list Item Parameter” data source, select “Batch” and click OK
    5. For the “Include” option select “XML subtree, including selected element”

    6. Complete the Data Connection Wizard

    Now that we have all the connections that are required, we now need to add the “submit” functionality to the form template.

    Step 7: Add Submit functionality

    1. Display the Data Source Task Pane
    2. From the Data Source dropdown box choose the Add List Item Template data connection
    3. Drill down through the data source, right-click on the Field node and choose Repeating Table

     

    We need to change the text box control in the “Name” column to Read-only – if these values were to be changed it would affect the CAML and the submit would fail.
    • Double-click on the text box in the Name column of the Repeating Table
    • Select the Display tab
    • Enable the Read-only property and click OK
    • Add a new Button control to the View
    • Double-click the button to display the Properties
    • Click the Submit Options button
    • Enable the option “Allow users to submit this form”
    • Enable the option “Perform custom action using Rules” and click the Rules button
    • Click the Add button
    • Click the Add Action button
    • From the Action dropdown box choose “Submit using a data connection”, select the “Web Service Submit” data connection and click OK
    • Click the Add Action button
    • From the Action dropdown box choose “Query using a data connection”, select the “MyContacts” data connection and click OK (this will automatically refresh the list in InfoPath so you can see the newly added record)

    • Click OK until you are back to your form

    NOTE: If you want to automatically clear out the submitted values, add another action to this Rule to “Set a field’s value” and the only option you need to specify is the “Field” option – select the “Field” node from the “Add List Item Template” data connection and then simply leave the Value option blank.

    Step 8: Test!

    1. Click the Preview button to preview the form
    2. Fill in values for each of the fields: Title, First Name, Last Name, E-mail and Phone

    3. Click the Submit button – the contact information should be submitted successfully and the “MyContacts” list automatically updated!

    A special thanks to Matt Faus of InfoPathDev for for initially posting this solution!

    Scott Heim
    Support Engineer

  • Microsoft InfoPath 2010

    Using the Contact Selector Control

    • 398 Comments

    (This post applies to InfoPath 2007. If you're using InfoPath 2010, then you should check out this post instead.)

    We have seen a number of requests on how to allow a user to enter (or select) a person’s name or logon alias and then validate that user against their Active Directory without using code. This has been especially true in workflow scenarios where User A needs to enter in the name of User B – the next person in the workflow process.

    Well, InfoPath 2007 ships with a control called Contact Selector Control that will resolve these issues! You may have seen our older article on the subject; this one aims to dive in deeper.

    The Contact Selector control is an ActiveX control but it is a special cased control, in that it can also be used in InfoPath browser forms. To use this control there are specific steps that need to be taken – let’s take a look at those now.



    Step 1: Add the Contact Selector control to your Controls Task Pane

    1) From the Controls Task Pane click the Add or Remove Custom Controls link

    2) Click the Add button

    3) On the first screen of the Add Custom Control Wizard select ActiveX control and click Next

    4) From the list of controls, choose Contact Selector and click Next

    5) Select “Don’t include a .cab file” and click Next

    6) For Binding Property select Value and click Next

    7) From the Field or group type box choose Field or group (any data type) and click Finish

    8) Click Close and then click OK

     

    Step 2: Create the data structure for the Contact Selector Control

    The Contact Selector control needs to have a specific data structure to work properly – this is documented on the “Items” tab of the Properties screen for the control; however, we’ll include that information here as well.

    **IMPORTANT!** Spelling and capitalization must be exactly the same, starting with the “Person” group!

    1) Add a non-Repeating Group named: gpContactSelector

    2) Add a Repeating Group named: Person

    3) Add the following 3 text fields to the Person group: DisplayName, AccountId and AccountType



    Step 3: Add and bind the Contact Selector control to the View

    1) Drag the gpContactSelector Group to the View and select “Contact Selector” from the list of controls

    2) You’re almost done…! :-)



    Step 4: Add a secondary data source XML file which specifies the SharePoint server

    The Contact Selector control needs to know the “context” of where the user validation should occur. These steps are not necessary if you are only displaying the form in a browser from SharePoint – in this case, it uses the context of the site from where it was provisioned; however, if you are in a mixed client/browser scenario you will need to include this XML file so forms opened in the client can use this functionality.

    1) Launch Notepad

    2) Copy and paste this one-line XML:

    <Context siteUrl="http://<servername>"/>

    **NOTE: Replace <servername> with the name of your server

    3) Save this as: Context.xml (again – naming and capitalization are important)

    4) Add Context.xml as a “Receive” type Secondary Data Connection to your form template and make sure the option “Include the data as a resource file” is enabled



    Step 5: Test!

    You should now be able to Preview the form, enter a name or logon alias, click the “Check Names” button and resolve the name! Alternatively you could click the “To” button to perform a Search if you do not know the complete name of the user.

    One other important point: if this control is something you will use numerous times, this process works great to create a “Contact Selector Template Part” – then you only have to complete these steps one time!

    Scott Heim
    Support Engineer

  • Microsoft InfoPath 2010

    Populating form data from SharePoint List Views

    • 105 Comments

    The SharePoint list data connection in InfoPath is a great declarative way to bring in data from a SharePoint list, but it does have some limitations.  For those willing to put in a little extra effort, there’s much more that can be done with SharePoint lists: you can bind to views based on these lists. Here are the steps for creating the connection to a list view.

    First, let’s get the URL:

    1. Navigate to the SharePoint site that contains the list, for example:
    http://contoso/sites/sales/Sales%20Contacts/Forms/AllItems.aspx
    2. Go to “Modify settings and columns”
    3. Copy the List={GUID} portion of the URL and paste this into a buffer like a Notepad window.
    4. In Notepad, create the following URL (the blue portion us taken from the step 1 URL, and the red portion must be added.

    http://contoso/sites/sales/_vti_bin/owssvr.dll?Cmd=Display&List={GUID}&XMLDATA=TRUE&noredirect=true

    This will return an xml file that can be used in an XML file data connection, as if it came from a file system.  After this, you can use the URL as the location of an XML data file when creating a data connection.

     

    Two caveats:
    - Form users must have read access to the SharePoint list.
    - During creation of the data connection, do not include the file in the form template, as it should be dynamically generated from the SharePoint list.

     

    Some tricks:
    1. When you’re in “Modify settings and columns,” if you click on one of the views in the list at the bottom, you should note that the URL is “enriched” with &View={ANOTHER_GUID}.  If you would prefer to use the columns from that view, you should similarly enhance the URL you use above.
    2. You can also use the url to filter data rows based on column values. For example:

    http://contoso/sites/sales/_vti_bin/owssvr.dll?Cmd=Display&List={115BC7B7-0A82-403E-9327-F3C73E6D37F3}&XMLDATA=TRUE&noredirect=true&FilterField1=xd__x007b_52AE1EF8_x002d_28E7_x002d_4CE4_x002d_AE23_x002d_54E23E80DDB5_x007d_&FilterValue1=Approved

    Note: be sure to remove the “ows_” from the beginning of the FilterField ID.

     

    With this filter, the XML file returned will be filtered to only display those projects that have been approved.  Without the green portion, you would see all the projects.

     

    In order to populate other fields with data from WSS, you create the secondary data source just like above, then in form code or script, you can use GetDOM(“dataSource”) and walk the DOM normally, updating the main DOM as appropriate.

     

    Ed Essey
    Program Manager

  • Microsoft InfoPath 2010

    Get the User Profile through MOSS Web Services

    • 37 Comments

    It is now easier than ever to pre-populate your InfoPath 2007 forms with the user profile information of the current user.

    Background:

    In Microsoft SharePoint Server 2003, the UserProfileService.GetUserProfileByName(string accountName) web service method required the caller to pass the account name (e.g., domain\alias) associated with the user profile to retrieve.  Though required, this argument was not needed when retrieving the profile of the current user.  After all, the form was running with the network credentials of the current user and those credentials were passed to the web service.

    The typical work-around was to deploy a custom WhoAmI web service as a façade for the UserProfileService.  This façade would provide a method (e.g., WhoAmI() ) that would detect the user's identity and effectively forward a call to the UserProfileService, returning the eventual result to the caller.

    New for Microsoft Office SharePoint Server 2007 and InfoPath 2007:

    In InfoPath 2007, you can get the logon name of the current user by just using a new built-in function; but what if you need to get more data than just the username? Manager name, phone number, office location, and other data are all accessible through the UserProfileService: read on.

    A form that uses the UserProfileService of MOSS to retrieve the User Profile of the current user no longer needs to explicitly pass the account information of the current user to the GetUserProfile method of the UserProfileService.  Simply passing a null value to this method will cause the web service to grab the user identity from the request.  The web service will then use that information as the account name and will subsequently return the User Profile of the current user.

    Use this technique when you want to pre-populate the fields of an InfoPath 2007 form with user information obtained from the MOSS 2007 User Profile Database. 

    The following instructions detail how to build a form to demonstrate this capability.

    Assumptions:

    • The default MOSS web application is configured to use Windows Authentication.
    • The MOSS server has an SSP with a User Profile Database that has been loaded from Active Directory
    • The end-user has a profile in the User Profile Database of the MOSS server
    • The end-user is logged into the client machine using his/her domain account.

     

    Step 1: Create the form

    1. Open InfoPath and design a new, blank form
    2. Save the form as UserProfileDemo.xsn

    Step 2: Design the form

    1. From the Layout Task Pane, add a 2 column x 4 row table to the form
    2. Place labels into the column 1 as follows: Name, Account, Email, and Phone
    3. Using the Controls Task Pane, drag four text box controls to your form, placing one in each row of column 2
    4. Using the Data Source Task Pane, rename the four "fieldX" data elements as follows: userName, userAccount, userEmail, and userPhone

     

    Step 3: Set the security level of the form

    1. From the Main Toolbar, select Tools | Form Options
    2. Select Security and Trust from the list box
    3. Clear the checkbox next to Automatically determine security level
    4. Select Full Trust
    5. Hit OK.

    Step 4: Add code to the form

    1. From the Main Toolbar, select Tools | Programming | Loading Event
    2. Right-click on UserProfileDemo node of the Project Explorer and choose Add Web Reference
    3. Enter the following for the URL: /_vti_bin/UserProfileService.asmx">http://<yourServerName>/_vti_bin/UserProfileService.asmx
    4. Enter the following for Web reference name: ProfileService
    5. Click Add Reference
    6. Replace the FormEvents_Loading event handler with the following code snippet:
    public void FormEvents_Loading(object sender, LoadingEventArgs e) {
    
        XPathNavigator myRoot = MainDataSource.CreateNavigator();
    
        ProfileService.UserProfileService profileService = new ProfileService.UserProfileService();
    
        ProfileService.UseDefaultCredentials = true;
    
        ProfileService.PropertyData[] userProps = null;
    
        try {
    
            // Passing null to this method causes the profile of the current user to be returned.
    
            userProps = profileService.GetUserProfileByName(null);
    
        }
    
        catch { }
    
        if (userProps == null || userProps.Length == 0) {
    
            return;
    
        }
    
        for (int i = 0; i < userProps.Length; i++) {
    
            XPathNavigator node = null;
    
            switch (userProps[i].Name.ToLower())  {
    
                // these property names can be obtained by reviewing the user profile properties in the MOSS SSP.
    
                case "preferredname":
    
                    node = myRoot.SelectSingleNode("/my:myFields/my:userName", NamespaceManager);
    
                    break;
    
                case "accountname":
    
                    node = myRoot.SelectSingleNode("/my:myFields/my:userAccount", NamespaceManager);
    
                    break;
    
                case "workemail":
    
                    node = myRoot.SelectSingleNode("/my:myFields/my:userEmail", NamespaceManager);
    
                    break;
    
                case "workphone":
    
                    node = myRoot.SelectSingleNode("/my:myFields/my:userPhone", NamespaceManager);
    
                    break;
    
                default:
    
                    continue;
    
            }
    
            ProfileService.ValueData[] values = userProps[i].Values;
    
            if (values.Length > 0) {
    
                if (node != null && string.IsNullOrEmpty(node.Value)) {
    
                    node.SetValue(values[0].Value.ToString());
    
                }
    
            }
    
        }
    
    }
    

     

    Step  5: Build and Preview

    1. Build the project and close VSTA.
    2. From the Main Toolbar, select File | Preview| Form
    3. When the form loads, the text boxes will be populated with your User Profile Information

    This example opens the door to simplifying the form submission process for your users by reducing the time they take to complete forms, as well as ensuring the accuracy of the data that they enter.

    Ronald Tielke
    Microsoft Consulting Services
    Desert Mountain District

  • Microsoft InfoPath 2010

    Comparing SharePoint List and Form Library Forms

    • 29 Comments

    So you’ve heard about SharePoint list form customization in InfoPath 2010 and you’ve seen the cool demos. But you may be asking yourself – What’s the difference between list and library forms and when should I use one or the other? In this post, we will answer these questions and provide guidance on when to create list vs. library forms.

    When designing InfoPath forms for SharePoint 2010, the first choice you need to make is between a SharePoint list form and a SharePoint form library form.

    Popular Form Templates

    Recommendation

    Use a list form if you just need to collect data and store it on SharePoint. Use a form library form if you want more advanced functionality such as complex or repeating data or code.

    What are list forms and form library forms?

    SharePoint list forms store data directly in a SharePoint list.  Each control (e.g. text box) in the form is bound to a column in the list. SharePoint list forms are directly connected to the list, which means that you don’t have to worry about setting up the publish and submit locations.
    Form library forms store data in XML files in a SharePoint form library. This means they are more flexible and you can do more with them. For example, they can be configured to save drafts and submit to different locations. However, they are more complex to work with and require more decisions to be made during configuration.

    Because the way data is stored between these template types is different, it is not possible to switch between them.

    Guidelines

    Here are some basic guidelines to help you decide what type of form to design.

    Use a list if:

    • You want to quickly get started building InfoPath forms on SharePoint
    • You need to use your form offline with SharePoint Workspace (formerly Groove)
    • You want to filter your SharePoint list based on a person or group
    • You would like to use the built-in display / edit views

    Use a form library if:

    • You have repeating or nested data
    • You are working from a predefined industry or complex schema
    • Your form needs to be digitally signed
    • You need code in your form
    • Your form is not hosted in SharePoint or you need to store results as an XML document

    How can I build advanced functionality into my forms?

    In general, form libraries provide better support for more complex and advanced forms. Here are a few examples of the way InfoPath can be used to build more powerful forms.

    Repeating data or complex schema

    • In some cases, you will want to collect repeating data in a form. For example, you have a project proposal form and want to include a list of potential risks for each project, or you have a book request form where users can request multiple books at once.
    • If you have a schema that has any nesting or repeating structures, or a defined industry schema such as Dublin core or Health Level 7, form library forms will allow you to organize your fields into groups to match your schema as opposed to having to flatten your schema to work with a list.
    • SharePoint lists store only one value per column; you can’t use list forms to store repeating data in a single item. As form library forms use XML to store data they can store repeating data in a single form.

    Using repeating data in list forms

    • If you have a SharePoint list form, you have several options for dealing with repeating data other than using the built in support of a form library.
    • If part of your content is repeating, consider flattening that schema so that it can repeat. For example, you could limit your book request form to no more than ten books per form.
    • You can also use multiple lists and link them together using lookup fields and web part connections. This works well for master/detail scenarios where one list tracks all the items and another contains the specific details for each item.

    Using repeating data in form library forms

    • Form library forms include controls that are designed to deal with repeating data inside the current item.  Form libraries have built-in support for repeating data with controls such as plain list, bulleted list, numbered list, repeating table, and repeating section.
    • They also support more customization of the form using the choice group and choice section controls. Advanced choice controls such as option button and optional sections are also available. All of these controls will be available by default in the controls gallery in InfoPath Designer for form library forms.

    Digital Signatures

    Managed Code

    • Form libraries support code-behind. This will allow you to do actions beyond logic in your form, such as advanced financial calculations.
    • Code can be used to extend InfoPath functionality or create custom business logic.
    • For example, in a pet food store you may use an InfoPath form to track food orders and use code behind the scenes to make sure you have enough inventory to meet the order and make sure that it isn’t sold before the form is submitted.
    • For more detail about forms with code, see Introduction to Programming in InfoPath 2010.

    Control over where your form is stored

    • Form libraries allow you to choose the location of where your form XML is sent when the form is submitted.
    • If you need to store your form as an XML document for use outside of SharePoint, then you should use a form library.
    • For example, if you have an insurance questionnaire and you want to store the completed form in a document collection with related content, a form library will allow you to do this.

    Bottom line

    Overall, both list forms and form library forms support much of the key functionality that InfoPath provides, such as data validation, custom rules, default values, and control over visual layout. In most cases, a list form will be sufficient for your needs. Lists have the most straightforward design and form management experience. However, for more complex scenarios such as repeating data or the need to add code, a form library may be necessary.

    Please leave a comment if you have any further questions!

    Daniel Broekman and Kate Everitt

    InfoPath Program Managers

  • Microsoft InfoPath 2010

    What's New in InfoPath 2010?

    • 63 Comments

    Here's a quick overview of some of the great new features in InfoPath 2010. Stay tuned for upcoming posts with more details!

    Microsoft InfoPath 2010 makes it easier than ever to design electronic forms. InfoPath now includes the Office Fluent UI and allows the creation of powerful, interactive forms, without having to write any code. With a few clicks, Office users can customize SharePoint list forms, add custom layouts and rules to validate the data, and take them offline in SharePoint Workspace.

    IT professionals can create custom forms for document workflows and Office Business Applications that include managed code, digital signatures and that connect to line of business data.

    In InfoPath 2010, we’ve made some big investments to make it much easier to build rich forms-based applications on top of the SharePoint Server 2010 platform.

    Quickly Design Forms with Easy-to-Use Tools
    New features to help you quickly and easily create forms include our new Fluent UI, pre-built layout sections, out-of-the-box rules, improved rules management, and varied styles. 

    The New tab in the Designer Backstage presents you with the available form templates that you can choose from. Most templates start you off with a default layout table.

    InfoPath 2010 Designer New Tab

    Stay tuned for more details on our new and improved form design features!

    Layout your Forms Using Pre-built Page and Section Layouts
    Laying out your form and making it look more attractive is now easier than ever. Insert one of our pre-built page layouts to give your form structure. Then, insert some section layouts into the page layout to start building your form.

    Page and Section Layouts in InfoPath Designer:

    InfoPath 2010 Designer Layouts


    New and Improved Controls
    We’ve added some new controls and narrowed the feature gap between client and browser forms, ensuring a more consistent form filling experience for all our users.

    New controls in InfoPath 2010 include:

    • Picture buttons – Instead of the default gray button, use any image as a button in your form.
    • Hyperlink capabilities –Allow users to insert their own hyperlinks when filling out forms.
    • Date and time picker – Allow users to insert dates and times in their forms
    • Person/Group pickers – Updated! This is now a first class control and is included by default in the Controls gallery.
    • Signature Line (Editor Only) – Allow users to digitally sign a  form

    Controls and functionality that are now supported in browser forms include:  

    • Bulleted, numbered, and plain lists, multiple selection list boxes, Combo boxes, Choice group and sections, and Filtering functionality.

    Add Rules to your Forms
    With our new out-of-the-box rules (or quick rules) and improved rules management UI, you can easily add rules to validate data, format your form, or perform other actions with just a couple of clicks, and without any code.

    Quick Rules in InfoPath Designer:

    InfoPath 2010 Designer Quick Rules

    Publish Forms Quickly
    Our new “quick” publish functionality allows you to publish forms in a single click (no more clicking through the Publishing Wizard every time you want to make an update to your forms!)
     

    Create Forms for SharePoint Lists
    Using InfoPath, you can now extend and enhance the forms used for creating, editing and viewing items in a SharePoint list. In a browser, simply navigate to a SharePoint list, and on the SharePoint Ribbon under List Tools, choose the Customize Form option. This will automatically generate a form which looks very similar to the default out-of-the-box SharePoint list form.

    You can then customize and enhance this form by modifying the layout, creating additional views or pages, and adding rules to validate your data, show or hide sections of the form or set a fields value (to name just a few of the options).

    Example of Customized SharePoint List Form:

     Customized SharePoint List Form
    Stay tuned for more details on SharePoint List Customization!

    We recommend using a form associated with a SharePoint list when possible. This provides the most straightforward design and form management experience. However, there are more complex scenarios where using a form associated with a form library is preferred e.g. if your form has a complex schema or if you need to add code to your form. 

    Create SharePoint Applications
    With InfoPath 2010, SharePoint Server 2010, and SharePoint Designer 2010, you can easily create powerful team, departmental or enterprise applications on top of SharePoint Server.

    • Form-based applications: InfoPath forms can be integrated with components such as workflow, reporting, and custom Web pages to create rich form-based applications.  
    • Document Workflows: InfoPath can be used to design custom workflow initiation and task forms that drive document management processes.
    • Business Connectivity Services: Integrating with BCS, it is straightforward to design InfoPath forms that create, read, update, and delete business data from a back-end system. 

    Stay tuned for more details on creating SharePoint applications!

    Create Mashups using the InfoPath Form Web Part
    Now, without writing a single line of code, you can host your InfoPath browser forms in Web pages by simply adding the InfoPath Form Web Part to a Web Part page. You can also connect it to other Web Parts on the page to send or receive data.

    Stay tuned for more details on the InfoPath Form Web Part!

    Build Forms with Code
    Using Visual Studio Tools for Applications, you can add managed code to your forms.

    Stay tuned for more details on programming with InfoPath! 

    InfoPath Editor
    The InfoPath 2010 Editor Fluent user interface provides a much improved, simpler user experience for filling out forms.

    Form opened in InfoPath 2010 Editor:

    InfoPath 2010 Filler
     
    SharePoint Workspace
    InfoPath 2010 is the forms technology used by SharePoint Workspace 2010 for creating and filling out forms.

    InfoPath Forms Services Administration and Management
    We have invested in many improvements to make it easier to manage your InfoPath Forms Services as a component of Microsoft SharePoint Server 2010.

     

    We hope you enjoy using InfoPath 2010 and look forward to getting your feedback!

    The InfoPath Team

     

  • Microsoft InfoPath 2010

    Creating an InfoPath Custom Control using C# and .NET

    • 14 Comments

    In Office 2003 Service Pack 1 (SP1), new features and the InfoPathControl and InfoPathControlSite objects were added to InfoPath to support the development of custom controls implemented using Microsoft ActiveX technology. ActiveX controls are developed using unmanaged COM code, typically written in C++ or Visual Basic 6.0. With the increasing popularity of the Microsoft .NET Framework, many developers are switching to working with managed code, such as C# and Visual Basic .NET. As an alternative to using unmanaged code to create a custom ActiveX control, you can create a user control (a control derived from the .NET Windows Forms UserControl class) that will function as an InfoPath custom control by using COM Interop. COM Interop provides interoperability between the .NET assembly compiled for your user control and the unmanaged code of InfoPath. Although Windows Forms user controls are not natively supported by InfoPath SP1, once you handle the details required for COM Interop and security, writing your .NET code is really easy. In this blog entry, we'll give you an overview of how to get a .NET control to work in InfoPath. This entry won’t go over the basics of writing .NET user controls, so if you are not familiar with user controls, you will need to find that information before the discussion in this blog entry will be useful to you. The basic steps for creating a user control are described in Walkthrough: Authoring a User Control with Visual C#. For additional details on creating custom ActiveX controls for InfoPath, you can view the Creating Custom Controls for InfoPath SP1 webcast, and work with the ActiveX Controls in InfoPath 2003 hands-on training.
     
    Adding the Right Attributes
    To get a .NET user control to work with unmanaged code, certain attributes will need to be added to its source code. In the ActiveX world, all controls have GUIDs (globally unique identifiers). To do this in .NET, you will need to use the GuidAttribute attribute to specify a GUID. This attribute is part of the System.Runtime.InteropServices namespace.

    COM interop will expose methods and properties based on the setting of the ClassInterface attribute. This attribute must be set to ClassInterfaceType.AutoDual in order for the control to work correctly in InfoPath.

    [ClassInterface(ClassInterfaceType.AutoDual)]

    But you will still need to expose the Value and Enabled properties of your control to InfoPath. To do this, you declare an interface for these properties that you will implement within the user control class. The InterfaceType attribute on this interface should be set to InterfaceIsDual as shown in the following line of code:

    [InterfaceType(ComInterfaceType.InterfaceIsDual)]

    This attribute setting will expose all of the properties on this interface.
     
    Additionally, for the property notifications to fire you will need to specify COM dispatch identifiers (DISPIDs) for the Enabled and Value properties of your control. To assign DISPIDs using COM interop, you use the DispId attribute, which is also part of the System.Runtime.InteropServices namespace.
     
    Putting all of this together, the skeletal code for your control should look something like the following example:

    [InterfaceType(ComInterfaceType.InterfaceIsDual)]
    public interface ICOMControl
    {
      [DispId(UserControl1.DISPID_VALUE)]
      string Value { get; set; }
     
      [DispId(UserControl1.DISPID_ENABLED)]
      bool Enabled { get; set; }
    }

    [Guid("6E6F8C69-2643-4f45-B111-3ABE034940D9")]
    [ClassInterface(ClassInterfaceType.None)]
    public class UserControl1 : System.Windows.Forms.UserControl, ICOMControl
    {
       ...
    }

    Note that ICOMControl is the name we’ve given to the interface we defined which must be implemented within the control class to expose the Value and Enabled properties. The user control class derives from this interface, provides the actual implementation of the get and set methods of the properties, and specifies the values for the DISPID_VALUE and DISPID_ENABLED constants. See the full listing later in this blog entry for more details. 
     
    The IPropertyNotifySink Interface
    The COM IPropertyNotifySink interface is required for InfoPath to know when to update the XML field which is bound to the ActiveX control. Property notifications should be fired by the control for this to happen. .NET user controls do not have an equivalent interface that will work in COM Interop, but you can work around this by importing the unmanaged IPropertyNotifySink interface and then writing your own implementation of it in managed code. This is accomplished by using the ComImport and InterfaceType attributes as shown in the following example.

    [ComImport]
    [Guid("9BFBBC02-EFF1-101A-84ED-00AA00341D07")]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    public interface IPropertyNotifySink
    {
       int OnChanged(int dispId);

       [PreserveSig]
       int OnRequestEdit(int dispId);
    }

    In addition to this code, you need to a create a delegate for the two events of your control class. The delegate should look like this:

    public delegate int PropertyNotifySinkHandler(int dispId);

    And your events should look like this:

    public event PropertyNotifySinkHandler OnChanged;
    public event PropertyNotifySinkHandler OnRequestEdit;

    You also need to specify that the imported IPropertyNotifySink interface is exposed as a source of COM events. You do this by adding the ComSourceInterfaces attribute to your control's class. The attribute should look like this:

    [ComSourceInterfaces(typeof(IPropertyNotifySink))]

    And finally, when implementing the Value and Enabled properties of the control, don't forget to fire the OnChanged event when the Value property is changed.
     
    Satisfying Security

    Custom controls written with a .NET language still have the same security restrictions as unmanaged ActiveX controls used in InfoPath: the .CAB file for the control must be signed with a digital signature, and the IObjectSafety interface must be implemented on the control. The IObjectSafety interface is an unmanaged interface but can still be implemented if you import and rewrite the interface in .NET. This is similar to what we did for the IPropertyNotifySink interface above:

    [ComImport]
    [Guid("CB5BDC81-93C1-11CF-8F20-00805F2CD064")]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    interface IObjectSafety
    {
       [PreserveSig]
       int GetInterfaceSafetyOptions(ref Guid riid, out int pdwSupportedOptions, out int pdwEnabledOptions);
                            
       [PreserveSig]
       int SetInterfaceSafetyOptions(ref Guid riid, int dwOptionSetMask, int dwEnabledOptions);
    }

    The user control class must derive from the IObjectSafety interface and implement the GetInterfaceSafetyOptions and SetInterfaceSafetyOptions methods. See the complete listing in the following section for details on how to do this.

    Coding Checklist
    We've gone over quite a few things that need to be done to create a .NET user control that works with InfoPath. Below is a checklist of the things you should have already done:

    • Add the Guid attribute to your control class
    • Add the ComSourceInterfaces attribute to your control class
    • Set the control’s ClassInterface attribute to ClassInterfaceType.None
    • Declare an interface for the Value and Enabled properties of your control, setting the InterfaceType attribute to ComInterfaceType.InterfaceIsDual
    • Import and implement the COM IPropertyNotifySink interface
    • Import and implement the COM IObjectSafety interface

    The following listing provides the code behind a simple .NET user control that contains a read-only TextBox control that can be bound to a field in an InfoPath form.

    using System;
    using System.Collections;
    using System.ComponentModel;
    using System.Drawing;
    using System.Data;
    using System.Windows.Forms;
    using System.Runtime.InteropServices;

    namespace WindowsControlLibrary1
    {
       /// <summary>
       /// Summary description for UserControl1.
       /// </summary>

       [InterfaceType(ComInterfaceType.InterfaceIsDual)]
       public interface ICOMControl
       {
          [DispId(UserControl1.DISPID_VALUE)]
          string Value { get; set; }

          [DispId(UserControl1.DISPID_ENABLED)]
          bool Enabled { get; set; }
       }

       [ComImport]
       [Guid("CB5BDC81-93C1-11CF-8F20-00805F2CD064")]
       [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
       interface IObjectSafety
       {
          [PreserveSig]
          int GetInterfaceSafetyOptions(ref Guid riid, out int pdwSupportedOptions, out int pdwEnabledOptions);
                           
          [PreserveSig]
          int SetInterfaceSafetyOptions(ref Guid riid, int dwOptionSetMask, int dwEnabledOptions);
       }

       [ComImport]
       [Guid("9BFBBC02-EFF1-101A-84ED-00AA00341D07")]
       [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
       public interface IPropertyNotifySink
       {
          [PreserveSig]
          int OnChanged(int dispId);
     
          [PreserveSig]
          int OnRequestEdit(int dispId);
       }

       public delegate int PropertyNotifySinkHandler(int dispId);

       [Guid("1FEE489F-A555-4408-8FBF-3F69F8C57A43")]
       [ClassInterface(ClassInterfaceType.None)]
       [ComSourceInterfaces(typeof(IPropertyNotifySink))]
       public class UserControl1 : System.Windows.Forms.UserControl, ICOMControl, IObjectSafety
       {
          public event PropertyNotifySinkHandler OnChanged;
          public event PropertyNotifySinkHandler OnRequestEdit;

          private System.Windows.Forms.TextBox textBox1;
          /// <summary>
          /// Required designer variable.
          /// </summary>
          private System.ComponentModel.Container components = null;

          // Constants for implementation of the IObjectSafety interface.
          private const int INTERFACESAFE_FOR_UNTRUSTED_CALLER = 0x00000001;
          private const int INTERFACESAFE_FOR_UNTRUSTED_DATA = 0x00000002;
          private const int S_OK = 0;

          // Constants for DISPIDs of the Value and Enabled properties.
          internal const int DISPID_VALUE = 0;
          internal const int DISPID_ENABLED = 1;

          public UserControl1()
          {
             // This call is required by the Windows.Forms Form Designer.
             InitializeComponent();
             // TODO: Add any initialization after the InitComponent call
          }

          // Implementation of the IObjectSafety methods.
          int IObjectSafety.GetInterfaceSafetyOptions(ref Guid riid, out int pdwSupportedOptions, out int pdwEnabledOptions)
          {
             pdwSupportedOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA;
             pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA;
             return S_OK;   // return S_OK
          }
     
          int IObjectSafety.SetInterfaceSafetyOptions(ref Guid riid, int dwOptionSetMask, int dwEnabledOptions)
          {
             return S_OK;   // return S_OK
          }

          protected int Fire_OnRequestEdit(int dispId)
          {
             if (this.OnRequestEdit != null)
                return this.OnRequestEdit(dispId);
             else return 0;
          }

          protected int Fire_OnChanged(int dispId)
          {
             if (this.OnChanged != null)
                return this.OnChanged(dispId);
             else return 0;
          }

          // Implementation of the Value property get and set methods.
          public string Value
          {
             get { return textBox1.Text; }
             set { textBox1.Text = value; }
          }

          /// <summary>
          /// Clean up any resources being used.
          /// </summary>
          protected override void Dispose( bool disposing )
          {
             if( disposing )
             {
                if( components != null )
                   components.Dispose();
             }
             base.Dispose( disposing );
          }

          // Component Designer generated code goes here.
          ...

          private void textBox1_TextChanged(object sender, System.EventArgs e)
          {
             Fire_OnChanged( UserControl1.DISPID_VALUE );
          }
       }
    }

    Compiling a .NET User Control for COM Interop
    To compile a .NET user control for COM Interop, follow these steps:

    1. In Visual Studio .NET 2003, open the Solution Explorer and right-click on the project item.
    2. Click Properties to display the properties pane for the project.
    3. Under Configuration Properties, click Build.
    4. Under Outputs, change Register for COM Interop to True.

    The next time you compile, your user control will be available to unmanaged code.
     
    Adding a .NET User Control to the InfoPath Controls Task Pane
    When you add a new custom control using the InfoPath Add Custom Control Wizard, InfoPath will look only for controls that are in the "Controls" category. However, when .NET Controls are compiled, they are categorized as ".NET Controls", which InfoPath does not look for. To manually add a .NET control, you must create an .ICT file and store it in the C:\Documents and Settings\username\Local Settings\Application Data\Microsoft\InfoPath\Controls folder. If you have not added any custom controls to InfoPath's Controls task pane, you will need to create this Controls folder yourself. The easiest way to create an .ICT file is to add an ActiveX control to the Controls task pane in InfoPath, and then copy the .ICT file which is created automatically by InfoPath.
     
    Getting a .NET User Control into a Self-Registering CAB file
    InfoPath requires custom controls to be packaged in CAB files for deployment. The normal way for .NET Controls to be deployed is to add a Setup Project to the solution in Visual Studio, which will produce an MSI file when the solution is compiled. An MSI file is required for a .NET control to be registered for COM Interop. The MSI file that is generated by the Setup Project can then be packaged in a CAB file, but CAB files do not automatically run and register MSI files. You can work around this by creating an .INF file similar to the following example which has hooks to execute the .MSI file after the CAB file is extracted:

    [Setup Hooks]
    hook1=hook1

    [hook1]
    run=msiexec.exe /i %EXTRACT_DIR%\MSI.msi /qn

    [Version]
    ; This section is required for compatibility on both Windows 95 and Windows NT.
    Signature="$CHICAGO$"
    AdvancedInf=2.0

    Note   There is a bug in the .NET Framework that will cause any Label controls used in a .NET user control to throw GDI+ exceptions. You can workaround this by using GDI+ to draw your own text, or you can use a TextBox control instead and set its ReadOnly property to True.

  • Microsoft InfoPath 2010

    Introduction to Programming in InfoPath 2010

    • 28 Comments

    Hello, my name is Christopher Brotsos, and I’m a Program Manager on the InfoPath team. In this post, I’m going to show you how to add business logic to your forms using managed code.

    Imagine a scenario where the accounting department at Contoso, Inc. tracks corporate assets through an Asset Management System built on SharePoint. One module in the system allows employees to order office equipment such as laptops, conference phones, and ergonomic chairs through an InfoPath form. At first, the order form was built using only declarative logic. It could enforce required fields, surface validation messages, and submit the form to SharePoint without any code.

    As the ordering process grew more complex, users started adding additional requirements to the system. The variety of inventory available to employees increased, so they wanted a way sort items by name and description real-time in the order form. Contoso also started shipping their office equipment out of three warehouses. This prevented the warehouse crew from fulfilling complete orders, and as such, the system needed to track shipping status and quantity of individual items in the order. To meet the new requirements, Contoso added the following features to the form:

    • A custom sort interface
    • Logic for managing complex data when the form is submitted
    • Logic to add items to a SharePoint list

    Sort interfaces, sophisticated submit routines, and database (i.e. list) management are common requirements for forms. Fortunately, this functionality can be added to InfoPath forms with a few lines of code. Let me explain these features, the code required to build them, and the prerequisites for developing managed code in InfoPath in more detail.

    Equipment Request Form

    The employee orders module in the Asset Management system consists of three core components:
    1. A SharePoint form library, “Equipment Orders”, where users go to fill out the Equipment Order Request form shown below.
    2. A SharePoint list, “Equipment Inventory”, which stores the items available for users to order. This list contains fields specifying items’ names, descriptions, and quantities used to populate the Equipment Order Request form.
    3. A SharePoint list, “Equipment Shipping”, which stores a list of items ordered by users that have been scheduled for shipping. This list contains fields for the names and quantities of items being ordered as well as the name of the user who placed the order.

    The Equipment Request Form enables users to sort through Contoso’s available inventory and submit a request to the warehouse for shipping.

    Equipment Order Request Form

    The order form is a repeating table, where each row in the table represents the name, description, and quantity of the item being ordered.

    Equipment Order Request Form 

    Sorting data in the form

    The Equipment Order Form has a Picture Button Control displaying an arrow next to each of the column labels.

    Equipment Order Request Form

    The buttons are used to sort the order items in ascending order by the respective column. When the user clicks the button, the values in the selected column are compared, and the rows of data are sorted based on the comparison result.

    The sorting routine in this example is based on a complete solution provided by Hagen Green. Read through his post to learn how to provide a descending sort which also takes localization and data types into consideration.

    private string GetValue(string xpath)
    
    {
    
      // return the value of the specified node
    
      XPathNavigator myNav = this.MainDataSource.CreateNavigator().SelectSingleNode(xpath, NamespaceManager);
    
      if (myNav != null)
    
        return myNav.Value;
    
      else
    
        return "";
    
    }
    
    private void Swap(string xpath1, string xpath2)
    
    {
    
      // swap two rows of the table 
    
      XPathNavigator item1 = this.MainDataSource.CreateNavigator().SelectSingleNode(xpath1, NamespaceManager);
    
      XPathNavigator item2 = this.MainDataSource.CreateNavigator().SelectSingleNode(xpath2, NamespaceManager);
    
      if (item1 != null && item2 != null)
    
      {
    
        // Make a copy of item1
    
        // Move item2 to item1
    
        // Make the original item2 be item1 that we cloned earlier
    
                    
    
        XPathNavigator item1Clone = item1.Clone();
    
        item1.ReplaceSelf(item2);
    
        item2.ReplaceSelf(item1Clone);
    
      }
    
    }
    
    private void SortOrder(string sortBy)
    
    {
    
      string itemsToSort = "/my:myFields/my:Order/my:OrderItem";
    
      XPathNodeIterator items = this.MainDataSource.CreateNavigator().Select(itemsToSort, NamespaceManager);
    
      if (items != null)
    
      {
    
        int numItems = items.Count;
    
        // basic bubble sort implementation
    
        for (int i = 1; i < numItems; i++) // xpath is 1-based
    
        {
    
          for (int j = i + 1; j <= numItems; j++)
    
          {
    
            // swap (i,j) if necessary
    
            string iValue = GetValue(itemsToSort + "[" + i + "]" + sortBy);
    
            string jValue = GetValue(itemsToSort + "[" + j + "]" + sortBy);
    
            if (String.Compare(iValue, jValue, true) > 0)                       
    
              Swap(itemsToSort + "[" + i + "]", itemsToSort + "[" + j + "]");
    
                            
    
          }
    
        }
    
      }
    
    }
    
    public void ItemNameSort_Clicked(object sender, ClickedEventArgs e)
    
    {
    
      // Sort order by ItemName
    
      // Repeat this code for the other buttons
    
      string sortBy = "/my:ItemName";
    
      SortOrder(sortBy);
    
    }
    

    Managing complex data during submit and updating SharePoint lists using the SharePoint object model

    The user is eventually going to finish selecting items and submit the order. Each item ordered through the form is handled independently because, for example, an item in the order may be delayed or shipped from a remote warehouse. So, we need submit logic which will break up the complex data (i.e. the repeating table of items being ordered) into individual rows, and add a shipping request to the Equipment Shipping list for each item-quantity pair. After an item is added to the Equipment Shipping list, a SharePoint workflow is used to track status and manage the Inventory Equipment list’s quantity values.
    1. The first thing you’ll need to do is use the Submit Options button on the Data tab in the ribbon to add a custom submit handler to your VSTA project.

      Submit Options

    2. Add a reference to Microsoft.SharePoint.dll to your VSTA project. This will allow you to develop code using the SharePoint object model. This DLL is installed in %CommonProgramFiles%\Microsoft Shared\Web Server Extensions\14\ISAPI with your licensed copy of Microsoft SharePoint Server.
    3. Add custom submit logic to create a SharePoint list item for each item in the order form. See the code below for an example, and notice the use of the ServerInfo class. The ServerInfo class is new to InfoPath 2010 and allows you to write portable code with relative references to SharePoint server URLs.

     

    public void FormEvents_Submit(object sender, SubmitEventArgs e)
    
    {
    
      // Loop through each item-quantity pair in the order form.
    
      // Submit pairs to the Equipment Shipping list.
    
      // Note: Workflow will handle updating item quantities and track shipping status.
    
      using (SPSite mySite = new SPSite(ServerInfo.SharePointSiteUrl.ToString()))
    
      {
    
        using (SPWeb myWeb = mySite.OpenWeb())
    
        {
    
          XPathNodeIterator orderItems;
    
          if (myWeb != null && myWeb.Lists["Equipment Shipping"] != null)
    
          {
    
            SPList shippingList = myWeb.Lists["Equipment Shipping"];
    
            myWeb.AllowUnsafeUpdates = true;
    
            orderItems = this.MainDataSource.CreateNavigator().Select("/my:myFields/my:Order/my:OrderItem", NamespaceManager);
    
            if (orderItems != null)
    
            {
    
              while (orderItems.MoveNext())
    
              {
    
                // Add rows from the form where user selected an item and specified a quantity.
    
                string itemName = orderItems.Current.SelectSingleNode("./my:ItemName", NamespaceManager).Value;
    
                string itemQuantity = orderItems.Current.SelectSingleNode("./my:ItemQuantity", NamespaceManager).Value;
    
                if (itemName != string.Empty && itemQuantity != string.Empty)
    
                {
    
                  SPListItem shipItem = shippingList.AddItem();
    
                  shipItem["Title"] = itemName;
    
                  shipItem["Quantity"] = itemQuantity;
    
                  shipItem.Update();
    
                }
    
              }
    
            }
    
          //cleanup
    
          //signal successful submit
    
          //return
    
          myWeb.AllowUnsafeUpdates = false;
    
          e.CancelableArgs.Cancel = false;
    
          return;
    
          }
    
        }
    
      }
    
    }
    

    Along with the features covered above, you’ll find that code is useful for implementing complex data validation logic and managing content from multiple data sources. Such requirements are especially common when your forms are part of an advanced application. You can learn more about validation and working with the InfoPath DOM in our MSDN XmlEvent.Validating documentation and our post on working with InfoPath data sources programmatically. You can also review the InfoPath and SharePoint object models on MSDN for a more granular view into programming with InfoPath 2010.

    If you’d like to get started with programming in InfoPath, then please read on. The rest of this post introduces our system requirements, integrated development environment, and programmability user experience.

    How to add code to an InfoPath form

    To add code to an InfoPath form:

    1. Make sure you meet the minimum system requirements.
    2. Install Visual Studio Tools for Applications (VSTA).
    3. Choose a programming language.
    4. Add event handlers and code.

    Minimum system requirements

    The minimum system requirement to get started with InfoPath 2010 development is Microsoft .NET Framework 2.0, but we suggest you install Microsoft .NET Framework 3.5 SP1 if you’re developing for the SharePoint platform. You can install all versions of Microsoft .NET Framework from http://www.microsoft.com/downloads.

    Installing Visual Studio Tools for Applications

    Visual Studio Tools for Applications (VSTA) is an optional installation component available in Microsoft Office 2010 setup. To install VSTA:

    1. Launch Office 2010 setup from your Office 2010 installation media or from the Control Panel Programs and Features application.
    2. If you’re installing a new copy of Office 2010, click the Customize button in the installer. If you’ve already installed Office 2010, choose the Add or Remove Features radio button in the installer.
    3. Set the Visual Studio Tools for Applications option to Run from My Computer and continue through the setup wizard.

    Office Setup

    Choosing a programming language

    InfoPath 2010 allows you to program in C# and Visual Basic .NET. If you want to program with Visual Basic, you do not need to do anything to select your programming language when designing InfoPath 2010 compatible forms. If you plan on programming with C#, or adding code to InfoPath 2007/2003 compatible forms, you can change the programming language by clicking the Language button in the Code group of the Developer tab.

    Developer Tab

    After you click the Language button, you can change your programming language by using the Form template code language drop down:

    Form Options

    Hint: You can change the default language for InfoPath 2010 compatible forms by using the Options menu in the Backstage.

    1. Click the File > Options tab
    2. Click the More Options button in the General category of the InfoPath Options dialog
    3. Change the Programming language dropdowns in the Programming Defaults section of the Design Options

    Options

    Adding event handlers

    The Developer tab is the primary entry point for programming in InfoPath 2010. It’s designed to help you add event handlers compatible with the controls and mode of the form you are designing. For example, if you don’t have a control selected on your form view, then you’ll only be able to select the events that apply to the entire form. Notice that the Loading and View Switched event below are enabled, but the entire Control Events group is disabled.

    Developer Tab

    But, as soon as I select a text box on the form, the Control Events group lights up.

    Developer Tab

    Notice that the Sign, Context Changed, and Changing events are disabled in both screenshots of the Developer tab. That’s because I’m working with a browser compatible form, and those events are only available for InfoPath Filler forms.

    Note: You’ll find a table of all events, and their compatibility, towards the end of this section.

    Certain control and form programming events can be accessed through buttons on other tabs in the ribbon. If you add a Picture Button control on the form view, highlight the button, and then click on the Properties tab then you’ll find the Custom Code button enabled. Clicking the Custom Code button in the ribbon will add an OnClick event for the Picture Button control.

    Custom Code Button

    In the Equipment Order Request form, we added a Submit event handler to add items to a SharePoint list. To do this, navigate to the Data tab, and click the Submit Options button in the Submit Form group.

    Submit Options Button

    This will launch the Submit Options dialog where you can check “Allow users to submit this form”, “Perform custom action using Code”, and then click the Edit Code button.

    Submit Options

    The Fields task pane is another main entry point to add event handlers. In the next screenshot, I access the Validating and Changed events for ItemDescription by right clicking the field in the Fields task pane and scrolling through its context menu.

    Fields Taskpane

    The following tables provide a list of all events and compatibility in InfoPath 2010. Note that InfoPath forms trigger three types of events: Form Events, Data Events, and Button Events. Aside from the button event, InfoPath event handling is different from other web programming paradigms (e.g. WinForm and HTML forms); events are fired when the data changes, not when control state changes. As such, you should consider the optimal configuration for your forms’ post-back settings to provide the best performance while still ensuring that events get fired when necessary. See our performance post on MSDN to learn more about general performance and event handler post-backs.

    Tables

    After you’ve designed your form and authored the source code, the final step is to publish the form. Your InfoPath form with code can be published to SharePoint and to client machines, but you need to make a security decision before you publish: configure the form as domain trust or full trust.

     

    Domain trust forms can be published to SharePoint as Sandboxed Solutions directly from the InfoPath 2010 Designer. With Sandboxed Solutions, SharePoint Server farm administrators can restrict the resources available to the code and developers cannot access resources subject to operating system security. This establishes a safe environment where Site Collection administrators can publish code to SharePoint without the overhead of administrator approval! For more details about Sandbox Solutions (and another method for sorting repeating tabular data), see our Introduction to Sandboxed Solutions post from Phil Newman.

    Note: Publishing full trust forms to a client-side environment requires that the form is signed with a code-signing certificate or installed through a custom MSI built in Visual Studio. Publishing a full trust form to SharePoint requires a farm administrator to activate the solution through the SharePoint Central Administration portal.

    Best Practice: You should always use the lowest level of trust possible when publishing forms.

    Summary

    Most forms you design with InfoPath 2010 are not going to require code, but when they do, just install Visual Studio Tools for Applications and you’re ready to start programming. To add code, select the language of your choice, and use entry points in the Ribbon and Fields task pane to automatically insert event handlers. Finally, decide whether or not your form requires full-trust, and publish it to SharePoint or a client environment accordingly. If you’re interested in learning more about the InfoPath and SharePoint programmability, please visit http://www.msdn.com and keep checking for updates here on the InfoPath blog.

  • Microsoft InfoPath 2010

    Passing Data into a Form: Input Parameters

    • 29 Comments

    This blog article discusses a new feature of Microsoft InfoPath 2007 that makes it possible to pass data into an InfoPath form at load time. A typical example would be retrieving records from a database for a particular user. At load time a ‘userID’ can be passed into the form. This userID can then be used to query the database and load the form with the user's data.

    Parameters can be passed into InfoPath form templates (XSNs) or InfoPath Forms (XMLs). The syntax for specifying input parameters is the same for both. This article focuses primarily on InfoPath client scenarios, but should apply for the most part to server scenarios as well.

    How to Pass Parameters into an InfoPath Form:

    There are two ways of launching an InfoPath form with parameters

    1) URL

    The syntax for passing parameters via the URL is the standard syntax for query parameters. For example:

    http://www.foo.com/bar.xsn?baz=1&biz=2

    Here two input parameters have been passed into the form namely 'baz' and 'biz'. Their respective values are 1 and 2. The 'Accessing Input Parameters in Form Code' section talks about how these values are stored and accessed in InfoPath code.

    The URL syntax can be used in a number of places like

    • Launching an InfoPath form in a browser by typing the URL into the address bar
    • Pasting the URL to a form or a form template into an email
    • Using the URL inside methods like NewFromFormTemplate, New, Open (XmlForms collection)
    2) Command Line

    The syntax for passing parameters via the command line is as follows:

    infopath.exe “C:\foo\bar.xml” /InputParameters "baz=1&biz=2"

    The switch /InputParameters is used to specify that parameters are being passed into the form, followed by the name/value pairs of input parameters.

    Accessing Input Parameters in Form Code

    Parameters passed into an InfoPath form template or form, are available during the Loading event as a read-only collection of name/value pairs. In order to access these parameters you will need to write code that reads from this collection. The InputParameters collection is exposed in all three InfoPath programming models – it is thus available in JScript, InfoPath 2003 SP1 managed code or InfoPath 2007 managed code. This example uses C# and the InfoPath 2007 managed object model. Syntax for the legacy models follows. The steps below outline how to add code that access the Input Parameters passed into a form.

    1. In the InfoPath designer, click on Tools menu -> Programming menu item.
    2. In the fly-out menu select the Loading event (will be On Load in older InfoPath versions).
    3. This will launch the appropriate IDE (MSE or VSTA or the Visual Studio Toolkit) with the code spit for the loading event inserted.
    4. Add the following code to access the input parameters ‘baz and ‘biz used in the examples above (example is in C# using InfoPath 2007 Managed Object Model)

    public void FormEvents_Loading(object sender, LoadingEventArgs e)

    {

       // Assign the value of the parameter 'baz' to the string 'bazValue'. bazValue = 1

       string bazValue = e.InputParameters["baz"];

     

       // Assign the value of the parameter 'biz' to the string 'bizValue'. bi000zValue = 1

       string bizValue = e.InputParameters["biz"];

     

       // Code that uses the parameters passed in to do whatever needs to be done

       // Example would be to create a custom query using these values and populate a table based

       // on the data returned
    }

    Input Parameter Syntax for Legacy Object models

    The following two code samples contain code for the InfoPath 2003 SP1 Managed Object Model (C#) and Jscript (InfoPath 2003 Object Model)

    1) C# InfoPath 2003 SP1

    In the InfoPath 2003 SP1 Object Model the InputParameters collection is exposed off the XDocument object not off the eventArgs object. Also since this is a new feature the XDocument object needs to be cast to the newer _XDocument3 interface to get access to the InputParameters collection. Hence the first line of code in the sample below.

     [InfoPathEventHandler(EventType = InfoPathEventType.OnLoad)]

     public void FormEvents_OnLoad(DocReturnEvent e)

     {
        
    // Cast XDocument to _XDocument3 to get access to the InputParameters collection
        
    _XDocument3 infopath2007XDocument = (_XDocument3)e.XDocument;

         string bazValue = infopath2007XDocument.InputParameters["baz"].Value;

         string bizValue = infopath2007XDocument.InputParameters["biz"].Value;

     }

    2) JScript

    function XDocument::OnLoad(eventObj)
    {
          var bazValue = eventObj.XDocument.InputParameters["baz"].Value;
          eventObj.XDocument.UI.Alert(bazValue);
    }

    Help

    Comprehensive documentation and additional code samples for this feature can be found under MSE Help or VSTA Help.

    Aditi Desai
    Software Design Engineer in Test

  • Microsoft InfoPath 2010

    Submitting to a Database (via Web Services) in InfoPath Forms Services

    • 38 Comments

    If you've ever designed and deployed a form that will be frequently used or require significant data analysis, you have probably looked into maintaining data in a SQL database.  With InfoPath 2003 and the InfoPath 2007 rich client, you get what you expect.  You create a main database data connection to the SQL server and pick tables and columns that meet the requirements for submit functionality.  When you open your form and click the "Run Query" button, you see the data pulled from the database as you'd expect.  You then happily insert, update, or delete records and, when the time is right, hit "Submit".  Luckily for you, the InfoPath client took care of maintaining the list of changes that you made while editing your form.  With this list of changes intact, your updated data streaks back to the database to await the next query.

    Enter InfoPath Forms Server... Here we don't get the change tracking for free, so we'll need to do some work to simulate change tracking outside of the form's execution.  Basically, what we're going to try to accomplish is to use an intermediate web service that will handle querying and submitting the data from and to the target database.  The web service will timestamp the data at query time and send the data to the form for editing.  Then the form filling user will edit the data and click "Submit".  When the data arrives back at the web service, we need to figure out what changed in the meantime.  This means that we'll have to check to see if anything has changed in the database since the time when we queried the data.  If it has, then the submitted data should be rejected and the user should re-query before re-applying her edits.  If it hasn't, we'll diff the submitted data with the database data and submit the difference back to the database!  Let's get started!

     

    Create the Web Service and Setup the Database

    Since the InfoPath data connection wizard is easiest to use when your web service is already established and available, let's start with creating the web service and setting up the database.

    1) Download the attached archive and extract it somewhere on your hard drive

    2) Create a new web site in Internet Information Services (IIS)
    NOTE:  IIS must be enabled as a Windows Component through "Add or remove Windows components" in the "Control Panel")

    • Launch IIS ("Start" >> "Run", type 'inetmgr')
    • Right-click the "Web Sites" node and select "New" >> "Web Site…"
    • Click "Next >" on the first page of the wizard.
    • Type a name for your web site (e.g., "IPFSDiffGram") and click "Next >"
    • Type a unique port number (referred to, hereafter, as '<portNum>') for the web site and click "Next >"
    • Enter the path to a folder where the site contents will be stored and click "Next >"
    • Check "Read" and "Run scripts (such as ASP)" permissions and click "Next >"
    • Click "Finish".
    • You may want to create a new Application Pool for this web site "to make your server more efficient and reliable".

    3) Create the web service

    • Launch Visual Studio 2005.
    • Click "File" >> "New" >> "Web Site…"
    • Select "ASP.Net Web Service" in the "Visual Studio Installed Templates" section.
    • In the "Location" drop-down, select HTTP and then click "Browse…"
    • Select the Web Site created in step 1 and then click "Open"
    • Click "OK" on the "New Web Site" dialog

    4) Add the code and service asmx files to the project

    1. Open the Solution Explorer task pane (click "View" >> "Solution Explorer")
    2. Right-click the top-level project icon (labeled http://localhost:<portNum>) and select "Add Existing Item…"
    3. Navigate to the "DiffGramService.asmx" file and then click "Add". Refer to the files you downloaded for the contents of this file.
    4. Right-click the "App_Code" icon and select "Add Existing Item…"
    5. Navigate to the "DiffGramService.cs" file and then click "Add". Refer to the files you downloaded for the contents of this file.

    5) Customize the web service code for your database

    1. Instance variables
      1. DBConnectionString -- The connection string to connect to your database.
      2. DBTable -- The name of the table to which the web service should connect.  The table must feature a surrogate single-column primary key with an integer data type.
      3. ColumnNames -- An array that contains the names of the data columns in your database.
    2. WebMethod query parameters
      1. DBData(parameter_list)

        • parameter_list should be the columns, with appropriate System.Types to match your database
        • You'll need to specify the appropriate SqlDbTypes that correspond to the columns in your database
      2. UpdateDBData(DataSet, parameter_list)

        • Do not change the DataSet parameter
        • parameter_list should be the columns, with appropriate System.Types to match your database
        • You'll need to specify the appropriate SqlDbTypes that correspond to the columns in your database

    6) Create the database table and DML trigger
    The web service includes logic to update the database table and create a DML trigger to maintain a timestamp of Last Update for each record.  However, you may want to create the timestamp column and trigger yourself.

    • Example SQL script to create a database named "DBTable" that is compatible with this web service is in the attached files, named "CreateDBTable.sql". The table will have a structure similar to the following:

    • Example SQL script to create a DML trigger that will maintain the timestamp of last update for each record is also attached, and called "CreateDMLTrigger.sql".

    7) Build the Visual Studio solution and publish the web site

     

    Design the InfoPath Form Template

    Now that we've setup our database and constructed our web service to do the querying and submitting for us, it'll be a breeze to design an InfoPath form template based on the web service.

    1) Design a new, browser-enabled form template, based on the web service that will query/submit the DataSet.

    1. Launch InfoPath and select "Design a Form Template…" on the "Getting Started" dashboard dialog.
    2. Check "Enable browser-compatible features only" (required only for browser-enabled form templates)
    3. Select the "Web Service" icon and click "OK".
    4. Select "Receive and submit data" and click "Next >"
    5. Type the WSDL URL for your web service (e.g., http://<server>:<port>/DiffgramService.asmx?WSDL) and click "Next >"
    6. Select the web method that will return the DataSet and click "Next >".
    7. Click "Next >" on the DataSet change-tracking page.
    8. Click "Next >" to name the query data connection and move on to define the submit data connection.
    9. If the submit WSDL URL is different than the query WSDL URL, enter it here and click "Next >".  Else, just click "Next >".
    10. Select the web method to which the DataSet will be submitted and click "Next >".
    11. Select the DataSet parameter in the "Parameters" listView.
    12. In the "Parameter options" section, click the button next to the "Field or group" field.
    13. In the "Select a Field or Group" dialog that pops up, expand the "dataFields" node until you see the node with the name of the DataSet (it's the parent of the repeating "(Choice)" node).

       

    14. Select the DataSet node and click "OK"
    15. If your web service takes parameters to constrain the select command, map these parameters to the queryFields generated during the creation of the query connection.
    16. Click "Next >" on the submit parameter mapping page.
    17. Click "Finish" to name the submit data connection and finish the Data Connection Wizard.

     

    2) Set the default values for the "ID" and "QueryTime" fields

    1. In the InfoPath Designer window, click the "View" menu and select the "Data Source..." option.
    2. In the "Data Source" taskpane, expand the "dataFields" node completely.
    3. Double-click the "QueryTime" node to open the properties dialog.
    4. Type "1/1/1900 12:00:00 AM" (without the quotes) in the "Value" field in the "Default Value" section and click "OK"
    5. Repeat steps 2.a-2.c for the "ID" field.
    6. Type "-1" (without the quotes) in the "Value" field in the "Default Value" section and click "OK"

     

    3) Insert the controls into the View.

    1. Click inside the dataFields controls area (it says "Drag data fields here" if you haven't clicked there)
    2. Click the "Insert" menu and select the "Repeating Table..." option.
    3. In the "Repeating Table Binding" dialog, completely expand the "dataFields" node.
    4. Select the group node that has the same name as your database table and click "Next >"
    5. For each of your data columns (e.g., 'Column1', ..., 'Column5'), select the column name on the left, and then click the "Add >>" button to make the column show up in the Repeating Table.

      NOTE:  If you include the 'ID' column, the user will be able to edit the values, and the DataSet may not be validated or merged correctly.
    6. Click "Finish" to accept the repeating table binding and insert the repeating table into the View.

    4) Publish the form template to your InfoPath Forms Server

    At this point, you have a form template that will work correctly when you open it in the InfoPath rich client.  But this post is all about getting things to work correctly in the InfoPath Forms Server.  So you'll need to configure your data connections to work in the browser by converting the main query and submit data connections to use Universal Data Connection (UDC) files in a Data Connection Library (DCL).  Now you should be all set.  The web service will query and submit the data to the database, and we'll make our best attempt at a diff of the database data against the submitted data.

    From here on out, it's up to you.  If you want to, for example, modify the database structure or change the way the trigger works, then you're going to need to modify the web service code.  You'll also need to use "Convert Main Data Source" to update your form template whenever you modify your web service.  You might also want to add support for multiple tables.  All this will take some exploration of ADO.Net DataSets, but it is a reasonable exercise as long as you're comfortable writing managed code.

    Forrest Dillaway
    Software Design Engineer in Test

  • Microsoft InfoPath 2010

    Create dependent drop-down / list-box in InfoPath using filters

    • 11 Comments

    Summary

    Suppose you want to have the items listed in a drop-down be dependent on the selection of another drop-down (this is also known as "cascading dropdowns). If you have InfoPath Service Pack 1 installed, you could use the "Filter Data..." feature to accomplish this.

    Example

    Picture of two drop downs - state and city. 

    You have one drop down labeled "State:" with the names of states and another drop-down labeled "City:" which gets populated with the names of the cities for the state you selected on the previous drop down.

    The city drop-down obtains its values from an xml file which might look something like this:

    <Cities>
      <City state="Washington">Redmond</City>
      <City state="Washington">Seattle</City>
      <City state="California">Los Angeles</City>
     
    <City state="Florida">Orlando</City>
    </Cities>

    Implementation

    1. In design mode, right click on the "City" drop down and open the Drop-down Properties dialog.
    2. Select to Look up values in a data connection to a database, Web Service, file, Share Point library or list.
    3. Click Add and follow the wizard to add the xml file containing the city data.
    4. After completing Data Connection Wizard, in the Entries field- select the source for the drop-down values by clicking the button on the right of the field. The Select a Field or Group dialog will appear, for this case you will select the "City" repeating group.
    5. Create a Filter by clicking the Filter Data... button and clicking Add... in the Filter Data dialog.
    6. You will want to create a Filter that displays the data in which the "state" attribute is equal to the field corresponding to the "State:" drop-down (Remember that the field value is kept in the form's "Main" data source)  

     Additional Notes/Tips  

    • Previous City selection will persist after changing state. You’ll need to set a Rule to change cities to empty after a change is made to states to avoid selected city remaining in City drop down. (Right click the "State" drop-down in design mode and open the Propeties dialog, click the Rules button and create an Action to set the "City" field value to empty, no condition is necessary since this rule will apply when a change is made). 
    • Instead of using drop-down controls you could also use list boxes. 
    • You could also use Conditional Formatting to disable the "City:" drop-down until a state is selected. 
    • If you'd like to implement dependent dropdowns in a browser-enabled form template, take a look at this article.
  • Microsoft InfoPath 2010

    SharePoint List Data Connections in InfoPath 2010

    • 30 Comments

    Hi, my name is Joey Wiggs and I’m a developer on the InfoPath team. In InfoPath 2010, one of the ways in which we've improved our integration with SharePoint Server 2010 is by providing richer capabilities for connecting to and getting data from SharePoint lists. In this post, I will compare SharePoint list data connections in InfoPath 2007 and InfoPath 2010, and discuss the benefits of using the new 2010 data connection type. I will also outline the steps required to upgrade your InfoPath 2007 SharePoint list data connections to the new and improved version.

    About SharePoint List Data Connections

    Let’s start by looking at a scenario when you would use a SharePoint list data connection in an InfoPath form.

    In Microsoft, when employees run into technical issues, they log a help ticket by filling out an InfoPath form. They start filling out the form by selecting an Problem category from a dropdown list. We could store the category names inside the form but that means that whenever a category is added, deleted or renamed, the form will need to be updated.

    Help Request Form

    Instead, we can store the Category names in a separate SharePoint list and pull this information into the form when users are filling it out. We can do this by adding a SharePoint list data connection to the form. The benefit of using a data connection is that the data can be maintained separately in a single location and the form will always pull in the most up to date information from that location.

    Why use the 2010 SharePoint List Data Connection?

    In InfoPath 2010, we have extended the functionality of the SharePoint list data connection.
    • Query fields are now supported
    • Additional field types are supported
    • The data pulled from the SharePoint list is no longer tied to the default list view in SharePoint

    Query Fields

    Setting a query field value allows you to filter the data before it is pulled into the form. SharePoint list connections in InfoPath 2010 now have query fields, allowing you to filter your data and return more scoped results. You can query on a number of different field types, including single lines of text, numbers, and even people and lookups. By filtering your list connections, you can ensure only the data you want is brought into your form. This can also speed up your form connection, as it may pull in less data than it would otherwise.

    For example: By setting the “Modified by” query field to the current user (using the username() function), the query will return only those list items that were modified by the current user.

    Fields Task Pane

    Additional Field Types

    In 2007 the list connection could only support simple field types, such as single lines of text, currency fields, and single choices. The new connection now also supports complex field types such as multiple choices, multiple lookups, attachments and person fields.

    Sorting results

    In previous releases, the number of items returned and the sorting order of said items were determined by the default view for the list in SharePoint. To work around this limitation, form designers had to go to the list settings page in SharePoint and modify the default list view to get the data they wanted into their forms. That’s no longer the case! The new 2010 list data connection will return all of the items in the list, regardless of the default view’s settings. You can also sort the incoming data by a particular field in the data connection wizard when creating a new connection, or modifying an existing one.

    Data Connection Wizard

    How can I get this in my forms?

    If you’re designing a new InfoPath 2010 form, you just need to add a SharePoint list data connection and you’ll have this functionality available to you from the start.

    The new list features are supported in InfoPath 2010 filler and browser forms only, so if you want to use the new connection in your existing InfoPath 2007 form you will need to upgrade your existing forms to InfoPath 2010. However, once upgraded, InfoPath 2007 clients will not be able to open the form.

    To upgrade the data connection, form designers must complete the following steps:

    1. Use the data connections dialog to upgrade the list connection
    2. Rebind your controls, rules and code
    3. Save the form as an InfoPath Web Browser Form Template or InfoPath Filler Form Template

    Data Connection Wizard

    Convert Data Connection to Current Version

    For each list data connection that retrieves data in your form, you will need to select it in the data connections dialog and press the “Convert to Current Version” button. You will be prompted if you want to continue. After conversion, you will see an information bar when that connection is selected stating that the data connection is incompatible with the current version of your form. That’s okay; we’ll be upgrading the form to the required version later.

    Data Connection Wizard

    Rebind Controls and Fix up Rules and Code

    After converting a data connection, you’ll need to rebind your controls and fix any field or XPath references inside rules and code. When rebinding, you’ll need to rebind the repeating sections to the d:SharePointListItem_RW group, then rebind the controls inside the repeating sections to the correct fields. You can rebind a control by selecting it, then right-clicking and choosing “Change Binding”. This brings up a dialog where you can choose what field or group to bind the control to.

    Control Binding

    Fixing your rules consists of finding the rule and updating any field references. Field references from the old adapter will look something like “@Title” after you convert your 2007 adapter to 2010. Select the reference, pick the field you want the rule to reference and away you go.

    Rule Fix up
    You can tell that the rule actually references the field by how it looks. If the field reference has a namespace, an @ symbol, or a full XPath then that rule won’t work and needs to be fixed.

    Save the Form

    Finally, you’ll want to save your form as an InfoPath form template (filler or web browser depending on your needs). Note that if you try to save it before converting the data connections, the design checker will prevent you from doing so. 2007 list data connections cannot be in a 2010 form, and 2010 list data connections cannot be in a 2007 form. There’s no mixing and matching, and the design checker will prevent you from saving the form unless they’re correct.

    Once you’ve saved your form, you will be able to avail of all the capabilities of the new 2010 SharePoint list data connection. At any time, you can use the data connections dialog to modify the newly upgraded connection, to add new field types, or to use the sort by functionality. You can also set the value of query fields using rules in your form.


    Enjoy!

    Joey Wiggs

    InfoPath Developer

  • Microsoft InfoPath 2010

    Data Connections in Browser Forms

    • 17 Comments
    A while back, I wrote a series of 3 blog posts about authentication that was targeted at advanced enterprise-level scenarios involving multi-tier delegation of credentials for data connections on the server. However, I never took the time to cover the basic scenarios around getting basic data connections to work on the server. This post will answer the question "how do I get my data connection to work on the server". Cart, meet horse.
     
    When we started defining the server experience for InfoPath forms, one of the guiding principles we espoused was "design-once." Meaning, provided you stick within the subset of functionality supported on the server, you could design a form once and it would run in InfoPath and in Forms Services. That is basically true for data connections, but there are two special considerations that differ significantly when moving to the server, namely
    • Authorization to perform cross-domain connections
    • Multi-tier authentication
    The cross-domain issue, server edition
    Short version:
    You can’t make a cross-domain connection from a domain security browser form unless your data connection uses a UDC file.  Period.
     
    Long version:
    InfoPath has three security modes, which we refer to as restricted (AKA "super-sandbox"), domain, and full-trust.  Restricted form templates don’t run on the server.  Full-trust form templates are allowed to do whatever and consequently need to be administrator-approved in order to run server-side.  Domain trust form templates constitute the vast majority of form templates in the enterprise, and roughly follow the Internet Explorer security model which dictates that by default, the user must approve any attempt to access resources that come from a different domain or Zone.  So, if you have a form template running on http://myserver/, and it tries to connect to a web service on http://yourserver/, InfoPath will prompt you before trying the connection.
     
    Works great in InfoPath, but when you run a form in the browser, you may be running server-side business logic.  That business logic may want to execute a data query.  Because HTTP is a stateless protocol, Forms Services can’t halt execution of a server-side process and return to the browser in order to ask you for permission to continue.  Additionally, the user in this case may not be the right person to own the decision about whether the cross-domain connection can take place.  So, this decision is placed instead in the hands of the server administrator who owns security around the form template.  Depending on whether the form is administrator-approved or just published to a document library by Joe User, this ownership falls on the farm administrator (I call her Julie) or the site collection administrator (henceforth known as Bob).
     
    The technology which allows Julie and Bob to determine whether forms can make cross-domain connections involves a system of checks and balances.  Central to this system is a data connection settings file in the Universal Data Connection V2 format, called a UDC file.  Bob’s UDC files live in a special type of document library called a Data Connection Library, or DCL.  Julie’s UDC files live in the Microsoft Office SharePoint Server configuration database, and are managed via the "Manage Data Connection Files" page in the Application Management section of SharePoint Central Administration (I tend to refer to this as "the store").
     
     
    The basic premise behind UDC files is that in InfoPath 2007 your data connection settings can live outside of the form template in one of these files, and both InfoPath and Forms Services will retrieve the current connection settings from this file at runtime before making the connection.  The UDC file itself is retrieved from a URL relative to the root of the site collection where the form was opened.  This enables lots of cool functionality - for example, you can now share settings across multiple forms and change them once when you move your data source. 
     
     
     
    You can also pre-deploy test and production versions of your data connection settings to your staging and production environments so that you don’t need to update the form template with new data connection settings when you go live. 
     
     
    For the purposes of this discussion the key takeaway is that a domain security form running in the browser will never make a cross-domain data connection unless those connection settings come from a UDC file.
    In other words, you can’t make a cross-domain connection from a domain security browser form unless your data connection uses a UDC file.  Period.
     
    Why is this more secure?  Well, if Bob is a good administrator, he controls access to Data Connection Libraries on his site collection.  A DCL requires content approval by default, and while members of the site with Contributor access can write files to the library, nobody but the owner of the file can use the file from InfoPath unless a content approver has approved the file.  By default, all members with Designer permissions have the Content Approval right.  In short, Bob can set up the site collection such that only people that he designates can approve UDC files.  Therefore, forms on Bob’s site collection can only make connections outside the farm unless he approves the connection first.
     
    Julie’s central store is more secure - only users with access to SharePoint Central Administration can modify those files.  Furthermore, by default only the server object model can access files in the store.  In order to make these files accessible to web clients such as InfoPath, the "web accessible" flag must be set.  Otherwise, the files can be used from browser forms only.
     
     
    Finally, if Julie wants to have complete control over cross-domain connections for the farm, she can turn off the ability for user form templates to make cross-domain connections at all (in fact, these are disabled in a default install).  When cross-domain connections are disabled for the farm, even connections that use settings from a UDC file can’t make cross-domain connections.
     
    Solving multi-tier authentication issues
    Once your form is allowed to make cross-domain connections, you’ll need to deal with getting access to the data.  If your data lives on a different computer than your Forms Services site, this means figuring out an alternative set of credentials for data access.  I’ve covered why this is true, and the various options for accomplishing this task, in a series of posts called "Advanced server-side authentication for data connections," but I left out one useful prototyping trick.  Consider the following UDC authentication block:
     
    <udc:Authentication>
           <udc:UseExplicit CredentialType="NTLM">
                  <udc:UserId>myusername</udc:UserId>
                  <udc:Password>mypassword</udc:Password>
           </udc:UseExplicit>
    </udc:Authentication>
     
    The UseExplicit element allows you to specify a username and password in plaintext.  When this is present, Forms Services will impersonate the specified user using the supplied credentials.  This is a great tool for prototyping - you can see immediately whether your connection can be made given valid credentials before you go to the trouble of setting up Office Single Sign-on.  However, I cannot stress enough that this is for prototyping only.  Because  the UDC file is in clear text and is accessible to anyone with read permission on the library, this puts a windows username and password in clear text on the network, which is bad-bad-bad.  You’ve been warned.
     
    Whatever Julie wants, Julie gets
    The "Manage data connection files" page (AKA "the store") gives Julie a great deal of power over the use of data connections in administrator-approved form templates.  Furthermore, Julie also has a great deal of control over what Bob’s users can  do.  The following defaults can only be modified on the Configure forms services page:
    • User form templates cannot make cross-domain connections (not even with a UDC files)
    • User form templates cannot use authentication embedded in a database connection string. 
    • User form templates cannot use the authentication section of the UDC file 
    • User form templates can use credentialType BASIC or DIGEST only if the connection is made using SSL.
    • User form templates cannot make cross-domain connections (not even with a UDC files)
    • User form templates cannot use authentication embedded in a database connection string.
    • User form templates cannot use the authentication section of the UDC file
    • User form templates can use credentialType BASIC or DIGEST only if the connection is made using SSL.
     
    The following default setting can only be modified on the Configure Web Service Proxy page:
    • User form templates cannot use the Web service proxy
     
    What’s next?
    Now that you’re motivated to use UDC files to enable data connections on the server, you’ll need to know how to create them and how to re-use them.  I’ll tackle that topic in a future post.
     
    - Nick Dallett
    Program Manager
  • Microsoft InfoPath 2010

    How to Pass Querystring data into an InfoPath Form

    • 34 Comments

    Hi there, Daniel Broekman here. After showing you how to customize a SharePoint list with InfoPath 2010, and describing the differences between SharePoint list forms and form library forms together with Kate Everitt, I’m back with a quick tip for easily sending  a value from the browser’s query string into an InfoPath form.

    Imagine one of the following scenarios:

    • You want to dynamically pull all the invoices for a specific customer into a single form. For example, you could have a link to http://server/site/ShowInvoices.aspx?Customer=Contoso, which could be set up to display a list of all the Contoso invoices in a table. If you then swap out “Contoso” with “Fabrikam” in the URL, you would see all of the Fabrikam invoices.
    • You want to track referrals for your form. You can do this by specifying a dynamic default value for the form indicating the referral source. For example, you can include a link to http://server/site/form.aspx?Referrer=Email in an email you send to users, and add a link to http://server/site/form.aspx?Referrer=Website on the homepage of your website, and capture the value of the “Referrer” parameter along with the rest of the form data.

    In InfoPath 2007, you could accomplish these scenarios with code. With InfoPath 2010 and SharePoint 2010, there is a much easier way to send data from the query string into an InfoPath form. Let’s take a look.

    The basic concept

    Using a web part page and a part-to-part connection between a Query String (URL) Filter web part and an InfoPath Form Web Part (new in SharePoint 2010), we can easily pass a value from the browser’s query string into the form.

    Step-by-step

    I’m going to assume you already have a list form published to SharePoint. I just created a simple form to collect feedback on a conference presentation. As you can see, I included a “Referrer” field that will track the referral source of users filling out my form.

    Conference Feedback Form

    To set up the rest of the scenario, follow these steps:

    1. Create a new web part page.
    2. Add 2 web parts to the page. From the “Forms” category, add the InfoPath Form Web Part, and from the “Filters” category, add the Query String (URL) Filter web part. Web Part Adder (Forms Category)Web Part Adder (Filters Category)
    3. Configure the InfoPath Form Web Part to point to the list or library where your form is published. InfoPath Web Part Tool Pane
    4. Configure the Query String (URL) Filter web part to specify the parameter name it should look for in the URL. In this case, we want it to find “Referrer”. Query String Web Part Tool Pane
    5. Next, set up the part-to-part connection by opening the Web Part edit menu and selecting Connections > Send Filter Values To > InfoPath Form Web Part. Query String Web Part Connection Menu
    6. This brings up a dialog where you can choose the field in the form where the data should be sent. Choose the field you want, and then click Finish. In this case, we want to map the data to the “Referrer” field. Web Part Connection Dialog

    Everything should be set up correctly now. Save your changes to this page, and then navigate to the page. You should see the blank form.

    Saved Web Part Page

    Testing the Connection

    To test that everything is working correctly, add “?Referrer=email” to the end of the URL, and you should see the Referrer field being populated with the value “email”.

    Testing the Query Parameter Connection

    That’s it! You now have a page that passes data from the query string into an InfoPath form, set up in less than 5 minutes, and without any code.

    For more advanced scenarios, you can use this as a starting point. For example, you could have a rule on the “Referrer” field that performs certain actions based on the incoming value, such as querying a secondary data source, loading a specific item, etc. In the “customer invoice” example I gave at the beginning of this post, you could have an “onchange” rule on the “Customer” field that queries a secondary data connection for all of that customer’s invoices.

    One final note: the InfoPath Form Web Part only supports one incoming part-to-part connection at a time, which means that you are limited to passing one value into the form using this method.

    Please leave a comment to let me know how you’re using this functionality in your forms!

    Daniel Broekman

    Program Manager – Microsoft InfoPath

  • Microsoft InfoPath 2010

    InfoPath Data Connections: Part 1

    • 17 Comments

    Summary

    This article is part of a series of documents explaining the Data concept in Microsoft Office InfoPath. This particular article is an overview of how Data Connections work in InfoPath. The intended audience is those who are new to InfoPath and those who use InfoPath, but have not built up knowledge in the way Data Connections work. For more exhaustive information regarding specific types of data connection, see the Links section at the end of this article.

    Terminology

    Definitions of certain terminology in this paper are as follows:

    • InfoPath client – the software program named "Microsoft Office InfoPath"
    • Designer ��� The person who is using the InfoPath client to create/design a form template
    • Form template – the XSN file that is created with InfoPath client and used to enter data by the form filler
    • Filler – the person who is putting data into the form
    • Form – a form that is either filled out or in the process of being filled out by the filler. Also known as the InfoPath XML file. 
    • Document Object Model (DOM) – XML structures in the form.  In InfoPath, there is a Main DOM on which the form is based and Secondary DOMs which hold data received from Receive Data Connections.

    Background

    The purpose of using an InfoPath form is to collect structured data. This data structure is represented by a schema (XSD) which defines the data fields and the hierarchical structure of the data.

    When using InfoPath client, data is accessible through data connections. These data connections are defined in the form template and used at runtime. During design of the form, the form designer will create the data connection. The designer must choose to either create new settings for a data connection or search for existing connections previously defined by an admin on a SharePoint server. In general, the data connection paradigm in InfoPath 2003 and 2007 is such that data connections are grouped into one of two types – submit connection type or receive (query) connection type. Receive connection types have a one-to-one relationship with secondary DOMs.

     

    Submit Data Connections

    Consider this scenario. The form filler places data into all of the fields on the form, presses a button labeled “Submit my data” and the data is pushed to some listener where it can be stored or processed.

    As simple as this scenario is, it must be configured by the form designer through the Submit type of data connection. After creating a submit data connection, the designer can apply the data connection to a user action – in this case, the button labeled “Submit my data”. When the filler executes that action, data in the main DOM of the form is transmitted to the target of the data connection as a submission.

    Submit data connections can currently bind to the following destinations:

    • Web Service – Using a data connection bound to the Web Services adapter, data is submitted according to the specifications of the web service.For web services that expose the type System.Dataset, InfoPath will track changes as the user edits the data.  When the data is submitted to the web service, the changes are sent using ADO.NET Diffgrams.
    • SharePoint document library – Data is submitted to a SharePoint document library by using a data connection bound to the SharePoint Document Library adapter.
    • E-mail – Using a data connection bound to the SMTP E-Mail adapter, this enables the submission to an e-mail address. The settings of the data connection can specify whether to submit the entire contents of the form as an attachment or just the current view as the body of the e-mail message.
    • The form hosting environment, such as an ASP.NET page or a hosting application (2007 ONLY) – Using a data connection bound to the “Submit to host” adapter, this raises a submit event to the host. The host is then responsible for handling that event and retrieving the data from the form. See http://msdn2.microsoft.com/en-us/library/ms778201.aspx for more info. 
    • Web Server (HTTP) – This is one exception where the submission is not bound to an adapter as a data connection, rather, the settings of the submit options on a control specify an HTTP URL. HTTP Post is used to submit the data in the form to that URL.
    • Database – Lastly, if the form is initially designed from a SQL Server or Access database, a submit action can be created to push the data back into that database. Note: the database option has some caveats in that large binary types cannot be submitted from InfoPath directly; these require a web service in front of the database.

     

    Receive Data Connections

    One of the major problems in filling out forms is accuracy of data. For instance, if someone was replying to a survey regarding what their favorite programming language is, they could have a text box to type it in. Now imagine that there are 50 respondents to the survey, each trying to explain in a text string what their favorite language is. Consider for a moment that it is C#. They could respond with any of the following and be just a correct or valid: C#, C-Sharp, Csharp, C, C# .NET. Obviously, allowing this type of data entry will create problems when the survey is interpreted.

    This type of scenario is a good reason to use a Receive data connection. What if the form designer was to pre-populate a drop-down control with specific choices which the filler could choose as their favorite programming language? The designer could create a list such as: VB, C++, VB.NET, C# and would thus ensure that the filler would be able to be successful in filling out the form with valid data that is consistent across all of those who respond. The person who aggregates the responses from the form will also be able to ensure that they have interpreted the data correctly and completely.

    To configure this scenario, the form designer now needs to create a Receive connection type. A receive data connection allows a query to be made to get data from an external source and return it to the form. External data is placed into the form as a secondary data source (represented as another DOM). Controls can then be configured to use these fields. Also, the designer can view the additional data sources by viewing the Data Source task pane and using the drop down to switch between data sources. If the dropdown is grey, then there is only one data source in the form.

    Receive data connections can currently connect to the following sources - all of these are supported in InfoPath 2003 and 2007: 

    • XML Document – This includes any URL that would return an XML document (For instance, an RSS feed)
    • Database (Microsoft SQL Server or Microsoft Access only)
    • Web Service
    • SharePoint document library or list

     

    Links

    For further and comprehensive information regarding data connections in InfoPath, see http://office.microsoft.com/en-us/infopath/HP012304861033.aspx?pid=CH100598301033

    For more information specific to data connections to Web Services, see http://office.microsoft.com/en-us/infopath/HP100913971033.aspx?pid=CH100598301033

    For more information on using InfoPath with Access, see http://office.microsoft.com/en-us/infopath/HP100950831033.aspx?pid=CH100598301033

    For more information on using InfoPath to connect to SharePoint data sources, see http://office.microsoft.com/en-us/infopath/HP100931601033.aspx?pid=CH100598301033

    For general topics of interest and further How To information on InfoPath data connection, see http://office.microsoft.com/en-us/infopath/CH100598301033.aspx

    Patrick Smith
    Program Manager

  • Microsoft InfoPath 2010

    Customize a SharePoint List Form using InfoPath 2010

    • 29 Comments

    Today sees the launch of our new "5 for forms" video demo series. In this series, we will demo a cool new InfoPath 2010 feature or scenario in less than 5 minutes.

    In the 1st video of the series, Daniel Broekman, a program manager on the InfoPath team will show you how you can customize a SharePoint list form with just a few clicks:

    Get Microsoft Silverlight

    We will post the next video in the series "Create tabs using Picture buttons"  after the holidays on January 7th.

    Enjoy!

  • Microsoft InfoPath 2010

    Cascading Dropdowns in Browser Forms

    • 29 Comments
    If you are building an InfoPath client-only solution and you need to filter drop-down list boxes, you can simply use the “Filter Data” feature when you set the Entries property for the control. However, since filters are not supported in browser-compatible form templates, how can you accomplish the same functionality?
     
    This is where .NET web services can “save the day!” By creating web methods that accept parameters, you can add those web methods as data connections and then pass the selected value from one drop-down list box to the appropriate data connection “queryField”. Once the queryField has been set, simply execute that data connection to retrieve the associated values.
     
    To setup this sample, you will need to have access to the SQL Server Northwind sample database and Visual Studio installed on your server.
     
    First, let’s create the web service and the two web methods we will use in this sample:
     
    Step 1: Open the appropriate web site
     
    1. Launch Visual Studio
    2. From the File menu, select Open and choose Web Site
    3. Select File System and then navigate to: C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\LAYOUTS
     
    NOTE: By choosing to open the LAYOUTS folder, your web service will be available from all provisioned sites. If you want the web service only to be available from a specific site (i.e. the default site) you would want to open: C:\Inetpub\wwwroot\wss\VirtualDirectories\80
     
    1. Click Open
    2. In the Solution Explorer, right-click on the web site and choose New Folder
     
     
    1. Rename this folder to: WebServices
    2. Because you may have multiple web services, let’s add a sub folder here that is specific to our web service:
      1. Right-click on WebServices and choose New Folder
      2. Rename this folder to: NorthwindTables
     
     
    Step 2: Create the web service
     
    1. Right-click on NorthwindTables and choose Add New Item
    2. From the Visual Studio installed templates list choose Web Service
    3. In the Name box, rename this to: NorthwindTable.asmx
     
     
    1. Uncheck the option “Place code in a separate file” and click Add
     
     
    Step 3: Add the web methods
     
    NOTE: For this sample, it is assumed the SQL Server database is installed on the same Microsoft Office SharePoint Server. 
     
    1. Add the following “using” declarations at the top of your code page: 

    using
    System.Data;
    using System.Data.SqlClient;
     
    1. Add the following web method to retrieve the CustomerID values from the Customers table in the Northwind database:
     
    [WebMethod]
    public DataSet GetCustomers() {
                // Create a SQL connection to the Northwind sample database
                SqlConnection cn = new SqlConnection("Data Source=(local);Integrated Security=SSPI;Initial Catalog=Northwind");
     
                // Create data adapter object passing it the SELECT
                // statement to retrieve the customer ID values
                SqlDataAdapter da = new SqlDataAdapter("SELECT Customers.CustomerID FROM Customers Order By CustomerID", cn);
     
                // Create a dataset object to store the data
                DataSet ds = new DataSet();
     
                // Open the connection
                cn.Open();
     
                // Fill the dataset
                da.Fill(ds, "Customers");
     
                // Clean up
                cn.Close();
                cn = null;
                da = null;
                
                return ds;
                }
     
    1. Add the following web method to retrieve the associated orders for the selected customer:

    [WebMethod]
    public DataSet GetOrdersForSelectedCustomer(string strCustID) {
                // Create a SQL connection to the Northwind sample database
                SqlConnection cn = new SqlConnection("Data Source=(local);Integrated Security=SSPI;Initial Catalog=Northwind");
     
                // Create a string variable for the modified SQL statement
                string strOrdersSQL = "";
     
                // Create a string variable for the default SQL statement
                string strOrdersOrigSQL = "SELECT * FROM Orders";
     
                // Some of the customer ID values contain apostrophe's - we need
                // to replace them with two single quotation marks so that all
                // single quotation marks in the CustomerID are parsed correctly.
                strCustID = strCustID.Replace("'", "''");
     
                // Concatenate the default SQL statement with the "Where" clause
                // and add an OrderBy clause
                strOrdersSQL = strOrdersOrigSQL + " Where CustomerID Like '%" + strCustID + "%' Order By OrderID";
     
                // Create data adapter object passing it the SELECT statement
                // to retrieve the OrderID values
                SqlDataAdapter daOrders = new SqlDataAdapter(strOrdersSQL, cn);
     
                // Create a dataset object to store the data
                DataSet Ds = new DataSet();
     
                // Open the connection
                cn.Open();
     
                // Fill the DataSet
                daOrders.Fill(Ds, "Orders");
     
                // Clean up
                cn.Close();
                cn = null;
                daOrders = null;
                     
                return Ds;
    }
     
    1. Build and save the project
     
     
    Step 4: Test the web methods
     
    NOTE: The Identity account of the Application Pool for the web site where this web service is published will need to have access to the SQL Server database.
     
    1. Open a browser and navigate to: http://<server>/_layouts/WebServices/NorthwindTables/NorthwindTables.asmx (replace <server> with the name of your server)
    2. You should see the two web methods created above along with the default HelloWorld web method:
     
     
    1. Click the GetCustomers link and then click Invoke – this should return a list of the CustomerID values
    2. Click the GetOrdersForSelectedCustomer link, in the strCustID box enter: BERGS and then click Invoke – this should return a list of only those OrderID values for BERGS
     
     
    Step 5: Create the InfoPath form
     
    1. Design a new, blank, browser-compatible InfoPath Form Template
    2. Add a drop-down list box to the view and modify the name to: SelectCustomer
    3. Add another drop-down list box to the view and modify the name to: SelectOrder
     
     
     
    1. Add a new “receive data” data connection to the NorthwindTables web service for each of the web methods created above as follows:
      1. GetCustomers:
        • Enable the option “Automatically retrieve data when the form is opened”
      2. GetOrdersForSelectedCustomer:
        • Use ALFKI as the sample value for the strCustID parameter when prompted in the Data Connection Wizard
        • Uncheck the option “Automatically retrieve data when the form is opened”
    2. Set the Data source for SelectCustomer to the GetCustomers data connection and use the CustomerID field for both the Value and Display name properties
    3. Set the Data source for SelectOrder to the GetOrdersForSelectedCustomer data connection and use the OrderID field for both the Value and Display name properties
    4. Create a Rule on SelectCustomer with the following actions:
      1. Set a field’s value: Set the SelectOrder field to nothing (e.g. leave the Value blank)
      2. Set a field’s value: Set the parameter value (strCustID) for the GetOrdersForSelectedCustomer data connection to the SelectCustomer field
      3. Query the GetOrdersForSelectedCustomer data connection
     
     
    1. Save the form locally as FilteredDrop-downs_IPFS.XSN
     
     
    Step 6: Publish the form
     
    1. Publish the form to a server running InfoPath Form Services
    2. Navigate to the form library where the form was published and click the New button
    3. From SelectCustomer choose BERGS
    4. Click SelectOrder – only those orders for BERGS are displayed
    5. Select a different customer – notice the orders have also changed
     
    Scott Heim
    Support Engineer
  • Microsoft InfoPath 2010

    Submitting to 'this' document library

    • 166 Comments

    Have you ever needed to develop an InfoPath form template that submits back to a SharePoint document library but you did not initially know the server or library name when developing the form? Or have a scenario where your InfoPath form template could be published (or added as a content type) to multiple SharePoint document libraries and you need the submit location to be dynamic? Well read on to find out how you can do this!

    When you create an InfoPath form template that needs to be able to submit to a SharePoint document library, you need to specify that connection in the initial design of the form template. However, at run time you can use managed code to determine the server and library name where the form was launched and then modify the “FolderUrl” property of the submit data connection so the form is submitted to the appropriate library.

    So let’s get started setting up this sample. The C# walkthrough below uses the new InfoPath 2007 managed object model; below, you will find attached the same logic implemented in InfoPath 2003 managed object model and in InfoPath 2003 JScript.

    Step 1: Create a sample InfoPath Form Template

    Create a browser-compatible form template as following:

    1. Add 3 text box controls, all with a data type of text, named as follows: strFormURL, strLocation and strFolderName
    2. Add a “Submit” data connection named “Main submit”:
      • Set the document library name to a dummy SharePoint document library (i.e. http://server/dummyLib)
      • Use the concat function to concatenate the strFolderName field and _Test for the File Name property: concat(my:strFolderName, "_Test")
      • Enable the Allow overwrite if file exists property
    3. Set the Security Level of the form to Full Trust and sign the form template with a digital certificate
    4. Enable the Submit functionality (Tools | Submit Options) and choose the “Perform custom action using code” option

    Now that we have the form, controls and submit functionality, let’s add the code to make this process work:

     

    Step 2: Add the code

    • Click the Edit Code button on the Submit Options dialog
    • Create the following FormState Dictionary object – this will be used to store the form’s location when the form is initially opened:

    private object _strUri
    {
       get { return FormState["_strUri"];
      
    set { FormState["_strUri"] = value; }
    }

     

    • Add the following code to the Forms Loading event: 

    // Get the Uri (or SaveLocation in a browser form) of where
    // the form was opened.
    // See if the form was opened in the browser

    Boolean OpenedInBrowser = Application.Environment.IsBrowser; 

    // If so, we will get the "SaveLocation" from the InputParameters

    if (OpenedInBrowser)
      
    _strUri = e.InputParameters["SaveLocation"].ToString();
    else  

       //If it was opened in the client, we will get the Uri
      
    _strUri = this.Template.Uri.ToString();

     

    // Populate the fields on the form - keep in mind, this

    // not necessary - this is simply to see the results

    PopulateLibInfo(OpenedInBrowser);

     

    • Add the following procedure to the Forms class: 

    private void PopulateLibInfo(Boolean OpenedInBrowser)

    {

    // Create a Navigator object for the main DOM
    XPathNavigator xnDoc = this.MainDataSource.CreateNavigator();

     

    // Create Navigator objects for each field

    XPathNavigator xnFormURL = xnDoc.SelectSingleNode("my:myFields/my:strFormURL", this.NamespaceManager);
    XPathNavigator xnLocation = xnDoc.SelectSingleNode("my:myFields/my:strLocation", this.NamespaceManager);

    XPathNavigator xnFolderName = xnDoc.SelectSingleNode("my:myFields/my:strFolderName", this.NamespaceManager);

     

    // Get the Uri stored in the FormState Dictionary variable

    string strUri = _strUri.ToString();

     

    // Create a variable to store the path (URL) to the document library

    string strPath = "";

    if (OpenedInBrowser == true) {

       //If we are open in the browser, the strUri value is just

       //the server name and library - so we just need to get

       //the URL without the last "/"

       strPath = strUri.Substring(0, strUri.LastIndexOf("/"));

    } else {

       // Parse just the path to the document library -

       // this would return something like this:

       //  http://server/library

       strPath = strUri.Substring(0, strUri.IndexOf("Forms") - 1);
    }


    // Now, parse the URL to where the document library resides;
    // this would return something like:

    //    http://server or http://server/site
    string strLoc = strPath.Substring(0, strPath.LastIndexOf("/"));


    // Lastly, parse the URL to return just the document library name -

    // in this case,we are looking for the last "/" character

    // knowing that what comes after this is the document library name

    string strFolder = strPath.Substring(strPath.LastIndexOf("/") + 1);

     

    // Populate the fields on the form – we will use these

    // values in the Submit process

    xnFormURL.SetValue(strUri);

    xnLocation.SetValue(strLoc);

    xnFolderName.SetValue(strFolder);
    }

     

    • Add the following code to the form’s Submit event:

    // Create a Navigator object for the main DOM
    XPathNavigator xnDoc = this.MainDataSource.CreateNavigator();


    // Create Navigator objects for the fields we will

    // use to modify the FolderUrl
    XPathNavigator xnLocation = xnDoc.SelectSingleNode("my:myFields/my:strLocation", this.NamespaceManager);
    XPathNavigator xnFolderName = xnDoc.SelectSingleNode("my:myFields/my:strFolderName", this.NamespaceManager);

     

    // Get a reference to the submit data connection

    FileSubmitConnection fc = (FileSubmitConnection)this.DataConnections["Main submit"]; 

     

    // Modify the URL we want to submit to by concatenating the

    // xnLocation and xnFolderName values

    fc.FolderUrl = xnLocation.Value + "/" + xnFolderName.Value;

     

    // Execute the submit connection

    try

    {

       fc.Execute();

       e.CancelableArgs.Cancel = false;

    }

    catch (Exception ex)

    {

       e.CancelableArgs.Cancel = true;
    }

     

    • Build and save the project
    • Publish and test

    And that is it! You now have an InfoPath form template that will submit to whatever document library the form was opened from so you do not need to know this information when designing the template.

     

    Scott Heim

    Support Engineer

  • Microsoft InfoPath 2010

    Person / Group Picker Improvements in InfoPath 2010

    • 51 Comments

    Hi, this is Frank Mueller, a developer on the InfoPath team. In this post which is the first of two blog posts about the Person / Group picker, I want to tell you about the improvements we’ve made to this control in InfoPath 2010.

    The Person / Group Picker (aka contact selector) control allows you to type or select users and groups from a SharePoint site, and validate those users against a directory provider. In InfoPath 2010, the Person / Group Picker control is now a 1st class citizen and is available out of the box in the controls gallery! With the new and improved person / group picker, we have eliminated the detailed steps required to insert and configure this control in your forms (the blog post outlining these steps has been one of our most viewed posts). In addition to making the control available in the controls gallery out of the box, we have added new features to improve its integration into SharePoint scenarios.

    For information on how to upgrade InfoPath 2007 forms with Person/Group Picker controls to InfoPath 2010, click here.

    Adding the Person/Group Picker to your form

    From the Controls Gallery on the Home tab or the Controls task pane, click the Person/Group Picker to insert it into the view.

    Controls Gallery

    Specifying a SharePoint site to query for people and groups

    The Person/Group Picker needs to connect to a SharePoint site to be able to function. Specify the SharePoint site as follows, unless you have already published the form to a SharePoint site, in which case that site will be used.

    1. Right-click the control in the view and select Person/Group Picker Properties from the context menu
    2. In the Person/Group Picker Properties dialog, select the SharePoint Server tab
    3. Type the URL of the SharePoint site you want to query

      Control Properties

    4. Click OK to close the dialog

    Specifying data validation (optional)

    In InfoPath 2010 it is now possible to mark the field the people picker is bound to as Cannot be blank. This means that users will not be able to submit a form without having entered at least one valid person or group in the control. You can mark a field as required by doing the following:

    1. Select the control in the view
    2. In the Properties tab in the Modify chunk, click the Cannot be blank checkbox

     

    PPickerCBB

    Testing the control

    Preview the form in InfoPath Designer or publish the form to a SharePoint site and view the form, enter a name or logon alias, click the “Check Names” button and resolve the name! Alternatively, you can click the “Address book” button to perform a search if you do not know the complete name of the user.

    For information on how to upgrade InfoPath 2007 forms with Person/Group Picker controls to InfoPath 2010, check out my other post here.

    Frank Mueller

    InfoPath Developer

  • Microsoft InfoPath 2010

    Email Submit "To" line (loops in formulas)

    • 60 Comments
    Everyone likes InfoPath's email data connection because it lets you collect forms using email only, no other infrastructure required (no need for Windows SharePoint Services, SQL Server, or even a file share). We've built even more Outlook integration in InfoPath 2007 Beta, but since most of you don't have that yet, let me share a tip that will work in both InfoPath 2003 and 2007.
     
    The basics: Single dynamic email address
    As your probably know, the To and CC line of the email data connection can come from a textbox in the form by using a formula. To do that, just use the Fx button next to the To line in the data connection wizard:
     
     
    The trick: Multiple email addresses from repeating controls
    Some forms have a list of names they want to send to, but the simple formula above won't work for that.
     
    For example, consider a repeating table that looks like this:
     
     
    With this data source (note that "person" is repeating):
     
     
    So you want to produce this semicolon-separated list of e-mails:
     
     
     
    A good instinct is to use the "concat" function, but unfortunately that only works on the first element in a repeating structure.
     
    So then comes the team insight: Our "eval" function returns a list of nodes which actually share an anonymous parent. That means you can use one eval functions to create a list of the email addresses, then wrap it in another eval function that gets the parent of that list.
     
    Voila, here's the formula to solve the problem:
    eval(eval(person, "concat(my:email, ';')"), "..")
     
    (Note that "person" can be inserted from the data source, but "my:email" needs to be typed by hand or you'll get an error.)
     
    For the curious: Here's how it's done
    Let's break down that XPath formula from the inside out:
     
    • "concat(my:email, ';')" - Adds a semicolon to each email address.
    • eval(person, "concat(my:email, ';')") - Loops through each person to create a list of email addresses
    • eval(eval(person, "concat(my:email, ';')"), "..") - Gets the anonymous parent of the email addresses, and converts them to a string.
     
    So the end result returns the contents of that anonymous parent, which is a series of semicolon-delimited email addresses. Phew!
     
    In summary
    We are using two tricks here:
    • The fields returned by eval() all have the same anonymous parent (feature of InfoPath's function)
    • The string value of a parent is the concatenation of all its children (W3C spec’ed)
     
    - David Airapetyan (Software Design Engineer) and Ned
  • Microsoft InfoPath 2010

    Inserting line breaks into text using Rules

    • 19 Comments

    Q: How do I insert line breaks into a multi-line text box using rules?

    First off, let’s introduce the concept of a multi-line text box properly. This functionality was added in InfoPath 2003 SP1. To enable it, insert a Text Box control, then on the Display tab, check “Paragraph breaks”. I usually also set the scrolling property to “Show scrollbars when necessary” and turn on “wrap text” which maps to the usual behavior for a multi-line text box. I also usually make the control bigger.

    Without the “Paragraph breaks” property set, line breaks (CR, LF or CRLF) in the XML data are treated as any other whitespace and show up in a text box as spaces. The Enter key is ignored, and breaks are stripped on paste. With this property set the breaks are preserved and show in the control, and can be typed and pasted.

    That’s good enough for round-tripping pre-existing breaks in the XML data and allowing user editing. And since you can party on the DOM as much as you want, inserting them via code is easy too – use whatever the escaping mechanism your language of choice provides – for example, in JScript you might use: oNode.text = "abc\r\ndef"

    How about rules? One of the rule actions available is to set a field’s value to the result of an expression. Behind the scenes, when the rule fires the expression is evaluated to return a string, and then the string is injected into the XML DOM as the node’s text. Specifying expressions like concat("abc", "&#xA;", "def") will result in a literal “&”, “#”, “x”, “A” and “;” appearing in the XML text. &-encoding is part of the file format, not of the DOM! The expression concat("abc", "\n", "def") and other variants don’t work either – there’s no escaping mechanism in the evaluation used here.

    So you need to figuratively copy/paste the line break from another source. Start off by literally doing a copy/paste of the following text into Notepad:

    <?xml version="1.0" encoding="UTF-8"?>
    <characters
        cr="&#xD;"
        lf="&#xA;"
        crlf="&#xD;&#xA;"
    />

    Save this as a file called “characters.xml”. Then in InfoPath go to Tools | Data Connections and click Add. Select Receive data, then XML Document. Browse to characters.xml then complete the wizard. When it asks “The selected file is not part of the form...add this file...?” click Yes. At this point we’ve just added a resource file to the template that gets loaded into a declaratively-accessible DOM - no code required.

    Almost there - now let’s use it!

    Add a Button control, open up the properties and click Rules. Add a Rule, and add an Action of the type “Set a field’s value”. For the field pick the text box’s field (e.g. field1). For the new value, use the formula builder and build the following expression:

    concat(field1, @crlf, "Hello, world!")

    The underlines indicate that this is a simplified version of the expression that conceals the full XPaths. Instead of typing it's easier to pick the fields using the “Insert Field or Group” button. Pick field1 from the main data source and pick @crlf from the “characters (Secondary)” data source (using the drop-down at the top of the dialog). Behind the scenes (as you can tell by clicking the “Edit XPath” button) this builds up the following expression:

    concat(my:field1, xdXDocument:GetDOM("characters")/characters/@crlf, "Hello, world!")

    Once you're done, click Preview, and try clicking the button a few times.

    As a final note, InfoPath is agnostic about the whole CR vs. LF vs. CRLF debate. Any of the three is equally treated as a line break.

     

  • Microsoft InfoPath 2010

    InfoPath File Attachment Control

    • 21 Comments

    File Attachment Control

    Applies to: Microsoft Office InfoPath 2003 SP1

    Microsoft Office InfoPath 2003 SP1 introduces a number of new controls.  One of these new controls, the file attachment control, enables you to insert files which will be encoded and saved with the form. This control opens up a number of new scenarios not easily possible before SP1. 

    For example, let’s say that you have created a form that will be used by your sales people in the field. Typically, your sales people may track large amount of sales data in an Excel spreadsheet which includes fancy charts and pivot tables.  When these sales people report their quarterly earnings, you would like them to fill out an InfoPath form so that you can gather data such as total sales per region.  However, since the sales people have already gathered all the detailed sales data in an Excel spreadsheet, you don’t want them to have to reenter the data into the InfoPath form.  Instead, your sales people click on a file attachment control and attach the spreadsheet containing their sales data.  Later, when you are reviewing the data in the InfoPath form, you can double-click the spreadsheet file and open it in Excel in order to view the detailed sales data.

    Adding a file attachment control to a form is easy.  Just follow these four basic steps:

    1. Start InfoPath and design a new blank form or design an existing form.
    2. Open the Controls task pane by clicking on the Controls link in the Design Tasks pane.
    3. Look for the File Attachment control under the File and Picture category of the Controls task pane.
    4. Insert the file attachment control by clicking on it or dragging and dropping it into the view.

    Now, when you preview the form or fill out a form based on this form template, users can attach files to your form.  Also, if you open a form that has existing file attachments, you can double-click on the control to open it.  When opening files that are already attached, by default, the application that is associated with that file’s extension on your system is opened in order to view the file.

    Security

    For security reasons, not all types of files can be attached to a form.  The last thing you want is for somebody to attach a malicious executable file that formats your hard drive.  For this reason, InfoPath blocks certain file types from being attached (e.g., .exe, .com, .bat, etc.).  To determine the types of files that are considered unsafe, InfoPath follows a similar model as Outlook which is documented in http://support.microsoft.com/default.aspx?scid=kb;EN-US;290497.

    In addition to the list of file types blocked by default, you can further restrict the types of files you want users to attach to your form.  To do so, perform the following:

    1. Follow the steps above to insert a file attachment control into the view.
    2. Double-click on the file attachment control that you just inserted into your form in order to open the properties dialog for the control.
    3. On the Data tab of the properties dialog, check “Allow the user to attach only the following file types” option.
    4. In the textbox below this option, enter the extension or extensions of the file types that you want your users to be allowed to attach to the form.  Use semi-colons to separate multiple file extensions (e.g., doc; ppt; xls).

    Technical Details

    Upon attaching a file, InfoPath first builds a header structure which includes information about the file being attached. The structure consists of the following:

    ·         BYTE[4]: Signature (based on the signature for PNG):

    (decimal)                       199       73         70         65
    (hexadecimal)                C7        49         46         41 
    (ASCII C notation)          \307      I           F          A 

    The first byte is chosen as a non-ASCII value to reduce the probability that a text file may be misrecognized as a file attachment.  The rest identifies the file as an InfoPath File Attachment. 

    ·         DWORD: Size of the header

    ·         DWORD: IP Version

    ·         DWORD: dwReserved

    ·         DWORD: File size

    ·         DWORD: Size of file name buffer

    ·         File name buffer: variable size

    After building the header structure described above, the header and file data are concatenated and base64 encoded.  This base64 data is then stored with the XML data in the form.  (More information about base64 encoding can be found here: http://www.w3.org/Protocols/rfc1341/5_Content-Transfer-Encoding.html.) 

    If you wish to write code to work with InfoPath file attachments, the .NET framework provides a Convert class that includes methods to encode and decode base64 data (e.g., Convert.FromBase64String). These methods can be used to decode existing InfoPath file attachment data or to encode a file for storing in an InfoPath form.

    When a file attachment control is inserted into an InfoPath form, the following processing instruction is inserted into the XML template for the form:

    <?mso-infoPath-file-attachment-present?>

    This processing-instruction is added as a convenience for InfoPath but is not meant to be a security feature. If this processing-instruction is removed, when users fill out the form, all file attachment controls will be disabled.

  • Microsoft InfoPath 2010

    Conditional Default Values

    • 24 Comments

    Sometimes you want the default value of a field to be dependent upon a condition. However, there isn’t any direct functionality to support IF statements in the default values of fields. Substituting a rule for a default value only gets you so far, as the rule is only applied when that field that changes, not the fields that the rule depends on. Updating the field whenever any dependent field is changed would require you to copy the rule to each field.  This is not very maintainable, so below I will describe two approaches to avoiding this.

    The first approach is simple, but it has some limitations and caveats.  The second approach is more complicated, but should work in all cases. 


    Method 1: Using the union and array indexer operators

    The first approach is to use the union operator ‘|’ along with an array indexer ‘[]’ to select the proper value.  For example,

    if (BoolCondition) {
       TrueResult
    } else {
       ElseResult
    }

    becomes

    (TrueResult | ElseResult) [(BoolCondition) + 1]

    You can see that (TrueResult | ElseResult) creates a node set, while [(BoolCondition) + 1] selects which node to choose.  BoolCondition will evaluate to 0 or 1 (depending on its truth value).  Then 1 is added because the node set is 1-based, not 0-based. 

    As a simple example, say that you want to set field3 to field2 if field2 is 10 greater than field1; otherwise set field3 to field1.  On field3’s default value, the expression would be

    (../my:field1 | ../my:field2)[( ../my:field2 > ../my:field1 + 10) + 1]

     

    There are two caveats to using this approach:

    1) The node set will always be returned in document order. It does not matter what the order is in the parenthesis, as (field1 | field2) == (field2 | field1). Since you cannot change the node set ordering, you may have to modify your BoolCondition to be NOT-ed. For more information on document order, you can visit the w3.org page on XPaths.
    2) Inside of the parenthesis, you must only have nodes; you cannot have strings or any other type. So (field1 | “hello world”) will not work.


    Method 2: Using concat, substring and string-length

    To overcome these caveats, you can use the second approach here.  That is to use concat, substring and string-length.  For example, the same generic if statement from the previous approach converts to

    concat(

    substring(TrueResult, 1, (BoolCondition) * string-length(TrueResult)),

    substring(ElseResult, 1, (not(BoolCondition)) * string-length(ElseResult)))

    The key here is that BoolCondition will evaluate to 0 or 1.  Therefore, the first substring will either take no characters (if BoolCondition is false), or it will take all of the characters (if it is true) of the TrueResult.  Conversely, the second substring is evaluated with the “not” condition.  Therefore, either the TrueResult or the ElseResult will be returned in their entirety, but not both. 

    Let’s say that we want to use the same example as the first approach above,

    concat(

    substring(../my:field2, 1, (../my:field2 > ../my:field1 + 10) * string-length(../my:field2)),

    substring(../my:field1, 1, (not(../my:field2 > ../my:field1 + 10)) * string-length(../my:field1)))

    The major advantage to this approach is that you can use strings, numbers or anything else as the TrueResult and ElseResult.  For example, we could have placed “Success” and “Undefined” instead of ../my:field1 and ../my:field2. 

    That is all you need to create conditional statements in your default values! I'm attaching a sample form template that has this technique implemented (save the XSN locally before opening it). This method works on InfoPath 2003, 2007, and in browser-enabled form templates. 

    Thanks to Alexei Levenkov and Gary Hsu for their assistance on this article. 

    Nicholas Lovell
    Software Design Engineer

  • Microsoft InfoPath 2010

    Date Calculations in InfoPath

    • 8 Comments

    The SP1 update of InfoPath 2003 added calculation support – the value of a node can be set to the result of an XPath expression. This makes it possible to avoid writing code (script or managed) in many InfoPath forms. Date calculations, however, still require knuckling down and writing old fashioned procedural code.

     

    InfoPath stores dates according to the W3C XML Schema standard, which in turn uses a variant of ISO 8601 dates. The XPath expression language, however, has no special support for date types – just strings, numbers, Booleans, node-sets and fragments. This means that while you can manipulate dates as strings – you can’t do calculations with them.

     

    Before we dive into some sample code, though, a few notes:

     

    You can do date comparisons with XPath! The date format is “yyyy-mm-dd” – always 4-2-2 – which means you can do lexical (“string”) comparisons on two dates and determine ordering and equality.

     

    As a guiding rule, you should be as paranoid with date calculations as you are with financial calculations. Identify and test your edge cases thoroughly, and make sure your code matches cultural interpretations, not code convenience. For example, if you compare two dates the context and desired result matters. The relationship between a duration in days and an age in years is not simply 1/365 (or 1/365.25, or … ) – the convention for age in most cultures is “has the person had a birthday yet?” so you’d better make sure the code matches. Who wants to miss their birthday?

     

    A good rule of software development is that if you have to think too much about a problem you’re writing too much code, and the more code you write the more likely you are to have bugs. So the moral of this story is: make someone else do all the work.

     

    The general pattern for dealing with date calculations in InfoPath is to use an existing library. The two handy libraries for this are the Windows Scripting engine and the .NET Framework. Since we have a lot of script examples on this blog let’s use .NET this time.

     

    The .NET Framework has a DateTime struct type and if you look in MSDN you’ll find it has plenty of methods and operator overloads for doing calculations such as adding days and computing TimeSpans. Looks good – I bet the .NET people know what they’re doing.

     

    So basically we just want to convert an XML date into a DateTime, do some stuff with it, then convert back.

     

    Here are the functions you need:

     

           private static DateTime Iso8601ToDate( string iso8601Date )

           {

                  if( iso8601Date == null )

                         throw new ArgumentNullException( "iso8601Date" );

     

                  return DateTime.ParseExact( iso8601Date, "yyyy-MM-dd", null );

           }

     

           private static string DateToIso8601( DateTime dateTime )

           {

                  return dateTime.ToString( "yyyy-MM-dd" );

           }

     

    Wow – after that preamble I bet that was a bit of a let down!

     

    Now let’s use it. I built a simple calculation form that looks like this:

     

    Date Calculation Form Screenshot

     

    The button handlers look like this:

     

           [InfoPathEventHandler(MatchPath="date1_add1", EventType=InfoPathEventType.OnClick)]

           public void date1_add1_OnClick(DocActionEvent e)

           {

                  IXMLDOMNode dateNode = thisXDocument.DOM.selectSingleNode( "/my:myFields/my:Date1" );

     

                  try

                  {

                         DateTime dt = Iso8601ToDate( dateNode.text );

                         dt = dt.AddDays( 1 );

                         dateNode.text = DateToIso8601( dt );

                  }

                  catch( FormatException ) {}

           }

     

    Then I added OnAfterChange handlers for the date fields which call a sync method:

     

           [InfoPathEventHandler(MatchPath="/my:myFields/my:Date2", EventType=InfoPathEventType.OnAfterChange)]

           public void Date2_OnAfterChange(DataDOMEvent e)

           {

                  if (e.IsUndoRedo)

                         return;

     

                  SyncDifference();

           }

     

           private void SyncDifference()

           {

                  IXMLDOMNode date1Node = thisXDocument.DOM.selectSingleNode( "/my:myFields/my:Date1" );

                  IXMLDOMNode date2Node = thisXDocument.DOM.selectSingleNode( "/my:myFields/my:Date2" );

                  IXMLDOMNode diffNode  = thisXDocument.DOM.selectSingleNode( "/my:myFields/my:Difference" );

                  IXMLDOMNode ageNode   = thisXDocument.DOM.selectSingleNode( "/my:myFields/my:Age" );

     

                  if( date1Node != null && date2Node != null && diffNode != null )

                  {

                         try

                         {

                               DateTime dt1 = Iso8601ToDate( date1Node.text );

                               DateTime dt2 = Iso8601ToDate( date2Node.text );

     

                               TimeSpan ts = dt2 - dt1;

                               diffNode.text = ts.Days.ToString();

                         }

                         catch( FormatException ) {}

                  }

           }

     

    You might notice that this is computing the difference in days. The TimeSpan structure represents an interval of time, and days are the maximum granularity that a pure duration can have – month and year durations require a fixed point in time to calculate from;  even weeks can be ambiguous – is that whole weeks or calendar-weeks-spanned? And whose calendar in the first place?

     

    So how do you go from two DateTime structures to an age? The old fashioned way – “have I had a birthday yet this year?”

     

           int ageInYears = dt2.Year - dt1.Year;

           if( ( dt2.Month < dt1.Month ) ||

               ( dt2.Month == dt1.Month && dt2.Day < dt1.Day ) )

           {

                  ageInYears--;

           }

           ageNode.text = ageInYears.ToString();

     

    Time calculations are even more fun. No-one mention leap seconds and we’ll get by just fine.

     

    (Update 1/25/05 @ 11:30 AM PST - having a problem uploading the screenshot to our images site. We'll fix that ASAP.)

    (Update 1/25/05 @ 11:50 AM PST - Fixed!)

  • Microsoft InfoPath 2010

    Accessing InfoPath forms from Outlook

    • 16 Comments
    We have made significant investment in Office 2007 to better integrate InfoPath with Outlook. To that effect we have made it really ease to use InfoPath forms from within Outlook. When you email InfoPath forms from InfoPath 2007(using File/Send To Mail Recipient or Email submit adapter), you will now have an enriched experience when viewing these InfoPath e-mail forms. In this post, I highlight just one of the several features that we have added to Outlook 2007.
     
    Let us say, while you are working on your emails, you remember that you need to fill out a (InfoPath) form. You don't need to switch from Outlook any more. You can access the InfoPath dashboard from within Outlook by clicking on the "Choose InfoPath Form" option under "New" menu as shown below.
     
     
    This will bring up a condensed version of the regular InfoPath "Fill out a form" dialog. Most of the editor functionality is available in this condensed version. If you need to switch to InfoPath design mode (or use any additional functionality not exposed in this condensed version) then you can click on "Open InfoPath" button at the bottom left of this dashboard to launch InfoPath application:
     
     
    To learn more about InfoPath Outlook Integration I encourage you to visit Tudor's blog titled "Using InfoPath e-mail forms" at http://blogs.msdn.com/tudort/archive/2006/02/22/536800.aspx 
     
    Hope you found this article useful and are interested in exploring the numerous features that Tudor talks about in his blog.
     
    Thanks!
    Anand
    Lead Software Design Engineer
Page 1 of 12 (298 items) 12345»