Welcome to MSDN Blogs Sign in | Join | Help

Check out this location.   Seems to be pretty active http://www.microsoft.com/office/community/en-us/default.mspx?lang=en&cr=US&dg=microsoft.public.infopath.    Some people who I'm in contact with are very diligent about responding to questions posted here, and it looks like a great resource to get your sticky InfoPath questions answered.

Thanks,

Tim

Folks,

I'm hearing a lot of issues about people having trouble getting InfoPath 2007 forms published to Forms Services on MOSS 2007 to run well.   People complain that the rendering and roundtripping operations just take too darn long.   There is some guidance available on how to build performant forms for the Rich Client (http://msdn2.microsoft.com/en-us/library/bb380251.aspx), and some of the concepts there would most certainly apply to forms published via Forms Services.   However, here are few more tips and tricks garnered from the experts that should help you improve the performance of Forms Services in your environment.

  • Upgrade to IE7 on the desktop.   There are performance benefits to moving up to IE7.  In some cases the difference is 5x to 10x.
  • Make sure the IE cache is big enough so our necessary 250K of content and scripts - needed for the browser to render Forms Services forms - doesn't get pushed out the cache after an initial download.   Customers with extraordinarily low thresholds (like ~1MB) will have issues.   Disk is cheap, increase that value to something reasonable like 10% of disk.
  • A good perf trick is to populate dropdowns via an XML file (especially if they are somewhat static) that is made a part of the form XSN.   We can cache that on the server and get good load performance optimization.  You can always republish the solution when the data changes.
  • If you have to download data via a data connection for a dropdown list or calculation, try to dynamically build a filtered query (via code) so that you are as efficient as possible with what you are retrieving.
  • Try to minimize On_Load activities like queries unless absolutely necessary.
  • Conditional visibility logic has some known performance problems.  A hotfix is available http://support.microsoft.com/kb/937206, which is manifested in a modifed 250K initial download when accessing Forms Services the first time.  The performance issue is related to the IE Script Engine and occurs at the browser level, not server-side.
  • Instead of using conditional visibility logic, try implementing multiple views on a form.   Splitting complex views into more than 1 view provides noticeable performance improvements.
  • Rich Text controls are noticeably slower in IE vs. Firefox, because Rich Text editing in Forms Services is an IE-only feature.  Limiting the number of Rich Text controls shown in the same view can really help form performance.
  • Try to prevent unnecessary roundtripping between the form browser and the server.  There are several round trip switches available on controls.   See the Browser Forms Tab on a given control to expose finer-grained options over the behavior.  Note what the warning messages you receive say about the form's potential round trip behavior when admin deploying the form.  It will tell you when multiple server roundtrips will be likely to occur when using your form.
  • If you have to do roundtrips to the server, try to have them triggered by buttons, so that the users know they initiated the wait themselves.  This UI trick can tend to reduce user dissatisfaction with the form performance.
  • Try not to treat an InfoPath form as a full, rich VB application.   It's not designed to be performant in that use case.
  • The more declarative logic (heavy use of rules, etc.) and managed code you have in the form, the slower it will be.   Try and follow the KISS method if at all possible (Keep it Simple, Stupid). 
  • Consider breaking out the server role of Forms Services to another machine on the MOSS farm.  Services such as indexing and query serving, or high file I/O operations can really impact the ability of Forms Services to get a time slice and perform properly.  

Hope this was helpful!

Tim

 

 

This code sample documents a block of VB.Net code I had to write recently for retrieving a block of data from a secondary datasource, and then copying that data into a child table of a dataset in the main datasource.    I've copied it over as is for my benefit as much as yours - I lost this code recently in a machine rebuild so want to have a copy somewhere!   I believe the syntax shown here will be helpful to many of you. 

 

Public Sub GetEscalations_Clicked(ByVal sender As Object, ByVal e As ClickedEventArgs)

' Write your code here.

' Define constants

Const secondaryDataSourceName As String = "GetUserEscalations"

Const secondaryListXPath As String = "/dfs:myFields/dfs:dataFields/ns3:GetUserEscalationsResponse/ns3:GetUserEscalationsResult/NewDataSet/Table"

Const secondaryRelativeEscalationIDXPath As String = "EscalationID"

Const secondaryRelativeDataXPath As String = "CompanyName"

Const mainObservationEvidenceName As String = "KeyObservationEvidence"

