Monday, September 28, 2009

The Joys of InfoPath & InfoPath Form Services – Part 1

For the last month or so, I've been working with InfoPath Forms in SharePoint. This has been such a frustrating experience. My main task was to get forms stored in a Form Library to "talk" to each other and share data. I have a collection of templates that have loads of redundant data. Instead of making the end user continually fill out the same field across multiple forms, we decided to sync the forms based off of information stored in a list.

The Story

The v1.0 forms contained alot of redundant code. Each form was doing pretty much the same thing in the Submit and Load functions. My first thing was to consolidate all of this code into a single assembly so we didn't have each form functioning slightly differently (because the code wasn't quite the same). This proved interesting because I had difficulties referencing the class. I came to find out that you need to sign the forms with a code signing certificate. Thankfully, my situation allows me to generate the certificate instead of paying Verisign or some other CA a load of money.

Next, I had to find a way to manipulate the forms on load and submit. I found out that you can't access the SharePoint object model from a form.

Why not use the SharePoint Web Services, you ask? I have a hang-up about using them. I don't know why and I realize that doesn't make me 1337, but I really don't care. The OM is so much easier to use.

Anyway, I found an answer that works for me. I have a custom Web Service (yes, I see the irony) that handles the Form_Load and a List Item Event that handles the Submit. The code is about 98% the same, so both of those call into a class. The reason for the Web Service, if you haven't already figured it out, is that it breaks the call stack (that's what I've been calling it…If you know what it's really called, feel free to inform me). My Web Service can now use the SPOM (it's way better tasting than SPAM) and makes my life much easier.

Why have 2 events to do the same thing?
  • Web Service: Pulls data from other forms into current form on load.
  • List Item Event: Pushes "this" form's data to other forms for updates on submit.
Ok, so far, so good. We have an Item Event, Web Service, a class that contains the "real" code for both of those, and a class that contains the "real" code for the forms. What's left? Oh, how about data that says which forms sync with each other and what data they sync? That's where a root web List comes in. I built a list with the following fields:
  • Enabled: Should this rule be used in the process?
  • SourceForm: Content Type name of the form template from where the data originates.
  • SourceXPath: XPath, from form root, to the field that will be sent to the target form.
  • TargetForm: Content Type name of the form template where the data will be sent.
  • TargetXPath: XPath, from form root, to the field that will receive the data.
  • XSLT: A blob of XSL that will format the source data to look like the field(s) that receive the data in the Target form.
I used a list because it makes the rules somewhat customizable. It's much easier to add a rule for some installations through a list instead of having to fix something embedded in the SP Solution (code, xml file, etc).

Finally, I have a Site Column Feature that basically gives easy-to-reference names to promoted fields in the forms.

Ok, well, that rounds out the high-level look on the project. I'll try to provide something more useful in a while.

Let me know what you think and feel free to ask questions. I know I had almost no luck in finding an answer, so I'm more than happy to do what I can to keep others from having their projects go well over deadline.

No comments:

Post a Comment