Getting to Workflow Information

Getting to Workflow Information

  • Comments 10

Hi, I'm Phil Allen, a developer with the SharePoint Designer team who works primarily on Workflow. Today I'd like to describe how you can get some important data about your workflow as usable data within a workflow action.

This is all about creating new workflow actions, and so, Visual Studio 2005 with the Extension for Windows WF installed will be very helpful. Boot Visual Studio, File -> New -> Project, Other Languages -> Visual C# -> Workflow, Workflow Activity Library is the place to start. Much of the early portions of this article is similar to the blog post on creating new actions for SPD, but is intended to show you how to get to some of the information about the workflow itself as part of the workflow.

It also builds on top of this MSDN magazine article:
http://msdn.microsoft.com/msdnmag/issues/06/12/windowsworkflow/

Suppose for a moment that you wanted to write an action that calculated the time since the workflow started and returns the number of minutes as a string. Create the shell of your activity, giving it the namespace and class name you want it to have. From there, you'll need to start by thinking about the Execute method of your activity:

namespace MyNamespace

{

    public class MyActivity : Activity

    {

        protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)

        {

            //More goes here later

            return ActivityExecutionStatus.Closed;

        }

    }

}

First, you need the current time:

DateTime currentDateTime = System.DateTime.UtcNow;

Notice the use of UtcNow instead of Now; Now is done in the timezone of the local machine, and not the timezone of the website that you are working with.

Second, you need the time the workflow was started. This is a bit trickier, but what you need to get access to is the SPWorkflowActiviationProperties for the current workflow. Every workflow receives one of these as part of OnWorkflowActivated; however, the goal is to make this work seamlessly in SharePoint Designer.

SharePoint Designer's workflow authoring capabilities has a few special names for properties that will automatically be set to certain values that should always be available in the workflow. Specifically, there's a table of the property names, which value they bind to, and the .Net type of that property.

Property Name

Value it is set to

.Net type

__ActivationProperties

__initProps, the SPWorkflowActivationProperties that was passed in via OnWorkflowActivated

Microsoft.SharePoint.Workflow.SPWorkflowActivationProperties

__ListId

__list, the name of the SPList the workflow is executing on.  This is typically a string datatype which contains the text of a System.Guid.

System.String

__ListItem

__item, the integer value of the list item in the list that the workflow is running on.

System.Int32

__Context

__context, the object that contains many helper methods and objects for use as part of workflow actions

Microsoft.SharePoint.WorkflowActions.WorkflowContext

In this case, browsing some of the MSDN pages and most importantly their properties, we find that SPWorkflowActivationProperties has a Workflow property of type SPWorkflow, which has Created property which is a DateTime representing the time the workflow started.

To get access to the SPWorkflowActivationProperties in your Execute method, you need to create a property that SharePoint Designer will automatically set to __initProps.

public static DependencyProperty __ActivationPropertiesProperty = DependencyProperty.Register("__ActivationProperties", typeof(Microsoft.SharePoint.Workflow.SPWorkflowActivationProperties), typeof(MyActivity));

 

[ValidationOption(ValidationOption.Required)]

public Microsoft.SharePoint.Workflow.SPWorkflowActivationProperties __ActivationProperties

{

    get

    {

        return (Microsoft.SharePoint.Workflow.SPWorkflowActivationProperties)base.GetValue(__ActivationPropertiesProperty);

    }

    set

    {

        base.SetValue(__ActivationPropertiesProperty, value);

    }

}

SharePoint Designer won't automatically do the hookup yet; you'll need to add a little bit to your actions file in order to do so. I'll come back to that later.

At this point, you have access to an object that will give you the SPWorkflowObject you want. You also need to have an output parameter of type System.Int32 to output your number of minutes to. Code for that will look like this:

public static DependencyProperty NumberOfMinutesProperty = DependencyProperty.Register("NumberOfMinutes", typeof(System.Int32), typeof(MyActivity));

 

[ValidationOption(ValidationOption.Required)]

public System.Int32 NumberOfMinutes

{

    get

    {

        return (System.Int32)base.GetValue(NumberOfMinutesProperty);

    }

    set

    {

        base.SetValue(NumberOfMinutesProperty, value);

    }

}

This is your output variable.

The last piece of the activity is to finish writing the Execute method:

protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)

{

    DateTime currentDateTime = System.DateTime.UtcNow;

//Set this to a recognizable value that would never be a valid value for the started time.

    DateTime startedDateTime = System.DateTime.MinValue;

//Set this to a recognizable value that would never be the result of the real calculation.

    NumberOfMinutes = System.Int32.MaxValue;

 

    if (__ActivationProperties != null)

    {

        SPWorkflow currentWorkflow = __ActivationProperties.Workflow;

        if (currentWorkflow != null)

        {

             startedDateTime = currentWorkflow.Created; //This time is returned in UTC

        }

    }

 

    if (startedDateTime > System.DateTime.MinValue)

    {

        TimeSpan timeWorkflowRunning = currentDateTime.Subtract( startedDateTime);

        NumberOfMinutes = timeWorkflowRunning.Minutes;

    }

    return ActivityExecutionStatus.Closed;

}

