Wednesday, November 28, 2007

Voyages with BlackPearl - 4. Replace InfoPath Attachments

I am using InfoPath as the user interface to a K2 BlackPearl workflow. The form allows attachments to be added and they will need to be accessible to other users as the workflow progresses. Since the attachments are quite large, I wanted to strip the attachments off and replace them with a link. This workflow allows mutliple attachments and there are several different files that can be attached. The workflow itself makes no refrence to the attachments. I would have used the K2 wizard to store the attachment to a SharePoint document library but it doesn't work for repeating nodes of file attachments and I would need extra code to find the file name and store this in the InfoPath form as a hyperlink, and then delete the original attachment.
My solution was to build a web service that does exactly what I want. Remove the attachment, store it in SharePoint, put the path to the document on another field and repeat this for all occurrences in the repeating node.
The challenge then is to forward the now amended InfoPath form onto the K2 InfoPathService.asmx.
Here is how its done. You'll need a class defined for an XmlNode Array because that is how the InfoPath form is submitted to the InfoPathService.asmx.
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.42")] [System.SerializableAttribute()] [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://schemas.microsoft.com/office/infopath/2003/myXSD/2007-05-17T16:24:11")] [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://schemas.microsoft.com/office/infopath/2003/myXSD/2007-05-17T16:24:11", IsNullable = false)]
public class nodeArray { [System.Xml.Serialization.XmlArray()] [System.Xml.Serialization.XmlAnyElement()] public System.Xml.XmlNode[] node; }

Then the web service method looks like this:
public void InfoPathReplaceAttachment(Object infoPathFormXml) {
nodeArray nodes = new nodeArray();
nodes.node = (System.Xml.XmlNode[]) infoPathFormXml;
string s = System.Web.HttpUtility.HtmlDecode(nodes.node[0].OuterXml);
// load the string into an XML dom called myDoc and replace the attachments
//.....
//Finally submit the XML to the InfoPathService.asmx
// do this to use escaped XML
XmlNode escNode = myDoc.CreateTextNode(myDoc.OuterXml);
// replace node with the amended version
nodes.node[0] = escNode;
infoPathFormXml = nodes.node;
K2submit.InfoPathService ws = new K2submit.InfoPathService();
ws.Credentials = System.Net.CredentialCache.DefaultCredentials;
ws.SubmitInfoPathData(infoPathFormXml);
ws.Dispose();
myDoc = null;

1 comment:

Jason Apergis said...

Interesting - I had to do something similar a few years ago with K2 2003. I posted my solution here. I was able to recently replicate this for a BlackPearl project I just finished up too. For the BlackPearl project I just re-used the K2 Document service to get the docuemnts up into WSS 3.0.

http://k2distillery.blogspot.com/2007/09/infopath-document-attachment-solution.html