'Define strings for mapping values to main datasource evidence table.

Const mainEvidenceKOID As String = "KOID"

Const mainEvidenceKOEvidenceID As String = "KOEvidenceID"

Const mainEvidenceKEID As String = "KEID"

Const mainEvidenceKEDetail As String = "KEDetail"

Const mainEvidenceKECreatedBy As String = "KECreatedBy"

Const mainEvidenceKECreatedDate As String = "KECreatedDate"

Const mainEvidenceKELastUpdatedBy As String = "KELastUpdatedBy"

Const mainEvidenceKELastUpdatedDate As String = "KELastUpdatedDate"

Const mainEvidenceKETypeID As String = "KETypeID"

Const mainEvidenceKETypeName As String = "KETypeName"

Const mainEvidenceKEDeleted As String = "KEDeleted"

 

'Get navigator to the root of the main datasource. There will only ever be one record in the

'main datasource.

Dim mainDOMNavigator As XPathNavigator = MainDataSource.CreateNavigator()

'Explicitly create a pointer to the root element of the KO. This is the pointer that will drive the appending of the child Key Evidences.

Dim mainDOMObservationNavigator As XPathNavigator

mainDOMObservationNavigator = mainDOMNavigator.SelectSingleNode("/dfs:myFields/dfs:dataFields/tns:GetKOsDataSetByQuickSearchResponse/tns:GetKOsDataSetByQuickSearchResult/NewDataSet/KeyObservation", NamespaceManager)

'Get navigator to the root of the secondary datasource.

Dim secondaryDataSource As DataSource = DataSources.Item(secondaryDataSourceName)

Dim secondaryDOMNavigator As XPathNavigator = secondaryDataSource.CreateNavigator()

 

'Setting up some other XPathNavigator Pointers

Dim secondaryEscalationIDNavigator As XPathNavigator

Dim secondaryEscalationEvidenceNavigator As XPathNavigator

Dim secondaryListItem As XPathNavigator

Dim escalationIDMapping As String

Dim escalationEvidence As String

'Get all the list items from the secondary datasource.

Dim secondaryListItems As XPathNodeIterator = secondaryDOMNavigator.Select(secondaryListXPath, NamespaceManager)

Do While secondaryListItems.MoveNext()

secondaryListItem = secondaryListItems.Current

'Get observation Id for the list item.

secondaryEscalationIDNavigator = secondaryListItem.SelectSingleNode(secondaryRelativeEscalationIDXPath, NamespaceManager)

escalationIDMapping = secondaryEscalationIDNavigator.Value

'Get the evidence to be copied into the main DOM.

secondaryEscalationEvidenceNavigator = secondaryListItem.SelectSingleNode(secondaryRelativeDataXPath, NamespaceManager)

escalationEvidence = secondaryEscalationEvidenceNavigator.Value

 

If Nothing IsNot mainDOMObservationNavigator Then

'Append the evidence child

Using evidenceChild As XmlWriter = mainDOMObservationNavigator.AppendChild()

Dim prefix As String = mainDOMObservationNavigator.Prefix

Dim namespaceUri As String = mainDOMObservationNavigator.NamespaceURI

evidenceChild.WriteStartElement(prefix, mainObservationEvidenceName, namespaceUri)

evidenceChild.WriteStartElement(prefix, mainEvidenceKOID, namespaceUri)

evidenceChild.WriteValue("-1")

evidenceChild.WriteEndElement()

evidenceChild.WriteStartElement(prefix, mainEvidenceKOEvidenceID, namespaceUri)

evidenceChild.WriteValue("-1")

evidenceChild.WriteEndElement()

evidenceChild.WriteStartElement(prefix, mainEvidenceKEID, namespaceUri)

evidenceChild.WriteValue(escalationIDMapping)

evidenceChild.WriteEndElement()

evidenceChild.WriteStartElement(prefix, mainEvidenceKEDetail, namespaceUri)

evidenceChild.WriteValue(escalationEvidence)

evidenceChild.WriteEndElement()

evidenceChild.WriteStartElement(prefix, mainEvidenceKECreatedBy, namespaceUri)

evidenceChild.WriteValue(currentUser())

evidenceChild.WriteEndElement()

evidenceChild.WriteStartElement(prefix, mainEvidenceKECreatedDate, namespaceUri)

evidenceChild.WriteValue(currentDateTime())

evidenceChild.WriteEndElement()