As for the actions file, I could write another, similar article on it. However, the important thing to know is that SharePoint Designer uses the content of the actions file when inserting the action to know that it should do this hookup for particular properties. Here's how someone might have created the actions file entry for this new workflow action:

<WorkflowInfo>

    <Actions>

        <Action Name=”Get Minutes Workflow Has Run”

               Assembly=”MyAssembly, Version=0.0.0.0, culture=neutral, PublicKeyToken=11111111111111”

               ClassName=”MyNamespace.MyActivity”

               Category=”Custom Actions”

               AppliesTo=”all”

        >

        <RuleDesigner Sentence=”Get number of minutes worklow has run, output to %1”>

           <FieldBind Field=”NumberOfMinutes” Text=”minutes” DesignerType=”ParameterNames” Id=”1” />

        </RuleDesigner>

        <Parameters>

           <Parameter Name=”NumberOfMinutes” Type=”System.Int32, mscorlib” Direction=”Out” />

           <Parameter Name=”__ActivationProperties” Type=”Microsoft.SharePoint.Workflow.SPWorkflowActivationProperties, Microsoft.SharePoint” Direction=”Out” />

        </Parameters>

      </Action>

   </Actions>

</WorkflowInfo>

The highlighted text is required for SharePoint Designer to do the automatic setting of __ActivationProperties to the __initProps value that is in every SPD created workflow.

Depending upon how exactly you chose to build this, you may run into an issue where the property doesn't automatically get set in SPD; this could be caused by having a stale proxy assembly. SPD will try to set the property, but it doesn't exist in the proxy assembly, so it fails to set the value. In order to clear the proxy assembly cache, follow the steps in this article.

With the SPWorkflowActivationProperties, the SPWorkflow that is a child of it, the name of the list, the ID of the item, and the WorkflowContext, you should be able to retrieve and use many interesting properties of your SharePoint Server.

- Phil

  • PingBack from http://www.artofbam.com/wordpress/?p=4142

  • Después de una semana un tanto ajetreada en el CII, noi podíamos faltar al tradicional recopilatorio

  • Hi, i have problem with __Context property, the value is alway null. I have followed step by step instructions on this article but not work for me. I'm using WSS 3.0 only and not SPD. Can you help me?

    Thanks

  • Después de algún tiempo sin postear el habitual recopilatorio de recursos interesantes de WSS 3.0 &amp;

  • Slightly off topic, but I'm making a workflow in SPD and trying to pull the initiating user information. I don't see any intuitive way of doing this. Am I missing something here?

    Any help is appreciated.

  • I've create BaseItemActivity class which declares __Context, __ListId and __ListItem properties. Activities inherited from BaseItemActivity doesn't work correctly in SPD. Does it mean that every activity which uses current item must declare its own __Context, __ListId and __ListItem?

    public abstract class BaseItemActivity : Activity

    {

       // Fields

       public static DependencyProperty __ContextProperty = DependencyProperty.Register("__Context", typeof(WorkflowContext), typeof(BaseItemActivity));

       public static DependencyProperty __ListIdProperty = DependencyProperty.Register("__ListId", typeof(string), typeof(BaseItemActivity));

       public static DependencyProperty __ListItemProperty = DependencyProperty.Register("__ListItem", typeof(int), typeof(BaseItemActivity));

    ...

    }

    Correct binding generated by SPD:

    __ListItem="{ActivityBind ROOT,Path=__item}" __Context="{ActivityBind ROOT,Path=__context}" __ListId="{ActivityBind ROOT,Path=__list}"

    Binding generated by SPD when inheriting from BaseItemActivity (__ListId and __ListItem are empty, __Context is ???)

    <... __ListItem="0" __ListId="" ...>

     <ns1:MyActivity.__Context>

     <ns2:C__153 xmlns:ns2="clr-namespace:My.WorkflowActions.ProxySupport;Assembly=My.WorkflowActions, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />

     </ns1:MyActivity.__Context>

  • Hi i have used ur blog to create the custom activity which returns me the UTC time, but when i use the sharepiouint designer string builder to cretae the string and append the datetime varible to it, it converts the datetime backt ot the local time while appending it to the string, but the same things work when i assing the valut ot datetime column, any solution for this.

    Sandeep

  • La semana pasada surgió el siguiente requerimiento algo especial, en este escenario se cuenta con un

  • Hi there, I’m Jordan Hull, a Software Development Engineer in Test on the SharePoint Designer Workflow

  • Muy interesante, muy buen artículo...

Page 1 of 1 (10 items)
Leave a Comment
  • Please add 7 and 8 and type the answer here:
  • Post