Manually starting workflows

XAF Team Blog
19 July 2011

In this post we are going to explore 2 different ways to start a workflow. So far we have looked at using the workflow server, together with the ObjectCreated and ObjectFitsCriteria, to automatically start the workflow. However there is often a necessity to start workflows from a client whilst entering additional parameters.

Scenario 1

An order form has been completed and the user hits enter. This will initiate a workflow that will asynchronously notify a call center employee to contact that user.

XpoStartWorkflowRequest Solution

The below code (inside a ViewController descendant) will start the workflow on the server asynchronously:

using DevExpress.Data.Filtering;
using DevExpress.ExpressApp;
using DevExpress.ExpressApp.Workflow;
using DevExpress.ExpressApp.Workflow.Xpo;
using DevExpress.ExpressApp.Xpo;

namespace YourSolutionName.Module.Controllers {
	public class YourControllerName : ViewController {
		public void SomeMethodName() {
			var criteriaOperator = CriteriaOperator.Parse("Name = 'My workflow'");
			IWorkflowDefinition definition = View.ObjectSpace.FindObject<XpoWorkflowDefinition>(criteriaOperator);
			if(definition != null) {
				var request = new XpoStartWorkflowRequest(((XPObjectSpace)ObjectSpace).Session);
				object currentUserId = SecuritySystem.CurrentUserId;
				request.TargetWorkflowUniqueId = definition.GetUniqueId();
				request.TargetObjectKey = currentUserId;
			}
		}
	}
}

WorkFlowInvoker Solution

The following code (inside a ViewController descendant) will start the workflow in synch with the client:

 

using DevExpress.Data.Filtering;
using DevExpress.ExpressApp;
using DevExpress.ExpressApp.Workflow;
using DevExpress.ExpressApp.Workflow.Xpo;
using DevExpress.ExpressApp.Xpo;
using System.Activities;
using System.Activities.XamlIntegration;// You must add assembly references to System.Activities and System.Xaml.
using System.Collections.Generic;
using System.IO;

namespace YourSolutionName.Module.Controllers {
	public class YourControllerName : ViewController {
		public void SomeMethodName() {
            var criteriaOperator = CriteriaOperator.Parse("Name = 'My workflow'");
            IWorkflowDefinition definition = View.ObjectSpace.FindObject<XpoWorkflowDefinition>(criteriaOperator);
            if(definition != null) {
                Activity activity = ActivityXamlServices.Load(new StringReader(definition.Xaml));
                var args = new Dictionary<string, object> { { "targetObjectId", SecuritySystem.CurrentUserId } };
                WorkflowInvoker invoker = new WorkflowInvoker(activity);
                invoker.Extensions.Add(Application.ObjectSpaceProvider); // You may want to modify this line to obtain a valid provider from a different place or even create it from scratch.
                IDictionary<string, object> results = invoker.Invoke(args);
                // If needed

                //((MyObject)View.CurrentObject).WorkflowResultData = (int)results["SomeIntOutArgument"];

            }
        }
	}
}

Scenario 2

Let’s make Scenario 1 a little bit more interesting by providing the option to choose a Product when placing the order. This time together with the current user id we need to set an additional parameter - the product id.

WCF Solution

It is interesting to note that it is also possible to apply the WorkFlowInvoker Solution from Scenario 1 here. This is because the WorkflowInvoker can receive a range of arguments. Now, in order to to model our workflow we are going to use the runtime designer. We need to create a new workflow definition, name it and set its target object to a dummy value. Since we are going to invoke the workflow using a WCF service the target object is redundant, however it is mandatory. The same rule applies to the other start workflow conditions (AutoStartWhenObjectIsCreated, AutoStartWhenObjectFitsCriteria).

image

Next we are going to use the native receive activity and bind it to the WCF service as shown.

image

it is imperative to check the CanCreateInstance attribute at this stage. At the same time we need to set the OperationName and ServiceContactName and define the following contract;

[ServiceContract]

public interface IPassOrder {

    [OperationContract(IsOneWay = true)]

    void PassOrder(Guid currentUserId, Guid productId);

}

 

Two variable declarations (productId, currentUserId) are required in order to hold them for later use. Moreover we need to assign them from the OperationName arguments.

 

 

image

To finish designing we can create a Task that will inform the employee. You can read more on this here.

image

Now, the final and most interesting part is to launch our workflow with a simple code like;

using DevExpress.Data.Filtering;
using DevExpress.ExpressApp;
using DevExpress.ExpressApp.Workflow.Xpo;
using System;
using System.ServiceModel;

namespace YourSolutionName.Module.Controllers {
    [ServiceContract]
    public interface IPassOrder {
        [OperationContract(IsOneWay = true)]
        void PassOrder(Guid currentUserId, Guid productId);
    }
    public class YourControllerName : ViewController {
        public void SomeMethodName() {
            var criteriaOperator = CriteriaOperator.Parse("Name=?", "Contact customer");
            var workflowDefinition = ObjectSpace.FindObject<XpoWorkflowDefinition>(criteriaOperator);
            var uri = "http://localhost:46232/" + workflowDefinition.GetUniqueId();
            var newEndpointAddress = new EndpointAddress(uri);
            var serverWorkflow = ChannelFactory<IPassOrder>.CreateChannel(new BasicHttpBinding(), newEndpointAddress);
            var productId = Guid.NewGuid();
            serverWorkflow.PassOrder((Guid)SecuritySystem.CurrentUserId, productId);
        }
    }
}

We would appreciate your feedback on this post. Has it been useful to you? Feel free to contact us  with any further questions

Related Links
Online documentation
Blog posts

Free DevExpress Products - Get Your Copy Today

The following free DevExpress product offers remain available. Should you have any questions about the free offers below, please submit a ticket via the DevExpress Support Center at your convenience. We'll be happy to follow-up.
No Comments

Please login or register to post comments.