Writing Advanced Event Handlers

Highlights

In this chapter, you will learn how to

For more information

Overview

To work through this chapter

The primary purpose of managed event-handling code is to implement business rules that you cant handle with declarative methods data validation rules, conditional formatting, and roles you establish in InfoPath design mode. Other managed code applications include modifying the content of custom task panes, testing for required digital signatures, displaying calculated values in expression boxes, and saving customized versions of InfoPath XML data documents.

The release version of the Microsoft Office InfoPath 2003 Software Development Kit (SDK) includes 14 Developer Sample Forms to demonstrate Microsoft JScript event- handling code in several scenarios. If youre an accomplished JScript programmer, reviewing the script behind these forms will help you write managed code in Microsoft Visual C# and, to a lesser extent, Visual Basic. NET. This chapter takes an approach thats similar to the Developer Sample Forms by providing examples of forms with complex Visual Basic event handlers. The emphasis is on accomplishing tasks that are required for production versions of the Really Simple Syndication (RSS) 2.0 and Northwind Traders Order Entry and Editing forms that youve progressively developed in the preceding chapters. Another objective of these forms is to demonstrate Visual Basic coding techniques for the new and updated objects, properties, methods, and events in InfoPath 2003 Service Pack 1 (SP-1).

Enabling Full Trust for Managed Code

This chapter s procedures require the Visual Basic .NET event-handling code to run with full trust. You can t digitally sign forms generated from the extracted template files in your project folder. In the .NET Framework s default configuration, you can build ”but not run ”forms that require full trust for event-handling code. You must specify Full Trust and add a digital signature to the TemplateName .xsn file in the project s ...inDebug or ...inRelease folder to run the forms. Alternatively, you can register TemplateName .xsn by creating a Microsoft Installer (.msi) file with Regform.exe and then executing the .msi file.

Debugging signed or registered forms ordinarily requires a Visual Studio instance connected to the INFOPATH.EXE process. The code in this instance is read-only, so you must open another Visual Studio instance to edit your code and rebuild (but not run) the project. The section Explore the SaveRssToFile Procedure, later in this chapter, shows you how to connect a Visual Studio instance to the INFOPATH.EXE process. Each time you rebuild the project, you must re-sign or reregister TemplateName .xsn.

 SP-1   Fortunately, SP-1 provides a workaround for InfoPath developers using managed code. To enable debugging of forms that require full trust, the .NET Framework 1.1 Configuration tool lets you specify full trust for the managed code behind an InfoPath form template. To do so, you add an InfoPath Form Templates code group to the All Code group and assign the new group s project folder and its subfolders Full Trust permissions. Full Trust permissions let you debug and run outside of the InfoPath sandbox managed code that accesses local computer resources without the additional ”and inconvenient ” INFOPATH.EXE connection. When you re ready to deploy the completed form, add a digital signature to the TemplateName .xsn file in the ...inRelease folder or create a TemplateName .msi file for a registered form.

Working with this chapter s sample forms requires Full Trust permissions for their Visual Basic .NET code. To assign full trust to InfoPath managed code in subfolders of C:Microsoft PressIntroducing InfoPath 2003Chapter 17, as an example, follow these steps.

Run specified InfoPath managed code with full trust

  1. In Control Panel, open the Administrative Tools folder, and double-click the Microsoft .NET Framework 1.1 Configuration shortcut to open the .NET Configuration 1.1 tool s window.
  2. Expand the Runtime Security Policy, Machine, and Code Groups nodes, as shown here:

  3. Right click the All_Code node, and choose New from the shortcut menu to open the Create Code Group dialog box. Type InfoPath Form Templates (case sensitive) in the Name box, and optionally add a description, as shown on the next page.

  4. Click Next to display the Choose A Condition Type dialog box, and select URL in the drop- down list. Type file://URLEncodedPathToProjectFolder/* (file://C:/Microsoft Press/Introducing InfoPath 2003/Chapter17/* for this example) in the URL text box as shown here:

    Note  

    Typing URL-encoded paths in the Choose A Condition Type dialog box

    URL-encoded paths ordinarily require all reverse (black) slashes () to be changed to forward slashes (/) and spaces to be replaced with %20. In this case, typing %20 isn t required, and the tool converts reverse slashes after file:// to forward slashes for you. If you substitute %20 for spaces, the tool reverts all instances to spaces. The /* suffix grants full runtime trust to assemblies in the designated folder s subfolders.

  5. Click Next, leave the default FullTrust permission set, and click Next and Finish to complete the full-trust assignment.
  6. Close and reopen the .NET Configuration 1.1 window to refresh its data. Your InfoPath Form Templates entry appears under the All_Code node, as shown here:

You can verify and edit the permission set you added in the preceding steps by right-clicking the InfoPath Form Templates node and choosing Properties from the shortcut menu. You must complete the preceding procedure to open this chapter s sample forms in preview mode.

Note  

Maintaining runtime security

If you select All Code in preceding step 4, you can t specify a folder and all assemblies on your development machine will run with full trust. In this case, malicious third-party assemblies could access and damage local resources ”such as your file system or registry. If you need to assign full runtime permissions to more than one folder simultaneously , see the procedure for adding child nodes to the InfoPath Form Templates node at www.oakleafe.ws/InfoPath/fulltrust.aspx.

Modifying the Text of a Custom Task Pane

InfoPath supports a single custom task pane with HTML and, optionally , JScript or Visual Basic Scripting Edition (VBScript) code that s contained in the HTML resource file you specify on the Advanced tab of the Form Options dialog box. You change the content of a custom task pane by replacing the resource file s code with a String variable containing the revised code. Most custom task panes are view- related , so the most common event handler for changing task pane content is OnChangeView . Retrieving and setting task pane code requires adding a reference to the .NET-enabled Microsoft. mshtml Component Object Model (COM) component and an Imports mshtml statement before or after the Imports Microsoft.VisualBasic statement. Creating mshtml objects requires a fully trusted form.

The Rss2EventsFinal project, located in the C:Microsoft PressIntroducing InfoPath 2003Chapter17Rss2EventsFinal folder, demonstrates dynamically changing the font size of the < div id= helptext > element of the Rss2EventsTaskPane.htm HTML code that s shown on the next page.

 

Following are instructions for completing the InfoPath RSS 2.0 data entry form:

Both form views ”AllSections and ItemsOnly ”have Toggle Task Pane Font Size buttons that execute the ToggleFontSize procedure, shown in Listing 17-1. For simplicity, the code changes the task pane s font size, not its text.

Listing 17-1: Code to toggle the task pane s font size.

Private Sub ToggleFontSize()

Testing for Required Digital Signatures

The Rss2EventsFinal project has two signed data blocks ” ChannelPlusItems (cosign) and Items (countersign). In most cases, each data block should have at least one signature before the form is saved. You can t use declarative programming to test whether the blocks are signed, because the Data Validation feature of the Field Or Group Properties dialog box s Validation And Event Handlers tab is disabled for groups. Conditional formatting doesn t solve the problem, because the Conditional Formatting dialog box s operator list doesn t include an Is Signed item. Thus, you must write a handler for the appropriate event ”usually OnSaveRequest ” to test for missing signatures and give the user the choice of adding missing signatures, saving the form without them, or canceling the save operation. If the signatures are invalid, the user s choices are limited to correcting the invalid signature or canceling the save operation.

