InfoPathHelper: add offline support to InfoPath!#

If you heard Yves and me talk about InfoPath and SharePoint on the TechNet session a while ago, you'll remember my promise that I'd get my InfoPath helper class I showed there out on the web sometime. Well, I finally got around to building it as v1.0 and wrapping it up nicely so here goes... A big thanks to Ned Friend from Microsoft for the original idea I based this on!

InfoPathHelper is a small reusable .NET library you can use to add offline support to InfoPath forms. That's right, you're finally able to make InfoPath a real smart client that is offline capable of submitting forms and querying data sources, without any extra security requirements whatsoever.

For the end user, the form will appear to continue working when the machine is offline or when the target you're submitting your form to is unavailable (a Web Service, a Sharepoint site, ...). The next time the machine goes online, any pending requests will be submitted. The same goes for querying data sources (files on a network share, Web Services, ...): if they're not available, the data will be taken from the local cache until the next time it can be refreshed.

For a developer using the InfoPath 2003 Toolkit for Visual Studio .NET, it boils down to inheriting from the CachingInfoPathForm base class, changing your submittal options to use form code, deleting the messy generated boilerplate code (you get cleaner properties and events for free in stead) and calling a few methods depending on your needs. The following example shows how to enable offline support for a form that has a submit data adapter named "WebServiceSubmit" and a data object named "Countries".

public class MyCachingForm : CachingInfoPathForm
{
    [InfoPathEventHandler(EventType=InfoPathEventType.OnSubmitRequest)]
    public void OnSubmitRequest(DocReturnEvent e)
    {
        // Attempt to submit the request and return a value to indicate if it worked.
        e.ReturnStatus = ProcessSubmitRequest( "WebServiceSubmit" );
    }

    [InfoPathEventHandler(EventType=InfoPathEventType.OnLoad)]
    public void OnLoad(DocReturnEvent e)
    {
        // Attempt to submit any cached requests and query a data object.
        SubmitCachedRequests( "WebServiceSubmit" );
        QueryDataObject( "Countries" );
    }
}

If you're wondering where the cached data is stored without needing any extra security requirements: welcome to the magical world of Isolated Storage :-)

Although I'm labelling it v1.0, I know there will still be some issues with it. I know of one particular problem I haven't been able to solve (but I suspect it's an InfoPath problem actually): if you populate a drop down list with data from a Web Service and cache that, a COM exception is shown when populating it from the cache saying "This DOM cannot be loaded twice". Any help solving this would be greatly appreciated :-)

Anyway, you're free to use this (as the enclosed license states, usual disclaimers apply) but it would be nice if you'd let me know if you're using it somewhere or if you're trying it out and think it's crap. All feedback is welcome! If there's enough interest in this little project, I might even write an article of some sort to explain the workings and usage a little more in depth than the current documentation file.

Enough talk, here's the goodies:

The JelleDruyts.InfoPathHelper 1.0 library and documentation (123,15 KB)
The JelleDruyts.InfoPathHelper 1.0 library, source code and documentation (218,74 KB)

Friday, January 20, 2006 8:33:28 AM (Romance Standard Time, UTC+01:00)
Hi Jelle
This code looks good; did you ever manager to solve the issue you refer to ("if you populate a drop down list with data from a Web Service and cache that, a COM exception is shown when populating it from the cache saying "This DOM cannot be loaded twice".")
Friday, January 20, 2006 8:46:51 AM (Romance Standard Time, UTC+01:00)
Unfortunately, I didn't find any solution yet. Any help would be much appreciated :-)
Friday, January 20, 2006 10:57:17 AM (Romance Standard Time, UTC+01:00)
Well, the method dataObject.DOM.replaceChild seems to look hopeful - most people say that this error in general can be overcome by using replaceChild rather than loadXML - I had a quick play but need to somehow create an object with the correct interface (Microsoft.Office.Interop.InfoPath.SemiTrust.IXMLDOMNode) - perhaps you woudl know what to do? How can I easily create an object in the QueryDataObject which properly inherits from the correct interface? If we can solve that, then the code just becomes replacing
dataObject.DOM.loadXML( xml );


with a working version of this:


Microsoft.Office.Interop.InfoPath.SemiTrust.IXMLDOMNode tempXmlDocument = new Microsoft.Office.Interop.InfoPath.SemiTrust.IXMLDOMNode();
tempXmlDocument.LoadXml(xml);
dataObject.DOM.replaceChild(tempXmlDocument.DocumentElement.CloneNode(true),XDocument.DOM.documentElement);
Saturday, January 21, 2006 1:01:23 AM (Romance Standard Time, UTC+01:00)
Hi again - seem to have fixed it. here is the code you need:

Replace:
dataObject.DOM.loadXML( xml );

With:

IXMLDOMDocument2 newDocument = (IXMLDOMDocument2)XDocument.CreateDOM();
newDocument.loadXML(xml);
dataObject.DOM.replaceChild(newDocument.documentElement, dataObject.DOM.documentElement);

And it works fine.
Saturday, January 21, 2006 10:35:24 PM (Romance Standard Time, UTC+01:00)
However, now I'm facing another issue, which may be specific to me. It looks like the IsolatedStorage GetStore methos is creating a new store every time it is run for Published forms; it works fine in Visual Studio, but when I publish the form I see a new directory created each time I run the form, and can't access the data from the previous session. Have you seen anything like this?
Monday, February 06, 2006 8:24:01 AM (Romance Standard Time, UTC+01:00)
Hi - this issue is sorted too. It is to do wioth the need to Strong Name or sign the assembly. It turns out the CLR can be explicitly told it can load a strong named assembly inside a partially trusted environment. This is where the System.Security.AllowPartiallyTrustedCallersAttribute comes in. When it’s applied to the assembly, everything suddenly starts working and the CLR is quite happy to load the code.

Hope that helps everyone else... cheers
Friday, March 24, 2006 10:13:59 PM (Romance Standard Time, UTC+01:00)
Hi guys,
I look at the source code and tried to use it in a simple infopath form. DataAdaptername is little confusing to me?
Is it name of DataSource or DataConnection in Infopath?
Please clarify. I tried both ways and it did give me a Null Reference Connection on isDataAdapterOnline Method on CachingInfoPathForm Class.
Thanks,
Murali.
Monday, November 27, 2006 8:56:13 AM (Romance Standard Time, UTC+01:00)
InfoJet Service, a product like InfoPath Form Services. http://www.infojetsoft.com
Comments are closed.
All content © 2008, Jelle Druyts
On this page

Recent Photos
www.flickr.com
This is a Flickr badge showing public photos from Jelle Druyts. Make your own badge here.
Advertising
Top Picks
Statistics
Total Posts: 344
This Year: 7
This Month: 0
This Week: 0
Comments: 522
Archives
Sitemap
Disclaimer
This is my personal website, not my boss', not my mother's, and certainly not the pope's. My personal opinions may be irrelevant, inaccurate, boring or even plain wrong, I'm sorry if that makes you feel uncomfortable. But then again, you don't have to read them, I just hope you'll find something interesting here now and then. I'll certainly do my best. But if you don't like it, go read the pope's blog. I'm sure it's fascinating.

Powered by:
newtelligence dasBlog 2.0.7226.0

Sign In