The term Information Worker is used to describe an individual in an enterprise who participates in the flow of business information or execution of processes. Many times, these workers perform a variety of repetitive but highly specialized tasks in the course of their normal job functions. These types of individuals are excellent candidates for using smart client applications. Such users are part of the fast-paced nature of business, and the effect of the competitive market has forced companies to offer both real-time and near real-time access to their enterprise data. Many of the dynamic features of the Microsoft .NET Framework have emerged as ways for enterprises to take advantage of these types of applications and provide a client services server model for distributing and consuming XML Web Services.
The goal of smart client applications is to enable enterprise customers to access their own enterprise data and allow them to continually update how and what types of information is shared with the Internet, with partners , and across disparate systems. This type of application paradigm affects all levels of an enterprise and enables companies to complete the shift to a loosely coupled distributed application environment. This type of application infrastructure provides the following key advantages:
Smart clients are based on an application model that provides an enhanced user experience through customization and personalization.
Application scalability is a natural byproduct of this type of application design.
The component-based design processes of the SOA provide easier application maintenance and reduced support costs.
The advanced toolsets enable application developers to shorten software development cycles.
The advantages of smart client technology that uses InfoPath in conjunction with other toolsets enable organizations to design a variety of solutions. These applications turn exposed XML Web Services into information that Information Workers can use.
Smart clients are any type of application designed to consume XML and interact with Web Services. The combination of these two enables the aggregation of multiple disparate sources into a common front end that is used to view and interact with these types of XML data sources. Smart clients also enable the integration of collaboration and communication technologies into the base of application logic and enable easy sharing of aggregated data.
Unlike traditional browser-based applications, smart clients are solutions that don t depend on a constant connection to the server for processing. As a matter of fact, the majority of processing and application logic is expected to occur on the local client machine to take advantage of the rich functionality built into the clients. Tools like InfoPath enable an enterprise to quickly and easily develop smart and effective client-based solutions.
InfoPath is designed as a client-based application. This means that in order for end users to interact with forms-based solutions that have been developed, the application client has to be installed. This doesn t mean, however, that as developers you can t take advantage of the features of XML within InfoPath when designing your applications.
CD-ROM The key advantage of smart client applications is that they integrate with XML Web Services. For example, let s create a Web Service that executes a stored procedure and returns a set of catalog tables to a dataset using a WebMethod , as shown in Listing 8.1. (This sample can be found in \Code\Chapter 8\Catalog\ClientCatalog\ClientCatalog.sln on the companion CD-ROM.)
<WebMethod()> Public Function GetNewCatalog() As DataSet 'create the DB connection Dim sqlConn As SqlConnection Dim sqlCmd As SqlCommand Dim strConstring As String strConstring = ConfigurationSettings.AppSettings("constring") sqlConn = New SqlConnection(strConstring) sqlConn.Open() sqlCmd = New SqlCommand With sqlCmd .Connection = sqlConn .CommandTimeout = 30 .CommandType = CommandType.StoredProcedure .CommandText = "spGetCatalogInfo" End With Dim RequestDA As SqlDataAdapter = New SqlDataAdapter RequestDA.SelectCommand = sqlCmd Dim RequestDS As DataSet = New DataSet RequestDA.Fill(RequestDS, "RequestType") Return RequestDS sqlConn.Close() End Function
When executed, this Web Service returns a list of catalog items that contains the XML shown in Figure 8.1.
This Web Service example enables people to access the current catalog data that is stored on the back-end server. In order to use an InfoPath form with this Web Service, we need to create a wrapper class that converts the dataset to an XMLDataDocument using the code in Listing 8.2.
<WebMethod()> Public Function InfoPathGetNewCatalog() As _ System.Xml.XmlDataDocument Dim ds As DataSet ds = GetNewCatalog() ds.Namespace = "Http://localhost/Catalog" Dim Info As System.Xml.XmlDataDocument =New _ System.Xml.XmlDataDocument(ds) Return Info End Function
With the new function created, we can now create and consume the form into an InfoPath-based document that we can use to access the data. Within this form, we will create only a single view that retrieves data from the Web Service and then displays it, as shown in Figure 8.2.
This form allows InfoPath users to access the Web Service when they are connected. If this form is opened and if the user can t connect with the Web Service, InfoPath displays the error message shown in Figure 8.3.
This is a major problem if we need to take the current solution mobile or need to provide any type of offline access. In this scenario, an InfoPath form that relies on connectivity to a Web Service may not be the best answer.
Using the .NET Framework, we can leverage the transformations that are used within the InfoPath .solution (xsn) file as a way of providing offline data. Also, as a side benefit, we can leverage the initial dataset as a way of accessing our data. Essentially, an XSN file is nothing more than a compressed CAB file that contains a list of files. If we export the current applications into a file directory, as shown in Figure 8.4, we can see that they are simply a series of XML and XSLT files. As we build out this solution, we will use them outside of InfoPath.
XSLT is used extensively within InfoPath as a way of rendering client data. It takes an XML file as input and applies a series of commands and outputs a formatted file. The XML file shown in Listing 8.3 contains the contact information shown in Figure 8.5.
<?xml version="1.0" encoding="utf-8" ?> <?xml-stylesheet type="text/xsl" ?> <customers> <customerinfo> <customername>Main Street Auto</customername> <address1>123 Anywhere St</address1> <address2>Suite 123</address2> <city>Nashua</city> <state>NH</state> <zipcode>03110</zipcode> <contactname>Mary Roberts</contactname> <currentbalance>1200</currentbalance> </customerinfo> <customerinfo> <customername>Second Street Manufacturing</customername> <address1>456 Main Street</address1> <address2>Building 12</address2> <city>Bedford</city> <state>NH</state> <zipcode>03060</zipcode> <contactname>Marvin Robbins</contactname> <currentbalance>750</currentbalance> </customerinfo> <customerinfo> <customername>East Side Excavating</customername> <address1>12 East St</address1> <address2>Suite 8512</address2> <city>Keene</city> <state>NH</state> <zipcode>03801</zipcode> <contactname>Chris Russo</contactname> <currentbalance>1600</currentbalance> </customerinfo> </customers>
The file now contains customer information and their current balances .
Using XSLT, we can create the transform shown in Listing 8.4, which results in the creation of an HTML page.
<?xml version="1.0" encoding="UTF-8" ?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="customers"> <html><body> <h1>Current Customer List</h1> <table width="800"> <xsl:apply-templates/> </table> </body></html> </xsl:template> <xsl:template match="customerinfo"> <tr> <td><xsl:number/></td> <xsl:apply-templates/> </tr> </xsl:template> <xsl:template match="customername address1 address2 city state zipcode contactname currentbalance"> <td><xsl:value-of select="."/></td> </xsl:template> </xsl:stylesheet>
This transformation produces an HTML page that contains the data that we are looking to show about the list of customers and is shown in Figure 8.6.
Visual Studio has a variety of built-in tools that allow you to create XSLT and apply transformations. It is important to remember that InfoPath makes extensive use of XSLT to both show views and apply other types of data actions. InfoPath and Visual Studio both use XML and XSLT.
CD-ROM If we revisit the catalog example using the Web Service (shown in Listings 8.1 and 8.2), we could extend this to take advantage of a client-based solution that extracts the data from the dataset and then caches the data locally. Using XSLT, we could extend this solution to include some transformations that show an HTML document, InfoPath document, and Word 2003 document. (This example is available on the companion CD-ROM in \Code\Chapter 8\Catalog\OfflineCatalog.xsn.)
Using the built-in HTML formatting and copying the style sheet within InfoPath, we can create the XSLT shown in Listing 8.5, which renders the document in HTML.
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:my="http://schemas.microsoft.com/office/infopath/2003/myXSD/2003- 09-12T22:55:52" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:xd="http://schemas.microsoft.com/office/infopath/2003" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns:xdExtension="http://schemas.microsoft.com/office/infopath/2003/xs lt/extension" xmlns:xdXDocument="http://schemas.microsoft.com/office/infopath/2003/xs lt/xDocument" xmlns:xdSolution="http://schemas.microsoft.com/office/infopath/2003/xsl t/solution" xmlns:xdFormatting="http://schemas.microsoft.com/office/infopath/2003/x slt/formatting" xmlns:xdImage="http://schemas.microsoft.com/office/infopath/2003/xslt/x Image"> <xsl:output method="html" indent="no"/> <xsl:template match="NewDataSet"> <html> <head> <meta http-equiv="Content-Type" content="text/html"></meta> <style controlStyle="controlStyle">BODY{margin- left:21px;color:windowtext;background-color:window;layout-grid:none;} .xdListItem {display:inline-block;width:100%;vertical-align:text-top;} .xdListBox,.xdComboBox{margin:1px;} .xdInlinePicture{margin:1px; BEHAVIOR: url(#default#urn::xdPicture) } .xdLinkedPicture{margin:1px; BEHAVIOR: url(#default#urn::xdPicture) url(#default#urn::controls/Binder) } .xdSection{border:1pt solid #FFFFFF;margin:6px 0px 6px 0px;padding:1px 1px 1px 5px;} .xdRepeatingSection{border:1pt solid #FFFFFF;margin:6px 0px 6px 0px;padding:1px 1px 1px 5px;} .xdBehavior_Formatting {BEHAVIOR: url(#default#urn::controls/Binder) url(#default#Formatting);} .xdBehavior_FormattingNoBUI{BEHAVIOR: url(#default#CalPopup) url(#default#urn::controls/Binder) url(#default#Formatting);} .xdExpressionBox{margin: 1px;padding:1px;word-wrap: break-word;text- overflow: ellipsis;overflow- x:hidden;}.xdBehavior_GhostedText,.xdBehavior_GhostedTextNoBUI{BEHAVIOR: url(#default#urn::controls/Binder) url(#default#TextField) url(#default#GhostedText);} .xdBehavior_GTFormatting{BEHAVIOR: url(#default#urn::controls/Binder) url(#default#Formatting) url(#default#GhostedText);} .xdBehavior_GTFormattingNoBUI{BEHAVIOR: url(#default#CalPopup) url(#default#urn::controls/Binder) url(#default#Formatting) url(#default#GhostedText);} .xdBehavior_Boolean{BEHAVIOR: url(#default#urn::controls/Binder) url(#default#BooleanHelper);} .xdBehavior_Select{BEHAVIOR: url(#default#urn::controls/Binder) url(#default#SelectHelper);} .xdRepeatingTable{BORDER-TOP-STYLE: none; BORDER-RIGHT-STYLE: none; BORDER-LEFT-STYLE: none; BORDER-BOTTOM-STYLE: none; BORDER-COLLAPSE: collapse; WORD-WRAP: break-word;}.xdTextBox{display:inline-block;white- space:nowrap;text-overflow:ellipsis;;padding:1px;margin:1px;border: 1pt solid #dcdcdc;color:windowtext;background- color:window;overflow:hidden;text-align:left;} .xdRichTextBox{display:inline-block;;padding:1px;margin:1px;border: 1pt solid #dcdcdc;color:windowtext;background-color:window;overflow- x:hidden;word-wrap:break-word;text-overflow:ellipsis;text- align:left;font-weight:normal;font-style:normal;text- decoration:none;vertical-align:baseline;} .xdDTPicker{;display:inline;margin:1px;margin-bottom: 2px;border: 1pt solid #dcdcdc;color:windowtext;background- color:window;overflow:hidden;} .xdDTText{height:100%;width:100%;margin- right:22px;overflow:hidden;padding:0px;white-space:nowrap;} .xdDTButton{margin-left:-21px;height:18px;width:20px;behavior: url(#default#DTPicker);} .xdRepeatingTable TD {VERTICAL-ALIGN: top;}</style> <style tableEditor="TableStyleRulesID">TABLE.xdLayout TD { BORDER-RIGHT: medium none; BORDER-TOP: medium none; BORDER-LEFT: medium none; BORDER-BOTTOM: medium none } TABLE.msoUcTable TD { BORDER-RIGHT: 1pt solid; BORDER-TOP: 1pt solid; BORDER-LEFT: 1pt solid; BORDER-BOTTOM: 1pt solid } TABLE { BEHAVIOR: url (#default#urn::tables/NDTable) } </style> <style languageStyle="languageStyle">BODY { FONT-SIZE: 10pt; FONT-FAMILY: Verdana } TABLE { FONT-SIZE: 10pt; FONT-FAMILY: Verdana } SELECT { FONT-SIZE: 10pt; FONT-FAMILY: Verdana } .optionalPlaceholder { PADDING-LEFT: 20px; FONT-WEIGHT: normal; FONT-SIZE: xx-small; BEHAVIOR: url(#default#xOptional); COLOR: #333333; FONT-STYLE: normal; FONT-FAMILY: Verdana; TEXT-DECORATION: none } .langFont { FONT-FAMILY: Verdana } </style> </head> <body> <div><xsl:apply-templates select="." mode="_1"/> </div> <div> </div> </body> </html> </xsl:template> <xsl:template match="NewDataSet" mode="_1"> <div class="xdSection xdRepeating" title="" style="MARGIN-BOTTOM: 6px; WIDTH: 542px" align="left" xd:CtrlId="CTRL8" xd:xctname="Section" tabIndex="-1"> <div><xsl:apply-templates select="RequestType" mode="_2"/> </div> <div> </div> <div> </div> <div> </div> </div> </xsl:template> <xsl:template match="RequestType" mode="_2"> <div class="xdRepeatingSection xdRepeating" title="" style="MARGIN- BOTTOM: 6px; WIDTH: 100%" align="left" xd:CtrlId="CTRL9" xd:xctname="RepeatingSection" tabIndex="-1"> <div>Catalog ID: <span class="xdTextBox" hideFocus="1" title="" xd:CtrlId="CTRL10" xd:xctname="PlainText" tabIndex="0" xd:binding="CatalogID" style="WIDTH: 130px"> <xsl:value-of select="CatalogID"/> </span> </div> <div>Item Name: <span class="xdTextBox" hideFocus="1" title="" xd:CtrlId="CTRL11" xd:xctname="PlainText" tabIndex="0" xd:binding="ItemName" style="WIDTH: 130px"> <xsl:value-of select="ItemName"/> </span> </div> <div>Item Quantityon Hand: <span class="xdTextBox" hideFocus="1" title="" xd:CtrlId="CTRL12" xd:xctname="PlainText" tabIndex="0" xd:binding="ItemQuantityonHand" style="WIDTH: 130px"> <xsl:value-of select="ItemQuantityonHand"/> </span> </div> <div>Item Price: <span class="xdTextBox" hideFocus="1" title="" xd:CtrlId="CTRL13" xd:xctname="PlainText" tabIndex="0" xd:binding="ItemPrice" style="WIDTH: 130px"> <xsl:value-of select="ItemPrice"/> </span> </div> <div>Item Description: <span class="xdTextBox" hideFocus="1" title="" xd:CtrlId="CTRL14" xd:xctname="PlainText" tabIndex="0" xd:binding="ItemDescription" style="WIDTH: 130px"> <xsl:value-of select="ItemDescription"/> </span> </div> <div>Item Sku: <span class="xdTextBox" hideFocus="1" title="" xd:CtrlId="CTRL15" xd:xctname="PlainText" tabIndex="0" xd:binding="ItemSku" style="WIDTH: 130px"> <xsl:value-of select="ItemSku"/> </span> </div> <div> </div> <div> </div> <div> </div> </div> </xsl:template> </xsl:stylesheet>
You may remember that earlier we talked about how when a Web Service is not connected to the Catalog Web Service, an InfoPath form like the one shown in Listing 8.5 that is bound to a Web Service would generate an error. If we create a second solution that uses a local copy of the data, we can create an XSLT that takes the data from the dataset and then applies an XSLT style sheet to it and outputs an InfoPath-compatible set of XML. The key in this is to use processing instructions that, when placed in the XML, the system will review to determine the type of editor to use for accessing this file. The XSLT to format a file to match our InfoPath document contains the code in Listing 8.6.
<?xml version="1.0" encoding="UTF-8" ?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" > <xsl:output method="xml" omit-xml-declaration="no"/> <xsl:template match="/"> <xsl:processing-instruction name="mso- infoPathSolution">solutionVersion="1.0.0.1" productVersion="11.0.5329" PIVersion="1.0.0.0" href="file:///D:\Programming%20Microsoft%20InfoPath%20A%20Developers%20 Guide\Chapter%208\Samples\Catalog\OfflineCatalog.xsn" language="en- us"</xsl:processing-instruction> <xsl:processing-instruction name="mso- application">progid="InfoPath.Document"</xsl:processing-instruction> <catalog:catalogData xmlns:catalog="http://schemas.mycompany.com/ns/offline/info"> <xsl:for-each select="NewDataSet"> <catalog:catalogInfo> <catalog:CatalogID><xsl:value-of select="CatalogID"/></catalog:CatalogID> <catalog:ItemName><xsl:value-of select="ItemName"/></catalog:ItemName> <catalog:ItemQuantityonHand><xsl:value-of select="ItemQuantityonHand"/></catalog:ItemQuantityonHand> <catalog:ItemPrice><xsl:value-of select="ItemPrice"/></catalog:ItemPrice> <catalog:ItemDescription><xsl:value-of select="ItemDescription"/></catalog:ItemDescription> <catalog:ItemSku><xsl:value-of select="ItemSku"/></catalog:ItemSku> </catalog:catalogInfo> </xsl:for-each> </catalog:catalogData> </xsl:template> </xsl:stylesheet>
Microsoft Word 2003 is also completely XML enabled and can use a similar type of processing set of instructions to consume XML. Word uses the Wordml XML-based model that defines its XML structure. Using the XSLT transformation shown in Listing 8.7, we can transform the same dataset into a Word 2003 XML document.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:o="urn:schemas- microsoft-com:office:office" xmlns:w="http://schemas.microsoft.com/office/word/2003/2/wordml"> <xsl:template match="/"> <xsl:processing-instruction name="mso- application">progid="Word.Document"</xsl:processing-instruction> <w:wordDocument xmlns:w="http://schemas.microsoft.com/office/word/2003/2/wordml"> <o:DocumentProperties> <o:Title>My Company Catalog Information</o:Title> </o:DocumentProperties> <w:body> <xsl:for-each select="NewDataSet/RequestType"> <w:p> <w:r> <w:t> <xsl:value-of select="ItemName"/> </w:t> <w:t> <xsl:value-of select="ItemQuantityonHand"/> </w:t> <w:t> <xsl:value-of select="ItemPrice"/> </w:t> <w:t> <xsl:value-of select="ItemDescription"/> </w:t> <w:t> <xsl:value-of select="ItemSku"/> </w:t> </w:r> </w:p> </xsl:for-each> </w:body> </w:wordDocument> </xsl:template> </xsl:stylesheet>