This section describes how to add handlers for the OnSaveRequest event and, for testing in preview mode, modify the btnViewItems_OnClick event. Listing 17-2 shows the code for the two event handlers. To complete this section s procedure, you must have a digital signing certificate. The section Obtaining a Digital Signing Certificate, in Chapter 11, describes how to obtain a digital signature from a Microsoft Windows Server 2000 or later certificate server.

Listing 17-2: Digital signature testing requires modifying one event handler and adding another.

_ Public Sub btnViewItems_OnClick(ByVal e As DocActionEvent) If blnIsPreview Then 'For preview testing; call from OnSaveRequest for a live form Dim blnCancel As Boolean = TestDigitalSignatures() thisXDocument.View.SwitchView("ItemsOnly") End If strViewName = " (Items Only)" End Sub _ Public Sub OnSaveRequest(ByVal e As SaveEvent) 'e.IsCancelled = e.PerformSaveOperation 'Invoke the function Dim blnCancel As Boolean = TestDigitalSignatures() e.IsCancelled = blnCancel If Not blnCancel Then 'Save the file e.PerformSaveOperation() End If e.ReturnStatus = True End Sub

Two handlers are required because preview mode disables the File, Save and File, Save As menu items. The blnIsPreview variable, whose value is set in the OnSwitchView event handler, determines which procedure calls the TestDigitalSignatures function. This function returns True if the user clicks the Cancel button of a Condition message box. The function has no data source or form design dependencies, so you can copy it directly into your projects.

Add a custom OnSaveRequest event handler

  1. With the Rss2EventsFinal form opened from Visual Studio in the InfoPath Designer, choose Tools, Form Options to open the Form Options dialog box, and click the Open And Save tab.
  2. Select the Save Using Custom Code check box, and click Edit, which adds an OnSaveRequest event-handling stub at the end of the FormCode.vb window if the event handler isn t present. In this case, the handler is present, so Visual Studio moves the insertion point to the end of the handler s last active statement.
  3. Close the dialog box, and add the code shown in Listing 17-2 inside the OnSaveRequest event handler to handle File, Save and File, Save As operations. If you don t close the dialog box, Visual Studio won t build the project.
  4. Choose Debug, Build Solution or press Ctrl+Shift+B to build the code; don t press F5 because a preview won t test your added code.
  5. Select the Fill Out A Form task pane, open the Rss2EventsFinal form in data entry mode, add a few characters to the Title and Description text boxes, and choose File, Save or File, Save As to test your code.

 SP-1   The TestDigitalSignatures function s code demonstrates use of the SignedDataBlocks collection and its members , the Signatures collection, the Signature object s SignatureRelation property, and the Certificate object s IssuedTo , IssuedBy , and Status properties. The function s code is too lengthy to reproduce here, so do the following to test and, optionally , step through the code.

Test and explore the TestDigitalSignatures function

  1. With the Rss2EventsFinal FormCode.vb window open in Visual Studio, press F5 to build and run the form. Click Yes to close the message box.
  2. Click Yes to hide the task panes, and click the Items Only button if the preview window opens in All Sections view. Otherwise, click All Sections and then Items Only. The initial digital signatures message opens, as shown here on the next page.

  3. Click Yes in the message box to open the Digital Signatures dialog box, add a single signature to each block, and click All Sections and then Items Only to display a message similar to this (ignore messages about missing required values):

  4. Click All Sections and Items Only, add a second copy of your signature to the ChannelPlusItems block, and click All Sections and Items Only again to display a message that cosigning a form with the same certificate is invalid, as shown here:

  5. If you want to add your own digital signature to a previously signed form, close the preview window, reopen the InfoPath designer, choose Fill Out A Form, and click the On My Computer link to display the Open dialog box.
  6. Navigate to the ...Chapter17Rss2EventsFinalRss2EventsFinal folder, double-click the sample Rss2 Date T Time .xml form, which has one signature for each data block, and click OK to acknowledge the digital signing message.
  7. Choose File, Save to display the message shown in step 4. Click Yes, and add your signature as the cosigner of the ChannelPlusItems message block.
  8. Choose File, Save again to display a message similar to that shown here:

Working with the Rss2Production Project

The Rss2Production project, located in your C:Microsoft PressIntroducing InfoPath 2003Chapter17Rss2Production folder, expands on the Rss2EventsFinal project by adding the following features:

The Rss2Production project has all of the important elements that are required to produce RSS 2.0 files for Web content syndication. It s becoming a common practice to include XHTML-encoded full text of weblog items in < body > elements, so Rss2Production includes this capability. The following sections describe the event-handling code that implements the features of the preceding list. The project must run with full trust because saving rss.xml and rss-no_body.xml requires access to the user s or the Web server s file system.

Using an RSS 2.0 Schema to Create a Data Source

You can t add a useful XHTML < body > element to an RSS 2.0 data source that you generate with Jorgen Thelin s rss-2_0.xsd schema, because you can t add an element to the item choice group that the schema generates, and the Rich Text (XHTML) data type isn t available when you add the element to the list repeating group directly. The unmodified schema also generates a large number of option and repeating option groups, which you see when you open the sample ...Chapter17Rss2FromSchemaRss2FromSchema.xsn template in design mode. Modifying the schema by changing xs:choice to xs:sequence groups and making a few other alterations solves the option groups problem and adds a body field with the xs:string datatype to the items group, as illustrated by the sample ...Chapter17Rss2FromSchema Rss2FromModifiedSchema.xsn template.

You can remove InfoPath s restriction on altering the structure and data types of a data source created from an XML schema by making a change to the manifest.xsf file. To do so, extract the form files, close the template, and open manifest.xsf in Notepad. Locate the < xsf:property name =" editability " type="string" value="none" >< /xsf:property > element, change none to partial, and save the change. Open manifest.xsf in design mode, choose File, Save As, and overwrite the original template. The ...Chapter17Rss2FromSchema Rss2FromEditableSchema folder contains a modified template and its form files.

The path of least resistance ”and effort ”in many cases of this type is to create the InfoPath data source from an XML document that has the required structure and real or simulated content and validates with the associated schema. (Rss2Production s data source is ...Chapter17Rss2FromSchemaRss2NewDataSource.xml, which validates with the original rss- 2_0.xsd schema, because the schema s < xs:any ... > elements permit adding undeclared fields and groups.) The final step is to specify the data types for non-string fields and default values, if applicable . The path of least resistance becomes the primrose path if the schema defines complex data types whose values are difficult or impossible to validate ”or conditionally format ”by declarative methods , validation event handlers, or both.

See Also  

For more information about Jorgen Thelin s rss-2_0.xsd schema, visit his Web site, at www.thearchitect.co.uk/weblog/archives/2003/06/000187.html.

Generating a Modified InfoPath Data Document

Some XML applications might require you to modify InfoPath s XML data document to suit a specific XML schema with a data structure, elements, or attributes that InfoPath doesn t support directly. An example is the item group s body field, which is an RSS 2.0 extension element that requires a < body xmlns="http://www.w3.org/1999/xhtml" > element. InfoPath won t let you add xmlns as an attribute name, because it s an XML reserved word and the InfoPath team considers it invalid in this context. Thus, you must generate and save a modified file to work around RSS 2.0 s use of this namespace to support RSS news reader/aggregator applications that recognize the < body > extension.

