Implementing the workflow activity

In Nintex Workflow 2013, custom workflow activities should be implemented from the ProgressTrackingActivity abstract class, in the Nintex.Workflow.Activities namespace. The ProgressTrackingActivity class, which is in turn derived from the Activity class, supports reporting functionality for Nintex Workflow 2013 export (.nwp) file from within the class itself, eliminating the need for external reporting activities to be added to the workflow for your custom workflow activity. This not only reduces overhead for your custom workflow activity, but also allows you to write messages for your custom workflow activity to the workflow history as well.

Creating the Visual Studio 2012 project

You can use the Workflow Activity project template, included with Nintex Workflow 2013 SDK, to create a new Visual Studio 2012 project for your custom workflow activity. Once the project is created, you can then modify the included class, already derived from the ProgressTrackingActivity class, to implement your workflow activity. For more information about the Workflow Activity project template, see Installing and using Visual Studio templates.

You can also use the Class Library template in Visual Studio 2012 to create a new Visual Studio project for your custom workflow activity. Once the project is created, you can then modify the project to implement the ProgressTrackingActivity class. However, this option is not recommended by Nintex.

For more information about creating Visual Studio 2012 solutions and projects, see Creating Solutions and Projects.

Tip: Nintex recommends that you first use the Workflow Action Adapter project template to create a Visual Studio 2012 solution for your workflow action adapter, and then use the Workflow Activity project template to add a new Visual Studio 2012 project for your workflow activity to that solution, for convenience when referencing the workflow activity from the workflow action adapter. For more information, see Implementing the workflow action adapter.

Creating the workflow activity class

The public class derived from the ProgressTrackingActivity class is referred to throughout this documentation as the workflow activity class. If you did not use the Workflow Activity project template to create your project, ensure that your Visual Studio project includes, at a minimum, the following references before creating the workflow activity class:

Implement the workflow activity class, ensuring that the class is derived from the ProgressTrackingActivity abstract class, as shown in the following example.

using System;
using System.Workflow.ComponentModel;
using Microsoft.SharePoint.Workflow;
using Microsoft.SharePoint.WorkflowActions;
using Nintex.Workflow;
using Nintex.Workflow.Activities;

namespace SampleActivity
{
    public class SampleActivity : ProgressTrackingActivity
    {
    }
}

Implementing standard dependency properties

The workflow activity class must implement at least some of the standard DependencyProperty objects as static variables, expected by Nintex Workflow 2013, to manage workflow scope and context information provided by the workflow. The objects store information about the current workflow context, and, if applicable, the identifiers for the current SharePoint list and the current list item in the SharePoint list. For more information about workflow scope and context, see Workflow scope and context.

Corresponding public properties must also be implemented for the static variables, to provide direct access to these values from the DependencyProperty objects. Each public property uses the GetValue and SetValue methods of the DependencyObject class in the getter and setter, respectively, to directly access values from the corresponding DependencyProperty object.

The following example illustrates how to implement the static variables and public properties for standard dependency properties in the SampleActivity workflow activity class.

    #region Standard dependency properties
    public static DependencyProperty __ListItemProperty = 
        DependencyProperty.Register("__ListItem", typeof(SPItemKey), typeof(SampleActivity));
    public static DependencyProperty __ContextProperty = 
        DependencyProperty.Register("__Context", typeof(WorkflowContext), typeof(SampleActivity));
    public static DependencyProperty __ListIdProperty = 
        DependencyProperty.Register("__ListId", typeof(string), typeof(SampleActivity));

    public SPItemKey __ListItem
    {
        get { return (SPItemKey)base.GetValue(__ListItemProperty); }
        set { SetValue(__ListItemProperty, value); }
    }
    public WorkflowContext __Context
    {
        get { return (WorkflowContext)base.GetValue(__ContextProperty); }
        set { SetValue(__ContextProperty, value); }
    }
    public string __ListId
    {
        get { return (string)base.GetValue(__ListIdProperty); }
        set { SetValue(__ListIdProperty, value); }
    }
    #endregion

Implementing additional dependency properties

If the custom workflow activity requires additional information to be received from or sent to the custom workflow action adapter, either as properties or events, then you must implement additional DependencyProperty objects and corresponding public properties or events to support that additional information.

Caution: Do not preface the names of additional dependency properties with two underline (__) characters, to avoid confusion with required dependency properties.

The type used for the DependencyProperty object must match the type provided by the corresponding public property, or an error occurs when the workflow activity is published.

The following example demonstrates how to add an activity-specific dependency property to the workflow activity class. In the example, the ActivityDate dependency property represents a DateTime value used by the workflow activity during execution.

// Add activity-specific dependency properties for the workflow activity.
#region Additional dependency properties
public static DependencyProperty ActivityDateProperty =
    DependencyProperty.Register("ActivityDate", typeof(DateTime), typeof(SampleActivity));

public DateTime ActivityDate
{
    get { return (DateTime)base.GetValue(ActivityDateProperty); }
    set { SetValue(ActivityDateProperty, value); }
}
#endregion

Implementing the Execute method

