You are here: Home » Modifying the Workflow Association Data in SharePoint 2007 Pre-Initiation

Modifying the Workflow Association Data in SharePoint 2007 Pre-Initiation

Posted by undercoverlaptop
No Comments »

One of our customers wanted to use the out-of-the-box Approval workflow but wanted to pre-fill the Approvers field with users from the items metadata.  In another words, each document in a document library can potentially have a difference approver so rather than have the Approvers field pre-filled from the initial Association data, they want it populated from the Approvers field on the initiated item.

Initially, I started out modifying the out-of-the-box Approval InfoPath form (Review-RoutingInit.xsn) and was able to successfully populate the Approvers field with hardcoded data but I then realized that I didn't know what Item the workflow had been started on, which meant I couldn't figure out who the Approver was for the specific item that the workflow had been started.  So, I scrapped that idea and decided to create a new InfoPath Workflow initiation page (this is the page that loads the InfoPath Forms on initiation).

After using Lutz Roeder's . NET Reflector to analyze the IniWrkflIPPage.aspx page, I was able to determine that if I wanted to change the AssociationData before it was populated into the InfoPath Form Control, I needed to modify the property m_formData before the page finished its databinding.

protected override void OnLoad(EventArgs ea)
{  
    base.OnLoad(ea);
  
   
/* Some code commented out */  
   
this.m_assocTemplate = SPWorkflowAssociationCollection.GetAssociationForListItemById(this.m_listItem, associationId);
  
   
this.m_formData = this.m_assocTemplate.AssociationData;  
–> this.m_formData = “My modified form data”;   
   
/* More code commented out */
  
   
this.DataBind(true);
}

I then went on to modify the form data using metadata from the item that initiated the workflow.  Because I wanted to inherit my custom InfoPath initiation form from IniWrkflIPPage.aspx, I realized that I couldn't change the code in the OnLoad event, but instead needed to change it on the DataBind event. 

protected override void DataBind(bool raiseOnDataBinding)
{   
   if (m_listItem["Approver"] != null)
   
  
{
        
      
// Load form data into an XmlDocument
        
      
XmlDocument xmlDoc = new XmlDocument();
         
       
xmlDoc.LoadXml(this.m_formData);
         
       // Defines the namespace manager to handle using the 'my' namespace
        
      
XmlNamespaceManager manager = new XmlNamespaceManager(xmlDoc.NameTable);
        
      
manager.AddNamespace("my", "http://schemas.microsoft.com/office/infopath/2003/myXSD");
         
      
// Gets a collection of all the Users specificed in the Approver field (Requires Approver field on document library)
        
      
SPFieldUserValueCollection users = new SPFieldUserValueCollection(m_listItem.Web, m_listItem["Approver"].ToString());
        
      
string personXml = string.Empty;
         
      
// Loops through each user and builds out a new Person element
         
      
foreach (SPFieldUserValue user in users)
        
      
{
             
         
personXml += "<my:Person><my:DisplayName>" + user.User.Name + "</my:DisplayName><my:AccountId>" + user.User.LoginName + "</my:AccountId><my:AccountType>User</my:AccountType></my:Person>";
         
       
}
      // Selects the Reviewers (aka Approver) in the form data and sets the innerXml = to the collection of users we built        
     
xmlDoc.SelectSingleNode("/my:myFields/my:Reviewers", manager).InnerXml = personXml;
          // overwrites the default association data with our newly modified data
         this.m_formData = xmlDoc.InnerXml;  
}
}

As it turned out, apparently some of the global variables in the IniWrkflIPPage.aspx don't “port” very well over to my custom page, so I ended up faking it a bit.  There is probably a better way to do this but at this point I didn't care J

using System;
using System.Collections.Generic;
using System.Security.Permissions;
using Microsoft.SharePoint;
using Microsoft.Office.InfoPath.Server.Controls; 

namespace TeamEli.Sharepoint.Workflow.ApprovalWorkflow
{
  [PermissionSet(SecurityAction.InheritanceDemand, Name = "FullTrust"), PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
  public class ApprovalIniWrkflIP : Microsoft.Office.Workflow.IniWrkflIPPage
  {
        //// Fields
        protected new string m_listItemName;
        protected new string m_listItemUrl;
        protected new string m_workflowName;
        protected new XmlFormView XmlFormControl;
         //// Methods
        protected override void OnInit(EventArgs e)
        {
            base.XmlFormControl = this.XmlFormControl;
            base.m_workflowName = this.m_workflowName;
            base.m_listItemName = this.m_listItemName;
            base.m_listItemUrl = this.m_listItemUrl;
            base.OnInit(e);
        }
         protected override void OnLoad(EventArgs ea)
        {
            base.OnLoad(ea);
            this.XmlFormControl = base.XmlFormControl;
            this.m_listItemName = base.m_listItemName;
            this.m_workflowName = base.m_workflowName;
        }

         protected override void DataBind(bool raiseOnDataBinding)        {            //// See above.        }
  }
}

With the code above precompiled into a DLL, all I needed to was modify two lines of my copied IniWrkflIPPage.aspx and that was to add my assembly and to change the page inherits to our new codebehind page.

<%@ Assembly Name="TeamEli.Sharepoint.Workflow.ApprovalWorkflow, Version=1.0.0.0, Culture=neutral, PublicKeyToken=<<PUBLICKEYTOKEN>>"%>
<%@ Page Language="C#" Inherits="TeamEli.Sharepoint.Workflow.ApprovalWorkflow.ApprovalIniWrkflIP" MasterPageFile="~/_layouts/application.master"   EnableSessionState="true" AutoEventWireup="false"  %>

All that was left was to create a new Feature that calls our new initiation page.  And volia!

Hopefully some of this made sense.  If not, let me know.

Eli

Your email is never shared.
Required fields are marked *




Allowed tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>