evidenceChild.WriteStartElement(prefix, mainEvidenceKELastUpdatedBy, namespaceUri)

evidenceChild.WriteValue(currentUser())

evidenceChild.WriteEndElement()

evidenceChild.WriteStartElement(prefix, mainEvidenceKELastUpdatedDate, namespaceUri)

evidenceChild.WriteValue(currentDateTime())

evidenceChild.WriteEndElement()

evidenceChild.WriteStartElement(prefix, mainEvidenceKETypeID, namespaceUri)

evidenceChild.WriteValue("1")

evidenceChild.WriteEndElement()

evidenceChild.WriteStartElement(prefix, mainEvidenceKETypeName, namespaceUri)

evidenceChild.WriteValue("Escalation SR#")

evidenceChild.WriteEndElement()

evidenceChild.WriteStartElement(prefix, mainEvidenceKEDeleted, namespaceUri)

evidenceChild.WriteValue(False)

evidenceChild.WriteEndElement()

evidenceChild.WriteEndElement()

End Using

End If

Loop

End Sub

Private Function currentDateTime() As String

Dim mainDomNavigator As XPathNavigator = MainDataSource.CreateNavigator()

Dim todayNavigator As XPathNavigator = mainDomNavigator.SelectSingleNode("/dfs:myFields/my:TodaysDate", NamespaceManager)

Return todayNavigator.Value

End Function

Private Function currentUser() As String

Dim mainDomNavigator As XPathNavigator = MainDataSource.CreateNavigator()

Dim userNavigator As XPathNavigator = mainDomNavigator.SelectSingleNode("/dfs:myFields/my:CurrentUser", NamespaceManager)

Return userNavigator.Value

End Function

VB.NET and probably the other managed code languages uses a new syntax for specifying nodes and traversing XML in a form.   I don't claim to have a firm grasp on this, I only know what works.   Let's say you've got a field in your form whose value you set via rules or defaults, like a datetime field.   Below is how you would specify a function to get into your main datasource, get to the value, set it to a variable and then do something with it.  This may be basic info for some of you, but it's a different syntax to me and is worth noting here.

Private Function currentDateTime() As String

Dim mainDomNavigator As XPathNavigator = MainDataSource.CreateNavigator()

Dim todayNavigator As XPathNavigator = mainDomNavigator.SelectSingleNode("/dfs:myFields/my:TodaysDate", NamespaceManager)

Return todayNavigator.Value

End Function

Folks,

Just starting to get involved in dealing with VB.NET and VSTA in InfoPath 2007.   A lot of what I've taken for granted in InfoPath 2003 and JScript no longer applies.   Take Custom Task Panes for example.   A neat idea, and super-useful.   Doesn't work the same way in InfoPath 2007.   Well some of it does.   For example, the format of the typical html file that you would use as a resource file for the task pane is formatted the same.   For those of you that haven't built one before, you'll copy and paste this into "mission-critcal notepad" and edit from there.  Here is a sample:

<html>
 <body>
  <font face="arial" color="black">
   <div id="fieldname1" style="display:none">
    <p><font color="blue"><b>KO Title</b></font></p>
    <br />
    Your text will appear here in the task pane.
    <br>
   </div>  
  
  
   <div id="fieldname2" style="display:none">
    <p><font color="blue"><b>KO Type</b></font></p>
    <br />
    Your different text will appear here in the task pane.
   </div>

  </font>
 </body>
</html>

The idea is that you have a div statement that separates what content to show when.   In InfoPath 2007, you'll go to the programming choices off the menu and choose Context Changed Event.  This will put an event handler in place and stub out the code you need.    Here is the code that works for me:

Private helpString As String 

Public Sub FormEvents_ContextChanged(ByVal sender As Object, ByVal e As ContextChangedEventArgs)

Try

If (e.ChangeType = "ContextNode") Then

' The XML selection or context has changed.

'Retrieve task pane object

Dim customTaskPane As HtmlTaskPane = Me.CurrentView.Window.TaskPanes.Item(0)

'Get the collection of html elements in the task pane.

Dim htmlDocument As mshtml.HTMLDocument = customTaskPane.HtmlDocument

Dim htmlDocumentAll As IHTMLElementCollection = htmlDocument.all

'Clear previous help topic from task pane

If Not String.IsNullOrEmpty(helpString) Then

'Get the first div that matches the helpString.

