Skelta Workflow.NET Help
Developing and Configuring Custom Actions

Skelta Workflow.NET provides some standard actions, which can be used for most of the workflows. However for some workflows there might be scenarios in which the standard actions need to be extended or completely different actions need to be developed. In such cases, the custom actions can be developed by implementing the IActionRun interface.

All the actions in Skelta Workflow.NET implement the IActionRun interface. The workflow engine calls the Run () method of the class implementing the IActionRun interface. The workflow engine passes parameters that provide information about the executing workflow, the executing action, the output of the action that led to the current action, the ‘execution id’ of the executing workflow and the ‘execution details id’ of the current action, to the Run () method. Refer to the API documentation for IActionRun, for an example of the implementation of the custom action. The IActionRun interface also defines GetActivityWebUIHandler () method that returns an instance of the control that displays the details of an activity added by the action, in the activity list. This method can return null for the actions that do not add an activity.

After developing the custom action it has to be added in the Actions.xml file, in the 'source elements' configured for the application in which the action is intended to be used. The <action> tag in the XML file identifies an action.

  1. Specify the name of the action using the name attribute. Provide a brief description about the action in the description tag.
  2. Place an image in the WorkflowElements\Application\en-US\Actions\Images\Normal\Large for both the normal and selected modes in the process designer, for the action. Specify the name of the image as the value of the resourcename attribute in the image tag.
  3. Specify the name of the class, and the assembly path as values to the classname and assembly attributes respectively, of the handler element.
  4. Configure all the properties used by the action in the properties tag. Workflow.NET provides a set of properties that can be used by the custom actions. Custom properties can also be developed by implementing the IPropertyType interface. Refer to the API documentation for an example on implementing the IPropertyType interface.
  5. An action can return values that can be used in conditional routing. You can configure either specified values or property values as return values for an action. Once the return values are configured, the links leading from the action can be assigned a return value of the action, in the Process Designer. The workflow engine executes the action, led by the link that matches with the output of the action. A sample code for a custom action is given below. This action has a property type workflowmemo through which the user can build a query while designing the workflow and will be executed at runtime.
namespace CustomDataBaseUpdate
   {
      public class DataBaseUpdate : IActionRun
      {
         private string CurrentActioName="", strQuery="";
         private Context ObjContext;
         privateIDataHandler handler;
         private Log logger= new Log();
         publicDataBaseUpdate()
         {

         }

         ///Implements the IActionRun interface method.
         public ActionResult Run(intExecutionID, intExecutionDetailsId, ContextCurrentContext, ActionCurrentAction, stringInlinkOutput, boolRetry, outstring Output)
         {
            ObjContext = CurrentContext;
            CurrentActioName = CurrentAction.Name;
            //Get the value entered for the property Query.

      strQuery=((Workflow.NET.PropertyTypes.PropertyWorkflowMemo)((Property)CurrentAction.Properties
               ["Query"]).PropertyHandler).GetProcessedValue(CurrentContext.Variables, CurrentContext.Contents, null);
            GetDataValues();
            Output = "";

            return ActionResult.Completed;

         }
         publicWorkflow.NET.Interfaces.IActivityWebUIHandler GetActivityWebUIHandler()
         {
            return null;
         }
         //Get the values needed for Update from Work Flow Data
         private void GetDataValues()
         {
            UpdateDB();
         }
         //Connection details are taken from ResourceHandler XML file
         static string connectionString;
         static string datasourceType;
         static DateTime lastWriteTime;

         void Initialize(Context ctx)
         {
            //Configuration files details can be read from ContextObject as given below.
            stringResourceXmldocPath = ObjContext.ProcessDefinition.ActionsDefinition.WorkflowConfigFile.ResourceClassParams;
            DateTimetemplastWroteTime = File.GetLastWriteTime(ResourceXmldocPath);
            if(lastWriteTime != templastWroteTime)
            {
               lastWriteTime = templastWroteTime;

               XmlDocumentxDoc = new XmlDocument();

               try
               {
                  xDoc.Load(ResourceXmldocPath);
               }
               catch(System.Exception e)
               {
                  logger.LogError(e, "Could not open the document ("+ResourceXmldocPath+")");
                  throw e;
               }
               //Get connection string
               try
               {
                  XmlNodexnc = xDoc.GetElementsByTagName("datasource").Item(0);
                  connectionString = xnc.InnerText;
                  datasourceType = xnc.Attributes["type"].Value;
               }
               catch(System.Exception e)
               {
                  logger.LogError(e, "datasource tag with connectionclass & assembly attributes has some problems or not existing");
                  throw e;
               }
            }
         }
         //Update the status in db.
         private void UpdateDB()
         {
            try
            {
               Initialize(ObjContext);

               handler = DataHandlerFactory.GetDataHandler(connectionString, datasourceType);
               using(handler)
               {
                  if(strQuery != null && strQuery !="")
                  {
                     handler.BeginTransaction();
                     //Enabling the cutom action to handle multiple update statements.
                     string[] strQueryarr = strQuery.Split(';');
                     foreach(string str in strQueryarr)
                     {
                        handler.ExecuteUpdate(str);
                        logger.LogInformation("Updated =>"+ str);
                     }
                     handler.Commit();
                     logger.LogInformation("Updated & CommittedSucessfully");
                  }
                  else
                  {
                     logger.LogInformation("UPdate DB Action not performed Query is empty" + strQuery);
                  }
               }
            }
            catch(Exception e)
            {
               logger.LogError (e, "Could not Perform DB Action for Query=>" + strQuery);
            }
          }
      }
    }

The configuration in Actions.xml for the above custom action will be as given below,

<action name="UpdateDataBase">
   <description>Used to Update the Application Tables</description>
   <image resourcename="dbupdate.gif"></image>
   <handler classname="CustomDataBaseUpdate.DataBaseUpdate" assembly="D:\Program Files\Skelta\Workflow.NET\bin\CustomDataBaseUpdate.dll"></handler>
   <properties>
   <property name="Query" type="workflowmemo" helpstring="Query to be Executed when action performed"></property>
   </properties>
   </action>