It's been a while since I released the original version of InfoPathHelper, a small reusable .NET library you can use to add offline support to InfoPath forms. I still think it's a nice little utility, and it makes me proud that even the InfoPath folks think enough of it to link to it on their Office Developer Center!
Unfortunately, I've always found it hard to really promote it since there was this one nasty bug that didn't make me very proud: it would sometimes blow up when caching data from a Web Service. But today, I'm happy to announce that I've fixed that bug and added a few other tweaks as well so I believe it's now a fully functional product!
I'll repeat the elevator pitch from my original post here just to round up what it does:
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 
Changes in v1.1:
- Strong-named the assembly. This is needed for the offline caching to work properly, otherwise a published form would apparently get a new directory in the Isolated Storage cache each time the form is run.
- Added the
AllowPartiallyTrustedCallers attribute to the assembly. This is needed to allow the now-strong-named code to run within InfoPath.
- Fixed the bug where a "This DOM cannot be loaded twice" COM exception would be thrown when caching data from a Web Service.
Thanks to David Downs at Microsoft for reporting and solving the issue with the isolated storage, and thanks to both David Downs and John Boesen for coming up with part of the solution for the bug with the Web Service!
Enough talk, here's the goodies:
The JelleDruyts.InfoPathHelper 1.1 library and documentation (125,12 KB)
The JelleDruyts.InfoPathHelper 1.1 library, source code and documentation (244,17 KB)