The OnClick event of the Save rss.xml buttons in both views calls the SaveRssToFile procedure, which creates the local rss-no_body.xml validation file and the production rss.xml file. The procedure s code requires adding a reference to the System.Xml namespace and adding Imports System.Xml , Imports System.IO , and Imports System.Text statements to simplify class references.

The code for SaveRssToFile is too lengthy to present here, so do the following to learn how the procedure works and how to debug a form connected to the INFOPATH.EXE process.

Explore the SaveRssToFile procedure

  1. Navigate to the C:Microsoft PressIntroducing InfoPath 2003Chapter17Rss2ProductionRss2ProductioninDebug folder, and open Rss2Production.xsn in design mode.
  2. Choose Tools, Form Options to open the Form Options dialog box. Click the Security tab, clear the Automatically Determine Security Level Based On Form s Design (Recommended) check box, select the Full Trust option, select the Sign This Form check box to apply your default code signing certificate, and click OK.
  3. Save your changes, and close InfoPath.
  4. Double-click the Rss2Production.sln file in the ...Chapter17Rss2Production Rss2Production folder to open the project in Visual Studio, and close the InfoPath design window. If the FormCode.vb window isn t visible, open it from Solution Explorer.
  5. Open Windows Explorer and double-click ShortOakLeafSiteRss.xml in the same folder to open a form that has a single item element and start the INFOPATH.EXE process.
  6. Return to Visual Studio s FormCode.vb window, and choose Tools, Debug Processes or press Ctrl+Alt+P to open the Processes dialog box. Double-click the INFOPATH.EXE process item to open the Attach To Process dialog box.
  7. Select the Common Language Runtime check box, if it isn t selected, and click OK to close the dialog box. The Processes dialog box appears as shown here:

  8. Leave the remaining defaults, click Close to return to the FormCode.vb window, navigate to the SaveRssToFile procedure s For intFile = 0 To 1 statement, and press F9 to set a breakpoint on the line.
  9. Display the ShortOakLeafSiteRss form, and click the Save rss.xml button to activate Visual Studio and position the cursor on the breakpoint.
  10. Pass the cursor over the last strRSS = statement to view the XML data with the processing instructions, white space, and unneeded attributes removed and the local XHTML namespace added to the < body > element.
  11. Press F11 repeatedly to create a StringBuilder object that holds the formatted XML string for the rss-no_body.xml file, and create the NameTable , XmlNameSpaceManager , and XmlParserContext objects required to create a namespace-aware XmlTextReader object, which is a fast, forward-only reader for XML documents. The Do While xtrRSS.Read loop formats the document with carriage return/ linefeed pairs and two-space indents per element level.

    See Also  

    For more information about the XmlTextReader class, choose Help, Index, and type XmlTextReader in the Look For box, filtered by Visual Basic. Double-click the XmlTextReader Class entry, double-click Reading XML Data With XmlTextReader in the Index Results pane, and follow the topic s links. A namespace-aware XmlTextReader isn t required for this document, but one might be needed for documents with namespace-qualified elements.

  12. To check the current StringBuilder contents, open the Command Window, and type ? sbDoc.ToString.
  13. Add a breakpoint on the strDoc = sbDoc.ToString statement, press F5 when you re tired of stepping through the first loop, press F11 once, and pass the mouse pointer over the statement to display the formatted text, as shown here. Notice that white space replaces the < body > element in this loop.

  14. Continue stepping through the two instructions that test the document for well- formedness by loading it into an XmlDocument object, and step into the ValidateNoBodyDocument procedure, which is the subject of the next section.

The reasons for using the System.Xml.XmlTextReader object to generate the new document are the ability to return the level property value for indentation, faster execution speed, and a smaller memory footprint than a native XmlDocument or a wrapped IXMLDOMDocument object. Alternatively, you can apply an XSL transform from an .xsl file or replace the StringBuilder object with an XmlTextWriter object ”either approach is a more complex undertaking.

Validating the XML of the rss no_body Document

It s a good programming practice to validate XML documents against their schema before passing them to a workflow application or ”for this example ”a public Web site. InfoPath won t generate a document that violates its schema, which includes data validation rules, but variations you generate with code need validation. You can use the GotDotNet validating parser that s described in the section Validating an XML Document Against an InfoPath Schema, in Chapter 3 for initial test purposes, but prudence dictates that every modified document should be validated before its use in a production environment. Listing 17-3 contains the code for the ValidateNoBodyDocument procedure and its ValidationError event handler, which validate the rss-no_body.xml file.

Private Sub ValidateNoBodyDocument(ByVal strDoc As String)

Listing 17-3: Code to validating a document against the rss-2_0.xsd schema.

'Validate the no

version against the RSS 2.0 schema Dim strRssSchema As String = strRssPath + " ss-2_0.xsd" If File.Exists(strRssSchema) Then strErrors = "" 'Create a schema collection and add the rss-2_0.xsd schema Dim xscRSS As New XmlSchemaCollection xscRSS.Add("", strRssSchema) 'Create a StringReader, XmlTextReader, and XmlValidatingReader Dim srRSS As New StringReader(strDoc) Dim xtrRSS As New XmlTextReader(srRSS) Dim xvrRSS As New XmlValidatingReader(xtrRSS) With xvrRSS 'Specify the validation type (XSD) and add the schema .ValidationType = ValidationType.Schema .Schemas.Add(xscRSS) 'Specify a ValidationError event handler AddHandler .ValidationEventHandler, _ AddressOf ValidationError While .Read 'Process the document End While .Close() End With Else strErrors = "The schema file ('" + strRssSchema + _ "') is missing. Can't validate the document." End If End Sub Private Sub ValidationError(ByVal sender As Object, _ ByVal args As ValidationEventArgs) 'Event handler for intercepting validation errors strErrors += args.Message.ToString + vbCrLf End Sub  

The System.Xml.Schema namespace provides an XmlSchemaCollection class to which you add the contents of one or more schema files, identified by their namespaces. This example uses a single schema, rss-2_0.xsd, for a document without a global namespace declaration. You use an XmlValidatingReader object, which is derived from the preceding section s XmlTextReader class. You specify the values of the XmlValidatingReader object s ValidationType and Schema properties and designate an event handler for exceptions raised by validation failures. As the XmlValidatingReader reads the document, elements or attributes that fail validation invoke the ValidationError event handler that you specify in the Add Handler [xvrRSS].ValidationEventHandler, AddressOf ValidationError statement. You must add the code for this event handler manually.

In Visual Studio, press F11 repeatedly to step through the code of the ValidateNoBodyDocument procedure. Add a breakpoint on the If intFile = 1 Then statement, and press F5 to continue.

Saving a Modified InfoPath Data Document as rss xml

The remaining code of the ValidateNoBodyDocument procedure, shown in Listing 17-3, uses a StreamWriter object to save rss-no_body.xml in the first loop iteration and, if the user clicks Yes in the Confirm message box, saves rss.xml in the second iteration. The Dim stwRSS As StreamWriter = New StreamWriter(strFile, False, Encoding.UTF8) constructor statement specifies overwriting earlier versions of strFile without warning and using default UTF-8 encoding. You can simplify the statement by substituting StreamWriter(strFile) , which assigns the overwrite and UTF-8 defaults. The stwRSS.Write(strDoc) statement writes to the stream, stwRSS.Flush ensures that the full stream is written to disk, and stwRSS.Close closes StreamWriter and releases the lock on the file. (A production form wouldn t save rss-no_body.xml; the file is for debugging purposes only.)

