I have developed a custom Visual Studio 2008 Sharepoint (WSS 3.0) state machine workflow that is initiated when an InfoPath 2007 form (published as a content type) is created in a form library. A requirement is that the InfoPath form needs to be updated at several points in the workflow (i.e. approvers and dates approved, purchase order number, etc.).
This is not a MOSS installation and Form Services is not installed. The InfoPath form is opened and edited in a local InfoPath client.
The InfoPath form has 2 views (edit and read only).
Everything is working as expected... if a user opens an instance of the form and leaves it open in their local InfoPath client, and another user approves the task that needs to update the instance of the InfoPath form. The workflow will wait... until the InfoPath form is closed, and then it will update the form and continue on its way. However, if the form is left open and the SharePoint server is shutdown for any reason, the workflow loses its place and the workflow just stalls.
Here is the code that executes when the need to update the InfoPath form arises:
private void UpdateInfoPathFile(bool updateFormNumber, bool updateRouting, bool updateApprovals, string approvalLevel, string approverName, bool updatePO)
{
SPFile file = this.workflowProperties.Item.File;
while (file.CheckOutStatus != SPFile.SPCheckOutStatus.None)
{
System.Threading.Thread.Sleep(1000);
}
MemoryStream inputStream = new MemoryStream(file.OpenBinary());
XmlDocument ipDoc = new XmlDocument();
ipDoc.Load(inputStream);
inputStream.Close();
inputStream.Dispose();
XPathNavigator ipNav = ipDoc.CreateNavigator();
XPathNavigator ipNav = ipDoc.CreateNavigator();
ipNav.MoveToFollowing(XPathNodeType.Element);
XmlNamespaceManager nsManager = new XmlNamespaceManager(new NameTable());
foreach (KeyValuePair<string, string> ns in ipNav.GetNamespacesInScope(XmlNamespaceScope.All))
{
if (ns.Key == string.Empty)
{
nsManager.AddNamespace("def", ns.Value);
}
else
{
nsManager.AddNamespace(ns.Key, ns.Value);
}
}
XPathNavigator nodeNav = ipNav.SelectSingleNode("/my:PurchaseReqFields/my:RequisitionNumber", nsManager);
if (nodeNav.MoveToAttribute("nil", "http://www.w3.org/2001/XMLSchema-instance"))
{
nodeNav.DeleteSelf();
}
XmlNode ipRoot = ipDoc.DocumentElement;
if (updateFormNumber)
{
XmlNode reqNumField = ipRoot.SelectSingleNode("/my:PurchaseReqFields/my:RequisitionNumber", nsManager);
reqNumField.InnerText = requisitionNumber;
}
<repetitious code deleted...>
if (updatePO)
{
XmlNode formPONumberField = ipRoot.SelectSingleNode("/my:PurchaseReqFields/my:PurchaseOrderNumber", nsManager);
formPONumberField.InnerText = purchaseOrderNumber;
}
MemoryStream outputStream = new MemoryStream();
ipDoc.Save(outputStream);
file.SaveBinary(outputStream.ToArray());
outputStream.Close();
outputStream.Dispose();
}
The while loop was added to allow the system to wait for the file to be uploaded before trying to update the requisition number on creation of a new instance. If I remove this loop or make it conditional on the first time through, the subsequent updates will not occur if the InfoPath form is open at the time this code is encountered... even if the form is closed after a short interval.
Fortunately, for the most part, this issue has been controlled procedurally at this client. The occasional stalled workflow just really bugs me...
My question is:
Does anyone know of a way to get exclusive control of the InfoPath form instance from SharePoint? Is there anything I can do from the InfoPath side to modify the read only view to not open the file in exclusive mode? Any other ideas would be greatly appreciated.