As most folk would be aware, the guts of an InfoPath form is simply (a lot of) XML. There is a schema & a bunch of namespaces, but is essentially just XML.
So, if there are elements within the form that you want to retrieve – and do something like save to a database, or use to piece together an email, or some other business logic – then you might want to consider digging inside the XML.
YES – you can certainly have fields that are published out from the form, and will thus become meta data columns within the SharePoint list, but sometimes that’s not wanted (like I had recently).
Having a workflow around an InfoPath form will mean that you can have a bunch of logic & functionality in place, but sometimes you need a little bit more – and have to craft some custom code – eg. call a web service.
The scenario I faced recently required email notifications to include data from the form, BUT these fields are not available via any specific workflow or metadata variables – and some logic needed – eg. skip if “N/A” – or blank.
The solution I’d put in place covers the following :
- Nintex workflow – passes the entire InfoPath form to a Web Service
- Using standard .NET code, determine the elements from the XML (ie. InfoPath form)
- Format the data values into a specific format (for an email in this case – but could be for anything)
C# XML Web Service
Starting with the web service is the best, as you won’t be able to add a “Web Service” call to the workflow otherwise – ie. if it doesn’t exist !
The web service will have ONE input variable, which is the binary representation of the form – ie. byte array.
The return value will be a ‘string’ – which I’ll format some text for the email notification.
- Open Visual Studio, and create a new Web Service project
- Add a new method (can replace the default one) – with something like this :
public string ProcessInfoPathForm(byte byteArray)
return ‘”hello from Web Service”;
- This initial web service method is enough to test out the ‘plumbing’.
- Can then include the web service call within the Nintex Workflow.
- The value to pass to the Web Service method is “[FileData]”
As the workflow has been assigned to the forms library itself, all instances of the workflow are ‘form-aware’. There are workflow variables sourced from the metadata properties in the library – and the ‘entire’ form is available to get into the XML.
So, what’s needed within the web service method is :
- Convert the byte to an XmlDocument
- Use XPath queries to get the relevant data items
- String together, update in a database, write to a log, whatever…
Here’s some code to explain this premise :
//convert from byte() to memory stream
MemoryStream ms = new MemoryStream(byteArray);
//load into XML document – for xpath’ing
XmlDocument xDoc = new XmlDocument();
//need namespace manager
XmlNamespaceManager mgr = new XmlNamespaceManager(xDoc.NameTable);
//define the namespace – based on the URI within InfoPath
Now that it’s into an XML DOM object, we can use XPath to grab out values.
//determine the XML node for "my:fields"
XmlNode xNode = xDoc.SelectSingleNode("//my:myFields/my:PersonName", mgr);
if (xNode != null)
personName = valueNode.InnerText;
That’s pretty much it – obviously there is additional XPATH methods needed for a ‘SelectNodes” – in which there’s a collection of items. I’ve bundled a few such commands into a ‘shared’ or ‘common’ class library for use in projects such as this.
Has been kinda interesting to investigate & process the XML internals of an InfoPath form – via a Web Service – which has been called from a Nintex Workflow – phew !