Adding a Custom Form Toolbar and Buttons

Toolbar buttons and menus are useful for changing views or initiating tasks in a specified sequence. Users also appreciate toolbar buttons for tasks that might require scrolling the form to make form buttons visible. When users add new item elements to the form in AllSections view, the Items Only and Save rss.xml buttons might not be visible, depending on display resolution. The sample form s AllSections view has Insert New Item Above, Items Only View, and Save rss.xml File buttons. The form toolbar and Insert New Item Above buttons are defined in the Section Commands dialog box, which opens from the Repeating Section Properties dialog box.

The Items Only View and Save rss.xml File buttons are custom buttons that are defined by adding button definition elements to the appropriate view definition in manifest.xsf. The button definition includes the name of an event-handling procedure for the button s OnClick event. The following code in manifest.xsf defines the AllSections form toolbar and its three toolbar buttons.

 

Here s the basic event-handling code for the two custom toolbar buttons:

_ Public Sub btnSaveRssFileTB1_OnClick(ByVal e As DocActionEvent) 'Toolbar button on AllSections view Call SaveRssToFile() End Sub _ Public Sub btnItemsOnlyTB1_OnClick(ByVal e As DocActionEvent) 'Toolbar button on AllSections view strViewName = " (Items Only)" thisXDocument.View.SwitchView("ItemsOnly") End Sub

If the button s name attribute value isn t identical to the event handler s MatchPath attribute value or the event handler isn t present, the preview window won t open when you press F5 to build and run the project. If you click the designer s Preview Form button, you receive an error message that displays the offending button s name.

To add a form toolbar and a set of buttons similar to the ItemsOnly view, follow these steps.

Add a form toolbar and button in the designer

  1. With the ItemsOnly view active in the InfoPath Designer, right-click the Repeating Section tab, and choose Properties from the shortcut menu to open its Properties dialog box.
  2. Click the Modify button to open the Section Properties dialog box, and click Customize Commands to open the Section Commands dialog box.
  3. Select Insert Above in the Action drop-down list, and select the Form Toolbar check box.
  4. Type Insert New Item Above in the Command Name box, and type Insert the latest item at the top of the list in the ScreenTip box, as shown here:

  5. Click OK three times to close the dialog boxes, and save your change.
  6. Preview the form, click the repeating section s selection button to enable the toolbar button, and verify its operation.
  7. Close the preview window, and close Visual Studio. You can t save form files when the project is open in Visual Studio.

Add two custom button definitions to manifest.xsf

  1. Navigate in Windows Explorer to the ...Chapter17Rss2Production Rss2Production folder, make a backup copy of manifest.xsf, and open manifest.xsf in Notepad.
  2. Search for the first Form toolbar instance, and copy the two custom button definition elements to the Clipboard.
  3. Search for the next Form toolbar instance, which you added in step 5 of the preceding procedure, and paste the elements below the only button definition element.
  4. Change Items Only View to All Sections View, btnItemsOnlyTB1 to btnAllSectionsTB2, and btnSaveRssFileTB1 to btnSaveRssFileTB2, as shown here:

  5. Save your changes, and reopen the Rss2Production.sln project in Visual Studio. If you receive an error message on opening the project, restore the backup copy of manifest.xsn, and repeats steps 2 through 4.
  6. Copy and paste the btnSaveRssFileTB1_OnClick event handler below the original version, and change both instances of btnSaveRssFileTB1 to btnSaveRssFileTB2.
  7. Search for btnViewAll , copy and paste the btnViewAll_OnClick event handler below the original, change both instances of btnViewAll to btnAllSectionsTB2, and save your changes.
  8. Press F5 to open a preview window. If the preview window doesn t open or displays an error message, open manifest.xsf, and verify that you completed steps 4 through 7 correctly. The ItemsOnly view with the repeating section selected appears as shown here:

Using the Errors Collection

Conditional formatting disables the Save rss.xml form button if the form has data validation errors. You can t control the enabled state of a custom toolbar button with managed code or script, so users can save an invalid rss.xml file. The rss-2_0.xsd schema requires content only in the pubDate and link fields. If you don t test for errors and the user deletes all text box content in the item repeating group, a validation error message appears, as shown in Figure 17-4. If content required by the schema is present, but the title and description field are empty, the user can save the invalid data.

Figure 17-4: This validation error message appears when you attempt to save an rss.xml file with all content removed from the item repeating group.

InfoPath has an Errors collection that lets you detect data validation errors by testing for a nonzero value of the collection s Count property. The TestFormForErrors function, shown in Listing 17-4, tests for data validation errors and, if errors are present, displays an error message, such as that shown in Figure 17-5. Specifying custom data validation rules for required fields ”rather than selecting the Cannot Be Blank check box ”provides a more informative error message.

Figure 17-5: This error message appears when the user makes no changes to the default item section in the AllSections view and clicks the Save rss.xml button.

Listing 17-4: This function detects data validation errors.

Private Function TestFormForErrors() As Boolean 'Test for form errors: Return True if none, False if errors exist 'This test is required for toolbar buttons only Try Dim intErrs As Integer Dim colErrors As ErrorsCollection = thisXDocument.Errors If colErrors.Count = 0 Then 'Form is OK Return True Else 'Display a detailed error alert Dim strMsg As String Dim intErr As Integer With colErrors strMsg = "You can't save the rss.xml file because " + _ the form has " + .Count.ToString + " errors:" + _ vbCrLf + vbCrLf 'Loop runs in reverse due to the sequence of addition 'of the validation rules for the fields For intErr = .Count - 1 To 0 Step -1 strMsg += "Error " + (.Count - intErr).ToString + ": " strMsg += .Item(intErr).ShortErrorMessage + vbCrLf Next intErr thisXDocument.UI.Alert(strMsg) End With Return False End If Catch excErr As Exception thisXDocument.UI.Alert(excErr.Message + excErr.StackTrace) End Try End Function

The ShortErrorMessage value is the text you add to the Data Validation dialog box s Message box. Members of the Errors collection appear in the order of their addition to the manifest.xsf file; the title and description field s validation rules were added after the rules for the link and guid fields. Matching the error numbers to the sequence of the fields on the form requires the loop to display the last error first.

Copying Data Between Fields

If your forms have fields that contain duplicate information or values derived from other field data, you can minimize data entry time and typographic errors by copying the text from the source to destination fields. The Rss2Production form has two fields that usually contain the same data: body duplicates description, and guid duplicates item. The user adds HTML markup and additional formatted content to the copied body text. For this example, all Web site content is permanent, so the link and guid values are the same, and the isPermaLink field value is true by default.

Listing 17-5 shows the code for the description and link fields OnAfterChange event handlers. Both procedures use the parentNode property to select the current item group and then copy the text to the appropriate node if it s empty or, for guid, if it contains the default value.

Listing 17-5: Procedures for copying description and link fields.

