Friday, November 30, 2007

Getting InfoPath attachments from a submitted form

This week I was not only busy with migrating old portals and solving problems but I was also busy with creating a console application that does the following :

  • Extract the attachments from a submitted InfoPath form and uploading those into a document library and return the links from the documents

Ofcourse this requirement is so generic that I had to be out there on our beloved world wide web ;) And luckily.. it was.. partly..! I found the following pieces of invaluable information: Upload an InfoPath attachment to a document library by Koen Roos and KB892730: How to encode and decode a file attachment programmatically by using Visual C# in InfoPath.

First things first.. what is Koen talking about in his post? Well he references another post that describes how you can generates classes out of your XML file. Since all submitted InfoPath forms are purely XML you can generate classes from it as well! So how does it work then?

  • Download a copy of a submitted form to your development machine
  • Run the Visual Studio Command line
  • Execute the following cmd : XSD "name of the submitted form"
  • Execute the following cmd : XSD "name of the created XSD file" /CLASSES
  • Open Visual Studio and open up your workflow project (see previous posts about how-to-do this)
  • Add the just created .cs file to your project
  • Then you can use code to get access to the values from the infopath fields in an OO way
System.Xml.Serialization.XmlSerializer xSerializer = new System.Xml.Serialization.XmlSerializer(typeof(myFields));
myFields res = (myFields)xSerializer.Deserialize(str);
Console.WriteLine(res.FirstName);

Where MyFields is the main datasource in my InfoPath form, so now when I want to access a particular field within my datasource I can use "res.AttachmentField" or "res.FirstName" to get the values. Now to get the binary data from the attached files I used the code from the KB article that can encode and decode the string and that will look like this :

InfoPathAttachmentDecoder dec = new InfoPathAttachmentDecoder(r.AttachmentField);

Now to put that back into a document library as a document we do the following

SPFolder AttachmentStore = web.GetFolder("Document Library");
AttachmentStore.Files.Add(dec.Filename, dec.DecodedAttachment);



To put it al together it will look like (so you can copy/paste it more conveniently ;))

SPSite site = new SPSite("http://portal/sites/subsite");
SPWeb web = site.OpenWeb();

SPFile file = web.GetFile(@"http://portal/sites/subsite/Document Library/form.xml");
System.IO.StreamReader str = new System.IO.StreamReader(file.OpenBinaryStream());
System.Xml.Serialization.XmlSerializer xSerializer = new System.Xml.Serialization.XmlSerializer(typeof(myFields));
myFields res = (myFields)xSerializer.Deserialize(str);

InfoPathAttachmentDecoder dec = new InfoPathAttachmentDecoder(res.AttachmentField);
SPFolder AttachmentStore = web.GetFolder("Document Library");
AttachmentStore.Files.Add(dec.Filename, dec.DecodedAttachment);

Now the next step is to make a custom workflow activity using this code.. but I will save that for another post ;)

 

Technorati tags:

3 comments:

SC said...

This is an excellent solution, but you may want to look at a publish and forget solution?

I've worked out a neat webhandler solution, that would work for any infopath form, with no extra coding.

take at look at: http://blog.mgallen.com/?p=350

SC

Aditya said...

Hi,

I am a .net developer.Working on the same issues you described in the blog.

But, can you please let me know where is the continuation of this blog,I have created the encoder and decoder classes.I don;t know where to use the serialization code and how to run/deploy it to read all the infopath files from a sharepoint document library.

digital certificates said...

Excellent! Thanks for this - I've been looking at this feature for ages. Followed your instructions and it works a treat!