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 will start the workflow on the server asynchronously
var criteriaOperator = CriteriaOperator.Parse("Name = 'My workflow'");
IWorkflowDefinition definition = View.ObjectSpace.FindObject<XpoWorkflowDefinition>(criteriaOperator);
if (definition != null) {
var request = new XpoStartWorkflowRequest(((ObjectSpace)ObjectSpace).Session);
object currentUserId = SecuritySystem.CurrentUserId;
request.TargetWorkflowUniqueId = definition.GetUniqueId();
request.TargetObjectKey = currentUserId;
}
WorkFlowInvoker Solution
The following code will start the workflow in synch with the client
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}};
IDictionary<string, object> results = WorkflowInvoker.Invoke(activity, 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).

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

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.

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

Now, the final and most interesting part is to launch our workflow with a simple code like;
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