_ Public Sub item_description_OnAfterChange(ByVal e As DataDOMEvent) 'Copy description to body if body is empty If e.IsUndoRedo Or e.Operation = "Delete" Then Return End If Dim strDescr As String = e.Source.nodeValue.ToString If strDescr <> "" Then 'Update the body element Dim nodBody As IXMLDOMNode = _ e.Source.parentNode.selectSingleNode("//body") If nodBody.text = "" Then nodBody.text = strDescr End If Exit Sub End If End Sub _ Public Sub item_link_OnAfterChange(ByVal e As DataDOMEvent) 'Copy the link value to guid, if guid hasn't been updated If e.IsUndoRedo Or e.Operation = "Delete" Then Return End If Dim strLink As String = e.Source.nodeValue.ToString If strLink <> "http://www.oakleaf.ws/" And strLink <> "" Then 'Update the guid element Dim nodGuid As IXMLDOMNode = _ e.Source.parentNode.selectSingleNode("//guid") If nodGuid.text = "http://www.oakleaf.ws/" Then nodGuid.text = strLink End If End If End Sub

Specifying a Form to Open in All Preview Windows

 SP-1   Choosing File, Preview, With Data File in the designer or Tools, Preview With Data File in Visual Studio opens a Choose Data File To Preview dialog box, from which you can navigate to and select an .xml file to open. When you re debugging a project that has required fields, such as Rss2Production, it s usually easier to type required values than to navigate from My Documents to the location of your test file.

InfoPath projects let you assign the test form to use in all project preview windows by specifying the file path and name in the Project Properties dialog box. To assign a test document as the default preview data file, follow these steps.

Assign an InfoPath XML data document as the preview window default

  1. Open Solution Explorer, right-click the ProjectName node under the Solution node, and choose Properties from the shortcut menu to open the ProjectName Property Pages dialog box. (The ProjectName node appears in boldface, because it s the startup project.)
  2. Click the button to the right of the Preview Data File Path box to open the Select Data File To Use For Preview dialog box, navigate to folder containing the test file, and double-click the file to assign to the project, as shown here:

  3. Click OK to close the dialog box, and press F5 to open the preview window to verify that the preview window appears as expected with your test document.

Selecting the ...Chapter17Rss2ProductionRss2ProductionShortOakLeafSiteRss.xml document assists testing regular expressions, which you ll do in the next section.

Validating Data with Complex Regular Expressions

 SP-1   The rss-2_0.xsd schema includes regular expression (pattern) tests for dates (pubDate and lastBuildDate) and e-mail addresses (managingEditor and webMaster). Following is the schema s definition of the tRfc822FormatDate type for a channel group s lastBuildDate and channel or item group s pubDate fields:

A date-time displayed in RFC-822 format. Using the regexp definiton of rfc-822 date by Sam Ruby at http://www.intertwingly.net/blog/1360.html

The preceding pattern, which has line breaks added for readability, grants much more date formatting latitude than the RSS 2.0 specification permits. The expression permits omitting the day of the week, two-digit years are allowed, and seconds are optional. The time zone can be represented by a +/- four-digit time offset from GMT or any U.S. time zone. Boldface type identifies elements that must be removed to create a pattern that ensures conformance with the RSS 2.0 specification s RFC822-based date/time format. Although the specification allows two-digit years, it recommends four-digit years .

Following is the simplified regular expression for validating the item repeating group s pubDate values to the RSS 2.0 specification and recommendation:

(((Mon)(Tue)(Wed)(Thu)(Fri)(Sat)(Sun)), )dd? +((Jan)(Feb)(Mar)(Apr)(May)(Jun)(Jul)(Aug)(Sep)(Oct)(Nov)(Dec)) +dddd? +dd:dd:dd? +(GMT)

Figure 17-6 shows the Data Entry Pattern dialog box displaying the first part of the expression and an example of a conforming entry.

Figure 17-6: The Data Entry Pattern dialog box, which opens from the Data Validation or Conditional Formatting dialog box, displays an example of an entry that matches the pattern.

You can verify that the pattern works in an Rss2Production preview window by removing the day of the week, required digits of dates and times, or GMT and then pressing Tab. Typing invalid characters in any date element also causes a validation failure. The conditional formatting rules for the Save rss.xml button also include a pattern-matching test for the preceding regular expression.

The schema s pattern for e-mail addresses, which validates the managingEditor field, is shown here:

([a-zA-Z0-9_-])([a-zA-Z0-9_-.]*)@ ([((25[0-5]2[0-4][0-9]1[0-9][0-9][1-9][0-9][0-9]).) {3}((([a-zA-Z0-9-]+).)+))([a-zA-Z]{2,}(25[0-5]2[0-4][0-9] 1[0-9][0-9][1-9][0-9][0-9])])

