11 November 2009

Displaying workflow item information from a custom ASPX task form



When building custom workflows, often we want custom Task edit screens as well.  A custom Task Content Type allows us to collect much deeper data than 'completed'.  However, since we are ditching the default Task edit pages, we lose a couple of useful features; a link to the underlying Workflow item as well as the implied context of the Task.

Given the need to provide context to the user when overrriding the default task form, you may come across the desire to display some file information, custom columns/properties, links, etc on the task edit page.  

To accomplish this, we need to gain two pieces of understanding:

  1. How and when to modify ASPX page elements from the code-behind c# class
  2. How to extract the underlying information from the Workflow's original item

When: during the page_load() of inherited class;
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!Page.IsPostBack)
            {

                    ...
                    //string _paramTaskListItemID Represents the ID Task List Item being worked on 
                    this._paramTaskListItemID = Request.Params["ID"];

                    //SPListItem _TaskListItem Represents the item within the task list 
                    this._TaskListItem = this._TaskListAttachedTo.GetItemById(System.Convert.ToInt16(this._paramTaskListItemID));

                    //Guid _workflowInstanceGuid Represents the ID of the running workflow
                    this._workflowInstanceGuid = new Guid(Convert.ToString(this._TaskListItem["WorkflowInstanceID"]));

                    // SPWorkflow _activeWorkflow Represents the current workflow 
                    // Instantiate the workflow, retrieve the SPworkflow object for the web 
                    this._activeWorkflow = new SPWorkflow(this._myTeamSite , this._workflowInstanceGuid );

                    // protected System.Web.UI.WebControls.Label labelFileURL is a reference to the aspx form's label
                    ...



                    ...
                try
                {
                    labelFileURL.Text += "Job ID is: " + this._activeWorkflow.ParentItem.File.Properties["Job ID"].ToString();
                }
                catch (NullReferenceException)
                {
                    labelFileURL.Text += "Job ID is not set.";
                }
                    ...



How do we modify the aspx page in flight - insert a placeholder aspx object within the task form - choose a good candidate object like a label;

<%@ Page Language="C#" AutoEventWireup="true" EnableSessionState="true" ValidateRequest="False"  Inherits="BI_IA_NS.BI_TaskApprovalForm" %>
...
<asp:content contentplaceholderid="PlaceHolderMain" runat="server">
        <p class="subheader">Job Information 
         <div class="greytext">
            <asp:Label ID="labelJobID" runat="server"></asp:Label>
            <asp:Label ID="labelFileURL" runat="server"></asp:Label>
         </div>
        </p>

These labels are placeholders that we can manipulate based on actions or events sent to the code-behind class. Now that we have the ability to modify the form in flight, this brings us to how we extract the workflow document data while editing a task.

The key is to build the correct SPWorkflow object - as it turns out, there are two constructors for this object. If you use the constructor based on the tasks' list item, all the information within the SPWorkflow object is relative to the Task List. So we want to use the SPWorkflow constructor with the SPWeb parameter.

SPWorkflow (SPListItem, Guid)
SPWorkflow (SPWeb, Guid)


The SPWorkflow object can be created like this:

                    ...
                    //string _paramTaskListItemID Represents the ID Task List Item being worked on 
                    this._paramTaskListItemID = Request.Params["ID"];

                    //SPListItem _TaskListItem Represents the item within the task list 
                    this._TaskListItem = this._TaskListAttachedTo.GetItemById(System.Convert.ToInt16(this._paramTaskListItemID));

                    //Guid _workflowInstanceGuid Represents the ID of the running workflow
                    this._workflowInstanceGuid = new Guid(Convert.ToString(this._TaskListItem["WorkflowInstanceID"]));

                    // SPWorkflow _activeWorkflow Represents the current workflow 
                    // Instantiate the workflow, retrieve the SPworkflow object for the web 
                    this._activeWorkflow = new SPWorkflow(this._myTeamSite , this._workflowInstanceGuid );


Then, by combining the techniques of modifying the label, and extracting the document metadada, gets us to our goal:
                try
                {
                    labelFileURL.Text += "Job ID is: " + this._activeWorkflow.ParentItem.File.Properties["Job ID"].ToString();
                }
                catch (NullReferenceException)
                {
                    labelFileURL.Text += "Job ID is not set.";
                }

To help understand what properties your file has, you can enumerate the whole set of properties (as a debugging step) - bonus code:
                System.Collections.Hashtable collHashes = this._activeWorkflow.ParentItem.File.Properties;
                System.Collections.ICollection collKeys = collHashes.Keys;
                string strList = "File properties are 
";

                foreach (object oKey in collKeys)
                {
                    strList += (SPEncode.HtmlEncode(oKey.ToString())
                    + " :: " +
                    SPEncode.HtmlEncode(collHashes[oKey.ToString()].ToString())
                    + "
");
                }
                labelJobID.Text = strList;


Reference on MSDN - Item or SPWorkflowActivationProperties from SPWorkflow

No comments:

Post a Comment

firstly, thanks in advance for your comment - I don't get very many, so I'm sure to follow up if you leave me a way - secondly, come again.