You must override the Execute method, from the Activity base class, in the custom workflow activity. The Execute method of the workflow activity determines its runtime behavior. Typically, the Execute method in a custom workflow activity performs the following steps:

  1. Confirm that the workflow activity is allowed to execute.

    The IsAllowed static method of the ActivityActivationReference class checks if the workflow action is allowed to run in workflows. This method is a security measure that, if the workflow action is not allowed to run on the SharePoint site in which the workflow is running, causes the workflow to fail.

  2. Retrieves the runtime workflow context data for the workflow action.

    The GetContext static method, from the NWWorkflowContext class, populates the dependency properties of the workflow activity from the runtime workflow context.

  3. Report the start of the workflow activity.

    The LogProgressStart method of the ProgressTrackingActivity base class logs the start of the workflow activity. This method writes a record to the [dbo].[WorkflowProgress] table in the Nintex Workflow content database. If the workflow publishing process allows workflow history logging and the value of the LogHistoryListMessage property is set to true, this method also logs the value of the HistoryListMessage property, set by the workflow publishing process, to the workflow history list.

    When viewing the running workflow in preview view, the custom workflow action for this workflow activity appears in yellow, indicating that it is in progress, until the LogProgressEnd method is invoked.

  4. Resolve workflow references in additional dependency properties.

    The workflow action adapter can include workflow references when setting the additional dependency properties in the context data used by the workflow activity. The AddContextDataToString method of the NWWorkflowContext object can resolve workflow references within the runtime workflow context, by replacing the workflow reference with the actual context data.

    Certain types of context data, such as dates or Transact-SQL statements, may require additional formatting. For example, the workflow activity may require that dates are returned in ISO 8601 format. You can use the GetContextData method of the NWWorkflowContext object to retrieve a collection of context data using specific context data options, and then provide the collection to the AddContextDataToString method to resolve workflow references using the formatted context data.

  5. Perform the tasks of the workflow activity.

    The workflow activity performs its intended tasks. Any unhandled exception that occurs during execution is caught by the workflow, which then invokes the HandleFault method of the workflow activity and stops the workflow. For more information about implementing the HandleFault method in the workflow activity, see Implementing the HandleFault method.

  6. Report the successful completion of the workflow activity.

    The LogProgressEnd method of the ProgressTrackingActivity class logs the end of the workflow activity. This method writes a record to the [dbo].[WorkflowProgress] table in the Nintex Workflow content database. If the workflow publishing process allows workflow history logging and the value of the LogHistoryListMessage property is set to true, this method also logs the value of the HistoryListMessage property, set by the workflow publishing process, to the workflow history list.

    When viewing the running workflow in preview view, the custom workflow action for this workflow activity appears in green, indicating that it has successfully completed.

  7. Return the execution status of the workflow activity.

The following example demonstrates how to implement the Execute method in the SampleActivity workflow activity.

protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
{
    // Confirm that the workflow activity is allowed to execute.
    ActivityActivationReference.IsAllowed(this, __Context.Web);

    // Get the workflow context for the workflow activity.
    NWWorkflowContext ctx = NWWorkflowContext.GetContext(
        __Context, 
        new Guid(__ListId), 
        __ListItem.Id, 
        WorkflowInstanceId, 
        this);

    // Report the start of the workflow activity.
    base.LogProgressStart(ctx);

    // TODO: Resolve workflow references in context data for dependency properties.
    // The following code resolves workflow references for the ActivityDate property, 
    // using default formatting for the context data.
    // string resolvedActivityDate = ctx.AddContextDataToString(this.ActivityDate);

    // The following code resolves workflow references for the ActivityDate property,
    // using specific formatting options for the context data.
    // NWContextDataCollection formattedData = 
    //     ctx.GetContextData(ContextDataOptions.DatesInIso8601Format);
    // string resolvedActivityDate = ctx.AddContextDataToString(this.ActivityDate,
    //     formattedData);


    // Perform the workflow activity. 
    try
    {
        // TODO: Your code goes here.
    }
    catch (Exception e)
    {
        // If an exception occurs that should stop the workflow, 
        // then throw the error. 
        throw;
    }
            
    // Report the successful execution of the workflow activity.
    base.LogProgressEnd(ctx, executionContext);

    // Return the execution status of the workflow activity.
    return ActivityExecutionStatus.Closed;
}

Implementing the HandleFault method

You must also override the HandleFault method, from the Activity base class, in the custom workflow activity. This method allows you to perform any additional actions needed upon encountering an unhandled exception during the invocation of the Execute method. Typically, this method should first call the HandleFault method of the ActivityErrorHandler static class, which logs an error message to the workflow history list, and logs further details, including a stack trace, to the SharePoint logs.

protected override ActivityExecutionStatus HandleFault(ActivityExecutionContext executionContext, 
    Exception exception)
{
    // TODO: Provide activity-specific text introducing the exception.
    string activityErrorIntro = "Error in SampleActivity";

    Nintex.Workflow.Diagnostics.ActivityErrorHandler.HandleFault(
        executionContext,
        exception,
        this.WorkflowInstanceId,
        activityErrorIntro,
        __ListItem.Id,
        __ListId,
        __Context);

    return base.HandleFault(executionContext, exception);
}

Creating the assembly

Once the workflow activity class is implemented, you can then build the Visual Studio project and create a .NET Framework assembly for your workflow activity.

In SharePoint 2013, an assembly that contains a workflow activity must be strongly named and installed into the Global Assembly Cache (GAC). Ensure that, before you compile your assembly, that you create a strong name key file and sign the assembly. For more information about signing assemblies, see Creating and Using Strong-Named Assemblies.

See Also

Concepts

Workflow activities

Workflow action adapters

Configuration pages

Operations

Working with workflow actions

Working with workflow activities

Reference

.NET Framework Reference