Dim htmlOldDivElem As mshtml.HTMLDivElement = htmlDocumentAll.item(helpString, 0)

htmlOldDivElem.style.display = "none"

End If

'Keep record of string to be displayed, so it can later be cleared

helpString = e.Context.Name

'Get the first div that matches the helpString.

Dim htmlDivElem As mshtml.HTMLDivElement = htmlDocumentAll.item(helpString, 0)

If Nothing Is htmlDivElem Then

'No known context node.

helpString = Nothing

Else

'Display DIV statement having same ID as the context node name

htmlDivElem.style.display = String.Empty

Return

End If

End If

Catch exn As Exception

MessageBox.Show(exn.ToString())

End Try

End Sub

I assume that you know how to tell the form to use a Custom Task Pane and to upload the html file you built previously as a resource file and associate it with the Custom Task Pane.  The only thing that sucks about this is that the form requires full trust with a level 2 code signing cert.   I've self-signed my form for now, but am hoping to get a resolution to that. At least InfoPath 2007 doesn't completely shut you down when it sees an untrusted cert like InfoPath 2003 did.

From http://msdn2.microsoft.com/en-us/library/ms496491.aspx.   This basically provides a control for GAL selection that supercedes my custom code that appears earlier in this blog.   From what I'm reading, this is strictly a Forms Services thing from MOSS 2007.  Haven't had a chance to play with it but looks to be a godsend. 
 
The Contact Selector Control 
[This topic is pre-release documentation and is subject to change in future releases. Blank topics are included as placeholders.]

Microsoft Office SharePoint Server 2007 includes the Contact Selector control, an ActiveX control that can be used on your Microsoft Office InfoPath 2007 workflow forms. The Contact Selector control enables users to specify contacts, either users or groups, and have that contact information validated. The Contact Selector control is also included in Office Professional 2007.

When a user enters a contact, the Contact Selector control attempts to validate the contact against the server. The set of users that the Contact Selector control can resolve is the same as the set that the server can resolve. This includes:

  • Local Microsoft Windows SharePoint Services 3.0 users

  • Microsoft Windows SharePoint Services 3.0 groups and users

  • Groups in the Microsoft Windows SharePoint Services 3.0 directory, which can include Active Directory or other LDAP servers

You can use the Contact Selector control on your Microsoft Office InfoPath 2007 workflow forms to enable users to specify contacts for workflow processes, such as assigning tasks or sending e-mail notifications.

Using the Contact Selector Control

Including a Contact Selector control in your workflow form requires several basic steps:

  1. Add the Contact Selector control to the Designer Control pane in Microsoft Office InfoPath 2007, so it is available for use on your workflow forms.

    For more information, see How To: Add the Contact Selector to InfoPath 2007.

  2. Insert the Contact Selector control onto your workflow form, and configure the control schema. You must also add the workflow context schema to the form as a secondary data source.

    For more information, see How To: Configure a Contact Selector Control on Your InfoPath Workflow Form.

  3. Add code to your workflow that accesses the form data sent to the workflow instance by Microsoft Windows SharePoint Services 3.0.

    For more information on accessing contact data from workflow initiation or modification forms, see How to: Access Contact Data in Workflow Initiation and Modification Forms.

    For more information on accessing contact data from workflow task forms, see How to: Access Contact Data in Workflow Edit Task Forms.

Recent request from a customer:

What we need to be able to do is to somehow programmatically access, in infopath, the sharepoint form library folder name from which the form was opened.

