Microsoft InfoPath 2010
The official blog of the Microsoft InfoPath team

  • Microsoft InfoPath 2010

    Tabs

    • 10 Comments
    In my last post I covered how to make Wizard-like forms. This time I want to talk about another common practice for organizing all the fields in a form: grouping each set of fields onto a "tab" so the user can switch between the sets in whichever order they wish. While wizards are useful in forms with a clear flow, tabs are useful when the same form will be updated multiple times in different places.
     
    In Windows XP, tabs look like this (this screenshot's taken from InfoPath's View Properties dialog):
     
     
    InfoPath doesn't have a built-in Tab Control, but it's easy enough to build one using tables, buttons, and views, so let's do it!
     
    The basic idea
    Here's what to build:
    • Views for the contents of each tab
    • Table with shading to give the visual effect of tabs
    • Buttons for each tab with a rule that switches the view
     
    For example:
     
     
    Then when the user clicks "Details" they switch views to see this:
     
     
    How To, with tricks along the way
    1. Create all of your views (from the Views task pane)
      • Select the same color scheme for each view (use the Color Schemes task pane)
      • Use Background Color on the Format menu to make the background of each view the second color for the current color scheme (the second-darkest color at the top of the color picker)
    2. Insert a layout table (on the Insert menu, click Table)
      • Make it two rows high. The first row will be for the buttons, the second will be for the tab content.
      • Split the first row to make a cell for each view, plus one extra cell to take the remaining horizontal space.
    3. Insert a button into each cell (from the Controls task pane)
      • Add a rule to each button to switch to the corresponding view. Do this even for the current view's button.
      • Make the current "active" button Bold, so it stands out.
    4. Use borders and shading (on the Format menu)
      • Select all the buttons at once (hold down the Control key and click each one), then remove all borders and shading from the buttons (they're invisible except for their label!).
      • Select the entire table, then add borders inside and out using the first color in the color scheme (the darkest color).
      • Select the non-active cells and set their shading to the third lightest color of the color scheme.
      • Select the active cell and the content cell, and set their shading to white.
      • Select the active cell and remove the bottom border so it becomes connected to the content cell.
      • Select the right-most "extra" cell and remove the top and right border
    5. Copy the table to each view
      • Update the borders and shading to change the "active" cell for each view
      • Put all your fields for each tab in its content cell
     
    Getting fancy
    If the tabs above aren't pretty enough for your form, add some images inside a few more table cells around each button to provide rounded corners and other visual effects. It's more work, and requires some image editing, but with a little elbow grease you could get something as schmancy as this:
     
     
     
    Enjoy,
    Ned
  • 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

    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

    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

    Modifying InfoPath manifest.xsf file from script (1/5)

    • 7 Comments

    In this five part series we’ll show the reader how to programmatically manipulate InfoPath form templates.

    Part 1 of 5: The story

    There are many scenarios where you might need to modify an InfoPath form template (.XSN) after it’s already in use. Let’s say the URL of your Web Service changes.

    With InfoPath 2003 you need to change the URL manually:

    1. Open the form in design-mode (e.g. Right-click on the XSN and select Design).
    2. Extract files of the form template (XSN) into the temporary directory using File | Extract Form Files…, then close InfoPath
    3. Find manifest.xsf in the directory and open it in Notepad (or some other text editor).
    4. Find and replace all instances of existing URL with the new one.
    5. Save the modified manifest.xsf.
    6. Right-click the modified manifest.xsf, select Design, and finally use File | Save As... to save the form template as a XSN file.

    With InfoPath 2003 with Service Pack 1 (SP1), just open the form in Design mode, go to Tools menu, select Change Data Source, and in the wizard locate the new URL.

    But this isn’t (just) a sneaky way to convince you to download the SP1 Preview.

    What if you are responsible for maintaining hundreds of InfoPath forms which rely on the Web service? Even with SP1 this would be a lot of work. It would be nice to do it programmatically.

    The good news is that this is possible, even without SP1. The InfoPath XSN format is really a CAB file, and the files that make up the template are XML files which can easily be modified programmatically. You can pack/unpack a CAB file with help of extract.exe and makecab.exe utilities that are accessible for Windows users. Now the only things you need is to implement a small utility using script or managed code that will do the described above sequence automatically. Inside of the utility you should do the following:

    1. Unpack XSN file using extract.exe utility to the local temporary directory.
    2. Find manifest.xsf file and open it as a plain XML file.
    3. Replace the corresponding URLs using the XML DOM.
    4. Save the modified manifest.xsf.
    5. Pack all files into the XSN using makecab.exe utility.
    6. Clean up your temporary directory.

    If you write a wrapper around this process to enumerate all the form templates, your hundreds of forms will be updated just in a few minutes.

    Using this approach you can change not only URLs but SQL connection strings, files names, etc. If you want to learn more about the XSN format and the files that make it up, check out the InfoPath 2003 SDK. As always, be careful – save backup copies, test your code, test the templates before and after, etc.

    At the end of this discussion, the patient reader expects a good sample that supports the idea explained above. And we will definitely do it in the following parts 2-5 of the series.

    To be continued.

     

  • Microsoft InfoPath 2010

    Digital Signature Support in InfoPath 2010

    • 32 Comments

    Hi, this is Gergely Kota, a developer on the InfoPath team. Digitally signing data when filling out a form makes the data tamper-proof, authenticates its signer, and is a key component of trusting form data. In this post, I’d like to share the improvements that have been made to digital signature support in InfoPath 2010. InfoPath 2010 allows you to make more secure signatures with improved cryptographic algorithms and makes long-term storage of signed forms more robust by supporting 3rd-party time stamping. This post describes these improvements and shows you how to strengthen any signature created in InfoPath 2010 Filler. For a primer on digital signatures, read an Introduction to Digital Signatures in InfoPath.

    Note - Data signing should not be confused with code/template signing, which remains unchanged.

    Signature Security

    Digital signatures are only as secure as the cryptographic algorithms they use to ensure signed data hasn't been tampered with. InfoPath 2007 and 2003 support RSA or DSA for signing and SHA1 for hashing. Though a combination of RSA and SHA1 is considered secure for now, algorithms become exposed to attack over time and are eventually rendered obsolete. If either the signing or hashing algorithm is cracked or compromised, the integrity of the signature can no longer be verified. InfoPath 2010 enables you to address these concerns by supporting newer, more secure, ECC signing and SHA-2 family of hashing algorithms.

    Signing with a particular algorithm

    When creating a signature, a user may sign with one of potentially many certificates installed on their machine. The signature algorithm is determined by the chosen digital certificate. To determine the algorithm:

    1. Begin the signing process Clickhere to sign
    2. Change your signing certificate ChangeCert
    3. Highlight desired certificate and click View Certificate 
    4. Look at the Public key field under the Details tab Viewcert

    Administrator Settings: Hashing algorithms

    By default, InfoPath 2010 hashes signature data using SHA1. This is done to maintain backwards compatibility with InfoPath 2007 and InfoPath 2003. InfoPath 2010 also supports the SHA2 family of hashing algorithms. If backwards compatibility is not a concern, an administrator can set the hashing algorithm in the registry.

    HKCU\Software\Microsoft\Office\14.0\Common\Signatures\SignatureHashAlg
    Value Description
    “sha1” (default) SHA1 hash algorithm
    “sha256” SHA256 hash algorithm
    “sha384” SHA384 hash algorithm
    “sha512” SHA512 hash algorithm

    Signing and Hashing Algorithm Compatibility

    The following table shows which versions of InfoPath are able to sign and/or verify signatures with the given combinations of signing and hashing algorithms:

    DigSigAlgoSupportMatrix

    Long-term Signature Support

    Certificates guarantee the identity of the signer, but expire after a while. This is to reduce the time attackers have to deduce an associated private key (which would allow them to impersonate a signer) and to limit the shelf-life of a compromised certificate. Certificates may also be revoked if they are taken out of commission before their expiration date. If the certificate used to create a signature is now expired or revoked, we should be cautious of whether the signed data is valid or not unless we can verify that the data was signed while the certificate was still valid. This poses an impending problem because all certificates expire (often in a year!), and we would require a trusted timestamp to confirm when the signature was created. Without such a trusted timestamp, InfoPath will show the signature as invalid, with the reason in the Signature Details dialog:

    InvalidSignature

    sigdetails_full_expired

    This can be especially problematic, for example, for a printed copy of the form which would show an invalid signature, and there would be no way to verify why. InfoPath 2010 adds support for XML Advanced Electronic Signature (XAdES), which allows for adding a trusted timestamp that can be used to resolve when the signature was added relative to the signing certificate's expiration and/or revocation time (see a detailed discussion of XAdES in Microsoft Office for details and level options). If such a timestamp exists and confirms that the signature was made when the signing certificate was valid, InfoPath can safely conclude that the signature is entirely valid:

    ValidSignature

    sigdetails_full_good

    Server Support

    InfoPath 2010 Forms Services signs forms using RSA and SHA1, and is able to verify any signature created in the InfoPath 2010 client. XAdES is a client-only feature.

    Final Word

    By leveraging the security improvements and time-stamping support described in this post, you are increasing the strength and longevity of your signatures. Happy signing!

    Gergely, InfoPath dev

  • Microsoft InfoPath 2010

    Tips and Tricks for Making Form Filling Faster

    • 11 Comments

    The less time it takes to fill out your forms, the more time your users can spend on other tasks. Also, odds go up that form fillers will complete forms when they take less time to fill out. This blog post will give you a few tips for speeding up form filling and improving accuracy so your forms are completed faster.

    In this post we will cover

    1. Using defaults
    2. Using contextual defaults for bringing in the current day and user

    Setting up default values

    For questions where one answer is much more common than others, it can be useful to set up default starting values.  The value you choose will appear when the form is opened, but the form filler is still able to change it.

    You can set default values by selecting the control and clicking on the properties pane, and then choosing “Default Value”.

    Let’s say I had a sailboat rental form, and when boats are rented employees need to fill out who checked out the boat, when it was checked out, what type of boat it was, the boat #, and customer information.

     

    Because the sailboat rental place has mostly 24 foot boats, we can set the default Size to be 24 feet.   Now employees won’t have to fill this field out most of the time. To set a default value, select the control (the boat size dropdown), choose the Properties tab, and select Default Value. Type the default value in the box provided. You can set the defaults for text boxes, combo boxes, check boxes and many other controls this way.

     

    Contextual values

    When a boat is being checked out, we need to log the person who checked it out and the date. Most commonly, boats are checked out for today’s date. We want to set the default value of “checked out by” date to be today’s date.

    To set the checked out date to today, select the date control, go to the properties tab, and choose “default value”. Choose the function builder at the right .

    Choose the “Insert Function” button and pick the now() function from the Date and Time Category. Click “OK” until you return to the form.  Now, when users open the form today’s date will be automatically filled in.
    When using today() or now(), the form will update the date when you re-open it unless you uncheck the “Refresh value when formula is recalculated”. Make sure to uncheck this box.

     

    today() vs now()

    today() and now() can both be used to set the default value of a date picker. However, the type of form you have can affect which one you use.

         - Use today() when you have a date-only field.

         - Use now() when your field requires a date and time.

    In general, when using a SharePoint list form, use now(). When using a form library or filler-only form, use today(), unless you have changed the data format of the date field to date and time.

     

    Setting up the default user

    Setting the default value of the Person/Group picker is done through the fields task pane. Show the fields task pane by selecting “Show Fields” on the data tab and expand your Person/Group picker field (in my case, outBy). Click “Show advanced view” to see the detailed view. Right-click on the AccountId and choose properties.

     

    Under default value, choose the function builder  and type userName().
    Again, make sure that “Refresh value when formula is recalculated” is unchecked, so that this rule is only run once and not every time the form is opened. Click Ok.

     

    Repeat this process with the DisplayName (optional) to get the best experience. Now the people picker will default to the person who opens the form.
    When we load the form, the date, boat type, and checked out by fields are already filled out. With half of the fields completed, it will take employees less time to check out boats.

     

    Hopefully, these tips will help you set good defaults and your users will spend less time filling out forms!

    Kate Everitt

  • Microsoft InfoPath 2010

    Filtering using the current() function

    • 7 Comments

    For some reason, the last week has been full of questions where the answer boils down to “use the current() function”.

     

    The current() function is an XSLT XPath function which returns the current node. You can read the full W3C Recommendation if you want the nitty-gritty details, but if you wanted to read the specification you’d probably have done that instead of reading this blog.

     

    You need this function in InfoPath if you’re trying to refer to data across repeating contexts. Some examples:

     

    ·        Within a repeating table row, you want to build cascading drop-downs

    ·        You want select or filter data from another context by data in the current row

    ·        You want one row in a repeating table to refer to data in the previous row

     

    These all come down to the same need – within an XPath expression, how do you say “this one”? That’s what current() is for. Whenever an XPath is being evaluated in a repeating context, current() returns the... well... current item.

     

    Scenario: Within a repeating table row, you want to build cascading drop-downs

     

    If your schema looked like this:

    • Root
      • Data
        • States
          • State (repeating)
        • Cities
          • City (repeating)
            • @state
      • Selection
        • SelectedState
        • SelectedCity

    And you wanted to have drop-downs bound to State and City which select from the appropriate list, you can build cascading drop-downs using filters. You’d end up with a filter on the list-box items that looked like this:

    /Root/Data/Cities/City[ @state = ../../../Selection/SelectedState ]

    (If you used the interactive condition builder, simply select “The expression” in the first drop-down to show the expression as an XPath.)

     

    Now let’s change the schema a bit to put the selections into a table – maybe with notes about each selection:

    • Root
      • Data
        • States
          • State (repeating)
        • Cities
          • City (repeating)
            • @state
      • Table
        • Row (repeating)
          • Selection
            • SelectedState
            • SelectedCity
          • Notes

    If you try this in a Repeating Table row (/Root/Table/Row) you’ll find that it doesn’t work as expected:

    /Root/Data/Cities/City[ @state = ../../../Table/Row/Selection/SelectedState ]

    The XPath /Root/Table/Row/Selection/SelectedState - which for practical purposes here is the same as ../../../Table/Row/Selection/SelectedState - actually returns all of the states in all of the rows, and in XPath the predicate a[b = c] returns all a's where any b equals any c. If you parse that explanation carefully, you'll see that you get far more results than you were expecting. In this example, you get a list of all cities from any of the selected states! What you need is a way to say “just the current Selection/SelectedState”.

     

    The fix then is to modify the XPath to read:

    /Root/Data/Cities/City[ @state = current()/Selection/SelectedState ]

    Scenario: You want select or filter data from another context by data in the current row

     

    This is actually just a simpler version of the previous case.

     

    Whereas a normal list of cities might be:

    /Root/Data/Cities/City

    And a static filtered list would be:

    /Root/Data/Cities/City[ @state = "WA" ]

    A dynamic filtered list would be:

    /Root/Data/Cities/City[ @state = /Root/Selection/SelectedState ]

    To pull the selection from the current table row the final XPath in the predicate needs to be made relative to the current row:

    /Root/Data/Cities/City[ @state = current()/Selection/SelectedState ]

    Scenario: You want one row in a repeating table to refer to data in the previous row

     

    This one is fun – let’s say you had a quiz (a list of true/false questions) and you wanted to disable controls in the current question until the previous question was answered. You’d use Conditional Formatting to disable the controls.

     

    If your schema looked something like this:

    • Root
      • Questions
        • Question (repeating)
          • QuestionText
          • AnswerText

    Then within each row you can use this expression to disable the controls:

    current()/preceding-sibling::Question/AnswerText = ""

    To enter this in the condition builder, select “The expression” in the first drop-down.

     

    (Note: In the example XPaths the namespace prefixes have been left out. Since InfoPath is extremely standards compliant - that is, nitpicky - when it comes to correct namespace usage you’ll need to include these.)

     

    [Edited 2004-09-13 @ 10:37 AM - one of the XPaths was incorrect]

  • Microsoft InfoPath 2010

    Compatibility between InfoPath 2003, 2007, and Forms Server

    • 20 Comments
    Ask and ye shall receive. Here's a short summary of how to think about compatibility when designing form templates in InfoPath 2007.
     
    1. InfoPath 2003 forms will work as-is in 2007
    Your existing forms should work. Period. If you find something that doesn't work, please leave a comment so we can get that bug fixed.
     
    2. InfoPath 2007 can save as InfoPath 2003 forms
    Most features actually work in 2003, we just made 2007 the default to be forward-looking. If you plan to design all your forms to be compatible with InfoPath 2003, you can change the default in the Options dialog off the Tools menu:
     
     
    You can also save individual forms as the file type 2003:
     
     
    When you save a file for InfoPath 2003, we automatically check this box in Form Options:
     
     
    So that the design checker will show you compatibility issues:
     
     
    You can get more info on each issue by clicking it, and then fix it appropriately. Forms with "Messages" will successfully save for 2003, but forms with "Errors" cannot be saved for 2003 until all the errors have been fixed.
     
    3. InfoPath 2003 forms can also work on the Forms Server
    If you have the InfoPath 2003 client rolled out to your desktops, and also have the Forms Server, then you can create forms that will open in the browser for people without any copy of InfoPath, but open in the client for those with InfoPath 2003 (and 2007, see point 1 above).
     
    First, follow the steps above to save your form to be compatible with InfoPath 2003. Then check this box in Form Options to make the form browser-compatible:
     
     
    Now you can fix any remaining issues shown by the design checker, and publish the form to Forms Server the same as any other browser-enabled form.
     
    Hope that helps,
    ned
  • Microsoft InfoPath 2010

    Calculating Elapsed Time…without code!

    • 59 Comments

    UPDATE: Due to the number of requests for adding more columns to this sample, I have re-designed the sample. If I have time in the future I will update the steps to create this new design; however, for now you can download the updated design here to see the changes. The expressions are very similar to the original design but I now use a repeating table for entering "break" times so you can have as many as you need! 

    How many times have you needed to calculate the difference between time entries…only to find out the only way to accomplish this was to write custom code? Well no more! If your time entries will not cross days, then you can use a number of functions and expressions to parse the entered times and calculate the difference. In the sample below we will show you the types of expressions that are needed for these calculations to work – I would encourage you to first create this sample as documented as the expressions are not for the “faint of heart!” :-)

    Note: if you choose to copy/paste the expressions for this sample, you will use the Default Value box for each field and after clicking the “fx” button, be sure to also enable the “Exit XPath” option before you paste these expressions.

    If you'd like to take a look at the completed version of this sample, here is the .xsn file - make sure to save it locally before opening it.

    Create the data structure

    1) Add a Repeating Table to your View with 4 columns

    2) Rename the fields and specify the data types as follows, from left to right:

    Name Data Type
    myDate Date (date), Format: *3/14/2001
    StartTime Time (time), Format: *9:46 AM
    EndTime Time (time), Format: *9:46 AM
    ActualTime Text (string)

    3) Change the first field in the table to a Date Picker control

     
    4)  Add 2 additional fields to the Repeating Group node (these will not be shown on the view – they are used to aid in the calculations)

    Name Data Type
    ElapsedTime Text (string)
    TotalMinutes Decimal (double)


    5) Add one final field to calculate the sum of all the entries – this should be added to the myFields node…not the Repeating node

    Name Data Type
    TotalTime Text (string)

    Your final data structure should look like this:

    And your form could look like this:

     

    Adding the expressions…let the fun begin!

    The first step is to convert the StartTime and EndTime values to minutes – this makes the calculation a bit easier. In addition, we don’t want to execute this calculation if either the StartTime or EndTime is blank. So to perform this “conditional statement”, we’ll use the logic explained in this blog entry.

    Step 1: Parse the Hours and Minutes

    1) We first need to parse the “hours” and convert this to minutes by multiplying that value by 60. To do this we will use the “substring-before” function to look for the colon (“:”) in the time field and extract the value before the colon:

    substring-before(../my:EndTime, ":") * 60)
    substring-before(../my:StartTime, ":") * 60

    2) To each of these values, we need to add the minutes that were entered after the colon. Now when time values are stored in the underlying XML, they are stored in this manner: hh:mm:ss. So to pull just the minutes entered, we will use a combination of the “substring-before” and “substring-after” functions since we need the value entered “after” the first colon and “before” the last colon:

    substring-before(substring-after(../my:EndTime, ":"), ":")
    substring-before(substring-after(../my:StartTime, ":"), ":")

    3) Now, at this point we could place each of these expressions together to get the total hours and minutes for each time entry:

    ((substring-before(../my:EndTime, ":") * 60) + substring-before(substring-after(../my:EndTime, ":"), ":"))
    ((substring-before(../my:StartTime, ":") * 60) + substring-before(substring-after(../my:StartTime, ":"), ":"))

    4) Keep in mind, we don’t want this expression to execute if either the StartTime or EndTime fields are empty and we also need to subtract the StartTime total minutes from the EndTime total minutes. So to do this we will use the “substring” function in conjunction with a “condition.” The substring function has the following signature:

    substring([String Value], [Starting Position], [Condition/Length])

    To incorporate our expressions into the substring function, it would look like this:

    Substring([EndTime – StartTime], 1, EndTime != “” and StartTime != “”)

    EndTime expression:

    ((substring-before(../my:EndTime, ":") * 60) + substring-before(substring-after(../my:EndTime, ":"), ":"))

    StartTime expression:

    ((substring-before(../my:StartTime, ":") * 60) + substring-before(substring-after(../my:StartTime, ":"), ":"))

    Starting position: 1

    Condition expression (that if true, evaluates to the length of what we want to return so we use the “string-length” function to get the length of our initial expression):

    (../my:StartTime != "" and ../my:EndTime != "") * string-length(((substring-before(../my:EndTime, ":") * 60) + substring-before(substring-after(../my:EndTime, ":"), ":")) - ((substring-before(../my:StartTime, ":") * 60) + substring-before(substring-after(../my:StartTime, ":"), ":")))

    So our final expression for the TotalMinutes field would look like this:

    substring(((substring-before(../my:EndTime, ":") * 60) + substring-before(substring-after(../my:EndTime, ":"), ":")) - ((substring-before(../my:StartTime, ":") * 60) + substring-before(substring-after(../my:StartTime, ":"), ":")), 1, (../my:StartTime != "" and ../my:EndTime != "") * string-length(((substring-before(../my:EndTime, ":") * 60) + substring-before(substring-after(../my:EndTime, ":"), ":")) - ((substring-before(../my:StartTime, ":") * 60) + substring-before(substring-after(../my:StartTime, ":"), ":"))))

     

     

    Step 2: Convert resulting Total Minutes to hours and minutes

    This expression will use the same basic logic we used above: first divide the resulting total minutes field by 60 to see how many hours have elapsed. If the result of that division contains a decimal point (i.e. 90 minutes / 60 = 1.5) then parse the value before the decimal point (for the hours) and then use the “mod” function to return the balance of the minutes.

    1) We need to divide the TotalMinutes field by 60 to get how many hours have elapsed; however, we also need to check if the resulting value contains the decimal point. So the first expression will use the “substring” function so we can incorporate the conditional test. For the conditional test, we will use the “contains” function to see if the result contains the decimal point:

    contains(../my:TotalMinutes div 60, ".")

    So our initial expression would be as follows: this incorporates the “concat” function so if the resulting value contains a decimal point, we will parse that value, concatenate a colon and the concatenate the result of TotalMinutes mod 60:

    substring(concat(substring-before(../my:TotalMinutes div 60, "."), ":", ../my:TotalMinutes mod 60), 1, contains(../my:TotalMinutes div 60, ".") * string-length(concat(substring-before(../my:TotalMinutes div 60, "."), ":", ../my:TotalMinutes mod 60)))

    2) If the resulting expression does not contain a decimal point, then we will simply concatenate a colon with the results of TotalMinutes mod 60:

    substring(concat(../my:TotalMinutes div 60, ":", ../my:TotalMinutes mod 60), 1, not(contains(../my:TotalMinutes div 60, ".")) * string-length(concat(../my:TotalMinutes div 60, ":", ../my:TotalMinutes mod 60)))

    3) So our final expression for the ElapsedTime field would be as follows:

    concat(substring(concat(substring-before(../my:TotalMinutes div 60, "."), ":", ../my:TotalMinutes mod 60), 1, contains(../my:TotalMinutes div 60, ".") * string-length(concat(substring-before(../my:TotalMinutes div 60, "."), ":", ../my:TotalMinutes mod 60))), substring(concat(../my:TotalMinutes div 60, ":", ../my:TotalMinutes mod 60), 1, not(contains(../my:TotalMinutes div 60, ".")) * string-length(concat(../my:TotalMinutes div 60, ":", ../my:TotalMinutes mod 60))))

     

     

    Step 3: Final Formatting - the ActualTime field

    The way the expression is written for the ElapsedTime field, if the resulting minutes is less than 10, only a single value will be returned (i.e. 0:9). Because of this, we want to test for this condition and if the minutes are less than 10, then concatenate a zero (“0”) before that value so the time appears correct. Now this expression could possibly have been incorporated into the ElapsedTime expression but for ease and clarity, I separated these two steps into different fields.

    This expression uses the “string-length” function to determine the length of the string after the colon. If the length is 2 (minutes are greater than 9) then simply concatenate the hours, a colon and the minutes. However, if the length is 1 (minutes are less than 10) then concatenate the hours, a colon with a zero (“:0”) and the minutes. Like before, we will use the “substring” function with a condition statement to determine what to return:

    concat(substring(concat(substring-before(../my:ElapsedTime, ":"), ":", substring-after(../my:ElapsedTime, ":")), 1, (string-length(substring-after(../my:ElapsedTime, ":")) = 2) * string-length(concat(substring-before(../my:ElapsedTime, ":"), ":", substring-after(../my:ElapsedTime, ":")))), substring(concat(substring-before(../my:ElapsedTime, ":"), ":0", substring-after(../my:ElapsedTime, ":")), 1, (string-length(substring-after(../my:ElapsedTime, ":")) = 1) * string-length(concat(substring-before(../my:ElapsedTime, ":"), ":0", substring-after(../my:ElapsedTime, ":")))))

    Step 4: Create the TotalTime expression for keeping a running total of the elapsed time

    The last step is to create the TotalTime expression – this is similar to the ActualTime expression except we now incorporate the “sum” function to get the running total:

    concat(substring(concat((sum(../my:group1/my:group2/my:TotalMinutes) - sum(../my:group1/my:group2/my:TotalMinutes) mod 60) div 60, ":", sum(../my:group1/my:group2/my:TotalMinutes) mod 60), 1, (sum(../my:group1/my:group2/my:TotalMinutes) mod 60 > 9) * string-length(concat((sum(../my:group1/my:group2/my:TotalMinutes) - sum(../my:group1/my:group2/my:TotalMinutes) mod 60) div 60, ":", sum(../my:group1/my:group2/my:TotalMinutes) mod 60))), substring(concat((sum(../my:group1/my:group2/my:TotalMinutes) - sum(../my:group1/my:group2/my:TotalMinutes) mod 60) div 60, ":0", sum(../my:group1/my:group2/my:TotalMinutes) mod 60), 1, (sum(../my:group1/my:group2/my:TotalMinutes) mod 60 < 10) * string-length(concat((sum(../my:group1/my:group2/my:TotalMinutes) - sum(../my:group1/my:group2/my:TotalMinutes) mod 60) div 60, ":0", sum(../my:group1/my:group2/my:TotalMinutes) mod 60))))

    Step 5: Test!
    Enter a Start and End Time in the form of: h:mm AM(PM), such as: 8:00 AM and 5:00 PM – the ActualTime field should display the difference (as 9:00) and if you continue adding rows, the TotalTime field should reflect the running total.

    This functionality allows you to create elapsed time scenarios that work in both client and browser forms without writing one line of code!

    Scott Heim
    Support Engineer

  • Microsoft InfoPath 2010

    Advanced server-side authentication for data connections, part 1

    • 8 Comments
    To tier three... and beyond!
     
    Real-world enterprise applications are seldom restricted to a single server.  Anyone who has created a nontrivial multi-tier application in a Windows environment has had to work around a fundamental limitation in NTLM authentication:  namely, that NTLM authentication tokens cannot be delegated past the second tier.
     
    Could you bounce off the wall and say that again?
     
    OK, in simpler terms:
    When you log onto your workstation, you present windows with primary evidence of your identity in the form of a username and a secret – usually a password, but sometimes a certificate or a biometric identifier such as a fingerprint.
     
    When you connect to a web application in a browser, your workstation contacts the web server and tells the server who you are.  The server trusts the workstation because it knows that the workstation has primary evidence of your identity, but the server has only second-hand evidence.
     
    When the web server connects to the data server, it passes your authentication token, but the data server won't accept it because the chain of trust is too long.  The data server has only third-hand evidence of your identity.  Bzzzzzzzzzt – thank you for playing!
     
    With InfoPath 2003, you never had to worry about these issues when designing your form.  You ran InfoPath on tier 1, and the database, Web service, or SharePoint site on tier 2 trusted your computer's first-hand evidence.  Now that you are designing forms that run in a web browser, you'll need to think about tier 3.
     
    There are a number of ways of dealing with tier 3 and beyond in forms services.  I'll start by briefly describing three simple techniques for noncritical applications, then I'll move on to enterprise-quality solutions, culminating in two technologies that are specific to Microsoft Office SharePoint Server.
     
    Keep in mind that for form templates that are not admin-approved and fully trusted, the connection settings need to be stored in a Universal Data Connection (UDC) file in a Data Connection Library in order to make a connection to another domain.
     
    Anonymous connections
    For trivial data connections, such as looking up a list of states to populate a drop-down list, you can simply allow anonymous users to access your data.  Removing the need to authorize the user means that it's no longer a problem that your identity can't be verified on tier 3.
     
    HTTP Basic Authentication
    In Basic authentication (or digest, which is a slightly more secure version of the same protocol), your browser prompts you to enter your username and a password, which are then passed in cleartext (or in digest form) to the web server.  The web server now has primary evidence of your identity, so the data server can trust it to tell it who you are.  You can set up IIS on your SharePoint server to use Basic authentication instead of Windows Integrated authentication.  While this is a quick way to do an end run around the tier 3 problem, it presents an awkward user experience on the intranet.   This is better suited to the extranet, where getting prompted for additional credentials is a more familiar experience. Don't forget to set up SSL so that your users' credentials are encrypted on the wire.  Otherwise, anybody monitoring your server traffic can read the passwords as they pass by.
     
    Embedded SQL credentials
    It's common practice in web applications to connect to a database using a SQL username and password embedded in the connection string.  Since this requires putting a password in cleartext in a configuration file, it is not considered a secure method of authentication.  By default, user form templates on the server are not allowed to use embedded SQL credentials.
     
    Kerberos
    Unlike NTLM authentication, a Kerberos authentication token, called a "ticket", can be independently verified at any point in an n-tier system and thus can be delegated indefinitely within the window of time that the ticket is valid.  For enterprises where Windows XP or better is the standard desktop and Windows Server 2003 is the standard server, Kerberos can replace NTLM as the standard authentication method in Active Directory.  This is the preferred method of overcoming the 2-tier restriction on token delegation when available.
     
    Constrained Delegation
    In constrained delegation, two services on two servers can be configured to allow a specific set of user accounts to be delegated from one service to the other without requiring independent verification of a password.  While this is considered a secure option, it is notoriously difficult to set up and maintain.
     
    Office Single Sign-on
    Office Single Sign-on (SSO) is a service on Microsoft Office SharePoint Server which was created to help applications on the server overcome authentication delegation issues.  At its heart, SSO is simply a database which stores encrypted username and password pairs.  An application running on the server can obtain a username and password associated with a known SSO application definition and can then use those credentials to log on to Windows and make a trusted connection to a data source. A form running on the server can use SSO to connect to external data by specifying an SSO application ID in the UDC file containing the connection settings.
     
    Web service proxy
    InfoPath Forms Services includes functionality to forward Web service requests from a form.  The web service request is made using the identity associated with the SharePoint web application.  In order to allow the web service to authorize access to the external data, the user's Windows username is passed in the SOAP header using a WS-
     
    Security UsernameToken
    In my next two installments, I'll describe in more detail how to use Office Single Sign-on and the Web service proxy to connect to enterprise data from your browser-enabled forms.
     
    In my next post we'll cover Single Sign On and write some code.
     
    - Nick
    Program Manager
  • 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

    Designing browser-enabled forms for performance in InfoPath Forms Services (Part 1)

    • 11 Comments

    Part 1 - Introduction

    InfoPath Forms Services (IPFS) is a Web service system integrated with SharePoint that enables you to deliver InfoPath forms on the Web through a browser. These browser-enabled forms extend the reach of your forms system, since your users do not require the InfoPath rich client to display and fill out the forms. When you are designing browser-enabled forms, optimizing performance should be an important objective for delivering the best possible form filling experience to your users.
     
    To help you reach this objective, we are introducing a series of articles about optimizing the performance of InfoPath browser-enabled forms. We will cover design issues and enhancements that can either degrade or improve the performance of your InfoPath forms system. Information in this series will help you gain a better understanding of differences between an InfoPath rich client form and a browser-enabled form, the interaction between the browser and the IPFS server system, what form features cause postbacks, factors affecting the rendering of a form in the browser, how to identify problems and monitor the performance of your forms system, and other tips for improving the performance of browser-enabled forms.

    Who should read this?

    Who should read this series about designing InfoPath browser-enabled forms for improved performance and scalability? First, anyone who is interested in learning more about the design and delivery of  InfoPath forms on the Web. Second, anyone who has to design and support large or complex forms. Third, anyone who needs to support a significant number of concurrent form users and is concerned with the performance and scalability of their Web form system under load. Whether you are an experienced form designer or are new to InfoPath, the information in this series will help you improve your understanding and control of the behavior of your InfoPath browser-enabled forms.

    What do we mean by "performance"?

    When describing the behavior of InfoPath browser-enabled forms on the Web, what do we mean by "performance"? Simply put, "performance" is the subjective perception of how responsive the form feels for the person filling it out in their browser. This perception is influenced by how quickly the form loads and how quickly it reacts to the user's input. Performance is good when your users don't have to wait for a form; it is bad when they do. As a form designer, your primary goal is to manage the overall user experience, and your primary performance goal is to minimize the time your users spend interacting with the forms. At the same time, it is equally important that your server system be able to scale to meet expected demand while maintaining an acceptable level of responsiveness. Of course, these are not your only goals - you must also deliver a form that meets a stringent set of design, business, and technical requirements. 
     
    Just as good form design requires balancing design and layout with business and technical requirements, good form performance happens as the result of a complex set of factors. Some of these factors might be outside of your direct control as a designer, but they must be considered in your design to achieve your performance goals. Some of these factors include:  the user environment, expected usage patterns, peak loads, network and server architecture, database design, custom code, and interaction with other applications in your SharePoint environment. The more you know about these factors of your form deployment and how they interact with your form design, the more effectively you can manage the issues that affect browser form performance. 
     
    Generally speaking, some of the most important objective measures for gauging performance are response time, throughput, and resource utilization. These measures can be used on the server to evaluate how efficiently requests are being processed. They can also provide insight about whether an issue is occurring on the server or in the browser. Use these measures to analyze actual performance, develop baselines, and understand the effect of your changes during troubleshooting and tuning activities. Although beyond the scope of this series, as you develop your framework for evaluating forms performance under various conditions, you should plan on developing load, stress, and capacity testing around these measures. The more objective you can become about performance, the more effective you will become at finding and removing performance bottlenecks. Later in this series you will learn more about tools for monitoring the performance your InfoPath forms system.
     
    Ultimately, because each environment and set of form requirements is unique, there is little prescriptive guidance that is both general and specific enough to be useful. As you optimize rendering performance in the browser, throughput might increase, but certain improvements in throughput might in turn reduce the responsiveness of a form in the browser. Or it might increase resource utilization on the server, reducing the server's ability to scale when subjected to heavy loads. In the end, you must make decisions and tradeoffs to resolve the various elements of form design with respect to the characteristics of your system, and your design, business, and performance goals. Armed with the information presented in this series of articles, you will be better equipped to make decisions that improve the performance of your InfoPath browser-enabled forms.

    Common causes of poor performance

    There are many conditions that can put a drag on the performance of browser-enabled forms in an InfoPath Form Services system. The following list is a sample of some of the most common conditions:

    • Slow network connections
    • This is an important factor in the actual performance of any server system, especially one that uses the Web. It’s something you should keep in mind as you design, test, and deploy any web-enabled form. Although there are many things that affect performance at the network and system level, and that can be done to improve it, these are beyond the scope of this series.

    • Large amount of HTML
    • Large forms that require large amounts of HTML to be transferred and rendered reduce the responsiveness of a browser-enabled form. Rendering performance will be the subject of an article in this series.

    • Large amount of XML
    • Again, large, complex forms can contribute to poor performance of an InfoPath Forms Services form system. Since Forms Services processes form XML on the server, forms with large amounts of complex XML require additional server resources. When there are many concurrent users, the additional stress on the server reduces scalability and throughput, and increases latency. In addition, a large amount of XML can slow form rendering in the browser. In this series we’ll look at a number of issues that make form processing more expensive.

    • Form features that cause postbacks
    • Certain form controls, actions, and features require the browser to communicate with the server during the form-filling session. This exchange of data during the session is called a postback, and it usually occurs when a form feature needs to send data to the server for processing and then has to wait for a response to update and re-render the form. We’ll look at specific features that cause postbacks in our next article.

     

    What's next?

    The next article in this series will look at some of the differences between InfoPath rich client forms and browser-enabled forms that have implications for performance. The most significant difference involves the postbacks that the browser sends to the server for processing. Whether you are familiar with InfoPath or you are new, you will learn something new and useful about the interaction between the browser and the InfoPath Forms Sevices server system.

     

  • 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

    Add a Dynamic Map to a Contact Form using REST Web Services

    • 25 Comments

    Update: Due to a change in the Bing Maps REST Web Service, the steps outlined in this blog post no longer work. We are looking into the possibility of using a different API, and will update this post soon with details.

    Hi, Phil Newman here from the InfoPath team. In this post, I’ll explain how to use the new REST Web service data connection in InfoPath 2010 to add a dynamic map to a contacts form. The form connects to two Web services. The first is a REST Web service that returns the coordinates of a given address from Bing Maps, the second returns an image of a map for a given coordinate set. When users enter address information in the form, the map will update to display the specified address.

    Get Microsoft Silverlight

    The following steps assume that:

    1. You’ve already created your Contacts list in SharePoint and customized the form for the list in InfoPath.
    2. You have a Bing Maps key (see http://msdn.microsoft.com/en-us/library/ff428642.aspx)

    Add the Data Connections

    1. In InfoPath Designer, click “From REST Web Service” on the “Data” tab. Data Tab, From REST Web Service
    2. On the first page of the Data Connection wizard, enter the URL of the Bing Maps REST Web service that will return the GPS coordinates for the specified address. The URL must contain sample parameters that will return valid values at runtime. Otherwise the connection will not be configured. Data Connection Wizard - Web Service Details Here is my starting URL (you will need to replace YourBingMapsKey with your own Bing Maps key value) :
      http://dev.virtualearth.net/Services/v1/GeocodeService/GeocodeService.asmx/Geocode?culture=en-us&count=10&query=1%20Microsoft%20Way%20Redmond%20wa%20&landmark=&addressLine=&locality=&postalTown=&adminDistrict=&district=&postalCode=&countryRegion=&mapBounds=&currentLocation=&curLocAccuracy=&entityTypes=&rankBy=&key=YourBingMapsKey 
      Note that I’ve included a default address of “1 Microsoft Way Redmond WA” so that the Web service will return valid XML.
    3. On the next page of the Data Connection wizard, specify a name for the data connection. Since in this scenario we only want the map to be displayed when the user enters an address, clear the “Automatically retrieve data when the form is opened” check box, and click “Finish”. Data Connection Wizard - Data Connection Name
    4. Because the Bing Maps Web service is not on the SharePoint server, the data connection must be converted to a data connection (.udcx) file. Click “Data Connections” on the “Data” tab, select the data connection, and click “Convert to Connection File”. The connection file must be saved to a Data Connection Library on the SharePoint site and approved before it can be used.  (For more about data connections and UDC files, go here)Data Ribbon tab - Data Connections

    RESTSaveConnectionFile

    RESTSaveConnectionFile2

    Add a Rule to query the REST Web Service

    The next step is to create a rule to change the parameters in the REST Web Service URL based on the address values entered in the form. The Web service will then be queried using these parameters.

    1. Add a button to the form.
    2. Select the button and click “Manage Rules” on the “Home” tab.RESTManageRules

      (NOTE – the button is being used as a temporary placeholder for creating the rules. In InfoPath 2010, you can copy and paste rules between controls. We’ve built in smarts so that when you copy a rule to a different control, field references are updated. In this case we do not want the references to be updated so we will create the rules on the button and then copy and paste it on to the Address fields.)

    3. On the “Rules” task pane, click “New”, “Action” and add a “Change REST URL” rule action. 
    4. Build an expression that concatenates values in the form to create the URL RESTRuleDetails
      • In the “Insert Formula” dialog, select the existing URL  RESTInsertFormula
      • Click the “Insert Function” button and add the Concat function from the “Text” category.
      • Replace the default value for the address with parameters from the form. Since the Concat function concatenates strings, each hard coded string must be in quotes. Use the “Insert Field or Group…” button to add fields from the form to the expression.
      • Click OK in the “Insert Formula” and “Rules Details” dialogs. The underlined words in the image below are fields in the form being used as parameters in the URL. RESTInsertFormula2
      • Here is the Formula (you will need to replace YourBingMapsKey with your own Bing Maps key value) :
        concat("http://dev.virtualearth.net/Services/v1/GeocodeService/GeocodeService.asmx/Geocode?culture=en-us&count=10&query=", Address, ", ", City, ", ", State/Province, "&landmark=&addressLine=&locality=&postalTown=&adminDistrict=&district=&postalCode=&countryRegion=&mapBounds=&currentLocation=&curLocAccuracy=&entityTypes=&rankBy=&key=YourBingMapsKey") 
    5. Add a “Query for Data” rule action to query the REST Web Service with the new URL parameters.

    Add a Rule action to set the URL of the Map picture control

    To display the map of the current location in the picture control, append the latitude and longitude values returned by the Bing Maps REST Web Service to the URL for that image.

    1. Add a “Set a field’s value” rule action to set the URL of the picture control to the map of the current location.
    2. Set the value of the field to the following expression in which “Latitude” and “Longitude” are fields from the REST Web service response. The expression used to build the map image URL is as follows (you will need to replace YourBingMapsKey with your own Bing Maps key value) :
      concat("http://api.tiles.virtualearth.net/api/GetMap.ashx?ppl=24,,", Latitude, ",", Longitude, "&key= YourBingMapsKey")
    3. Add a condition to the rule so that it only executes if the Address, City and State / Province fields are not blank.
    4. Copy the rule from the button you created earlier and paste it onto the Address, City and State / Province controls.
    5. Add a rule to the picture control to hide it if the URL is blank.
    6. From the File tab, click “Quick Publish”.

    Now, open the form in the browser and fill it out. As soon as you have entered an address, the map of that location will appear in the form.

    3 important things to remember when using the REST Web Service data connection:

    1. Always start with a valid URL for your REST Web service.
    2. To change the parameters in the URL, add a “Change REST URL” rule action.
    3. To execute the connection, add a “Query for Data” rule action.

    Please leave a comment if you have any questions or feedback about this feature!

    Phil Newman

    Program Manager

  • Microsoft InfoPath 2010

    InfoPath 2007 Training Labs

    • 3 Comments

    I’m pleased to announce that InfoPath 2007 training labs are now live on MSDN. Just like with the hands-on labs for InfoPath 2003, we created a set of exercises that walk you through a real-life scenario, introducing a new InfoPath feature in the process. Here are the new labs:

    Lab 1: Publishing an InfoPath 2007 Form Template to a Server Running InfoPath Forms Services
    Lab 2: Deploying and Managing InfoPath 2007 Forms
    Lab 3: Integrating InfoPath 2007 with the Data Connection Library
    Lab 4: Enabling Digital Signatures in InfoPath 2007 Form Templates
    Lab 5: Importing Word Forms into InfoPath 2007
    Lab 6: Using InfoPath 2007 E-mail Forms
    Lab 7: Restricting Permissions to InfoPath 2007 Forms and Form Templates
    Lab 8: Using the InfoPath 2007 Object Model and Visual Studio Tools for Applications
    Lab 9: Designing InfoPath 2007 Forms for Mobile Web Browsers
    Lab 10: Creating and Inserting InfoPath 2007 Template Parts
    Lab 11: Integrating InfoPath 2007 Forms in Web Sites Using Visual Studio
    Lab 12: Using SharePoint Server Workflows with InfoPath 2007

    Many InfoPath 2003 labs are still relevant - so if you need a refresher on fundamentals, here's the list:

    Lab 1: Editing forms and working with form data (Level 100)
    Lab 2: Creating forms and layout (Level 200)
    Lab 3: Form deployment (Level 200)
    Lab 4: Working with controls (Levels 200 and 300)
    Lab 5: Business logic (Levels 200 and 400)
    Lab 6: Active X controls (Level 400)
    Lab 7: User roles (Level 200)
    Lab 8: Working with data sources (Levels 300 and 400)
    Lab 9: Working with ADO.NET DataSets (Level 400)
    Lab 10: Digital signatures (Levels 300 and 400)
    Lab 11: Advanced form merging (Level 400)
    Lab 12: Workflow support (Level 400)
    Lab 13: Working with schemas (Level 300)
    Lab 14: Working with custom task panes (Level 400)
    Lab 15: Business logic using managed code (Level 400)
    Lab 16: External automation (Level 400)

    Alex Weinstein
    Program Manager

  • Microsoft InfoPath 2010

    Using InfoPath e-mail forms

    • 9 Comments
    First I’d like to mention that, as part of a recent announcement, the product name for InfoPath “12” is Microsoft Office InfoPath 2007. This is the name I’ll be using from now on in my blog. In my first post I talk about the benefits of browser-enabled forms. I’d like to focus now on the InfoPath rich client and give you a sense of how it can streamline your daily work with InfoPath e-mail forms. If you are familiar with InfoPath SP1 you probably know that it already allows you to send forms as attachments in email. So why is “e-mail forms” a new feature in Office InfoPath 2007? Well, the limitation in InfoPath SP1 is that forms are just regular attachments and they are not integrated in your Outlook email environment. So in Office 2007 we’ve decided to make forms a first class item in Outlook. That means forms can now be viewed, edited, saved, and forwarded similar to email messages, meetings, or tasks. In addition, e-mail forms can leverage Outlook PIM features like categories and follow up to add a new dimension to your forms workflow. E-mail forms now have their own folder type and they even have their own icon J. This tighter integration makes it really easy to work with forms and to leverage all the structured information they provide without having to leave your familiar Outlook environment. Let’s walk thru a short scenario using InfoPath e-mail forms.
     
    Let’s assume I need to collect information about the computers used by my team. First I need to design a form template to collects this information. For our scenario, InfoPath ships out-of-the-box an Asset Tracking template, which I will use for this example. In order to be sent out safely in email, forms like Asset Tracking need to work only with data from within the form and can contain only declarative logic, no code. Because of these security restrictions we call such forms “restricted” forms. Once the template is completed, I need to deploy it using the Publishing Wizard and selecting the option “to a list of e-mail recipients”. I then need to specify the recipients, add an optional comment, and send out the form. The screenshot below shows the e-mail deployment of my Asset Tracking form:
     
     
    When a member of my team receives the form, she clicks “Reply”, which opens the form in InfoPath. She then fills out the computer information and sends the completed form back to me, as shown in the screenshot below. She has the choice to send me an editable XML form, which is the default, or to send back just a read-only view. She can also add a comment related to the form in the “Introduction” field. This comment is in fact metadata that travels with the forms. The same field can be used, for example, to ask her assistant to fill out the asset information for her and, for more complex forms, to give instructions on how to complete the form. Here is an example of a completed asset tracking form (In this case I’ve completed it as a team member and I’m sending it back to myself):
     
     
    Note that at design time I could include a submit button in the form. This will let my team members double-click on the form, edit it in InfoPath and then click “Submit” to send it back to me in e-mail, same as if they replied. However, “Submit” will validate the form and will enforce the return e-mail address. This helps if I need to implement a more formal workflow process using e-mail forms.
     
    Now I’m switching back to being the data collector. I’m expecting to receive a fairly large number of e-mail forms from my team and I want to be ready to process them. To this end, I’m setting up a new Outlook folder to collect the asset data. I right click on Mailbox and select “New Folder”. In the “New Folder” dialog I need to select the option “InfoPath Form Items”, which is new in Outlook 2007, and associates the folder with InfoPath forms. Here is the dialog that creates the “assets” folder for e-mail forms:
     
     
    Once I’ve created the folder, I can also create a rule that automatically routes incoming asset forms to this folder. This rule should refer to InfoPath forms, as shown in the Rules Wizard dialog below. Then I need to pick-up the specific form type out of the list of all the templates that have been cached on my local machine. For each incoming message, the rule will check if it is an e-mail form of type “asset tracking” and will route all the matching e-mails to the “assets” folder. 
     
     
    Note that forms can be stored in any Outlook folder. However dedicated forms folders will create by default a new e-mail form based on the template associated with the folder. In addition those folders will allow property promotion, as explained below.
     
    When each form is saved into the “assets” folder, the properties that have been market for data promotion in the template are copied as Outlook properties. The forms in this folder can now be sorted and filtered based on their promoted properties, You may know how useful it is to take advantage of promoted properties in SharePoint form libraries. You can see at a glance the work progress captured in weekly status reports or the results of a team survey. The same experience is now also available on your local machine, using e-mail forms and form folders in Outlook. Like in SharePoint, the data stored in form folders can be aggregated and exported to Excel for further processing. Below is an example of asset forms with properties promoted in the “assets” folder:
     
     
    As you can see, in addition to using the properties promoted from forms, I can take advantage of other properties, like Categories and Flags that Outlook provides for all item, regardless of type. In the example above I’ve flagged the machines that need to be replaced, upgraded, or the new ones that have been purchased in the last quarter.
     
    When I get all the replies from my team, I will go ahead and process the data. As I mentioned before, the data is not in some collection of text e-mail messages that I need to read in order to extract information for my report. It is in a collection of structured forms that I can very easily process and extract the data to report on.
     
    My next step is to export the data to Excel. I select all the forms in the folder and then select the “Export to Excel” option from the toolbar. This option automatically generates a spreadsheet with all the data mapped from the forms into Excel. Note that the export to Excel is not limited to the promoted properties in my folder but rather to the entire XML of each form in the folder. Once I have all the data in Excel, I create a simple pivot table with the number of laptop, desktop, and lab machines for each functional team and then I chart the data using the new graphics engine. Here is the result of my data gathering scenario using the e-mail form for asset tracking: 
     
     
     
    When should you use e-mail forms?
     
    We’ve seen how I’ve used e-mail forms to gather asset information from my team. E-mail forms could also be used for many similar scenarios, often ad-hoc, in order to collect data quickly from a group of people, via e-mail. Examples are creating a survey for your department, gathering feedback from customer visits, or collaborating with your team on a status report. The common elements of these scenarios are:
    • The data needs to be structured – otherwise you’d just use regular e-mail
    • The data collection is done ad-hoc – there’s no need to set up a more formal process
    • You own the final results – it is ok for the final results to be collected in your own mailbox
    Once you have the replies, you could process them as needed and/or share the data with your team. In our example, I am the consumer of the collected information. I will export the data to Excel, review it, and order new hardware as necessary. For status report, the team lead will be assembling the report, then will publish it, and present it to the team.
     
    A broader scenario is using e-mail to make other forms available to your users. Your forms could be part of a formal team scenario like tracking weekly status, a department workflow solution, or an enterprise wide line-of-business application allowing every employee in the company to update benefits or to submit their performance reviews. In all these scenarios, the forms can be delivered, filled out, and submitted in Outlook. We will cover integrated scenarios for e-mail forms in a follow-up post.
     
    Finally an important benefit of e-mail forms is offline filling. As you may know, form templates are automatically downloaded on your machine on first use. Forms can also be installed as part of a client setup. Once you’ve used a form once on your machine, you can fill out any similar forms offline. To make things even simpler, “restricted” form templates can be included in the same message with the actual e-mail form. A user can download the form in Outlook, open it, fill it out, and submit it back as e-mail form. An additional benefit here is that you can complete the form offline, submit it, and be done. The form will be stored in the Outlook Outbox folder and will be sent out automatically next time Outlook connects to your e-mail server.
     
    I hope I’ve been able to give you a sense of the value of InfoPath e-mail forms as first class items in Outlook and get you interested in trying them out in Office 2007. I’ll follow up shortly with other posts on new InfoPath features. Stay tuned! I’d also love to hear your thoughts and feedback.
     
    Tudor Toma
    Group Program Manager
  • 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

    Create tabbed navigation using picture button controls

    • 9 Comments

    In the 2nd installment of our "5 for Forms" video demo series, Charlie Han, a program manager intern on the InfoPath team shows how you can use our new picture button control to create tabs to more easily navigate your forms.


    Get Microsoft Silverlight

    (There are additional steps required to create tabs in display views. Click here to find out more.)

    Enjoy!

  • Microsoft InfoPath 2010

    InfoPath Quick Tip: Exporting InfoPath forms to Word

    • 10 Comments

    Want to export your InfoPath form view to a Microsoft Office Word document?

    The easiest way to do this is to export your InfoPath form to an MHT file using File | Export To | Web... while filling out your form. Then, just open the MHT file in Microsoft Office Word.  The Word document that you create based on the MHT file exported from InfoPath will look very similar to the InfoPath form itself.

  • 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

    Creating Complex InfoPath Controls in C#

    • 8 Comments

    One of the problems with InfoPath controls is their limited availability. For example, there is no such control like the NumericUpDown control in WinForms. Or you may have a predefined complex UI, which you want use multiple times.

    In these circumstances, what we need is a mechanism for control extensibility. Today, InfoPath provides two different control extensibility mechanism: Template parts and ActiveX controls.

    Basically, template parts are predesigned InfoPath form templates, that can be imported into other templates. This mechanism provides a good way of reusing the same controls again and again, but on the dark side, you are still restricted with the control set of InfoPath.

    Other mechanism, which is extensibility via ActiveX controls lets you go beyond the control set of InfoPath and use whichever ActiveX control you want. In this blog, we will drill down into using a Windows control in InfoPath forms, and more importantly provide a way of binding data to these controls. This blog will give details of using WinForm controls that are registered for COM Interop, inside InfoPath forms. Two mainly used types for binding ActiveX controls to InfoPath data sources are 'Simple Binding', ‘Stream Binding’ and 'Node Binding'. In this article we will cover node binding. You can find more information about types of binding between ActiveX controls and InfoPath data source here:

    http://blogs.msdn.com/ajma/archive/2004/07/07/175568.aspx
    http://blogs.msdn.com/ajma/archive/2004/07/08/177512.aspx
    http://blogs.msdn.com/ajma/archive/2004/07/09/178857.aspx

     

    Simple Binding

    If your external control needs to be bound to a single field in InfoPath main data source, then you can use single binding between your ActiveX control and data source. An excellent simple binding example by InfoPath team can be found here: Creating an InfoPath Custom Control using C# and .NET. I highly recommend you to read this article first both to understand how to register our Windows Forms controls for Com Interop, and how simple binding is done for a primitively typed single field. Rest of the article will assume you read and applied the principles told in this article.

    Node Binding

    When binding to a single field or attribute is not enough, or you need your ActiveX controls to interact with data coming from different fields, node binding is the way to go. A classical example would be an ActiveX control capable of showing an Address type complex structure composed of Street, City, State and ZipCode fields.

    In this case, you need an Xml node in InfoPath form template as a data source that obeys the schema of Address object.

    InfoPath form

    We will design the data source of InfoPath first. Let's just write a schema file that corresponds to the structure of Address class. A simple schema file just including address data would be similar to this:

    <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">

          <xsd:element name="fields">

                <xsd:complexType>

                      <xsd:sequence>

                            <xsd:element ref="address" minOccurs="0"/>

                      </xsd:sequence>

                </xsd:complexType>

          </xsd:element>

          <xsd:element name="address">

                <xsd:complexType>

                      <xsd:sequence>

                            <xsd:element ref="street" minOccurs="0"/>

                            <xsd:element ref="city" minOccurs="0"/>

                            <xsd:element ref="state" minOccurs="0"/>

                            <xsd:element ref="zipCode" minOccurs="0"/>

                      </xsd:sequence>

                </xsd:complexType>

          </xsd:element>

          <xsd:element name="street" type="xsd:string"/>

          <xsd:element name="city" type="xsd:string"/>

          <xsd:element name="state" type="xsd:string"/>

          <xsd:element name="zipCode" type="xsd:integer"/>

    </xsd:schema>

    Start to design a new InfoPath form template from XmlSchema and use this schema as your source. InfoPath should parse the schema, and should create the data source entries in Data Sources tab in design task pane for you. At this point, let's create 4 text boxes that will display each of these fields. For the educational purposes of demo, do not drag and drop the whole address node onto the surface. Instead, drag and drop individual fields on to the design surface. This is because, after designing the ActiveX such that it is bound to whole DOM node, we will get a binding structure like this:

     

    UserControl

    Since we finished the main part of the form template, let's start to prepare the ActiveX object that we will use in the template. Assuming you read the article Creating an InfoPath Custom Control using C# and .NET, I will just touch the points not told there.

    Design the control
    Simply drag and drop four Labels and four TextBoxes on to the user control for each of the fields in Address type.

    Register for ComInterop

    As told in the article, we will need a Guid attribute for Visual Studio to register the control for Com Interop. What is not told in the article is, we need one more attribute to be able to register the control via Visual Studio: ComVisible. Although, UserControl class is donated with ComVisible(true) attribute in .Net framework, we have to state it explicitly one more time, because ComVisible attribute is created with AttributeUsage(…, Inherited = false), which prevents the value of the attribute to be inherited to children classes. So, our control should look similar to this for a successful registration:

    [Guid("08E623D3-BEAD-4bd3-8401-EFF51FD754CD")]

    [ComVisible(true)]

    public class ComplexUserControl : UserControl

    After building this code, a quick search through registry for Guid, will prove that class is really registered.

    Interfaces
    You should import the IObjectSafety interface exactly as told in the article. Before discussing IPropertyNotifySink, let's first take a look at the control interface, that will define the Value and Enabled property. In simple binding example, we had a primitive property in ICOMControl interface. Since we are no longer binding to a primitive field, we have to define a new interface.

    Let's define an IComplexControl interface similar to IComControl interface in the article. For Value property, we will use IXMLDOMNode type defined in Microsoft.Office.Interop.InfoPath.Xml.dll assembly that you will find in your Office 12 installation directory. This corresponds to a node in InfoPath main DOM data source. At the end, our interface should be similar to this:

    [InterfaceType(ComInterfaceType.InterfaceIsDual)]

    public interface IComplexCOMControl

    {

        [DispId(ComplexUserControl.DISPID_VALUE)]

        IXMLDOMNode Value { get; set; }

     

        [DispId(ComplexUserControl.DISPID_ENABLED)]

        bool Enabled { get; set; }

    }

    As stated in the article, Constants.DISPID_VALUE should be 0, and Constants.DISPID_ENABLED should be 1, in order for InfoPath to correctly communicate with our control.

    Now let's inspect IPropertyNotifySink interface. One of the main differences between Simple Binding and Node Binding is the type of the Value property. Simple binding deals with primitive types, whereas node binding deals directly with DOM. In simple binding a rough sequence of events would be like this:

          Property change in data source --> … -->Set Value property of ActiveX

    And the other way around:

          Property change in ActiveX --> Raise OnChanged -->InfoPath queries for Value property --> … -->Set Value property of ActiveX

    However, since InfoPath sends the whole DOM node as our Value property by reference, we don’t need to set an intermediary Value property. Instead we can directly change DOM values from DOM node reference. So we can safely ignore RaiseOnChanged and InfoPath queries for Value property steps. Since IPropertyNotifySink interface is used mainly for property change notification purposes will not implement it in this demo. If you care about Enabled property changes, you still have to implement this interface and notify InfoPath when Enabled property changes.

     

    Value property implementation

    When InfoPath first calls the setter of Value property after instantiating our control, it will pass in the IXMLDOMNode representing the main DOM of InfoPath. We have to keep this node in our control, in order to be able to change the data values corresponding to changes in UI.

    In the getter of the property, since we are not changing the reference of DOM node, it is safe to return this kept value.
    Whenever some field (or subfields in our group field)changes in DOM, InfoPath will call the setter of our Value property. In the setter, we should query the DOM according to XPaths of our fields, and then update the UI according to the values if necessary. At the end, our Value field should look like this:

    private IXMLDOMNode domNode = null;

    public IXMLDOMNode Value

    {

       get

       {

          return domNode;

       }

       set

       {

            if (domNode != null)

            {

                ChangeUI(streetTbx, domNode.selectSingleNode("/fields/address/street").text);

                ChangeUI(cityTbx, domNode.selectSingleNode("/fields/address/city").text);

                ChangeUI(stateTbx, domNode.selectSingleNode("/fields/address/state").text);

                ChangeUI(zipCodeTbx, domNode.selectSingleNode("/fields/address/zipCode").text);

            }

        }

    }

     

    private void ChangeUI(TextBox tbx, string text)

    {

       if (tbx.Text != text)

       {

        tbx.Text = text;

       }

    } 

    At this point we have completed the one direction of binding, originating from data source and going to UI. Now, let's handle the other way around, from UI to data source. In order to do this, we have to create a simple event handler that will catch change events in UI. Then register for all four text boxes' TextChanged events, such that each of them will be handled by this event handler. Code should look like this:

    public ComplexUserControl()

    {

        this.InitializeComponent();

     

        // Register for UI change events

        this.streetTbx.TextChanged += this.HandleChangesInUI;

        this.cityTbx.TextChanged += this.HandleChangesInUI;

        this.stateTbx.TextChanged += this.HandleChangesInUI;

        this.zipCodeTbx.TextChanged += this.HandleChangesInUI;

    }

     

    private void HandleChangesInUI(object sender, EventArgs e)

    {

        TextBox senderTbx = (TextBox)sender;

        if (senderTbx == this.streetTbx)

            this.ChangeDOM("/fields/address/street", this.streetTbx.Text);

        else if (senderTbx == this.cityTbx)

            this.ChangeDOM("/fields/address/city", this.cityTbx.Text);

        else if (senderTbx == this.stateTbx)

            this.ChangeDOM("/fields/address/state", this.stateTbx.Text);

        else if (senderTbx == this.zipCodeTbx)

            this.ChangeDOM("/fields/address/zipCode", this.zipCodeTbx.Text);

    }

     

    private void ChangeDOM(string xPath, string value)

    {

        if (domNode != null)

        {

            IXMLDOMNode singleNode = domNode.selectSingleNode(xPath);

            if (singleNode.text != value)

            {

                singleNode.text = value;

            }

        }

    }

    Integration

    In order to be able to use the ActiveX Control in the design of a form template, we have to make one final trick: Placing the .ict file that describes the control and its binding, to our controls directory. In order to add custom controls design task pane in InfoPath, generally you first go to the Controls tab, then click Add or Remove Custom Controls at the bottom of this tab, select to add a new ActiveX control, and finally select the ActiveX you want to add from the list of registered controls. If you have ever done this before, there should be a directory named

    C:\Documents and Settings\username\Local Settings\Application Data\Microsoft\InfoPath\Controls

    In this directory there should be a .ict file for each of the ActiveX controls that you have done this operation for. We have to create a new .ict file for our control. If above directory does not exist, create it. Then create a file with name "{yourClassGUIDHere}.ict". This file should be in this format:

    <?xml version="1.0" encoding="UTF-8" standalone="no"?>

    <ict:control name="Complex C# Control, v1.0" xmlns:ict="http://schemas.microsoft.com/office/infopath/2003/ict" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xdSdl="http://schemas.microsoft.com/office/infopath/2003/xct" xmlns:ict2="ict2" xmlns:xd="http://schemas.microsoft.com/office/infopath/2003">

          <ict:designTimeProperties>

          <ict:iconBitmap>Qk3uAAAAAAAAAHYAAAAoAAAAEAAAAA8AAAABAAQAAAAAAAAAAADEDgAAxA4AABAAAAAQAAAAAAAA/wAAgP8AgAD/AICA/4AAAP+AAID/gIAA/4CAgP/AwMD/AAD//wD/AP8A/////wAA//8A/////wD//////4iIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiP//////////eIiIiIiIiI94RIRIRIiIj3hEhEhEiIiPeESESESIiI94RIRIRIiIj3iIiIiIiIiPd3d3d3d3d3eIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiA==</ict:iconBitmap>

          </ict:designTimeProperties>

          <ict:deployment>

                <ict:controlPackage classid="{yourClassGUIDHere}"/>

          </ict:deployment>

          <ict:shapes>

                <!--default shape-->

          </ict:shapes>

          <ict:schemaEditing>

                <ict:any/>

          </ict:schemaEditing>

         <ict:view>

               <ict:controlObject bindingProperty="Value" bindingType="xmlNode" enabledProperty="Enabled" enabledValue="true"/>

         </ict:view>

    </ict:control>

    Note the bolded text. You should place the correct GUID for your control, and note that we are actually specifying 'xmlNode' as bindingType. Rest of the file is almost standard except the iconBitmap part, which specifies the icon that will be displayed next to your control in design task pane.

    Since we have a ready control now, we can safely use it in our form template. Open the InfoPath form you have designed in design mode again. Go to Controls tab in design task pane. At the bottom, under Custom section, you should see the 'Complex C# Control, v1.0' with icon I have copied from Microsoft Forms Progress Bar control. Drag and drop this control to design surface. According to your security settings, it may ask you if you want to run ActiveX control. If so, press 'Yes' and continue. Since we have already defined a data source in the form, InfoPath will ask which field or group do we want our control to bind to. Choose address here. Now you should see the control on the surface, and its binding field is specified as /fields/address. Press Ctrl+Shift+B to preview the form. You should see the corresponding InfoPath TextBoxes and our UserControl's TextBoxes are synchronized, because they are bound to same data source fields.

    Now we have a functional complex WinForm UserControl, that we can display in an InfoPath form template, and even better, this UserControl is bound to InfoPath main DOM.

    Improving ActiveX Discrepancies

    If you played with the form a few minutes, you must have noticed that there is something weird going on. If you are changing the text value of InfoPath TextBoxes, you see a flicker in the UserControl before data is reflected to it. Similarly, if you change the value of a TextBox in your UserControl, you also see a flicker in the UserControl, and focus is continuously given to first TextBox added to UserControl.

    Main reason for this issue is, whenever a data field that is bound to your ActiveX is changed, InfoPath destroys your control and create a new one. This is mainly because InfoPath has to apply your view xsl to your data source to create the view you see on the display. Every time data source changes, InfoPath re-applies the xsl file and creates the view from scratch for controls that are bound to changed data fields. If you are debugging the form, you can easily see this by putting a breakpoint in the constructor of UserControl. Clearly, this leads us to write stateless controls, since each time the controls are destroyed, state is destroyed too. Or, as a second approach, we can take advantage of a helper interface, InfoPathControl interface, to save the state to some persistent storage just before destruction, and retrieve it after re-creation. Let's inspect how this approach works.

    InfoPathControl interface is defined in Microsoft.Office.Interop.InfoPath primary interop assembly. Add a reference to this assembly to your project and implement the interface on your UserControl. I advise you to read the explanation of all four methods of the interface, and how they are used in MSDN. Here, we will only concentrate on two of them, which are Init and SaveState methods.

    SaveState is called by InfoPath, just before the destruction of the older control, which makes it a perfect point to save the state to some storage. Init is called after creating the new control, which lets us to use it to retrieve the saved state and apply it to our control.

    Init method takes a parameter of type InfoPathControlSite. This interface gives us the main DOM node and XDocument of InfoPath form template, which basically enables us to access pretty much all of the object model of InfoPath. So, we don't have to wait for the setter of Value property anymore. We can cache the domNode here in Init method. We will also cache the XDocument for storing the state in, since we will need a persistent storage for our state while we are destroyed. In general, Init method body should be similar to this:

    private XDocumentClass xDocument = null;

    public void Init(InfoPathControlSite pControlSite)

    {

      this.domNode = pControlSite.Node;

      this.xDocument = (XDocumentClass)pControlSite.XDocument;

      this.RestoreState();

    }

    We will inspect RestoreState method after SaveState method.

    For simplicity, we will assume that we only want to keep which control has the focus in UserControl and give focus to that control after re-creation. Saving the name of the active control should be enough for state restoration. In reality in a control like this we should also keep the location of the cursor inside the TextBox as well as which TextBox is active.

    We said that we will use XDocument to save the state. This is because XDocument lives with the form template, so it is persistent during the lifetime of our control, and XDocument has a property bag that we can use for this purpose. We can update this property bag by calling SetNamedNodeProperty and querying it by calling GetNamedNodeProperty method on XDocument object. At the end, SaveState and RestoreState methods should be similar to this:

    public void SaveState()

    {

        if (this.xDocument != null)

        {

            this.xDocument.SetNamedNodeProperty(this.domNode, "ActiveControl", this.ActiveControl.Name);

        }

    }

     

    private void RestoreState()

    {

        if (this.xDocument != null)

        {

            Control activeControl = this.Controls[this.xDocument.GetNamedNodeProperty(domNode, "ActiveControl", this.Controls[0].Name)];

            if (activeControl != null)

            {

                activeControl.Focus();

            }

        }

    } 

    In the call to GetNamedNodeProperty in RestoreState method, third parameter is the default value, which will be returned back if specified property name can't be found in property bag. This will be the case when control is first created.

    Now, each time data source has changed, we save which control was active in UserControl before it is destroyed. Then InfoPath instantiates a new instance, we restore the state if there is any. Then InfoPath sets the Value property with updated fields.

    Saving the whole state in a WinForm control is a non-trivial task and maybe somewhat cumbersome. I'm optimistic about this re-creation of ActiveX controls will be optimized by InfoPath team in the next release.

    At the end, our code will look like this attached file.

    Deniz Demircioglu
    Software Design Engineer

  • 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

    Free InfoPath 2010 Web Cast: Best Practices in Form Design

    • 3 Comments

    The fourth and final session in the InfoPath 2010 Academy Live series, Best Practices in Form Design, by InfoPath PM lead Daniel Witriol takes place this Wednesday, May 5th at 8:30 AM (PST).

    You can sign up for this free Web cast on https://www.eventbuilder.com/event_desc.asp?p_event=a2d1f10w.

    If you’ve missed any of our earlier sessions, you can watch them on demand at the links below:

    Academy Live

  • Microsoft InfoPath 2010

    Behind the Scenes of Administrator-Approved Form Templates

    • 8 Comments

    If you’re a server administrator for Microsoft Office InfoPath Forms Services 2007, there may be a time when you’re tried to perform some action on a form template and received an error message that looks like the following:

    “Form template was deployed as part of the 9b518781-2fcd-40fe-a1f4-964b2cd4c0b8 feature”

    This feature name probably doesn’t mean a whole lot to you, and the error message could be a bit more actionable, right?  What the heck is this feature thing that the message refers to?  You might also have come across other IDs or other weird timing issues on a multiple server farm.
     

    Starting the Tour

    So, to shed some light on this, let’s go back-stage to see a little of what’s going on behind the scenes.  The stage is Windows SharePoint Servers Central Administration, where you will find 5 options in the Microsoft Office InfoPath Forms Services group on the Application Management landing page. This tour will mainly be concerned with the Upload Form Template page and a little bit with the Manage Form Templates page. 

    Let’s start at the Upload Form Template page, which is how a form template gets approved by the administrator.  Each new form template uploaded to the farm also adds a new FormTemplate object to the FormsService.FormTemplates which is the singleton FormTemplateCollection object for the farm’s administration object model.  This FormTemplate object allows the same manipulation that is available through the UI.  It also contains a lot of information used only internally to InfoPath Forms Services.  The most important internal property is the converted file, which is essentially a compiled version of the form template that can quickly render as a form template in the browser.

    When InfoPath form templates are uploaded to a server, the Windows SharePoint Services solution deployment and featurization infrastructures are being used to turn the form template into an administrator-approved form template..  Behind the simple click of the Upload button, InfoPath Forms Services creates a feature to deliver the form template (.xsn file).  The feature is then wrapped in a Windows SharePoint Services solutions package which is a .wsp file (just a renamed .cab file) that contains the feature and some other packaging information.


    The Solution Package

    This solution package is the means of deployment to all of the servers in a farm.  All Web front-end servers will have the form template propagated to their file systems, via the solution’s package.  So, there may be a delay in showing up on a multiple-server farm, hence the ellipsis in the “Installing…” status which remains until the form template is deployed to all machines in the farm.  These are propagated via the SPTimerv3 service which runs on each box and is scheduled to pick up jobs from servers running the central administration Web Application (where the Upload took place) and it uses the SPAdmin service to install the solution on the machine, via the administrator account.  So, InfoPath Forms Services deployment needs these services running on each machine, just like WSS solution deployment, because it’s actually the same thing.  Once deployment is completed, the form template is marked with “Ready” status.

    [Side Note: An implementation just like what we use for solution deployment is also available to you.  Our shipping documentation covers how to create features and solutions from scratch.  You might want to do this to bulk deploy many form templates at the same time, to indicated InfoPath form templates in other features or solutions, or to create a custom workflow that contains custom InfoPath form templates.  These custom-created solutions are still registered into the InfoPath Forms Services OM, but will be treated a little differently in IPFS, for instance, you cannot activate/deactivate/remove/upgrade these form templates through IPFS management, because that might invalidate the overall solutions that were constructed.  The whole features must be activated the same way that other custom features are activated (see Ready for Activation, below).]


    Ready For Activation

    The Ready status indicates that the form template can be used and is in normal operation.  The feature created, is a site collection-scoped feature (that’s SPSite-scoped in WSS OM-speak), which can be activated on an site collection like most other site collection-scoped features.  If you are a site collection owner, navigate to Site Settings, and see Site Collection Features under the Site Collection group heading.  Every form template that was administrator-approved through the upload page is available here along with the other site collection scoped features.

    You can also activate and deactivate features from the Manage Form Templates page in Central Administration.  This is exactly the same thing, and is provided as a courtesy for farm administrators who are also site collection owners.


    Behind the Scenes of Activation and Invocation

    An activated form template is added as an item in the Form Templates library at the root site of the site collection (SPSite.rootWeb) in the /formservertemplates path.  The form template is not actually present in the content database for the library, it is stored as a ghosted entry.  A user invoking the form template with the Microsoft Office InfoPath 2007 rich client is actually pulling the form template from the file system of the Web front-end server where it was placed by solution deployment.  Invoking the form template via the browser will pull the converted file from the FormTemplate object in the administration object model.

    The Form Templates library is special in a few ways.  The most important special aspect is that activated form templates cannot be unghosted.  This is to ensure that the converted file version and the on-disk version cannot be different, so that no matter what client you fill the form in, it’s the same form. 


    Be a Better IPFS Admin with this Knowledge

    Our hope is that this article will make our behavior more clear and expose a few tricks to help you be better Administrators.  Here are a few tricks in how to use that information to your advantage.

    Handle the error:  “Form template was deployed as part of the 9b518781-2fcd-40fe-a1f4-964b2cd4c0b8 feature”

    If you receive this, you most likely want to remove the form template and start over.  Here’s the action to take, and it’s only available from the command line:
    "%ProgramFiles%\Common Files\Microsoft Shared\web server extensions\12\BIN\STSADM.EXE" -o uninstallfeature -filename 9b518781-2fcd-40fe-a1f4-964b2cd4c0b8\feature.xml

    Form template’s status never leaves “Upgrading…” or “Removing…” states

    These states seem to indicate that you're running a multiple-machine server farm, and on your server farm, you're running into some issues in propagating changes to all of the machines.  If you have not done so already, I highly recommend turning on the following services on each machine: SPAdmin, and SPTimerV3 You can do this by running:
                    net start SPTimerV3
                    net start SPAdmin
    On each machine.  Net start is a ensure semantic, so this will not inadvertently toggle or cause any damage if run on a machine where the service is already started.  Now that that's done, you can go on to correcting the problems that you have.

    From Central Administration, go to the Operations page, under the Global configuration group, click on Timer Job Status.  On that page, look for timer jobs that have the name in the following formatting.  If you filename is FOO.xsn, it will look like:
    Windows SharePoint Services Solution Deployment for "form-FOO.wsp"

    See if there was a failure.  If so, go back a page, and go to Timer Job Definitions.  Drill down in the timer job definition that you care about and you can perform the following:

    >> For the case of status stuck on “Uploading”:
    1.       Try to restart the job if that is available.
    2.       If restart is not available, delete the job, then attempt to upgrade again.

    >> For the case of status stuck on "Upgrading":
    1.       Try to restart the job if that is available.
    2.       If restart is not available, delete the job, then attempt to upgrade again.

    >> For the case of status stuck on "Removing":
    1.       Try to restart the job if that is available.
    2.       Else, Remove the job. (continue to step 3)
    3.       Then, go back to the Manage Form Templates and try again to Remove the form template.

    Ed Essey
    Program Manager
    Alexei Levenkov
    Software Design Engineer
Page 2 of 12 (298 items) 12345»