Sunday, September 12, 2010

SharePoint 2010 Pluggable Workflow Services – Part 1

Along with the many advancements and new features, SharePoint 2010 introduces a yet another important feature of Pluggable Workflow Services. While Pluggable Workflow Services have been around since Windows Workflow Foundation in .Net 3.5, its support was missing in SharePoint 2007. But now the SharePoint 2010 workflow engine supports it.

So what’s a Pluggable Workflow Service all about?

Here is what MSDN says:

Pluggable workflow services provide a mechanism that allows external applications or components to programmatically communicate with workflow instances currently running on the server.

This means that workflows in SharePoint 2010 now can interact with a wide variety of external events and allows a developer to control up to which point the workflow gets executed and waits for information from an external process.

Now when you say that the workflow instance waits for information from an external process, it doesn’t mean that the workflow instance needs to wait in an active state and consume server resources (like CPU, RAM etc.) till the time it gets the response back. The workflow instance would be dehydrated (aka the state of the workflow instance would be written to the database) and rehydrated back (aka workflow instance state read back from the database) once the external activity gets completed.

In this post I will attempt to explain a simple pluggable workflow service taking an order tracking system as an example. The order tracking system implements a sequential workflow which gets started as soon as a new order request is created. This workflow tracks the delivery status and the invoice status for a particular order.

When a new order request is created (via SharePoint list), the workflow calls a pluggable workflow service which tracks whether the order was delivered to the customer or not (creating a new database table entry) and accordingly updates the workflow about this information.

For running this example, you would need to

  • Restore ContosoOrderTracking.sql script for creating the ContosoOrderTracking database.
  • Create an Orders list using the Orders.stp list definition.

Create a Sequential Workflow

  1. Open visual Studio 2010, Select New->Project.
  2. Under the installed templates, select the SharePoint -> 2010.
  3. Select the Empty SharePoint Project Template and enter the project name as OrderTrackingSystem and click OK.
  4. Enter the target site collection name for debugging purpose. Now, since we are going to create a Visual Studio workflow, we need to deploy this solution as a farm solution. DeploymentType

5. Click Finish

At this point we have a bare metal SharePoint solution ready. Now we will add a new Sequential Workflow SPI (SharePoint Items) to this solution.

6. Add a new item and select Sequential Workflow and name it OrderTracking.AddSequentialWF

7. Click Add.
8. Name the workflow as Order Tracking and leave the workflow type as List Workflow.WorkFlowType

9. Click Next.
10. From the library or list dropdown, select the Orders list (as shown below) which you created using the attached stp file and leave the other selections as is.SelectList

11. Click Next.
12. We want this workflow to get started on new item creation as well as manually. Leave the current selections default and click Finish.ConditionToStart

At this point our solution should look like as shown below. Before we move ahead, we would need to make some changes to this solution for consistency.SolutionStructure

13. Rename the Feature1 to a sensible name as OrderTrackingWorkflow.

At this point we are done creating a very basic SharePoint sequential workflow solution. You can optionally hit F5 to ensure that everything is fine which I am sure it would be J.

Creating a Business Object

Now we will need a custom business object “Order” which can encapsulate the order information and makes it easy for us to communicate with our workflow and the Pluggable Workflow Service.

  1. Add a new class Order to our workflow solution.
  2. We will add 6 properties to our order class representing the attributes of an order namely ID, Title, Quantity, Amount, Customer, DeliveryStatus.
  3. Since we are dealing with a workflow where persisting the object state is a must, we would need to make Order class Serializable by implementing ISerializable interface and decorate it with Serializable attribute.
  4. Also we would need to implement the GetObjectData method for serializing the object and the default constructer to deserialize it.
    At this point the Order class should look like this.
  5. using System;
    using System.Runtime.Serialization;

    [Serializable()]
    public class Order : ISerializable
    {
    public string ID { get; set; }
    public string Title { get; set; }
    public string Quantity { get; set; }
    public string CustomerName { get; set; }
    public string Amount { get; set; }
    public string DeliveryStatus { get; set; }

    public Order()
    {}

    public Order(SerializationInfo info, StreamingContext context)
    {
    ID = (string)info.GetValue("ID", typeof(string));
    Title = (string)info.GetValue("Title", typeof(string));
    Quantity = (string)info.GetValue("Quantity", typeof(string));
    CustomerName = (string)info.GetValue("CustomerName", typeof(string));
    Amount = (string)info.GetValue("Amount", typeof(string));
    DeliveryStatus = (string)info.GetValue("DeliveryStatus", typeof(string));
    }

    public void GetObjectData(SerializationInfo info, StreamingContext context)
    {
    info.AddValue("ID", ID);
    info.AddValue("Title", Title);
    info.AddValue("Quantity", Quantity);
    info.AddValue("CustomerName", CustomerName);
    info.AddValue("Amount", Amount);
    info.AddValue("DeliveryStatus", DeliveryStatus);
    }
    }

Adding Life to thee Workflow

Now we will add some activities to the sequential workflow we created above.

  1. Switch to the workflow design view and drag and drop a Code and LogToHistoryList activity on the design surface.WorkflowDesign_part1

2. Right click in codeActivity1 and click Generate Handlers from the menu. This will add a code behind method for this activity.

3. Back in the code create in instance of the Order class.

public Order order = new OrderTrackingSystem.Order();

4. Also the following code to the codeActivity1_ExecuteCode method.

In the code below we are taking the current list item on which the workflow is running and initializing the order object with the required properties. Also we are updating the list item DeliveryStaus choice field to Dispatched indicating that the order has been dispatched to the customer.

private void codeActivity1_ExecuteCode(object sender, EventArgs e)
{
SPListItem item = workflowProperties.Item;
order.Title = item.Title;
order.ID = item.UniqueId.ToString();
order.Quantity = item["Quantity"].ToString();
order.Amount = item["Amount"].ToString();
order.CustomerName = item["CustomerName"].ToString();

item["DeliveryStatus"] = "Dispatched";
item.Update();
}

5. At this point it would be a good idea to update the workflow history list with a status message. Repeat #2 to generate handlers for logToHistoryListActivity1 and add the following code.

private void logToHistoryListActivity1_MethodInvoking(object sender, EventArgs e)
{
logToHistoryListActivity1.HistoryDescription = "Order dispatched to the customer.";
}


6. Put a break point in codeActivity1_ExecuteCode hit F5 to deploy and debug the solution.


Now let’s add a new item to the Orders list and see if the workflow is functioning properly.

NewItem

As soon as you save the above item, the break point in our workflow gets hit where you can further play around and see the runtime properties of the objects. Further hit F5 to come out of debugging mode.

DebugCode

This will complete you workflow on the item you created above and now the DeliveryStatus field shows Dispatched. Also the workflow status field show Completed.

ItemStatus

Also clicking on this Completed link will navigate you to page below where you can see the status page of the workflow where we can see the comments in workflow history.

WorkflowStatus

In the next post we will dive into the details of creating a Pluggable Workflow Service.

The associated code and other resources can be downloaded from here:

No comments:

Post a Comment