Sunday, 8 March 2009

Update InfoPath Form from Workflow

Trying to update a datasource in an InfoPath form that has been promoted to a SharePoint column from the workflow?

This took me a while to solve, you would think that updating the "The item["fieldname"] = Something " would work and SharePoint would be clever enough to update the InfoPath form, sadly not.

I hope this method helps; I modified this method from another post. Sorry I could not link back to the author.

         /// <summary>
        /// Updates the element within a InfoPath form.
        /// </summary>
        /// <param name="xPath">The x path.</param>
        /// <param name="value">The value.</param>
        public void SetElementOnForm(string xPath, string value)
        {
            //First, get the SharePoint Listitem
            var myWeb = new SPSite(_workflowProperties.SiteId).
            OpenWeb(_workflowProperties.WebId);
            var myItem = myWeb.Lists[_workflowProperties.ListId].GetItemById(_workflowProperties.ItemId);
            //Then get the File for that ListItem - i.e. the XML data
            var myFile = myItem.File;
            var myInStream = new MemoryStream(myFile.OpenBinary());
            var myDoc = new XmlDocument();
            myDoc.PreserveWhitespace = true;
            myDoc.Load(myInStream);
            //Then make your changes to the XML in here - below is what I did, as an example
            var myRoot = myDoc.DocumentElement;
            var incidentFormNav = _incidentInfoDoc.CreateNavigator();
            if (incidentFormNav != null)
            {
                var xmlNSManager = new XmlNamespaceManager(incidentFormNav.NameTable);
                xmlNSManager.AddNamespace(_settings.NamespacePrefix, _settings.Namespace);
                if (myRoot != null)
                {
                    XmlNode myColumnToAlter = myRoot.SelectSingleNode(xPath, xmlNSManager);
                    myColumnToAlter.InnerText = value;
                }
            }

            // the XmlDocument object back into SharePoint as a file.
            var myOutStream = new MemoryStream();
            myDoc.Save(myOutStream);
            myFile.SaveBinary(myOutStream.ToArray());
        }


 


 

A slight change to the above method that returns the value from an InfoPath form:

/// <summary>

/// Gets the inner text of a element on a InfoPath form, it will return an Empty

/// if the xpath does not find the element.

/// </summary>

/// <param name="xPath">The x path.</param>

/// <returns></returns>

public string GetElementOnForm(string xPath)

{

var rtnValue = string.Empty;

// First, get the SharePoint Listitem

var myWeb = new SPSite(_workflowProperties.SiteId).

OpenWeb(_workflowProperties.WebId);

var myItem = myWeb.Lists[_workflowProperties.ListId].GetItemById(_workflowProperties.ItemId);

// Then get the File for that ListItem - i.e. the XML data

var myFile = myItem.File;

var myInStream = new MemoryStream(myFile.OpenBinary());

var myDoc = new XmlDocument();

myDoc.PreserveWhitespace = true;

myDoc.Load(myInStream);

// Then get my string here

var myRoot = myDoc.DocumentElement;

var incidentFormNav = _incidentInfoDoc.CreateNavigator();

if (incidentFormNav != null)

{

var xmlNSManager = new XmlNamespaceManager(incidentFormNav.NameTable);

xmlNSManager.AddNamespace(_settings.NamespacePrefix, _settings.Namespace);

if (myRoot != null)

{

XmlNode node = myRoot.SelectSingleNode(xPath, xmlNSManager);

// Set the return value

rtnValue = node.InnerText;

}

}

return rtnV


 

~ Christopher Jones

1 comments:

Anonymous said...

how do you avoid infinite loop for a WF triggered on item change - you change the item, the WF triggers, within the WF, the item is changed (by the code above), etc....