Skip to content
Nick Airdo edited this page Apr 24, 2015 · 2 revisions

Workflow might just be the best kept secret in Rock. You've made it to level 303, so now you're ready to learn about this technology. Interestingly enough, tapping into the workflow engine is actually very simple, but before we show you how, let's just cover a few basics about Rock's workflow.

Overview

A "workflow" is a set of one or more Activities (WorkflowActivity), and Activities are collections of one or more Actions (WorkflowAction).

Workflows are either persisted or non-persisted. Persisted is what you think it is, so we won't belabor you with the obvious. While persisted workflows are stored in the database, non-persisted workflow are not, however they are useful for real-time processing which is transient in nature -- such as what you might have during a check-in operation. When a non-persisted workflow's activities have completed, the workflow is gone.

Workflow Activity

When a workflow is kicked off, each of its activities can be set to be "Activated" based on how it was configured in the Workflow (via the "Activated with Workflow" setting). This will allow those who create (or assemble) workflows to fire off several activities in parallel.

Custom Workflow Actions

Before you ask... yes, your custom actions can have attributes! That's what makes Rock awesome.

Your custom actions must inherit ActionComponent (a custom MEF component class in Rock) and basically requires you to implement theExecute( action, entity, out errorMessages ) method.

    public class YOUR_ACTION : ActionComponent
    {

Ok, there is a bit more to it than that. There is this tiny Managed Extensibility Framework (MEF) stuff you need to worry about too. It what let's Rock find the custom actions you and others create. Without going into the guts of MEF (which you are encouraged to read about if you like) you basically just have to decorate your class with an Export attribute and the ExportMetadata attribute which will set the "ComponentName" of your action.

    [Export(typeof(ActionComponent))]
    [ExportMetadata("ComponentName", "Send Email")]
    public class SendEmail : ActionComponent
    {

Methods

Execute( WorkflowAction action, IEntity entity, out List<string> errorMessages )

  • action - (WorkflowAction ) This is the instance of the action being executed.
  • entity - (IEntity) The entity that the action is operating against.
  • errorMessages - (out List<string>) This is a list of error messages you add to if an error is encountered while trying to process the action.

Example Custom Action

Here is a simple action that sends an email to a recipient and includes the name of the entity that the action is being performed against. The action has several customizable attributes including one to set the recipient's email address and one to designate which email template to use.

    [Description( "Email the configured recipient the name of the thing being operated against." )]
    [Export(typeof(ActionComponent))]
    [ExportMetadata("ComponentName", "Send Email")]
    [EmailTemplateField( "EmailTemplate", "The email template to send" )]
    [TextField( "Recipient", "The email address to send to" )]
    public class SendEmail : ActionComponent
    {
        /// <summary>
        /// Executes the specified workflow.
        /// </summary>
        /// <param name="action">The action.</param>
        /// <param name="entity">The entity.</param>
        /// <param name="errorMessages">The error messages.</param>
        /// <returns></returns>
        public override bool Execute( WorkflowAction action, IEntity entity, 
            out List<string> errorMessages )
        {
            errorMessages = new List<string>();
            var recipientEmail = GetAttributeValue( action, "Recipient" );
            var recipients = new Dictionary<string, Dictionary<string, object>>();
            var mergeObjects = new Dictionary<string, object>();

            if ( entity != null )
            {
                mergeObjects.Add( entity.GetType().Name, entity );
            }

            recipients.Add( recipientEmail, mergeObjects );
            Email email = new Email( new Guid( GetAttributeValue( action, "EmailTemplate" ) ) );
            email.Send( recipients );

            action.AddLogEntry( string.Format( "Email sent to '{0}'", recipientEmail ) );
            return true;
        }
    }

Triggering Workflows

Workflow Triggers can be set up to automatically create a workflow anytime a particular EntityType is saved or deleted. You can set these up under Rock's Administration panel.

These triggers can be set up to occur in one of four ways:

  • Pre-Save
  • Post-Save
  • Pre-Delete
  • Post-Delete

As you might expect, the "Post" trigger types will fire after the entity is saved/deleted and the "Pre" types will be invoked before the entity instance has been saved/deleted. It's also important to note that a Workflow Action that "fails" will prevent the entity save/delete from occurring. This is generally useful when an organization wants to enforce some rule using Workflow.

Checkin Workflow

The check-in system uses workflow behind the scenes in conjunction with a set of check-in Blocks. These matters are covered in the z. Check-In System wiki page.

Clone this wiki locally