EPiWiki.se  - EPiServer notes shared with others
 

Sample EPiServer workflow with a custom user interface

[Edit]
A sample EPiServer workflow based on Microsoft workflow foundation. This workflow is started from some pages workflow tab, assigns a task to the role everyone with a custom user interface and terminates when the user clicks accept.

Download source code


EPiServerWorkflowWithGUI.zip

Create the workflow


Create a new project in Visual studio 2008 (the only working one for CMS 6 R2) using the "State Machine Workflow Library" standard template.
Add the EPiServers activity by drag the EPiServer.WorkflowFundation assembly to the tools folder.

Create a .Net 3.5 state machine workflow


Add the EPiServer and EPiServer.WorkflowFoundation assemblies as references to the project
Add a Serializable class to handle event arguments (inheriting from ExternalDataEventArgs)

using System;
using System.Workflow.Activities;
using EPiServer.Core;
namespace EPiServerWorkflowWithGui
{
   [Serializable]
   public class AcceptedEventArgs : ExternalDataEventArgs
   {
      public AcceptedEventArgs(Guid instanceId, PageReference pageLink)
           : base(instanceId) {}
      public PageReference PageLink { get; internal set; }
   }
}

Add a workflow service interface (decorated with the ExternalDataExchange attribute) here called IAcceptedService with one event handler named Accepted.

using System;
using System.Workflow.Activities;
namespace EPiServerWorkflowWithGui
{
   [ExternalDataExchange()]
      public interface IAcceptedService
      {
          event EventHandler<AcceptedEventArgs> Accepted;
      }
}

Use the wca.exe tool to generate event driven activities from the IAcceptedService
wca EPiServerWorkflowWithGui.dll
Two classes should be generated IAcceptedService.Invoke.cs and IAcceptedService.Sink.cs include them in the project.
Build a simple workflow with
One start state activity called Start
One start finish activity called End
Set the properties InitialStateName to Start and CompleleStateName to End
Add a state activity WaitForAccept add an EventDriven activity with your own Accepted activity named WaitForAccepted. Finnish the event by a set state activity with the TargetStateName to End.
To decorate your activity with the ActivityPlugIn so it will work as the GUI for the activity –add a partial class to the activity sinks Accepted class

using EPiServer.WorkflowFoundation.UI;
namespace EPiServerWorkflowWithGui
{
   [ActivityPlugIn(
      Area = EPiServer.PlugIn.PlugInArea.None,
      Url = "~/Templates/Plugins/Workflows/AcceptWorkflow.ascx")]
   public partial class Accepted{}
}

To the Start state add a StateInitialization with a CreateTask activity to create the EPiServer task, fill the properties
AssingTo: <your login name> or any group you want to assign the task to
AssosiatedActivity: WaitForAccepted
TaskDescription: Description
TaskSubject: Subject
Add a SetState activity with the property TargetStateName set to "waitForAccept"

Create a service to communicate between the workflow host and your application



using System;
namespace EPiServerWorkflowWithGui
{
   public class AcceptedService : IAcceptedService
   {
      public event EventHandler<AcceptedEventArgs> Accepted;
      public void InvokeAcceptedEvent(AcceptedEventArgs args)
      {
         EventHandler<AcceptedEventArgs> acceptedEvent = Accepted;
         if (acceptedEvent != null)
         {
            acceptedEvent(null, args);
         }
      }
   }
}

Register the workflow service in the sites episerver.config (or web.config)



<episerver...
   <workflowSettings…
      <externalServices>
         <externalService type="EPiServerWorkflowWithGui.AcceptedService, EPiServerWorkflowWithGui" />

Create the user interface


Add a reference to the EPiServerWorkflowWithGui and System.Workflow.Activities to your sites project
Add a user control to use as the user interface for our task in the folder \Templates\Plugins\Workflows

AcceptWorkflow.ascx



<%@ Control Language="C#"
    AutoEventWireup="true"
    CodeBehind="AcceptWorkflow.ascx.cs"
    Inherits="EPiServer.Templates.Plugins.Workflows.AcceptWorkflow" %>
Accerpt this workflow and finnish it!

AcceptWorkflow.ascx.cs



using System;
using System.Web.UI;
using EPiServer.Core;
using EPiServer.WorkflowFoundation;
using EPiServer.WorkflowFoundation.UI;
using EPiServerWorkflowWithGui;
namespace EPiServer.Templates.Plugins.Workflows
{
   public partial class AcceptWorkflow : UserControl, IWorkflowTaskControl
   {
      protected void Page_Load(object sender, EventArgs e) {}
      public void ContextData(
         Guid workflowInstanceId,
         int taskId,
         string eventQualifiedName,
         EPiServer.Core.PageReference pageLink){}
         public string InvokeButtonText{ get { return "Accept"; } }
        public bool InvokeEvent(
             Guid workflowInstanceId,
             int taskId,
             string eventQualifiedName)
        {
            AcceptedService service =
               WorkflowSystem.WorkflowManager.GetService<AcceptedService>();
               service.InvokeAcceptedEvent(
                  new AcceptedEventArgs(workflowInstanceId,
                     PageReference.EmptyReference));
            return true;
         }
         public void PageHasChanged(
            EPiServer.Core.PageReference previousPageLink,
            EPiServer.Core.PageReference newPageLink)
        {}
    }
}

Test the project


Add the workflow in Admin mode by selecting "Workflows" below the "Tools" heading.
EPiServerWorkflowWithGui: AcceptWithGui
Class name: EPiServerWorkflowWithGui.Accept
Assembly name: EPiServerWorkflowWithGui
Start the workflow from edit mode

Add a startup configuration interface

References


EPiServer Workflow foundation SDK
A well written sample state machine workflow sample
Troubleshooting EPiServer workflows
Version author:
Mattias Lövström

EPiServer version

All