This pattern permits combinations of letters and numbers, hyphens, and underscores in the name and a valid domain name as the address component. In this case, the Data Entry Pattern dialog box s example is somewhat misleading; open the Data Validation dialog box for the managingEditor field to see the example pattern: --@[250.250.250.AA .

See Also  

For more information about regular expressions, go to msdn.microsoft.com , type "Regular Expression Support" (include the quotation marks) in the Search For box, select the Regular Expression Support in Microsoft Office System Smart Tags topic, and click the link A Brief Introduction To Regular Expression Syntax. The .NET Regular Expression Repository at www.3leaf.com/resources/articles/regex.aspx has a regular expression tester and a tutorial that offers several useful patterns for validating form data. The rss-2_0.xsd schema s e-mail pattern is one of the site s sample regular expressions.

Displaying Running Sums in an Expression Box

One of the fundamental rules of database design is to eliminate storing in tables duplicate data or information that s calculated from database column values. Using the NorthwindCS database as an example, storing the extended net amount of an Order Details record in an Extended column requires updating the Extended value whenever the Quantity or Discount values change. Similarly, storing the sum of Extended values as the total order amount ”less freight, taxes, and other charges ”requires recalculating this value each time an Extended value changes or line items are added to or deleted from the order. The most common practice is to create views or stored procedures that provide calculated values. Views with calculated values aren t updatable.

The preceding rule doesn t apply to XML documents that you generate from databases because each document is a static representation of the column values at the time the document is created. Thus you can add to a basic InfoPath form fields that store calculated data. However, if you create your form s main data source from a database or Web service, you can t add calculated fields to the main data source, because the schema is locked. You must use expression boxes to display calculated values in database or Web service client forms.

The section Calculating Values with the Expression Box, in Chapter 6, describes how to add an Extended Amount expression box to display net extended values. Displaying a running sum of Extended Amount values with an expression box in the table footer is a more complex process. You add an expression box to the table footer, relocate and modify the ViewName .xsl file s expression box definition, and then add a function that calculates the running sum from the repeating table s element values and returns the value to the expression box. InfoPath doesn t offer a means for summing the values of the row s expression boxes.

The ExprBoxSumProject in the C:Microsoft PressIntroducing InfoPath 2003 Chapter17ExprBoxSumsExprBoxSumProject folder is a simple running sum example. This project is an upgraded version of a sample form posted by Microsoft s Joel Alley in the microsoft.public.infopath newsgroup. The project sums an element and attribute value with an XPath expression to populate the row s expression box and generates a running sum in the table footer, as shown in Figure 17-7.

Figure 17-7: This form, which demonstrates calculating running sums of repeating table values, is an upgraded version of a Microsoft sample project from the InfoPath newsgroup.

Note  

Upgrading VBScript code to Visual Basic .NET

The original Microsoft sample form is one of the few examples that use VBScript rather than JScript. The InfoPath product team has a predilection for JScript and Visual C#, which undoubtedly has contributed to many VBScript, VBA, Visual Basic 6, and Visual Basic .NET programmers perceiving themselves as second-class citizens . Most forms that use VBScript code will build in Visual Basic .NET with Option Strict Off and, in some cases, Option Explicit Off compiler directives. Build errors that appear in the Task List usually are easy to correct. The original VBScript code for the project, which is included in the project s FormCode.vb file, required only one minor change to compile with Option Explicit On .

Here are the basic steps for adding a running sum expression box to a table footer.

  1. Add a table footer, if it s missing, and insert an expression box control under the column you want to sum.
  2. Close the project, create a backup copy of ViewName .xsl file, and open ViewName .xsl in Notepad. Locate the element that defines the expression box, cut the element to the Clipboard, and replace the element with an < xsl:apply- templates match= groupName mode= xd:preserve / > instruction. If your form has a single group , substitute . , which represents the data source s root element, for groupName . The mode= xd:preserve attribute prevents InfoPath from deleting the element and its children when you make subsequent design changes to the form.
  3. Add an < xsl:template match= groupName mode= xd:preserve / > starting element, paste the code you cut below the element, and add an < /xsl:template > closing element. In this case, you can t replace groupName with . .
  4. After the < span ... / > element, add an < xsl:value-of select="xdExtension:functionName(XPathPointerToTableRowDataSource)"/ > element that calls functionName with an IXMLDOMNodeList argument value that represents all nodes of TableRowDataSource . The xdExtension: prefix is required to call a script or managed code function.
  5. Save the ViewName .xsl file, open the file in Internet Explorer to verify that it s well- formed , and close Internet Explorer and Notepad.
  6. Reopen the project in Visual Studio, add the Public Function functionName(ByVal objNodeSet As IXMLDOMNodeList) As dataType stub, and write the code to iterate the rows and column values to generate the running sum.
  7. Preview the form to test your work.

You can use the same approach to display in table footer cells averages or other values that you can t create with declarative XPath statements.

To test your XSLT editing skills, follow these steps to duplicate the ExprBoxSumProject s running sum expression box from a sample project without the expression box in the ...Chapter17ExprBoxSums ExprBoxSumExercise folder.

Add and test a running sum expression box

  1. Navigate to the ...Chapter17ExprBoxSumsExprBoxSumExercise folder, and double-click ExprBoxSumProject.xsn to open the project and display the InfoPath designer.
  2. Click the task pane s Controls link, and drag an Expression Box control to the repeating table s rightmost column. Leave the XPath box empty, and click OK to add the expression box.
  3. Save your design change, close the project so that you can edit the view1.xsl file, make a backup copy of view1.xsl, and open view1.xsl in Notepad with Word Wrap enabled.
  4. Search for the third and last instance of xdExpressionBox , which is associated with code similar to this:

     

    The second instance of xdExpressionBox is the table row s expression box. (The xd:CtrlId attribute value s number might differ .)

  5. Select the entire < span ... / > element, and cut it to the Clipboard. Replace the code you deleted with the < xsl:apply-templates match= . mode= xd:preserve / > instruction. The < div > ... < /div > element code appears as shown here:

     

    This instruction runs the template you add in the next few steps.

  6. Move to the end of the file. Immediately above the < /xsl:stylesheet > element, add an < xsl:template match= my:myFields mode= xd:preserve / > line, paste the code you cut below this line, add an ending < /xsl:template > element, and indent the < span ... > element. The last few lines of the stylesheet appear as shown here:

     

  7. Immediately after the < span ... / > element, add an < xsl:value-of select="xdExtension:testFunction(//my:sampleTable/my:sampleRow)"/ > element that calls testFunction with a IXMLDOMNodeList argument; testFunction calculates and returns the running sum as a Double value. Your template code now appears as shown here:

     

    The project includes the testFunction code, so you don t need to add it.

  8. Save your changes, return to Windows Explorer, and double-click view1.xsl to open it in Internet Explorer. Scroll to the end of the page to verify that your template is well-formed.
  9. Close Internet Explorer and Notepad, and reopen the project. The form in design mode appears as shown here:

    The Preserve Code Block control results from elements with the mode= xd:preserve attribute you added in steps 5 and 6.

  10. Preview the form, and verify that the running sum value is correct.

If you experience problems with the preceding procedure, use Notepad or Internet Explorer to compare your modifications to view1.xsl with the version in the ...Chapter17ExprBoxSumsExprBoxSumProject folder.

Exploring the NWOrdersWSProject Web Service Client

The NWOrdersWSProject.sln solution in your C:Program FilesIntroducing InfoPath 2003Chapter17NWOrdersWSNWOrdersWSProject folder is a major upgrade to the original NWOrdersWS Web service client that you developed in Chapter 14, Designing InfoPath Web Service Clients . Figure 17-8 shows the upgraded version with an added Insert Order button and several enhancements to the OrderDetail repeating table. The original version, NWOrdersWS.xsn, is in the Chapter17NWOrdersWS folder.

Figure 17-8: NWOrdersWSProject is an upgraded version of Chapter 14 s NWOrdersWS template that adds the capability to insert a new order and adds new features to the OrderDetail repeating table.

Because NWOrdersWSProject has more than 500 lines of commented Visual Basic .NET code, reproducing the code here isn t practical. To get the most out of this section, open NWOrdersWSProject.sln, and examine the code. The sequence of event handlers, functions, and a procedure in the FormCode.vb window follows the order of this list of form features added by managed code:

NWOrdersWSProject.sln demonstrates that you can design and deploy a production- quality Web service client with InfoPath SP-1. You could implement all the preceding features with JScript or VBScript, but writing managed Visual Basic .NET or Visual C# code in Visual Studio .NET makes debugging much easier and enables advanced features that are very difficult or impossible to implement with script. As an example, you can write managed code in an OnSubmitRequest event handler for a Web service that requires SOAP headers. If you re an accomplished ASP.NET Web services programmer and have Web Services Enhancements (WSE) 2.0 installed, you can implement the WS-Security specification s digital signing feature, which eliminates the need to customize Web services to accommodate InfoPath form-level digital signatures and offers the added security of encrypted transmission. WSE 2.0 also lets you consume Web services that implement the WS-Addressing, WS-Policy, WS-SecurityPolicy, WS-Trust, and WS- SecureConversation specifications.

See Also  

For more information about WSE 2.0, go to msdn.microsoft.com/ webservices / , and choose Building, Web Service Enhancements (WSE) from the menu. For the details of Microsoft s implementation of the WS-series specifications, visit msdn.microsoft.com/webservices/understanding/advancedwebservices/ .

Creating Your Own NWOrdersWS Web Service

Relying on third-party Web services is chancy if the Web service publisher doesn t provide quality-of-service guarantees . The OakLeaf Demonstration Web site, which is connected to the Interned by a DSL line, has had 99.3 percent uptime for two years , but there s no guarantee that this level of service will continue indefinitely. Thus, there s the possibility that you won t be able to connect to the NWOrdersWS Web service at www.oakleaf.ws/nwordersws/nwordersws.asmx . Visual Studio .NET makes creating ASP.NET Web services a quick and easy process, so you might want to create a local ASP.NET Web service as a learning exercise, as well as for insurance against an inability to run the OakLeaf demonstration service.

To create the NWOrdersWS virtual directory for the local Web service, follow these steps.

Add an Internet Information Services (IIS) virtual directory

  1. Navigate to the Inetpub wwwroot folder, and add a new folder named NWOrdersWS. Alternatively, you can add the folder in step 4.
  2. Open IIS Manager, right-click the Default Web Site node, and choose New, Virtual Directory from the shortcut menu to start the Virtual Directory Creation Wizard. Click Next.
  3. In the Virtual Directory Alias dialog box, type NWOrdersWS, and click Next.
  4. In the Web Site Content Directory dialog box, click Browse, navigate to and select the folder you created in step 1, click OK, and click Next.
  5. Click Next to accept the default access permissions, and click Next and Finish to add the virtual directory and close the wizard.
  6. Right-click the NWOrdersWS node, choose Properties from the shortcut menu to open the NWOrdersWS Properties dialog box, and click the Directory Security tab.
  7. Click the Edit button in the Authentication And Access Control section to open the Authentication Methods dialog box. Select the Enable Anonymous Access check box (if it isn t selected), click OK twice to close dialog boxes and apply the change, and close IIS Manager.
  8. If you have Windows SharePoint Services installed on your test server, use the SharePoint Central Administration tool to exclude the NWOrdersWS virtual directory from SharePoint management, as described in the note in the section Obtaining a Digital Signing Certificate, in Chapter 11.

You must run the NWOrdersSP.sql Transact-SQL script to create the stored procedures for the main and secondary data sources. Substitute SQL Server 2000 s sample Northwind database if you aren t running MSDE 2000 with the NorthwindCS database. You can t add the stored procedures as a group in the Stored Procedure box of an Access 2000 or later data project, so you must use the command-line osql.exe tool if you don t have SQL Server Query Analyzer installed. You also must change the Order Details table s Discount data type from real to decimal(4,3) to avoid rounding errors that affect the expression box s value.

To create the stored procedures with osql.exe and fix the Discount data type problem, follow these steps.

Add stored procedures to NorthwindCS with the osql utility

  1. Open a Command Prompt window, and navigate to the C:Microsoft PressIntroducing InfoPath 2003Chapter17NWOrdersWS folder.
  2. Type osql -E -d NorthwindCS -i NWOrdersSP.sql, and press Enter. This command uses Windows authentication for the local (default) SQL Server instance, specifies the NorthwindCS database, and runs the NWOrdersSP.sql script.
  3. Type quit, and press Enter to exit osql. Close the Command Prompt window.
  4. Start Access 2002 or later, open the sample NorthwindCS.adp project in your ...Microsoft OfficeOffice{1011}Samples folder, and open the Order Details table in design view.
  5. Change the data type of the Discount column to decimal, and set Precision to 4 and Scale to 3 to accommodate three decimal places, as shown here:

    The Discount column inherited values with rounding errors from the Jet version. Rounding errors cause InfoPath expression boxes to display NaN (not a number) messages for some discount values instead of expected numeric values.

  6. Close the Order Details: Table window, click Yes to save your changes, and click Yes in the Save window.

    Caution  

    If you don t complete steps 5 and 6, invoking the GetOrderSP and UpdateOrInsertOrderSP Web methods throws an Invalid OrderID value SOAP exception. If you don t have Access 2002 or later, you must make this data type change with SQL Server Enterprise Manager.

  7. Click the Queries button, and verify that the four stored procedures ”ipGetOrder, ipInsertDetail, ipInsertOrder, and ipUpdateOrder ”are present in the list.
  8. Double-click ipGetOrder, type a valid OrderID value ”such as 11076 ”in the Enter Parameter Value box, and click OK to display values for the order; Order Details values don t appear in the grid.

In this section s final procedure, you ll create and test a local copy of the NWOrdersWS Web service with the NWOrdersWSLocal.xsn solution in the ...Chapter17NWOrdersWSNWOrdersWSLocal folder.

Create and test the NWOrdersWS Web service

  1. Open Visual Studio, and choose File, New, Project. Select Visual Basic Projects, click ASP.NET Web Service, change the Location text to http://localhost/NWOrdersWS, and click OK to create the project in the virtual directory folder.
  2. Open Solution Explorer, and change Service1.asmx s name to NWOrdersWS.asmx. Right- click the node, and choose View Code from the shortcut menu to display the default Web service stub. Delete all code.
  3. Navigate to the C:Microsoft PressIntroducing InfoPath 2003Chapter17NWOrdersWS folder, and double-click NWOrdersWS.txt to open it in Notepad. Press Ctrl+A, Ctrl+C to copy the code to the Clipboard, and then return to Visual Studio and paste the code.
  4. If the SQL Server sa account is password-protected, search for pwd= and add the password after the equal sign in both connection strings.
  5. Press F5 to build the Web service and display the help document for the service, as shown here:

  6. Verify the database connection by clicking each of the Get... method links to open the test page for the method and clicking Invoke to display the SOAP response message payload. The GetOrderSP method requires a valid OrderID parameter, as shown here:

  7. Open NWOrdersWSLocal.xsn from the ...Chapter17NWOrdersWS NWOrdersWSLocal folder and verify that the query, update, and insert operations behave as expected.

Changing the URL of a Web Service

It s a common practice to design and test new ASP.NET Web services on a local computer or development Web server and then migrate the service to a production server after testing. Changing the URL for a Web service in Windows or Web form clients is easy; the process is more complex for InfoPath Web service consumers.

 SP-1   InfoPath lets you use the Data Connection Wizard to change the location (URL) and the namespace of the form s main and secondary data sources. If you have several data sources, making these changes with the wizard is tedious and fraught with opportunity for generating fatal errors, which you don t discover until you save the changes to the template. Changing data sources substitutes ns2: for the default s0: namespace prefix in most extracted template files and InfoPath event-handler attributes, but not in the XPath expressions of code you write.

A faster and less error-prone approach is to make the required serviceUrl , soapAction , and xmlns:s0 namespace changes to the project s manifest.xsf, .xml, and .xsl files directly. Here are the basic steps.

Make namespace changes directly in project files

  1. Obtain the new serviceUrl , soapAction , and xmlns:s0 namespace values from the location , soapAction , and targetNamespace values of the relocated service s Web Services Description Language (WSDL) document.
  2. Replace the serviceUrl and soapAction values in the manifest.xsf file.
  3. Replace the xmlns:s0 namespace value in the manifest.xsf, .xml, .xsl, and FormCode.vb files.

Note  

Expediting the search and replace process

A multifile Notepad replacement ”such as Just Great Software s EditPad Lite (free for noncommercial use) or EditPad Pro ”speeds the replacement process. You can download either version from www.editpadlite.com .

The following procedure requires creating the local version of the NWOrdersWS Web service, as described in the preceding section. To change the NWOrdersWS Web service location from www.oakleaf.ws/nwordersws/nwordersws.asmx to localhost/nwordersws/nwordersws.asmx , follow these steps.

Change the URL of a copy of NWOrdersWSProject

  1. Create a copy of the NWOrdersWSProject folder in your ...Chapter17 NWOrdersWS folder, and rename the folder to NWOrdersWSTest or the like.
  2. Open Solution Explorer, right-click the NWOrdersWSProject node (immediately under the Solution node), and choose Set As StartUp Project from the shortcut menu.
  3. Rename the solution file to NWOrdersWSTest, right-click the Solution node, and choose Save NWOrdersWSTest.sln.
  4. Double-click FormCode.vb in Solution Explorer, press F5, verify that the preview works with the OakLeaf Web service, and then close the project. Optionally, remove NWOrdersWSProject.sln and NWOrdersWSProject.suo to avoid confusion with the source project.
  5. Open http://localhost/nwordersws/nwordersws.asmx?wsdl in Internet Explorer, and note the location , soapAction , and targetNamespace attribute values.
  6. If you re using a multifile editor, select manifest.xsf, FormCode.vb, and all .xsd, .xml, and .xsl files to edit simultaneously . Otherwise, skip to step 9.
  7. For this example, replace www.oakleaf.ws with localhost.
  8. Replace oakleaf.ws with localhost, and save all changes. (The sequence of steps 7 and 8 is important.) Skip the remaining steps.
  9. If you re using Notepad, make the changes in steps 7 and 8 to manifest.xsf, and save the changes. (The manifest.xsf file is the only file that contains serviceUrl and soapAction values.)
  10. Make the changes in step 8 to FormCode.vb, and to each .xsd, .xml, and .xsl file in your project.

Test the project and fix a potential OrderDate problem

  1. Reopen NWOrdersWSTest.sln, press F5 to build the project, and open the preview window.
  2. Run a query with several of the last 10 orders, including those with non-Null ShipDate values.
  3. If the Ship Date date picker value is today s date for all queries, perform the following steps. Otherwise, skip to step 8.
  4. Close the preview window, and open InfoPath in design mode. Click the Data Source link, expand the Date Fields node, and right-click OrderDate and choose Properties from the shortcut menu to open its Properties dialog box.
  5. Change the default value from now() to 1/1/2001, click OK, and save your changes.
  6. Add the following code immediately after the Try statement of the OnContextChange event handler:

    Dim nodOrderDate As IXMLDOMNode = _ e.XDocument.DOM.selectSingleNode("//s0:OrderDate") If Not nodOrderDate Is Nothing Then If nodOrderDate.text = "2001-01-01T00:00:00" Then nodOrderDate.text = DateTime.Now.ToString("s") End If End If

    This code runs only when the form opens and solves a problem that can occur when you use a computed rather than a fixed default value for dates.

  7. Rerun the project, and verify that the Order Date values are correct.
  8. Update and insert one or two orders to verify that the service behaves as expected.

Summary

Adding managed Visual Basic .NET or Visual C# code event handlers and functions to InfoPath projects frees you from reliance on VBScript and JScript and lets you take full advantage of the .NET Framework 1.1. This chapters example procedures incorporate managed code counterparts of several InfoPath SDK Developer Sample Forms. The examples require running the forms code with full trust, which you enable with the .NET Framework 1.1 Configuration tool.

The Rss2EventsFinal.sln solution demonstrates how to use Visual Basic to change the contents of a custom task pane and test a form with signed data blocks for missing digital signatures. The Rss2Production.sln project is an upgraded version of Rss2EventsFinal.sln that adds several new fields and illustrates how to generate a production-quality, fully formatted rss.xml file thats validated by Jorgen Thelins RSS 2.0 schema, which you can download from his Web site. This project also shows you how to add a form toolbar and create event handlers for custom toolbar buttons , detect errors before saving a file with a toolbar button, write a complex regular expression to validate RSS 2.0compliant date/time values, and write event handlers to copy a fields content to another field.

The ExprBoxSumProject.sln solution shows you how to display in a footer expression box running sums of values calculated from field values of repeating table rows. The NWOrdersWSProject.sln Web service client project provides a more sophisticated running sum example. This project also explains how to write event-handling code that calculates and tests date values, prevents violation of a database tables primary key fields, adds values from a single secondary data source to two fields of a repeating table, inserts new database records, and emulates return values from Web service submit operations.

This books final procedures show you how to create a local version of the NWOrdersWS ASP.NET Web service and change the URL for a Web service thats moved to a new location.

Heres hoping that youve enjoyed your introduction to Microsoft Office InfoPath 2003 SP-1. Youre now ready to take full advantage of InfoPath SP-1s power, the .NET Framework 1.1s advanced features, and the Visual Basic .NET language to develop enterprise-level , XML-based forms.

Q A

Does the XDocument.Solution.URI property value return a different path when you open a form from its .xsn file in the ...inDebug or ...inRelease folder instead of from the InfoPath solution s folder?

Yes. When you open an existing form or create a new one from the .xsn file, XDocument.Solution.URI returns the well- formed path to the .xsn file. Open Rss2EventsFinal.xsn in the ...Chapter17Rss2EventsFinalRss2EventsFinalinRelease folder, create a new form, and choose File, Save As to verify that the file is saved in the correct folder.

1.  

Must users change their .NET Framework 1.1 security level for InfoPath Form Templates to run fully trusted forms?

2.  

Why do I need to resign a fully trusted form s template .xsn file after every build to test it with an XML data document?

3.  

Is there any limit to the number of text boxes or other controls I can populate with a single secondary data source?

Answers

1.  

Not if the deployed form has been digitally signed or published as a custom-installed template. It s an uncommon practice to deploy a production form without signing the code, even if the form doesn t require full trust. The code signing certificate ensures that the form hasn t undergone unauthorized modifications. This assurance depends on users who carefully examine the signing certificate when they first open a new or modified form and don t automatically trust the publisher.

2.  

Even if you don t change the form s design or managed code, building the form deletes and re-creates the .xsn file.

3.  

The only limitation is the size of the secondary data source document, which affects the opening time of forms that receive data from Web services or stored procedures. If your data changes infrequently, you can add an Update Data Sources button to the form and write an event handler to query the database or Web service and write the data to a local XML file. In this case, your secondary data source must be an XML document that s not incorporated into the form as a resource file. You can add a receive-data Web method that reports the date of the last update to each secondary data source and compare the local XML file s modified date to determine whether a refresh operation is required.

On Your Own

Here are some advanced exercises to test your knowledge of the topics in this and the preceding two chapters:

  1. Using the techniques you learned in the section Setting Custom File Paths and Names, in Chapter 16, use the XDocument.Solution.URI property value, which returns the path and file name of the forms template, to set the forms Caption property to NW followed by the OrderID value and save documents as NW OrderID .xml.
  2. Create a copy of the NWOrdersWSProject or NWOrdersWSLocal folder, and write an event handler to request and save the GetProductsDetailed Web methods response document file in the project folder. Optionally change the data source for the ProductID combo box to the XML file.
  3. Add a Line Item number expression box to the repeating table of the copy you created. Hint: You can use the XPath position function or a counter to determine the item number.
  4. Add an SKU expression box to the repeating table, and populate it with the SKU text of the GetProductsDetailed secondary data source. This process is similar to but a bit trickier thanprogramming the running sum expression box.
  5. Create a custom, formatted XML file thats identical to the payload of the SOAP response document of a query. Make < GetOrderSPResult > the root element, include all its child nodes, and change the root element name to .

Категории