Cool way to get this done (from Scott Heim's inexhaustible code sample archive):

substring-before(substring-after(/processing-instruction(), 'href="'), '"')

 

Used as the default value in a text box returns this:

 

http://servername/URITest/Forms/template.xsn

 

In this case, as you can see from the returned URL, the form was opened from my document library “URITest”

Just posted on using C# and the new object model in InfoPath 2007 to retrieve the current user.   I have 3 other posts that deal with this issue as well.  Believe it or not, the product team has actually addressed this in with a no code solution in InfoPath 2007.  Follow these steps to see for yourself.

  1. Create a new form by Designing a New Form Template
  2. Choose blank form
  3. Add a text box to the form (Field1)
  4. Go to Tools | Form Options
  5. Go to the Open Behavior section and click on Rules
  6. Add Action to Set a Field's Value
  7. Choose the field you added above as the field to populate
  8. For the value, click on the Fx button and choose Insert Function
  9. View All in the Categories drop down
  10. At the bottom you'll see userName, pick it
  11. The formula that gets dropped in is userName()
  12. Preview the form, you'll see your UserName in field1

That, my friends, is progress!

Tim

Folks,

Got a little code sample from a fellow watcher of Pashman's Goldmine (thanks Huseyin) on how to retreive the username of the current user via C# code.  Since all code samples are useful, I've posted it below:

public void FormEvents_Loading(object sender, LoadingEventArgs e)

{

string xpath = "/my:oneriForm/my:nameTxt";

string userName1;

XPathNavigator field1 = MainDataSource.CreateNavigator().SelectSingleNode(xpath, NamespaceManager);

//string oldValue = field1.Value; // Read

string strUserName = System.Environment.UserName;

//userName1 = System.Environment.

field1.SetValue(strUserName);

// Write

In this case the user wanted the full user name too, and I advised him to try and replace the System.Environment.UserName with System.Environment.FriendlyName.   I'll let you know if that worked.

Application.XDocuments.NewFromSolution(urlToXsnFile) or Application.XDocuments.Open(urlToXmlFile)

 

Your form will need to require full trust in order to use either of these OM methods.

 

Keep it simple, right?

Tim

Folks,

Don't claim to understand this 100%, but I do know it works.   Put this formula inside a formula dialog box for an expression box on your form, and when you invoke it it'll show you the current solution version - without having to write code!

substring-before(substring-after(/processing-instruction(), 'solutionVersion="'), '"')

Thanks,

Tim

 Edited on 10/7 per input from Karsten, thanks!

Hey folks,

Like many of you, I'm being dragged into the land of managed code in order to achieve things that I've had oodles of JScript code samples to do for a long time.   The InfoPath Toolkit for VS.NET allows you to write code in either VB or C#; since C# looked more like JScript, and I had both JScript and C# code samples for the easy part of what I wanted to do, I decided to go with C#. 

So the task at hand that I needed to do was to pick up the username attribute from the local environment and populate that into a field on the form, and then use that field as a lookup value into a secondary datasource and populate a "friendly" username and office location number and friendly name for the office location as well.   Oh by the way I needed to do it all in the OnLoad event of the form.  This sounds easy - and in fact the username part was super-easy.   Getting the right syntax though to address the secondary datasource and pluck values out was a major pain in the butt.   To make matters worse, my form was tied to a database, so the namespaces are all "dfs" and "d" instead of "my".  It gets confusing since all datasources that are SQL-based follow the same basic nomenclature, and you have to figure out how to navigate between them.   The only thing that might be hard to follow below is the fact that I don't store the friendly office location name in the destination table that the form is tied to, so in my schema I just created a node outside of the dataFields to hold the friendly office location name for purposes of display. 

 

[InfoPathEventHandler(EventType=InfoPathEventType.OnLoad)]

public void OnLoad(DocReturnEvent e)

{

// This code populates the local username. This was the easy part.

IXMLDOMNode nodeEmployee=thisXDocument.DOM.selectSingleNode("dfs:myFields/dfs:dataFields/d:DestinationTable/@username");

nodeEmployee.text=System.Environment.UserName;

//Call the LookupTable datasource and populate other fields.

//This variable declaration looked very foreign to me.  Chalk that up to being new to C#

DOMDocument50 objPeopleStuff = (DOMDocument50)thisXDocument.GetDOM("LookupTable");

objPeopleStuff.setProperty("SelectionNamespaces","xmlns:dfs='http://schemas.microsoft.com/office/infopath/2003/dataFormSolution'"+" xmlns:d='http://schemas.microsoft.com/office/infopath/2003/ado/dataFields'");

ADOAdapterObject myAdapter = (ADOAdapterObject)thisXDocument.DataAdapters["LookupTable"];

//This method below seemed to be clunky to me at first, but turns out to be helpful later, as you'll want

//to set the query string back to nominal later on.

string origCommand = "";

origCommand=myAdapter.Command;

myAdapter.Command=origCommand + " WHERE username = '"+ nodeEmployee.text +"'";

myAdapter.Query();

//Sets friendly name value

IXMLDOMNode nodeFriendlyName=thisXDocument.DOM.selectSingleNode("dfs:myFields/dfs:dataFields/d:DestinationTable/@friendlyname");

IXMLDOMNode nodeReturnedName=objPeopleStuff.selectSingleNode("dfs:myFields/dfs:dataFields/d:LookupTable/@FriendlyName");

nodeFriendlyName.text=nodeReturnedName.text;

//Sets office code unfriendly value

IXMLDOMNode nodeUnFriendlyOfficeName=thisXDocument.DOM.selectSingleNode("dfs:myFields/dfs:dataFields/d:DestinationTable/@officecode");

IXMLDOMNode nodeReturnedCodedOffice=objPeopleStuff.selectSingleNode("dfs:myFields/dfs:dataFields/d:LookupTable/@OfficeCode");

nodeUnFriendlyOfficeName.text=nodeReturnedCodedOffice.text;

//Sets office code friendly value. Small nuance here is that I was lazy

//and don't write OfficeName to actual destination table. Follow syntax of other nodes in

//actual solution.

IXMLDOMNode nodeFriendlyOfficeName=thisXDocument.DOM.selectSingleNode("dfs:myFields/my:OfficeName");

IXMLDOMNode nodeReturnedOffice=objPeopleStuff.selectSingleNode("dfs:myFields/dfs:dataFields/d:LookupTable/@OfficeName");

nodeFriendlyOfficeName.text=nodeReturnedOffice.text;

//resets the lookup dataconnection to remove WHERE clause

myAdapter.Command=origCommand;

myAdapter.Query();

}

Unfortunately, this code does need the form to have full trust and be signed with a Level 2 code signing certificate to run.   That's a bummer, but I see no way around it for now.

Thanks,

Tim

Folks,

   Had an issue recently where a user of one of my solutions had pretty terrible bandwidth to the SQL server where they needed to submit data.   The default timeout value on submits is 30 seconds.   As it turn out, the default for queries too is 30 seconds.   You can reset that value fairly easily in code.    Here is an example of code that you put behind the submit button to increase the timeout value, do the submit and throw up a thank you message:

 XDocument.QueryAdapter.Timeout=120;

XDocument.Submit();

XDocument.UI.Alert("Thanks for using the AD Data Collection Form");

I'm pretty sure that if you tweak the value for the timeout, it applies to every query and the submit behavior in your form.

Thanks,

Tim

Quick update to this post (6/7/2007).   Saw this article http://msdn2.microsoft.com/en-us/library/aa945450(VS.80).aspx which is pretty comprehensive on this topic.   Worth a read. 

Folks,

Getting tired of waiting for a list to be published, so will start to build my own from scratch as I go along.   Many of you know that InfoPath 2007 will have the ability to build forms that are "web-enabled".  What that means is that Microsoft Office SharePoint Server (MOSS) 2007, if you've bought Enterprise CALs, will allow you to build an InfoPath form that will render either in the rich client application or can be served up as an ASP.NET page.   This has been done with cross-platform, zero-footprint considerations in mind.   It's a nice and much-asked-for capability.  However, there are a bunch of things that won't work when you go to web environment.   Here is a small list that I've started to compile.  It will grow and I will repost as I discover more things.

  1. No native write to SQL databases.   The ease of use of establing an ADO connection to SQL or Access, and being able to query and write back to a database is lost.   Instead you will probably need to talk to the DB via a web service.
  2. No roundtripping for cascading picklists.   Something I do all the time is have one picklist be a filter for another picklist.  Common example, pick a state, which then filters the city field dropdown.   Can't do that in a web form.
  3. Summary list of controls that aren't supported in web forms:
    • ComboBox
    • Multiple-Selection List Box
    • Master/Detail
    • Bulleted, Numbered and Plain List
    • Picture
    • Ink Picture
    • Vertical Label
    • Scrolling and Horizontal Region
    • Horizontal Repeating Table
    • Choice Group
    • Repeating Choice Group
    • Choice Section
    • Repeating Recursive Section
    • ActiveX Controls

More to follow.

Folks,

I had to skill up recently on the use of digital signatures in InfoPath, and this webcast I found is pretty amazing.   I had no idea how rich the support in InfoPath for digital signatures was, and this webcast goes into *deep* detail.   I found myself dozing off after about 45 minutes, but that was because I had what I needed by then.   Still, it's a great resource.

http://msevents.microsoft.com/cui/WebCastEventDetails.aspx?EventID=1032259545&EventCategory=5&culture=en-us&CountryCode=US

The presenter is Mihaela Cristina Cris and she is a big brain at Microsoft on InfoPath.

More Posts Next page »
 
Page view tracker