Microsoft InfoPath 2010
The official blog of the Microsoft InfoPath team

  • Microsoft InfoPath 2010

    Using TFS for Source Control in InfoPath 2010

    • 18 Comments

    In this video demo, Philip Newman and Christopher Brotsos from the InfoPath program management team show how you can use Team Foundation Server (TFS) to manage source control for your InfoPath forms with code.

    Get Microsoft Silverlight

    Follow up

    Team Foundation Server (TFS) is an effective repository and source control program for your InfoPath solutions. Teams add InfoPath forms and their related Visual Studio Tools for Applications (VSTA) projects to TFS, and then proceed to collaborate on the overall solution. Form designers focus on adding controls, rules, and layouts to their local copy of a form while developers add C# or Visual Basic .NET code to their local copy of a form code project. Then, by using the TFS visual tooling environment, designers and developers can easily merge their changes together into a complete InfoPath solution.

    There are, however, some best-practices that you should, and in some cases must, implement in order to be successful.

    Setting up your environment

    Configure a portable local workspace

    If your team plans to collaborate on an InfoPath solution, ensure all contributors work within a directory that everybody in the team can access via the same path. For example, use a common mapped drive, a UNC path, or as in the video, a local path that can be the same for all users of the project. In the video, we specifically used:

    1. %Root Directory% – C:\InfoPath Projects
    2. %Project Directory% - %Root Directory%\<ProjectName>
    3. %XSN Components Directory% - %Project Directory%\XSN Files
    4. %VSTA Project Directory% - %Project Directory%\XSN Sources

    InfoPath’s default root directories, for XSNs and VSTA projects, fall under %USERPROFILE%. Because the %USERPROFILE% directory has a different name for each user, it will not be accessible through a common path for all those contributing to the project.

    Work with the form template component files and not the XSN

    When you collaborate on an InfoPath solution, you should work with the XSN component files themselves, and not the XSN. When you add a control, rule, or new attribute to a form it is common for more than one component file in the XSN to be updated. If you work with the XSN, and not the component files, the template will be treated as a binary object. Most source control programs do not let you diff and merge changes to binary objects, and without this granular view/control of the XSN, you will not be able to successfully collaborate with your teammates.

    To work with the XSN component files, setup the local workspace and save/export the files as follows:

    Starting a new project

    1. After selecting the template from the New tab in the Backstage, immediately export the XSN component files
      1. Choose Export Source Files from the Publish tab in the Backstage.
      2. Specify the %XSN Components Directory% as previously described and export.
    2. Set the VSTA project path
      1. Choose Form Options from the Info tab in the Backstage.
      2. Select the Programming category from the Form Options dialog, and set the %VSTA Project Directory%, as previously described, in the Project location text box.
    3. From now on, work with the component files instead of the XSN. To do this, open the XSF in the InfoPath Designer instead of the XSN.

    Committing an existing project

    It’s likely that your existing project is not already configured according to the requirements. So, make a backup of said project(s), and then change the configuration to support a shared design environment.

    1. Move the copy of the XSN to %Project Directory%.
    2. Move the copy of the VSTA project files to %VSTA Project Directory%. Note: do not copy over the current VSTA project root folder.
    3. Open the XSN in design mode.
    4. Export the XSN component files
      1. Choose Export Source Files from the Publish tab in the Backstage
      2. Specify the %XSN Components Directory% and export.
    5. Change the VSTA project path
      1. Choose Form Options from the Info tab in the Backstage.
      2. Select the Programming category from the Form Options dialog, and set the %VSTA Project Directory% in the Project location text box.
    6. Save your changes and from now on, work with the component files instead of the XSN. To do this, open the XSF in the InfoPath Designer instead of the XSN.

    Read-only file properties, TFS, and InfoPath

    Before Philip and I opened the XSF in design mode, you saw us remove the read-only property from the %Project Directory% instead of executing a check-out in TFS to remove the TFS file lock. Executing a check-out in TFS is not best-practice when working with an InfoPath project because InfoPath 2010 needs access to all of the component files during design mode. Likewise, you also saw Philip execute an atomic check-out/check-in before he updated the repository with the date field and validation rule he added. TFS won’t let you check-in until you check-out, so the two commands should be executed in sequence in order to successfully check-in updated files. (Note: I didn’t check my code into TFS in the video, but if I had, I would also have executed a check-out followed immediately by a check-in).

    Configure TFS to check-in your DLLs and PDBs. In a standard Visual Studio project, this isn’t necessary because DLLs and PDBs can be built dynamically at build-time. InfoPath also generates DLLs and PDBs dynamically, but it also lists said files in the template manifest. As such, if the DLLs and PDBs aren’t in the %XSN Components Directory% then the Designer will fail to open with a schema validation error.

    Multiple developers and designers working on a form

    Avoiding conflicts with the schema, control properties, and the layout of a form can be managed by maintaining the following best practices in your team:

    1. Do not have more than one designer adding controls or modifying the layout of the form simultaneously.
    2. Do not have more than one designer adding rules to the form simultaneously.
    3. All controls and fields added to a form should be given a unique name.

    SVN

    Apache SVN works equally as well for collaborating on InfoPath form templates and their related VSTA projects. If the guidelines in this post are followed, your team can use SVN as a repository and source control management solution in the same way as Visual Studio Team Foundation Server. Each version control solution has its own benefits and caveats though, and you should evaluate each to determine which solution works best for your team. As an example: SVN doesn’t apply file locks to local copies of projects; its check-in/check-out paradigm differs from TFS. So, your team may find the file management aspects of SVN more intuitive and efficient. On the other hand, you will likely conclude that the CLI is the best choice for managing your project with SVN, and as such, you will lose the graphical/auto merge feature. Again, experiment, evaluate, and choose the solution which works best for your team.

    Conclusion

    InfoPath makes designing forms easy, and it provides you with a managed object model and access to the .NET Framework. This programmability support is available so that you can extend your forms into a variety of scenarios on the client and SharePoint. As your projects grow in size and complexity, you will find that using a managed repository is a quick and effective way for sharing solution amongst multiple developers and designers.

  • Microsoft InfoPath 2010

    Goodbye WhoAmI! Hello userName()

    • 18 Comments
    Anyone who's tried to get the username of the person filling out their form in InfoPath 2003 knows the WhoAmI web service. That was the only way to get the username without writing Visual Basic or C# managed code and using System.Environment.UserName.
     
    In InfoPath 2007 we built an easier way.
     
    Announcing a new formula function: userName()
    Now you can simply set the default value to the current form-filler's username. No code, no data connections, no custom web service. Just use the formula dialog and select the function from the category "All":
     
     
    To get a default value like this:
     
     
    If that's too easy for you, use it in script
    If you're writing script anyway, or if you need to check this value as part of a bigger algorithm and don't want to persist the username anywhere in the form, then you can also access this value in script:
     
    Application.User.UserName
     
    Of course, you can also use this in C# or Visual Basic, but you could always use System.Environment.UserName, so that's nothing new.
     
    Either way requires Domain Trust
    For security reasons, either approach will make your form require domain trust, so you'll need to publish the form to a shared location (like Windows SharePoint Services) for the function to work.
     
    Enjoy!
    -ned
  • Microsoft InfoPath 2010

    "Design Once" and the new InfoPath 2007 Object Model

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

    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

    Add items to a SharePoint list using managed code

    • 16 Comments

    In this video demo, Phil Newman shows how you can write managed code in an InfoPath form to add items to a SharePoint list, and then publish this form as a sandboxed solution to SharePoint.

    In InfoPath 2010, forms with code can now be published directly to SharePoint without requiring the farm administrator to approve and upload them! These forms run in a sandboxed environment which protects other resources on the SharePoint server from malicious code.

    Get Microsoft Silverlight

    For more details on publishing InfoPath forms with code as sandboxed solutions to SharePoint, see Phil’s earlier post Introduction to Sandboxed Solutions - Sort data in repeating tables using managed code.

    Here’s the code that was used in this demo:

    NOTE: To develop code using the SharePoint object model, you need to add a reference to Microsoft.SharePoint.dll to your VSTA project. This DLL is installed in %CommonProgramFiles%\Microsoft Shared\Web Server Extensions\14\ISAPI with your licensed copy of Microsoft SharePoint Server.

    public void school_Changed(object sender, XmlEventArgs e)
    
    {
    
      using (SPSite FormSite = new SPSite(ServerInfo.SharePointSiteUrl.ToString()))
    
      {
    
        using (SPWeb FormWeb = FormSite.OpenWeb())
    
        {
    
          //Get the list and query for the item - "Schools" is the name of the list I am retrieving
    
          SPList LookupList = FormWeb.Lists["Schools"];
    
          SPQuery MyQuery = new SPQuery();
    
          //"Title" is the field where I keep the school name
    
          ///my:myFields/my:school is the xpath to the school field
    
          MyQuery.Query = "<Where><Eq><FieldRef Name='Title' /><Value Type='Text'>" + GetDomValue("/my:myFields/my:school") + "</Value></Eq></Where>";
    
          SPListItemCollection ReturnedItems = LookupList.GetItems(MyQuery);
    
          //Add the item to the lookup list if no items were returned in the query
    
          if (ReturnedItems.Count == 0)
    
          {
    
            SPListItem NewItem = LookupList.Items.Add();
    
            ///my:myFields/my:school is the xpath to the school field
    
            NewItem["Title"] = GetDomValue("/my:myFields/my:school");
    
                            
    
            //Set AllowUnsafeUpdates = true to update the database
    
            FormWeb.AllowUnsafeUpdates = true;
    
            NewItem.Update();
    
            FormWeb.AllowUnsafeUpdates = false;
    
          }
    
        }
    
      }
    
    }
    
    private string GetDomValue(string XpathToGet)
    
    {
    
      return this.CreateNavigator().SelectSingleNode(XpathToGet, this.NamespaceManager).Value;
    
    }
  • 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
  • Microsoft InfoPath 2010

    Creating a Multi-Select List Box in InfoPath SP1 Preview

    • 16 Comments

    Creating a Multi-Select List Box in InfoPath SP1 Preview

     

    While InfoPath does not include a multi-select list box control, it is possible to create one using the controls present in InfoPath SP1 Preview:

     

     

    Like all form design decisions in InfoPath, the first thing you need to do is think about the data you want to collect – how do you want the multiple selections represented in the XML saved or submitted by the InfoPath form? Additionally, do you want the selections to be determined at form design time (static), or at runtime (dynamic)?

     

    Here’s one approach that allows either a static or dynamic list of choices by including the choices – and the selection state – right in the form data.

     

    First, create a data structure as follows:

     

     

    Here are the steps to do this:

     

    1. Go to the Data Source task pane
    2. Click the Add button, and add a node named “options” of type Group
    3. Add a node under options named “option” of type Group and check Repeating
    4. Add a node under option named “selected” with data type True/False (boolean)
    5. Add another node under option named “text” (with the default properties)

     

    Note that if you want a very different data structure the rest of these instructions won’t apply directly, but they should get you started down the right path in terms of understanding how to create a complex control out of the primitives that InfoPath provides.

     

    Now you need to build the view – here’s what I came up with, showing the design-time structure:

     

     

    This is a Scrolling Region as the outer container for the control, containing a Repeating Table for the options, with a Check Box and Expression Box for each option. Here’s how you make it:

     

    1. Go to the Controls task pane
    2. Insert a Scrolling Region control, and resize it to the size you want the Multi-Select List Box control to be.
    3. Go to the Data Source task pane
    4. Drag the option group from the task pane into the Scrolling Region control; when the popup menu appears, select Repeating Table
    5. Double-click the Repeating Table indicator to show its properties
    6. On the Data tab, uncheck Allow users to insert and delete rows
    7. On the Display tab, uncheck Include header, then click OK
    8. Inside the Repeating Table, delete the text next to the check box in the first cell (which should say “Selected”), and resize the table cell so that the checkbox just fits within it
    9. Right-click the Text Box in the second cell, point at Change To and select Expression Box on the fly-out menu

    Next, tweak the layout and borders to make it look professional:

    1. Double-click the Scrolling Region indicator
    2. On the Size tab, set the Top, Bottom, Left and Right Padding to 0 px, then click OK
    3. Select Format | Borders and Shading..., click Outline, then click OK
    4. Select the Repeating Table indicator, then go to Format | Borders and Shading..., select None, and click OK
    5. Click inside the Scrolling Region – although you can’t see them, there will be several empty paragraphs. Arrow down until the blinking insertion point is in the last paragraph, then hit Backspace to erase them. (If you forget to do this you may see blank lines after the options when you preview the form.)

    Finally, if you want to make the selected options stand out clearly, you can use Conditional Formatting:

    1. Click the Repeating Table indicator, then go to Format | Conditional Formatting... and click Add...
    2. In the third drop-down, select TRUE (so the condition reads “selected” “is equal” “TRUE”)
    3. Click the Shading drop-down, and select a background color (e.g. light gray)

    At this point, the Multi-Select List Box control is ready to go – but it doesn’t have any options! Maybe those options are specified by your form’s back end data source (a database or web service). But for now, let’s assume the list is static:

     

    1. Go to Tools | Default Values
    2. Right-click on the option node, and select Add another option below; repeat this to create as many options as you need.
    3. Expand each option, select the text node, and type the option name in the Default value text box at the bottom of the dialog. (To make an option selected by default, select the selected node and then select TRUE in the Default value drop-down.)

    That’s it! Now just hit the Preview button on the toolbar to try our your new Multi-Select List Box control.

    Note: You can also create ActiveX controls that do XML data binding with the InfoPath SP1 Preview.

  • Microsoft InfoPath 2010

    The InfoPath 2003 SP1 Preview

    • 15 Comments

    Do you know about the InfoPath 2003 SP1 Preview release? There are actually two free downloads available:

    1. The InfoPath 2003 SP1 client: new features and improvements added to the InfoPath client.
    2. The InfoPath 2003 Visual Studio toolkit: this provides the ability to write .NET managed code business logic in your InfoPath form.

    Anyone can download and install this version of InfoPath and use it until it expires.

    When the Office System 2003 SP1 is released (mid-2004), InfoPath will be updated to have many new features, in addition to performance improvements and bug fixes (and if you just want the performance improvements and bug fixes, the new features can be turned off).  The SP1 is completely backwards compatible with InfoPath 2003.

    This preview gives you a chance to try out an initial version of the SP1 bits now so that you can learn the new features and plan for the SP1 deployment within your company.

    The SP1 release is very important in that we were able to address customer wishes.  Give it a try!  We're certainly excited about it and will be posting about InfoPath SP1 here often (and we'll make it clear when a post is SP1 specific).

  • Microsoft InfoPath 2010

    E-Mailing a Custom View

    • 15 Comments

    Lately, we've had a lot of interest in e-mailing a custom view with InfoPath forms that are submitted via e-mail.  There are a few simple tricks that will allow you to do this.

    Before we start, note that, in the InfoPath rich client, you have the option to "Send to Mail Recipient" from the file menu in the Editor.  In this case, you're stuck sending the currently active view of the form.  The user filling the form would have to manually click or change data in order to fire an event to switch to a custom view.  While this is feasible, we can do better with a pre-defined e-mail submit data connection.

    To define an e-mail submit data connection in the InfoPath Designer:

    1. Click "Tools" >> "Data Connections…"

    2. Click "Add…"

    3. Select "Create a connection to" >> "Submit data" and click "Next >"

    4. Select "As an e-mail message" and click "Next >"

    5. Enter an e-mail address in the "To" header field, or bind it to a field in your form template.

    6. Fill out any other e-mail header information and finish the wizard.

    7. Click "OK" / "Finish" / "Close" to get out of the wizard and finalize your e-mail submit data connection.

    Now that we've defined the e-mail submit data connection for our form template, we can move on to the custom view portion…

    The easiest option is to send a blank view.  To accomplish this, you'll simply want to switch views before you submit.  This is easily accomplished using a rule on button click.  Here are the steps, in the InfoPath Designer, to configure the "Main Submit" toolbar button to send the blank view:

    1. Create a blank view

      1. On the "View" menu, click "Manage Views…"

      2. In the Views TaskPane, click "Add a new view…"

      3. Type a name for the view and click "OK".

    2. Configure main submit to submit the blank view with the e-mail

      1. Click "Tools" >> "Submit Options…"

      2. Check the "Allow users to submit this form" checkbox.

      3. Select the "Perform custom action using Rules" radio button.

      4. Click the "Rules..." button.

      5. Click "Add..." in the "Rules for Submitting Forms" dialog.

      6. Click "Add Action..." in the "Rule" dialog.

      7. Select "Switch Views" and select the blank view in the "View" drop-down list box.

      8. Click "OK" to close all the dialogs.

    Now, when the user clicks "Submit", the view will first be switched to the blank view, and then the form will be submitted to the mail recipients.  InfoPath sends the active view contents in the body of the e-mail message, so the blank view will be sent in the message body!

    But now the next obvious question is, "Wait a second, I thought we were sending custom views, not just blank ones!"  Good call.  InfoPath Forms Services treats the "switched-to" view a bit differently than the InfoPath rich client.  In browser-enabled form templates filled out in the browser, you can add controls, text, pictures, etc. to the blank view to which we switched before submitting, and the message body will display the data in the custom view, along with the Introduction specified in the e-mail submit data connection wizard.  In the InfoPath rich client, you'll still only see the blank view due to view-switching concurrency limitations.  So we need an alternate solution…

    Basically, instead of e-mailing a custom view, we'll e-mail custom view content.  We'll have two sections in one view:  one to hold the controls where the user can fill out the form, and one where the custom "view" contents will be stored.  Then, at submit time, we'll run a rule to first hide the editing section and show the custom e-mail body section, and then submit via our pre-defined e-mail submit data connection.  This works identically in the browser and the InfoPath rich client Editor.  Here are the high-level steps:

    1. Insert two "Section" controls into the form view.  Name one "EditSection" and the other "EmailSection".

    2. Fill the sections with the relevant controls, formatting, etc.  Create your "custom view" inside the "EmailSection" and create the normal form-filling "view" in the "EditSection".

    3. Create a "True/False (boolean)" data source node.  Name it "ShowCustomEmailSection", and set its default value to "FALSE".

    4. Add conditional formatting to hide and show the "EmailSection" and "EditSection" sections.

      1. Set the "EditSection" conditional formatting to "hide this control" when "ShowCustomEmailSection" is TRUE.

      2. Set the "EmailSection" conditional formatting to "hide this control" when "ShowCustomEmailSection" is FALSE.

    5. Configure your submit button as above with the blank view case, but, instead of adding a rule action to switch views before submitting, add a rule action to set the value of the "ShowCustomEmailSection" field to the "true()" function.  This will conditionally hide the "EditSection" and show the "EmailSection".  All that will show up in the message body is an HTML rendering of the contents of the "EmailSection".

    And that's it!  Note that you may have to set the "Postback Settings" for the relevant controls to "Always" for browser-enabled form templates to get the conditional formatting to work as expected.

    Forrest Dillaway
    Software Design Engineer in Test

  • Microsoft InfoPath 2010

    Create a SharePoint list using InfoPath 2010

    • 14 Comments

    This week’s “5 for forms” video demo continues the theme of SharePoint list customization. In the 1st video in this series, Daniel Broekman showed how you can take an existing list on SharePoint and customize the form for that list in InfoPath.

    In this week’s video demo, Ines Khelifi, a developer on the InfoPath team shows how you can create a new SharePoint list and custom form directly from InfoPath Designer.

    Get Microsoft Silverlight

     

    Enjoy and please send us 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

    Moving fields in the data source

    • 13 Comments
    As most folks figure out quickly, InfoPath doesn't support drag-and-drop of fields in the data source. There are a lot of technical reasons for this, and even a usability concern that people won't realize they can drag fields onto the form as controls if we also allowed them to drag fields around in the data source. But we've heard enough feedback that changing that has made it onto the long list of possible features for future releases. Keep the feedback coming!
     
    So how do you move fields groups in the data source?
    One way is to right-click the field or group and select "Move Up" or "Move Down". This is great for novices because it's discoverable, but it's a painful number of clicks if you're an expert who has to move a lot of fields in many forms.
     
    A trick for the keyboardist
    The fastest way to move a field or group a long distances is:
    1. Open the data source task pane
    2. Type the "F6" key
    3. Click tab until a field in the data source is highlighted in orange
    4. Use the Up/Down arrow keys to select the field you want to move
    5. Hold down the CTRL key and use the Up/Down arrow keys to move the field
     
     
    Note that this only moves the field in order, it won't move it as a child of a different group. To do that you still need to right-click the field and select "Move".
     
    Hope that helps!
    ned
  • Microsoft InfoPath 2010

    Digitally Signed Fully Trusted Form Templates

    • 13 Comments

    In the InfoPath 2003 Service Pack 1 Preview you can create a fully trusted form template by signing the XSN with a code signing certificate.  Here’s what you do:

     

    • While in the InfoPath designer, select Tools | Form Options | Security
    • Uncheck the “Automatically determine security level based on form’s design
    • Select Full Trust
    • Click the Sign this form button

    At this point, you need to choose a certificate that can be used for code signing.

     

    If you do not have a certificate, you can choose the Create Certificate button.  This will create a test certificate – not a certificate that has been authenticated by a certificate authority.

     

    While you are developing your form template, you will not be able to preview with full trust permissions unless you register the form template. 

     

    The first time your users fill out the form that you have signed with a certain certificate, they will see a Security Warning dialog that notifies them that the form template is digitally signed and asks if they trust the publisher.  Once they have checked the box to trust the publisher, they will be able to open any form template that asks for full trust and is signed with that same certificate.

     

    You can view the list of trusted publishers in the SP1 version of InfoPath by selecting Tools | Options and clicking on the Trusted Publishers button.

     

    If users find that the option to trust the publisher is disabled, that means that the root of the certificate used is not trusted on the user’s machine. 

     

    When you received your code-signing certificate, you asked the CA (Certificate Authority) for it. What the CA delivered to you is a certificate that is now in your personal folder that is trusted by you and by anybody who trusts the CA that issued it.  So, for example, if you get a code signing certificate from Verisign, any user will have the option to trust you as a publisher as long as they also have Verisign in the list of Trusted Root Certification Authorities on their machine.  Once a user has trusted the root of a certificate, the option to trust the publisher will be enabled in the Security Warning dialog that is displayed when they fill out a fully-trusted, signed form.

     

    Users can trust the root of a certificate through the Security Warning dialog that comes up when they open a form template.  When the Security Warning dialog is open:

     

    • Click on the Details button
    • Click on the Certification Path tab
    • Click on the CA Root Certificate
    • Click View Certificate button
    • Click Install Certificate
    • Follow through the Certificate Import Wizard
    • After the import is successful, close out of all of the dialogs
    • Open the form to fill out again and when the Security Warning is displayed the option to trust the publisher should be enabled.

     

     

  • Microsoft InfoPath 2010

    Debugging Sandboxed Code in InfoPath 2010 Forms

    • 13 Comments

    In this video demo, Phil Newman from the InfoPath program management team shares some tips and tricks for debugging InfoPath forms with sandboxed code on SharePoint server 2010.

    Get Microsoft Silverlight

    Here is this link to the ULS viewer tool that is used in the demo:

    Filters:

    • Process=SPUCWorkerProcess (for administrator-approved forms, filter on the W3WP process)
    • Message=Exception thrown from business logic
  • Microsoft InfoPath 2010

    Workflow user experience in InfoPath

    • 12 Comments

    Microsoft Office SharePoint workflow can be described as a series of tasks implemented with specific business needs to help people manage their project tasks. In Microsoft Office InfoPath 2007, we provide the workflows user experience for InfoPath forms. Additionally, we enable InfoPath business logic to key off workflow properties.

    This article will demonstrate how to enable an InfoPath form to respond to workflow status. Let's explore the following scenario: Nicholas has created an expense report form template and has associated it with a form library with the “Approval” workflow defined. He wants a form to be displayed at different view when the workflow for that form is approved.


    Step 1: Create a expense report document library by publishing a form template

    • Launch Office InfoPath 2007.
    • Create your expense report form template with two views. For example, one is the expense detail view and one is the summary view.
    • Click the File menu | Save to save your template.
    • Publish your form template to a new document library on a SharePoint site. Name the library ‘Expense Report’.

    Note: please leave the form template open as we will come back to customize this template more in later sections.


    Step 2: Switch to SharePoint and add an Approval workflow to the expense report library

    • Navigate to the SharePoint site.
    Note: you will see Expense Report library created on the SharePoint site.
    • Open the Expense Report library.
    • Add an Approval workflow to this Expense Report library via Form Library Settings | Permission and Management | Workflow

    Note: When adding this workflow, you can specify how, when or by whom a workflow to be started and other options regarding how this workflow should work.


    Step 3: Switch back to InfoPath and add a data connection

    This section explains how to add a secondary data connection to query the workflow status of the workflow you added in the previous section. This secondary data connection provides the data that enables business logic in the form to switch views according to the status of the workflow.
    • Switch back to InfoPath. You should still have your expense report form template opened from step 1.
    • Add a Data Connection that receives data from Expense Report library via Tools | Data Connection | receive data from SharePoint library or list.
    • On the page of Select fields, select the check box next to the name of the field that matches the workflow name.
    • Click Include data for the active form only, and then click Next.
    Note: this step is the key point to retrieve current form’s workflow status.

    • Follow all the default options to finish the Data Connection Wizard.


    Step 4: Add a Rule to the form template to switch to a specific view according to current form’s workflow status

    For this example, we want to add business logic to the form that it will switch to summary view when this form’s workflow is approved. This can be achieved by applying an on load Rule to switch view when current form’s workflow status is equal to “Approved” status.

    • Set on load Rule via Tools | Form Options | Open and Save | Rules
    • When setting Condition, you want to select the workflow status field from the secondary data source you added in the previous section in your first dropdown of the condition builder
    • In the second dropdown, choose "is equal to".
    • In the third dropdown, click Type a number, and then type the value that corresponds to the workflow status.

    Status Numeric value
    In progress 2
    Complete 5
    Canceled 15
    Approved 16
    Rejected 17

    In our example, we choose number 16, corresponding to status "Approved".


    Step 5: Republish the form template

    • Click the File menu | Save to save the changes you made to the template.
    • Click the File menu | Publish.
    • Since you republish the form template, the Publishing Wizard will repopulate previous values. Click Nexts -> Publish -> Close to finish the Publish Wizard.

    Now you have successfully designed a workflow driven expense report form template. When a user fills out an expense form from this library, the view of the form will be displayed according to the status of the workflow.

    Emily Ching
    Software Design Engineer in Test

  • Microsoft InfoPath 2010

    The xsi:nil attribute

    • 12 Comments

    Have you ever tried to programmatically set a value on a field only to get a “schema validation” error? Many times, this error is caused by the “nillable” attribute being present on the node. The nillable attribute is a special attribute that can appear on an xsd:element within an XML schema. If an element has the xsi:nil attribute specified, it indicates that the element is present but has no value, and therefore no content is associated with it.

    However, if you attempt to programmatically set a value on this node and the nillable attribute is present, you will get an error similar to: “Schema validation found non-data type errors.” You will find the nillable attribute is typically present on the following data types:

    • Whole Number (integer)
    • Decimal (double)
    • Date (date)
    • Time (time)
    • Date and Time (dateTime)

    To resolve this error, your code will simply need to test if the nil attribute is present and if so, remove that attribute before setting the value on the node. The following sample procedure takes an XpathNavigator object, checks that node for the nil attribute and if it exists deletes the attribute:

    public void DeleteNil(XPathNavigator node)

    {

    if (node.MoveToAttribute("nil", "http://www.w3.org/2001/XMLSchema-instance"))

          node.DeleteSelf();

    }

    The above procedure is generic - you can easily call this procedure as needed before programmatically trying to set the value of a field. As an example, this code is called from the click event of a button:

    //Create a Navigator object for the main data source

    XPathNavigator xn = this.MainDataSource.CreateNavigator();

     

    //Create a navigator object for the field (node)

    //where we want to set the current date value

    XPathNavigator xnfield1 = xn.SelectSingleNode("/my:myFields/my:field1", this.NamespaceManager);

     

    //Check if the "nil" attribute exists on this node

    DeleteNil(xnfield1);

     

    //Create a new dateTime object for the current date

    DateTime curDate = new DateTime(DateTime.Today.Year, DateTime.Today.Month, DateTime.Today.Day);

     

    //Set the value of field1 to the current date in the

    //correct format: yyyy-mm-dd

    xnfield1.SetValue(curDate.GetDateTimeFormats().GetValue(5).ToString());

    Scott Heim
    Support Engineer

  • Microsoft InfoPath 2010

    Another Way of Sorting Repeating Data

    • 12 Comments

    If you have ever attempted to sort repeating node data (i.e. a Repeating Table or Repeating Section) on an InfoPath form, you will find this functionality is not available through the UI. However, using .NET classes you can easily implement a sorting routine that will work in both client and browser scenarios. We discussed one way to make this happen through custom code in a recent article; this post will show a different way to make it happen. We will take a look at how to implement this functionality along with taking advantage of some new features in InfoPath 2007:

    • Dynamic button labels
    • Complex default value on the Button label to change the caption based on the sort order of the selected field (discussed in this article)

    In this sample scenario, let’s assume you are capturing the following data in a Repeating Table:

    • Last Name (name: LastName)
    • First Name (name: FirstName)
    • Age (name: Age)

    In addition, you want to allow your users to select the field they want to sort on (using a button in the column header) and clicking the button will toggle the sort between Ascending and Descending. Here is a sample form showing those options:

    ** NOTE: Notice the “(Asc)” in the Last Name button label? We’ll show you how to do that at the end of this post!

    The data structure for the above sample is as follows:

    So in this scenario, the user would simply click the button above the field they want to use to sort the data and by default, the first click would sort the data in Ascending order and clicking it again would sort the data in Descending order. Let’s now go ahead and take a look at the code on the click event of the buttons that implements this functionality.

    When each button is clicked, the first thing we do is set the value of the SortOrder and SortField nodes. For ease of implementation, we created a “SpecifySortOptions” procedure that is called from the click event of each button:

    SpecifySortOptions("LastName",XmlDataType.Text,e.ControlId);

    When each button is clicked we call this procedure passing it the field we want to use for sorting (in this case, LastName), the data type of this field (XmlDataType.Text) and the ControlID of the button that was clicked. (The ControlID is used in the Expression for the Default Value property of each button to determine how to change the label.)

    Here is the SpecifySortOptions procedure:

    public void SpecifySortOptions(string SortField, XmlDataType dataType, string ControlID)

    {

    //Create Navigator objects for the main DOM and

    //for the SortOrder and SortField fields

    XPathNavigator xn = this.MainDataSource.CreateNavigator();

    XPathNavigator xnSortOrder = xn.SelectSingleNode("/my:myFields/my:SortOrder", this.NamespaceManager);

    XPathNavigator xnSortField = xn.SelectSingleNode("/my:myFields/my:SortField", this.NamespaceManager);

     

    //Check to see if the value of the SortField is equal

    //to the ControlID that we passed to this procedure. If

    //it is the same and the SortOrder field is an SortOrder

    //emptry string or is set to "Desc" then set the field to

    //"Asc". If the SortField value does not equal the

    //ControlID that we passed to this procedure, then that

    //would mean either the SortField is an empty string or

    //it was set to another field - either way, we will

    //then want the SortOrder value to be "Asc"

    if (xnSortField.Value == ControlID)

    {

       if (xnSortOrder.Value == "" || xnSortOrder.Value == "Desc")

          xnSortOrder.SetValue("Asc");

       else

          xnSortOrder.SetValue("Desc");

    }

    else

       xnSortOrder.SetValue("Asc");

     

    //Call the SortTheData() procedure passing in the values

    //specified above

    SortTheData(SortField, xnSortOrder.Value, dataType);

     

    //Set the SortField value to the current ControlID

    xnSortField.SetValue(ControlID);

    }

    After calling the SpecifySortOptions procedure from the click event of each button, this procedure calls the SortTheData procedure, which accepts a string value for the sort field (strSortField), a string value for the sort order (strSortOrder) and an XmlDataType value (dataType) for the type of data being sorted. This is the code that will actually perform the sorting.

    The first thing we need to do is this procedure is create “XPathNavigator” objects for the main DOM:

    //Create a Navigator object for the main DOM

    XPathNavigator xn = this.MainDataSource.CreateNavigator();

    We then will create an XmlSortOrder object so we can specify either an Ascending or Descending sort. In this sample, we will specify an Ascending sort as the default; however, we will check the value of strSortOrder and if this is set to “Desc”, change the XmlSortOrder object accordingly:

    XmlSortOrder sortOrder = XmlSortOrder.Ascending;

    if (strSortOrder == "Desc")

    sortOrder = XmlSortOrder.Descending;

    To actually perform the sort, we will be using the “AddSort” method of an XPathExpression object – as such, we need to create an XPathExpression object for the repeating (group) node that we are going sort:

    XPathExpression xe = xn.Compile("/my:myFields/my:group1/my:group2");

    Now we can use the AddSort method on the Expression object using the field name (strSortField) that we passed into this procedure, the sort order using the sort order object (sortOrder) we created above and the data type using the data type object (dataType) we passed into this procedure:

    xe.AddSort("*[local-name()='" + strSortField + "']", sortOrder, XmlCaseOrder.None, "", dataType);

    We need to specify a NamespaceManager for the Expression object and for this we will use the SetContext method:

    xe.SetContext(this.NamespaceManager);

    The next step is to create an XPathNodeIterator object, passing it our XPathExpression object, so we can iterate all the nodes now that they are sorted - in addition, we will use this object (in the lastNode expression below) to get a count of the total nodes in this repeating group:

    XPathNodeIterator xi = xn.Select(xe);

    In the end, the way this procedure works is to delete the existing “un-sorted” nodes and add back the “sorted” nodes via the XPathNodeIterator object. So the next step is to now delete the existing “un-sorted” data. To do this, we will create XPathNavigator objects to reference the first and last nodes in this repeating group and then use the DeleteRange method to delete those nodes:

    XPathNavigator firstNode = xn.SelectSingleNode("/my:myFields/my:group1/my:group2[1]", this.NamespaceManager);

    XPathNavigator lastNode = xn.SelectSingleNode("/my:myFields/my:group1/my:group2[" + xi.Count + "]", this.NamespaceManager);

    firstNode.DeleteRange(lastNode);

    At this point, we have the sorted data in memory and the un-sorted data has been removed so we are ready to add that sorted data back to the form. For this process, we will use the XPathNodeIterator object we created earlier to iterate over the nodes.

    while (xi.MoveNext())

    {

    //Create string variables to hold the values of each field

    //as we iterate the nodes

    string strLastName = xi.Current.SelectSingleNode("my:LastName", this.NamespaceManager).Value;

    string strFirstName = xi.Current.SelectSingleNode("my:FirstName", this.NamespaceManager).Value;

    string strAge = xi.Current.SelectSingleNode("my:Age", this.NamespaceManager).Value;

     

    //Call the AddNewRow method to append a new row

    // to the repeating group

    AddNewRow(xn.SelectSingleNode("/my:myFields/my:group1", this.NamespaceManager));

     

    //Since we are continually appending new rows, the 

    //"last" row will always be the one where we need

    //to set the values - so here we will create a

    //Navigator object for this newly added row - we

    //will use this for setting the field values below

    XPathNavigator xnNewRow = xn.SelectSingleNode("/my:myFields/my:group1/my:group2[last()]", this.NamespaceManager);

     

    xnNewRow.SelectSingleNode("my:LastName", this.NamespaceManager).SetValue(strLastName);

    xnNewRow.SelectSingleNode("my:FirstName", this.NamespaceManager).SetValue(strFirstName);

     

    //Since the Age field is numeric, it will contain

    //the "nil" attribute. We need to remove this

    //arrtibute prior to programmatically setting the

    //value. To do this, we'll call the DeleteNil

    //procedure passing it the node that contains

    //(or may contain) the nil attribute

    DeleteNil(xnNewRow.SelectSingleNode("my:Age", this.NamespaceManager));

     

    //Now we can set the value of the Age field

    xnNewRow.SelectSingleNode("my:Age", this.NamespaceManager).SetValue(strAge);

    }

    In the while loop above, we used the “AddNewRow” and “DeleteNil” procedures – these are documented below:

    public void AddNewRow(XPathNavigator docXN)

    {

    //Create a Navigator object to reference the node

    //we will be adding. To do this, we can use the

    //templates' "Manifest.xsf" file to get the

    //appropriate node to add. As you can see, this is

    //specific to the control's "name", which you can

    //get from the Advanced tab on the Properties window

    //for the repeating control. Once you have this,

    //use the "Save As Source Files" command from the 

    //File menu in InfoPath and locate the appropriate

    //expression in your Manifest.xsf file

    XPathNavigator xnNode = this.Template.Manifest.SelectSingleNode("//xsf:xDocumentClass/xsf:views/xsf:view/xsf:editing/xsf:xmlToEdit[@name='group2_1']/xsf:editWith/xsf:fragmentToInsert/xsf:chooseFragment/my:group1", this.NamespaceManager);     

     

    //Append the node from the Manifest file to the main DOM

    docXN.SelectSingleNode("/my:myFields/my:group1", this.NamespaceManager).AppendChild(xnNode.InnerXml);

    }

     

    public void DeleteNil(XPathNavigator node)

    {

    //Check to see if the nil attribute exists

    //and if so, delete it

    if (node.MoveToAttribute("nil", http://www.w3.org/2001/XMLSchema-instance))

        node.DeleteSelf();

    }

    And that’s it! You now have the functionality of sorting data in a repeating node. For reference, the complete code for this sample is attached.

    Now – about that button label…how did we do that??!

    With InfoPath 2007, we have a new feature that allows you to specify a dynamic value for the button label. To do this, simply click the “fx” button next to the label property and you can choose to use an expression of a field/group from your form:

    However, for this sample the conditional logic for the button label is quite complex: we need to determine which button was clicked and whether we should show “(Asc)” or “(Desc)” next to the correct label. For this, we used the process demonstrated in this blog post: Conditional Default Values.
    So here is the logic that needed to be implemented when each button is clicked; for example, for the Last Name button:

    • See if the SortField value (which is set to a button’s ControlID in the SpecifySortOptions procedure) is equal to the clicked button’s ControlID and if the SortOrder value is either an empty string or equal to “Asc”
      • If it is, then set the label to: Last Name (Asc)
    • See if the SortField value is equal to the clicked button’s ControlID and the SortOrder value is “Desc”
      • If it is, then set the lable to: Last Name (Desc)
    • If neither of the above are true, then a different button must have been clicked so set the label to: Last Name

    This is the logic that needs to be implemented for each button. Here is a sample expression for the LastName field:

    concat(substring("Last Name (Asc)", 1, ((my:SortOrder = "" or my:SortOrder = "Asc") and my:SortField = "btnLastName") * string-length("Last Name (Asc)")), substring("Last Name (Desc)", 1, (my:SortOrder = "Desc" and my:SortField = "btnLastName") * string-length("Last Name (Desc)")), substring("Last Name", 1, not(my:SortField = "btnLastName") * string-length("Last Name")))

    Each of the above “substring” expressions are tested in order – so if the SortOrder field does not equal an empty string or does not equal “Asc” and the SortField value does not equal “btnLastName” then we test the next condition. If the SortOrder value does not equal “Desc” and the SortField value does not equal “btnLastName” then we test the last condition. And here we only need to check the value of my:SortField – if this does not equal “btnLastName” then we know a different button was clicked and we only want the label to display “Last Name”.

    So there you have it! A way to sort data in your repeating table and a really cool way to let the user know which field they clicked for sorting and in which order the data has been sorted!

    ** NOTE: It seems we may have a bug with our expression box in that it will accept the entire conditional statement noted above but once you close and re-open the box, the string gets truncated. Once you have this working, you may want to keep that expression saved in a text file.

    Scott Heim
    Support Engineer

  • Microsoft InfoPath 2010

    Survey Creator

    • 12 Comments

    Scenario

    A school department wants to create a standard digital template to use when administering tests to students. Since the template is to be a standard format across multiple classes, the department requires that teachers be able to enter questions appropriate to their individual classes. To simplify things, the department decides to allow three types of questions: True/False, Multiple Choice, and Free-Form Essay (write-in). So, in short, teachers create questionnaires for the students, determining what type of answer to collect for each. The form is then given to the students taking the test, who step through the questions one-by-one. After the test, the teachers compile the answers, creating a master form for grading. The two main views of the form will look similar to the following:

     

    Wizard-Style Form: One Question at a Time

    The heart of the wizard-like functionality of the solution to this scenario is the use of an index counter by which a view is then filtered when the form is being edited. The "Next" and "Back" buttons we see in so many cases appear on this InfoPath solution but they simply change the value of the counter, adding one to the index if "Next" is clicked, subtracting one if "Back" is clicked. In this case, the index counter is placed on the repeating section that is the container for test questions in this form. 

    Data Source

    We will use a repeating group of questions; each question will have a questionText (what's being asked) and one of the following subnodes (implemented as a choice group):

    1) trueFalse: keeps track of the student's answer to this question, if this question is a true/false question. Boolean.

    2) writeIn: keeps track of the student's essay answer to a write-in question. Text or Rich-Text (XHTML).

    3) multipleChoice: we need to remember two things here:

     - possible choices (provided by the teacher; repeating group of text fields)

     - student answer

    Since we want to show students only one question at a time, we will need an auxiliary index field to remember the current question that's being shown. The index counter used by the filter is a field that does not take any direct user input. Give the field a value of 1, which will then be incremented using the buttons.

    All-in-all, the data source looks similar to the following:

    Views

    This forms solution is structured around a repeating section field that appears in both views. To create the duplicate repeating sections, create two views and place a repeating section in the first view. Next, open the second view, open the data source task pane, and drag the repeating section field onto the canvas.

    To show the students one question at a time, we need to apply a filter: open the student view and then open the Properties of the repeating section in that view. Click the display tab and then click the "Filter Data…" button. Since we will set the counter to be the question number, and since we want to display only the current question, set the filter to display data for which index = position().

    Navigation among the questions is enabled by "Next" and "Back" buttons included in the student view. Insert two buttons into the student view. Double-click the first button: Select "Rules and Custom Code" in the action menu, give the button the label "<< Back" and click the "Rules…" button. Add an action as appears below:

    For the "Next >>" button, follow a similar procedure as for the back button but add 1 to the value of index in the above dialogue.

    Now we need to take care of the actual question display: each question requires a serial number, the text of the question, and the field for response (which could be one of several pre-defined types.) The teacher's view contains user-editable fields for question text and a choice of answer type; the Student view displays the text of the question and contains the editable response field.

    In detail:

    Question Text: collected through a Text Box in the Teacher view and then displayed using an Expression Box in the Student view.

    Response data is contained in a choice group. The Teacher selects the most appropriate of the three response types permitted by the form and, in the case of multiple choice, adds the necessary choices to a numbered list. No "answer" data field appears in the Teacher view of any of the answer types because all the teacher need do is choose the type of answer. The default Choice Group appears with two Choice Sections but can contain as many as necessary, simply insert the Choice Group and then add more Choice Sections. For this scenario, add the Choice Group and Sections to the Teacher view and then label the Choice Sections with the appropriate answer type. For the multiple-choice Choice Section, add a Numbered List control to the section to contain the options for any multiple-choice section.

    The controls to hold student responses to questions are contained in a Choice Group placed into the Student view by dragging the existing Choice Group into that view from the Data Source Task Pane. This action creates a mirror of the Choice Group structure contained in the Teacher view but without the controls or text placed into the Teacher view. Into the Choice Sections in the Student view place, respectively, a set of 3 Option Buttons for True/False/I Don't Know, a Rich Text field for written response, and a List Box for multiple choice. This last has the slight complication that we want to pull in the options the teacher set for the particular question. To do this go to the "Data" tab of List Box Properties and select the second option under "Data": "Look up values in the form's data source." Select the field that holds the values from the Numbered List and these will populate the List Box for each multiple choice question.

    To display the question number, add an expression box that displays the value of the index. Type "Auto" into the width property of the expression box and the control will size itself to the value. To display the total number of questions, use an expression box in which you use the following formula where the fields used are the Choice Sections within the Choice Group used to contain responses:

    The basic mechanics of this test form are now complete. What remains to be set up are things like submission and review options and settings. Some examples of possible additions to this scenario are as follow:

    • View permissions so the students can only see the view intended for them.
    • User roles limiting what members of the student body are permitted to take the test. 
    • A review and submission function that shows the "Review and Hand-In Test" button only after all questions have been viewed. This button would then take students to a summary view of all of their question-answer pairs along with links to return to a particular question should they want to change their answers and a button to finally submit the test. (This option is a logical product of the calculation and display of the total number of questions and of the current question - making it simple to determine when the user has reached the end of the slate of questions.)
    • Settings for the teacher to merge all answers into a single master form for grading, especially if marks depend on comparison among all the answers. The summary field, once marked, could produce individual reports for students that could be e-mailed out automatically (they would be required to authenticate themselves with their school e-mails to be able to take the test in the first place. 
    • Submit settings to send all the tests to a MOSS document Library.

    The sample form template that has this technique is attached; make sure to download the XSN to your computer before opening it. Note that this technique works in InfoPath 2003 and 2007, but will not work in browser-enabled form templates.

    Jonathan
    Program Manager

    Thanks to our brilliant ex-colleague Ned Friend for building the sample form template.

  • Microsoft InfoPath 2010

    The anatomy of a UDC file

    • 12 Comments

    OK, we’ve talked about super-fantastic high end authentication scenarios. We’ve talked about cross-domain security and administrative control. We’ve talked about generating UDC files using InfoPath and consuming them again in the designer. Now let’s drill into the structure of the file itself.

    UDC V2 is an XML format, and like any good XML format, there is a schema and a namespace associated with it. I’ll give you the full schema at the end of this post.

    A handy tip: copy the schema into notepad and save it with an xsd extension, then follow the steps outlined in Aaron Stebner’s blog here: http://blogs.msdn.com/astebner/archive/2005/12/07/501466.aspx to add the xsd file to Visual Studio’s intellisense cache. Once that’s in place, Visual Studio will help you generate your UDC files!


    Basic Structure of the File

    Every UDC file you create will have the structure below, so copy it to notepad and use it as the basis for all your files. This is the infrastructure – the metadata that describes the connection and allows external components such as SharePoint and InfoPath to understand what’s inside.

    <?MicrosoftWindowsSharePointServices ContentTypeID=”0x010100B4CBD48E029A4ad8B62CB0E41868F2B0”?>
    <udc:DataSource MajorVersion="2" MinorVersion="0" xmlns:udc="http://schemas.microsoft.com/office/infopath/2006/udc">
      <udc:Name/>
      <udc:Description/>
      <udc:Type MajorVersion="2" MinorVersion="0" Type=""/>
      <udc:ConnectionInfo Purpose="" AltDataSource=””/>
    </udc:DataSource>

    The file begins with a processing instruction specifying a Content Type Id. This is necessary to associate the file with the UDC content type on a Microsoft Office SharePoint 2007 server. Having the content type identified allows the Name, Title, Description, Type, and Purpose fields to be promoted into columns in the data connection library so that the InfoPath designer can see the file.

    By the way: there’s a known issue on Windows Vista where the title property doesn’t get promoted when using the Convert function in the InfoPath designer. To work around this issue, save the file to your local disk, and then re-upload the file to the library using the SharePoint library upload function.

    The root node is called DataSource, and it specifies the UDC version of 2.0, as well as the udc V2 namespace. The Name and Description fields are promoted into SharePoint columns, and they show up in the InfoPath designer when browsing to the file in the data connection wizard. So, while these fields are not strictly required, you should use them to provide useful information about what the data connection is about, and maybe even contact information for the owner of the data source.

    Type (specifically, the Type attribute on the Type element) and Purpose are both required, and very easy to fill once you know the possible values:

    DataSource/Type/@Type:

    Value

    Use for

    SharePointList

    SharePoint list query connection

    SharePointLibrary

    SharePoint Library submit connection

    Database

    Database query connection

    XmlQuery

    Xml file query connection

    XmlSubmit

    HTTP Post submit connection

    WebService

    Web service submit or query connection


    DataSource/ConnectionInfo/@Purpose:

    Value

    Use for

    ReadOnly

    All query connections

    WriteOnly

    All submit connections

    ReadWrite

    Web service only, when both query and submit methods are specified and they reference the same WSDL

    The AltDataSource attribute specifies a second UDC file in the same library. When specified, InfoPath will use the original file, and Forms Services will use the file specified in the attribute. The attribute's value should be the filename of the alternate UDC file. Naturally, the two files should specify equivalent connections - specifically, the connections have to have the same Type and Purpose, and they have to return the same data, or data in the same format.


    The ConnectionInfo Element

    The meat of the connection information is here, and each type of data connection requires specific elements. So, the contents of this element will change depending on the Type and Purpose attributes.

    Let’s run ‘em down, shall we? I’m confident that you can learn by example, so I’m not going to do a lot of explaining here. As I noted in a previous post, we’re working on a schema reference that will fill in the details.

    1. Web Service
    This example is for a query connection. For a submit connection, the Purpose would be WriteOnly, and the ServiceUrl and SoapAction would be contained within an UpdateCommand element rather than SelectCommand.

    Web service is the only connection type that can have both a SelectCommand and an UpdateCommand in the same file. The two operations need to share the same WSDL, and the Purpose in that case is ReadWrite.

    <udc:ConnectionInfo Purpose=”ReadOnly”>
       <udc:WsdlUrl>
       http://www.someserver.com/service/service1.asmx?wsdl
     </udc:WsdlUrl>
     <udc:SelectCommand>
      <udc:ServiceUrl>
       http://www.someservice.com/service/service1.asmx
      </udc:ServiceUrl>
      <udc:SoapAction>
       http://www.someservice.com/service/SomeOperation
      </udc:SoapAction>
     </udc:SelectCommand>
    </udc:ConnectionInfo>

    2. Database
    A database connection is always marked as ReadOnly. InfoPath determines at design time whether submit can be enabled for the connection.

    <udc:ConnectionInfo Purpose=”ReadOnly”>
     <udc:SelectCommand>
      <udc:ConnectionString>
    Provider=Microsoft.ACE.OLEDB.12.0;User ID=Admin;Data Source=C:\temp\Database1.accdb;Mode=Share Deny None;Jet OLEDB:System database=&quot;&quot;;Jet OLEDB:Registry Path=&quot;&quot;;Jet OLEDB:Database Password=&quot;&quot;;Jet OLEDB:Engine Type=6;Jet OLEDB:Database Locking Mode=1;Jet OLEDB:Global Partial Bulk Ops=2;Jet OLEDB:Global Bulk Transactions=1;Jet OLEDB:New Database Password=&quot;&quot;;Jet OLEDB:Create System Database=False;Jet OLEDB:Encrypt Database=False;Jet OLEDB:Don't Copy Locale on Compact=False;Jet OLEDB:Compact Without Replica Repair=False;Jet OLEDB:SFP=False;Jet OLEDB:Support Complex Data=False;
      </udc:ConnectionString>
      <udc:Query>SELECT * FROM Table1</udc:Query>
     </udc:SelectCommand>
    </udc:ConnectionInfo>

    3. SharePoint list query
    <udc:ConnectionInfo Purpose=”ReadOnly”>
     <udc:SelectCommand>
      <udc:ListId>{8fe80d4c-2203-4fa3-a411-f57f2e8be459}</udc:ListId>
      <udc:WebUrl>http://someserver/sites/somesite</udc:WebUrl>
     </udc:SelectCommand>
    </udc:ConnectionInfo>

    4. SharePoint library submit
    The FolderName element specifies the default folder name that is used to prepopulate the data connection wizard.  Form designers will still need to specify the file name, as it is stored in the form template.

    <udc:ConnectionInfo Purpose=”WriteOnly”>
     <udc:UpdateCommand>
      <udc:FileName>ExpenseReport.xml<udc:FileName>
      <udc:FolderName AllowOverwrite=”true”>
       http://someserver/sites/somesite/somelibrary
      </udc:FolderName>
     </udc:UpdateCommand>
    </udc:ConnectionInfo>

    5. XML file query
    <udc:ConnectionInfo Purpose=”ReadOnly”>
     <udc:SelectCommand>
      <udc:Query>http://someserver/somefile.aspx</udc:Query>
     </udc:SelectCommand>
    </udc:ConnectionInfo>

    6. HTTP Post
    <udc:ConnectionInfo Purpose=”WriteOnly”>
     <udc:UpdateCommand>
      <udc:Submit>http://someserver/somefile.aspx</udc:Submit>
     </udc:UpdateCommand>
    </udc:ConnectionInfo>


    Authentication

    I’ve described the contents of the Authentication element in previous blog posts, so I won’t go into a detailed explanation. Two things are important here:
    1. The Authentication element must be the last child of ConnectionInfo
    2. If both SSO and UseExplicit are specified, Forms Services will use the credentials specified in the SSO element and will ignore the UseExplicit element.
    This section is used only for forms running in the browser – InfoPath always ignores the authentication element.

    <udc:Authentication>
     <udc:UseExplicit CredentialType="">
      <udc:UserId/>
      <udc:Password/>
     </udc:UseExplicit>
     <udc:SSO AppId="" CredentialType=""/>
    </udc:Authentication>


    The Universal Data Connection 2.0 schema

    Download the XSD from here.

    - Nick Dallett
    Program Manager

  • Microsoft InfoPath 2010

    How to Enqueue Submits While Offline

    • 12 Comments

    How to Enqueue Submits While Offline

    Applies to: Microsoft Office InfoPath 2003 SP1

    Scenario:

    User fills out forms for a particular form template while the laptop is disconnected from the network.  Upon reconnection, seamlessly syncrhonize the offline forms to a Windows SharePoint Services form library. 

    Solution:

    Using OnSubmitRequest, you can have the code save to the offline folder depending on if we're offline or not, as in the following code, which is written in C# using our Visual Studio .NET Toolkit.  You will also need to add a project reference to System.Xml.dll and the using System.XML; directive to your form code.

      public void OnSubmitRequest(DocReturnEvent e)

      {
     
        if (thisApplication.MachineOnlineState == XdMachineOnlineState.Online)
        {
         // submit to Sharepoint using DAVAdapter
         (thisXDocument.DataAdapters["Submit to Sharepoint"] as DAVAdapter).Submit();
        }
        else
        {
         // We are offline or working offline.
         XmlDocument oDOM = new XmlDocument();
         Microsoft.Office.Interop.InfoPath.SemiTrust.IXMLDOMDocument oWrappedDOM = thisXDocument.DOM;
     
         oDOM.PreserveWhitespace = true;
         oDOM.LoadXml(oWrappedDOM.xml);
         oDOM.Save("C:\\Submit\\Form_"
                + DateTime.Now.ToString("yyyy.MM.dd_HH.mm.ss.ff") + ".xml");
        }
      
        e.ReturnStatus = true;
      }
     

    Then, if you've been offline for a while and a number of files have built up, you can run the following jscript to invoke InfoPath externally and force a submit looping through the files, as below:

     
    var oFileSys = new ActiveXObject("Scripting.FileSystemObject");
    var oSubmitDir = oFileSys.GetFolder("C:\\Submit");
    var oFilesInSubmitDir = new Enumerator(oSubmitDir.Files);
     
    var oApp = new ActiveXObject("InfoPath.Application");
     
    var fso = new ActiveXObject("Scripting.FileSystemObject");
     
    for (; !oFilesInSubmitDir.atEnd(); oFilesInSubmitDir.moveNext())
    {
     var strFileName = oFilesInSubmitDir.item().Name.toLowerCase();
     
     if (strFileName.length >= 4
         && strFileName.lastIndexOf(".xml") == (strFileName.length - 4))
     {
      try
      {
       var oDoc = oApp.XDocuments.Open(oFilesInSubmitDir.item().Path);
       oDoc.Submit();
       oDoc.View.Window.Close();
       
       var f = fso.GetFile(oFilesInSubmitDir.item().Path);
       f.Delete();
     
      }
      catch (e)
      {
       WScript.echo("ERROR: " + e.description);
      }
     }
    }
    oApp.Quit();
     
     
  • 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

    Programmatic Selection in InfoPath

    • 11 Comments

    InfoPath supports two methods on the View OM object - "SelectText" for data entry controls and "SelectNodes" for structural controls - in order to enable programmatic selection.

    Data entry controls that can be programmatically selected (using View.SelectText):

    • Text Box
    • Rich Text Box
    • Date Picker

    Structural controls that can be programmatically selected (using View.SelectNodes):

    • Optional Section
    • Choice Section
    • Repeating Section (items)
    • Repeating Table (rows)
    • Repeating Recursive Section (items)
    • Bulleted, Numbered & Plain List
    • File Attachment

    Programmatically setting focus to these controls is not supported:

    • Drop-Down List Box
    • List Box
    • Check Box
    • Option Button
    • Button
    • Picture (Linked or Included)
    • Ink Picture
    • Hyperlink
    • Expression Box / Vertical Label
    • ActiveX
    • Section

    Examples:

    Steps to select rows in a repeating table using SelectNodes:

    In order to set selection extending the 1st two rows of a repeating table you can do the following steps:

    1. Insert a "repeating table" from the controls task pane

    2. Insert a "button" from the controls task pane

    3. Double click on the button control to bring up Button Properties

    4. Click on the "Edit Form Code" button

    [you may be asked to install Microsoft Script Editor if you don't already have it installed]

    5. This should bring up script.js file in Microsoft Script Editor with a function such as

    function CTRL5_5::OnClick(eventObj)

    {

    // Write your code here

    }

    6. Insert the following code inside the above function

    var nodeSelStart = XDocument.DOM.selectSingleNode("/my:myFields/my:group1/my:group2[1]")

    var nodeSelEnd = XDocument.DOM.selectSingleNode("/my:myFields/my:group1/my:group2[2]")

    XDocument.View.SelectNodes(nodeSelStart, nodeSelEnd)

    [This assumes that the repeating table is bound to my:group2. You can figure the XPath by looking at the Data Source task pane after selecting the appropriate repeating table.]

    7. Now you should be able to preview the form and verify that clicking on the button causes the expected selection. Please note that you have to have at least two rows in the table in order to select the first two rows. Otherwise you will see an error.

    Steps to select text in a text box using SelectText:

    In order to select text in a text box you can do the following steps:

    1. Insert a "text box" from the controls task pane

    2. Insert a "button" from the controls task pane

    3. Double click on the button control to bring up Button Properties

    4. Click on the "Edit Form Code" button

    [you may be asked to install Microsoft Script Editor if you don't already have it installed]

    5. This should bring up script.js file in Microsoft Script Editor with a function such as

    function CTRL2_5::OnClick(eventObj)

    {

    // Write your code here

    }

    6. Insert the following code inside the above function

    var nodeSelText = XDocument.DOM.selectSingleNode("/my:myFields/my:field1")

    XDocument.View.SelectText(nodeSelText)

    [This assumes that the text box is bound to my:field1. You can figure the XPath by looking at the Data Source task pane after selecting the appropriate text box.]

    7. Now you should be able to preview the form and verify that clicking on the button causes the expected selection.

  • Microsoft InfoPath 2010

    Where do UDC files come from?

    • 11 Comments
    Where do UDC files come from? - I knew you’d ask. (For those of you who are wondering what a UDC file is, you should go read my post entitled "Making data connections work in browser forms.")
     
    There are a couple of ways to go about it. UDC files are just xml files with a specific namespace and schema, so once you have a few examples you can probably get around handily with notepad and cut and paste. However, we’ve made it easier than that with the new Convert functionality on the Manage Data Connections dialog. (For those intrepid souls who prefer the notepad route, a schema reference is being prepared for publication.)
     
    If you start out by designing your data connection the way you normally would, you can then use the Convert button to change the connection from settings in the form template to settings in a data connection file. (In fact, you can open any existing form template in InfoPath 2007 and convert existing data connections the same way.)
     
    To start with, make sure you have write permissions to a data connection library (henceforth "DCL") on the Microsoft Office SharePoint 2007 server you’re going to publish your form to. Then, using InfoPath 2007 Beta 2 or later, create your data connection or open a form template with an existing data connection. Make sure the connection is to a source supported by UDC. (E-mail connections, connections to a Microsoft Access database, or connections to an XML file in the form template cannot be converted to UDC connections.)
     
    Here’s the data connections dialog showing a few connections I threw together (you can get to this dialog off of the "tools" menu in InfoPath design mode):
     
     
    Click the Convert button and specify the path to your data connection library. If you click "Browse...", InfoPath will suggest a filename based on the name you gave the data connection when it was created.
     
     
    If you choose a data connection file that already exists, InfoPath will use the settings in the file you chose - don’t expect it to overwrite the original file with new settings. This could have unexpected results if the file that’s already in the library is a different connection type or returns data that does not conform to the schema your form template expects.
     
    For most cases, you want to leave the default connection link option. Choosing "centrally managed connection library" will cause InfoPath and Forms Services to look for the UDC file in the "Manage data connection files" library in SharePoint central admin. This is fine, but it means that you need to copy the file from the DCL where you created it to that location before you can use it. This presumes you have access to SharePoint Central Admin. See my last blog post entitled "Making data connections work in browser forms" for more information on this option.
     
    Once you click "OK" on this dialog, your UDC file will be created and saved to the location you specified, and the connection in the form template will be modified to retrieve settings from the UDC file rather than from the form template.
     
    NOTE: There’s a known issue in the Beta 2 release where you will see an "invalid URL" dialog at this point. This is benign and is no longer seen in the technical refresh.
     
    You now have a UDC file in your DCL, but you’re not quite done. By default, a DCL will require content approval before anyone other than the file’s owner can use the UDC file you uploaded. Unless the content approval requirement has been removed, a site administrator or someone else with the content approval right will need to set the file’s status to "approved."
     
    Adding Authentication
    InfoPath does not automatically configure server-only authentication options for you. However, when creating a UDC file, InfoPath automatically creates an authentication block within the UDC file that is preconfigured to use Office Single Sign-on. In order to use this authentication option, you’ll need to uncomment the authentication block within the file and add both the SSO application ID and the CredentialType. Most of the time, you’ll want to use the SSO credential to log onto Windows, for which you’ll need to specify "NTLM" as the CredentialType. The full list of possible credential types is as follows:
     
    Value
    Description
    Sql
    Credentials will be embedded in a database connection string for authentication against a SQL server.
    NTLM
    Credentials will be used to impersonate a Windows user
    Kerberos
    Credentials will be used to impersonate a Windows user using Kerberos
    CD
    The username will be used to impersonate a Windows user using Constrained delegation
    Basic
    Credentials will be used to perform HTTP Basic authentication
    Digest
    Credentials will be used to perform HTTP Digest authentication
     
    Reusing existing UDC files
    Once you’ve created your UDC file, you may want to use the same connection for other form templates. Among other things, this has the benefit of sharing settings for multiple forms in a common location. Changing the settings in the UDC file will cause all of the related forms to pick up the changes the next time they are used.
     
    There are several places in InfoPath where we expose the ability to re-use data connection settings exposed as UDC files in a data connection library. Here are a few examples:
     
     
     
     
    All of these entry points lead to this dialog:
     
     
    When you specify one or more SharePoint sites to search, this dialog allows you to browse available UDC files containing in DCLs on those sites. Based on the context, this dialog is filtered to show only applicable connections (for example, if you start from the "Design a form" dialog, this dialog will only show Web service and database connections).
     
    Once you’ve specified the UDC file to use, you may need to specify some properties for the connection that are not contained in the file (for example, for a SharePoint list connection, you’ll be asked to specify which columns to include in the data source), but otherwise, you’re done.
     
    - Nick Dallett
    Program Manager
  • Microsoft InfoPath 2010

    Use Visual Studio to create InfoPath forms… without code

    • 11 Comments
    Although the primary purpose of Visual Studio 2005 Tools for Office (InfoPath 2007 Support) is to add C# and Visual Basic code to your InfoPath form template, you can still take advantage of hosting InfoPath inside Visual Studio to design forms that don't have any code.
     
    When you create a new InfoPath form template project in Visual Studio, by default, it will be created with code enabled.  To obtain a form without code, you need to explicitly remove the code from the form by using the remove code button in the programming tab of the form options dialog.
     
     
    After clicking on this button, you might be confused to see that the code file is still present in the project.  Don’t worry about this.  When you build the project, the hosted designer will not add the output assemblies to the form template.
     
    How it works
    After a new project is created, the “enabled” attribute of the “managedCode” element in the manifest.xsf defaults to “yes”.  Clicking the remove code button sets this attribute to “no”.
     
    <xsf2:managedCode … enabled="no"></xsf2:managedCode>
     
    This attribute is set back to “yes” when you insert an event handler using the hosted InfoPath designer.
     
    After a success build, the output assemblies will only be included with the form template when this attribute is set to yes.
     
    - Gary
    Software Development Engineer
Page 2 of 12 (298 items) 12345»