Sie sind auf Seite 1von 22

Collaborative Workflow

Improvements in SharePoint 2010


Paul Andrew SharePoint 2007 introduced workflow for collaborative applications and many organizations have benefited by moving manual processes into SharePoint workflow. The primary reason why we use workflow in software design is to manage long running processes. And while computer hardware is designed to complete processes as fast as possible, waiting for people to complete forms, make decisions, or share results of external actions always takes longer than the millisecond response time required to keep a CPU busy. SharePoint workflow is the ideal way to automate these manual processes which previously required paper or the use of complex software to record and monitor any long running activities. Windows Workflow Foundation was first introduced in 2005 and was originally included in the Microsoft .NET Framework 3.0. Today, SharePoint 2010 offers many new improvements for workflow developers and builds on the popularity of workflow in SharePoint 2007. SharePoint workflow is recommended for longrunning human workflows where we are often waiting for people to complete tasks. This article will introduce you to the key concepts and describe the new features available. First, I will talk about the new features in SharePoint 2010 for workflow developers and then I will walk through a couple of new user scenarios.

Workflow Model Design Tools Improvements


SharePoint 2010 provides more choices in tooling to better fit the needs of those creating and maintaining workflow models. The tools for workflow development include Visual Studio 2010, SharePoint Designer 2010 and Visio 2010. It should be noted that SharePoint 2010 requires .NET Framework 3.5. The next version of the .NET Framework 4.0 is currently in development but product timelines meant SharePoint 2010 was not dependent on it. Visual Studio 2010 includes many tooling improvements for SharePoint projects, specifically for workflow projects. The new SharePoint Solution (WSP) packaging helps deploy your workflows easily onto the SharePoint server, allowing you to add ASPX workflow initiation and association forms to Visual Studio 2010 workflow projects (Figure 1). In a walkthrough later in this article, I will show you how to add an initiation form.

Figure 1 The Visual Studio 2010 SharePoint Project Templates SharePoint Designer 2010 also has a new graphical workflow designer for designing workflows and deploying them directly to SharePoint. It can also be used as a prototyping tool before workflows are further developed in Visual Studio 2010. Another improvement in SharePoint Designer 2010 is that it now allows you to edit the out-of-the-box workflows that come with SharePoint. It will also use InfoPath forms if InfoPath is installed or the Data Form Web Part if InfoPath is not installed; previously, only ASPX forms were used by SharePoint Designer 2007. Since you can use InfoPath forms now, it makes it very easy to edit those forms later with InfoPath to improve them. If you have new columns specified in a workflow, they will automatically be added to the schema of the list that you associate with the workflow. These are known as association columns and can be used throughout the SharePoint Designer workflow. User profile data can be bound to properties in workflow, making it possible to get information about the SharePoint user profile. For example, you could look up the name of a direct manager for approvals. SharePoint Designer 2010 includes a new task process designer that creates an activity in the workflow but allows flexibility in how you manage the approval process all within that one activity. This includes defining escalation processes, delegation, defining approval requirements and semantics of what happens if the underlying document is changed during the approval. Workflow models can be created in Visio 2010 for further editing in SharePoint Designer 2010. Visio 2010 supports Business Process Modeling Notation. It also supports sub-processes and containers to break up the diagram and validation to analyze a diagram to ensure it is properly constructed.

New Workflow Models in SharePoint 2010


Site Workflows Site workflows release workflow developers from requiring a list item or document item to run workflows against. This is useful for when the process that the workflow is implementing does not start as a result of a list

item or document. This is such a common scenario that developers will create dummy lists and items in order to just to add workflows. In Visual Studio 2010, you simply pick Site Workflow when creating the workflow project item, as shown in Figure 2.

Figure 2 The Site/List Workflow Dialog Page You can get to the activated site workflows by choosing Site Workflows from the Site Actions menu in SharePoint. It shows you new workflows you can start, any running site workflows and completed workflows. Since site workflows dont have a list item or document to start from, they must be started manually through the SharePoint user interface or via the SharePoint API. Reusable Declarative Workflows In SharePoint Designer 2010, you can create reusable declarative workflows. In SharePoint 2007, a workflow model created in SharePoint Designer could only be associated with one list. These reusable workflows do not rely on a specific list but can be associated with any list. The workflow design can be reused and associated with multiple lists. Also, the Save as Template command can be used to create a WSP file containing a reusable workflow which can be moved to another SharePoint server or to Visual Studio 2010. In SharePoint Designer, this means you dont have access to the list fields to access data since no specific list structure is connected.

Runtime and Hosting Improvements


High Privilege Workflows In SharePoint 2007, workflows ran as the identity of the logged on user. In SharePoint 2010, with high privilege workflows you can specify an account to run a workflow as to give it additional needed permissions (see Figure 3). When creating a workflow in SharePoint Designer 2010, individual steps can be added that enable it to run as the author of the workflow instead of the logged on user.

Figure 3 The SharePoint Designer Workflow Showing a High Privilege Impersonation Step SPTimer Location SharePoint executes workflow instances in one of two places depending on the last action. If the last action in the workflow was waiting on a user input, the workflow continues to execute on the Web front end where the user completed that input. If the workflow is continued from a delay timer or from an event being received elsewhere, it executes within the SPTimer service. Using a new option in SharePoint Central Administration, you can now set the preferred server where the SPTimer service runs. To do this, click in the Manage Content Databases menu of the Application Management section of SharePoint Central Administration. Then click on your content database and scroll down to the setting for Preferred Server for Timer Jobs (as shown in Figure 4). You can also manually stop the SPTimer service on any servers you dont want it to run on.

Figure 4 Setting of Preferred Server for Workflow Timer Jobs

Workflow Messaging Improvements


SharePoint 2010 adds four new workflow Event Receivers for list based workflows. The four workflow event receivers available are Starting, Started, Postponed and Completed (as shown in Figure 5). These are similar to other SharePoint event receivers and they execute code on the server in response to the event. To make development easier, Visual Studio 2010 includes event receiver project types to make using these events fairly simple. The new events attach to a specific list and fire whenever the event occurs on workflow instances associated with that list, which means that these event receivers cant fire on site workflows. Event receivers also require a list.

Figure 5 The Event Receivers That Can Be Built in Visual Studio 2010 SharePoint 2007 made it easy to involve people in workflows, but it was difficult to send and receive messages with external systems. The recommended approach was to use task items to send a message to the external system using a Web service and have the external system update the task to return the result. SharePoint 2010 adds support for pluggable workflow services. These will be familiar to Windows Workflow Foundation (WF) developers and are defined by creating an interface containing methods and events. This interface is connected to a pair of activities called CallExternalMethod and HandleExternalEvent. A tool comes with WF in the .NET Framework called WCA.exe to generate strongly-typed activities for sending and receiving based on the interface. These generated activities can be used in SharePoint workflow also. They do not require the interface to be set as properties and instead can be dragged directly from the toolbox to the workflow design surface. The service code that integrates with SharePoint workflow is loaded into the GAC for access by the workflow. It needs to inherit from the SPWorkflowService base class and it needs to be referenced in the web.config. Using these new activities, you can send asynchronous messages to an external system right from within the SharePoint workflow. I will investigate creating and using these activities later in this article in the second walkthrough.

Walkthrough of Building a Simple Workflow in Visual Studio 2010


The key thing in SharePoint workflow is to interact with people, so the simplest thing to do is assign a task to someone and wait for their response. The following shows how the new Visual Studio 2010 SharePoint tools make that task assignment really easy to build. Step 1 - Create a new SharePoint Sequential Workflow project

Creating a new SharePoint workflow project is easy. Choose sequential workflow on the new project template selector as shown previously in Figure 1. This can also be done with the state machine workflow style. The new workflow project wizard has four pages. The first is a page that all SharePoint tools project templates have in common, where you identify the URL of the local SharePoint site you want to use to deploy and debug your solution, as shown in Figure 6.

Figure 6 First Page of the New Workflow Project Wizard The second is a page where you supply the name of the workflow and choose whether to associate it with a list or as a site. This page is shown earlier in Figure 2. The third page is where you decide if Visual Studio will automatically associate the workflow for you or if you can do it manually after it has been deployed. If you choose to leave the box checked, it has selections for the list to associate with (if you previously chose a list-based workflow), the workflow history list to use and the task list to use (see Figure 7). Typically, the history and task list will not need changing.

Figure 7 Third Page of the New Workflow Project Wizard The fourth and final page is where you select how the workflow can be started (see Figure 8). You should not unselect all three of these or your workflow will be very difficult to start. For a site workflow, you can only choose manually starting the workflow. For a list-based workflow, you can also choose to start the workflow instance when a document is created or to start when a document is changed.

Figure 8 Fourth Page of the New Workflow Project Wizard The new blank workflow model looks like Figure 9 in the design surface in Visual Studio 2010. The workflow activated activity is derived from the HandleExternalEvent activity and provides initialization data from SharePoint to the workflow instance. I will cover more of the HandleExternalEvent activity later.

Figure 9 The Default Blank Workflow Showing the WorkflowActivated Activity Step 2 Add an initiation form to the workflow An initiation form can be shown to the user when they start the workflow. It allows the workflow to gather parameters before it gets started. This can be added in Visual Studio 2010 easily by right clicking on the workflow item in Solution Explorer and choosing Add then New Item, as shown inFigure 10. Select the Workflow Initiation Form template and the new form is automatically associated with the workflow. It is an ASPX form that you edit in HTML (see Figure 11).

Figure 10 Adding a Workflow Initiation Form One method called GetInitiationData needs editing in the code behind the ASPX file. This method only returns a string; if there are multiple values, it is recommended you serialize them into an XML fragment before returning them. Once the workflow instance is running, it is easy to get to this string just by referencing workflowProperties.InitiationData. The multiple values will need to be de-serialized from the XML fragment if they were serialized in GetInitiationData.

Figure 11 The Default Workflow ASPX Initiation Form

For the initiation form, a single text field will be added and then that field will be returned from the GetInitiationData method. The tags in the following code are added inside the first asp:Content tag, like so:
<asp:TextBox ID="MyID" runat="server" /> <br />

The GetInitiationData method already exists and just needs to have code added to return the MyID.Text property. The following code shows the updated method code:
private string GetInitiationData() { // TODO: Return a string that contains the initiation data that will be passed to the workflow. Typically , this is in XML format. return MyID.Text; }

Step 3 Add a workflow log activity The LogToHistoryList activity is extremely easy to use. Each workflow instance created has a history list that can display in the SharePoint user interface. The activity takes a single string parameter and adds an item to that list. It can be used for reporting the status of workflow instances to users in production. Simply drag the LogToHistoryList activity from the toolbox to the workflow design and set the description property (see Figure 12).

Figure 12 The Visual Studio Toolbox Showing SharePoint Workflow Activities Properties in workflows are called dependency properties. These are bound at runtime to another activities dependency property, such as a field, a property or a method. This process is often called wiring up and it is what allows activities to work together in a workflow even though they dont have specific type information for each other at compile time. Each property in the property window in Visual Studio is wired to a class field or class property in the workflow class. Fields are the simplest to create and the dialog that comes up when wiring up the workflow property allows for creating new fields, creating new properties or wiring to existing ones.

Figure 13 Dependency Property Binding to a Created Field Figure 13 shows adding a new field with the default name. The following shows the added code to the MethodInvoking event handler for the activity to set the property to the workflow initiation data:

public String logToHistoryListActivity1_HistoryDescription1 = default(System.String);

private void logToHistoryListActivity1_MethodInvoking(object sender, EventArgs e) { logToHistoryListActivity1_HistoryDescription1 = workflowProperties.InitiationData; }

You can actually set the HistoryDescription property directly in code since this property doesnt connect between activities, but it is a good simple activity in order to learn a little about dependency properties. Step 4 Add a CreateTask activity This next step is the main part of human workflow interaction known as the SharePoint task item. Create a task, assign it to a person and then wait for the person to make changes to that task. The CreateTask activity has to be dragged onto the workflow design surface and then configured with all the required properties. Figure 14 shows the CreateTask properties window just after the activity is dragged on to it.

Figure 14 The Properties Pane Showing the CreateTask Activity The first thing needed here is a correlation token for the task. A correlation token is used for message correlation in workflow. It provides a unique identifier that enables a mapping between a task object in a specific workflow instance and the workflow runtime in SharePoint. This is used so that when SharePoint receives a message for the workflow instance it can locate the correct task within the correct workflow instance. The CorrelationToken property must be configured and its not recommended to use the WorkflowToken for tasks, although this isnt prevented in the tool. Enter the new name for the correlation token as TaskToken and press enter. Then expand the (+) symbol which appears and click the drop down to the right of OwnerActivityName and choose the workflow. The TaskId must be configured and a new GUID specified for the task id. This is done by selecting the TaskId property and clicking the [] ellipsis to bring up the property editor. Click the Bind to a new member tab, choose Create Field, and then click OK. The same must be done for the TaskProperties property by again selecting the property, clicking on the ellipsis and adding a new field. Next, double click on the new CreateTask activity on the workflow design surface to bring up the createTask1_MethodInvoking handler code and set the properties in code. The new task must be given a title, and for good measure I will set the task description to the string I got from the initiation form. Once all those properties have been set, this is the added code:
public Guid createTask1_TaskId1 = default(System.Guid); public SPWorkflowTaskProperties createTask1_TaskProperties1 = new Microsoft.SharePoint.Workflow.SPWorkflowTaskProperties();

private void createTask1_MethodInvoking(object sender, EventArgs e) { createTask1_TaskId1 = Guid.NewGuid();

createTask1_TaskProperties1.Title = "Hello"; createTask1_TaskProperties1.Description = workflowProperties.InitiationData; }

Step 5 Add the OnTaskChanged and CompleteTask activities Use the While activity to wait for multiple changes to the task until you see the changes you want. The While activity must contain another activity, such as the OnTaskChanged activity. The Listen activity can also be used to listen for multiple events at one time by adding a Listen activity with actual event receiver activities inside the Listen branches. Alternatively, you can just wait until the task is deleted with the OnTaskDeleted activity. A common requirement is to escalate or timeout waiting for an event. This is done by using a Listen activity to listen for both the task changed message and a timer message by using a Delay activity. The first message to be received by either contained activity resumes the workflow and the other activity stops waiting. The Delay activity is sent a message when the timeout occurs. There are lots of options described above but the simplest is to use OnTaskChanged which will wait for any change to the task item and then continue on. To configure the OnTaskChanged, you need to wire up the CorrelationToken and the TaskId properties to the same fields as the CreateTask. Last, add a CompleteTask activity and again set the CorrelationToken and TaskId properties. As shown in Figure 15, the activities that wait for a message are green while activities that send a message are blue. This is consistent throughout SharePoint workflow.

Figure 15 The Completed Simple Task Workflow Model Step 6 Deploy and Test the Workflow

Now the workflow is almost complete, so press F5 and wait for the deployment. Pressing F5 will compile the workflow, package the workflow into a WSP, deploy that WSP to SharePoint, activate the SharePoint features, attach the Visual Studio 2010 debugger to SharePoint and start Internet Explorer with the SharePoint site. Once the SharePoint site appears, choose Site Workflows from the Site Actions menu. You will see all of the site workflows and you can click on yours to start it. Once it is selected, you will see your workflow initiation form, as shown in Figure 16.

Figure 16 The Workflow Initiation Form Other improvements can be added to this basic starter workflow model, such as using a content type to define the task you assign to a person, using email to notify the user they have been assigned a task, and even using InfoPath forms to create more complex forms for users to complete in email or online.

Walkthrough of Building a Pluggable Workflow Service


New in SharePoint 2010 is the ability to add pluggable workflow services to SharePoint. This has always been possible in Windows Workflow Foundation, but the SharePoint-hosted workflow runtime was locked down and previously didnt allow this. Primarily pluggable workflow services are designed for sending and receiving messages out of a workflow instance. But they are also valuable for any long-running system operation such as a long-running calculation. This is the mechanism which the workflow runtime uses to manage long-running work as a generalization of messaging. It simply executes the short-running work within activities and suspends the workflow until longrunning actions have completed or a message is received to indicate a person completed a task. So while waiting for a person to respond, the workflow instance is dehydrated and does not take up CPU or RAM resources on the server it is executing on. (Dehydrated simply means the state of the workflow instance is written to a database record in such a way that it can be rehydrated back and continue on later.) All types of long-running work are handled the same way by workflow. First, it starts the long-running work or sends a message and then it suspends the workflow until the long-running work is finished or the response is

received. The correlation token is used to ensure the correct workflow instance is resumed when a response is received. As an example, consider two common examples of long-running work. One example is a synchronous Web service request where the caller is blocked until a response is received on the channel. This is not suited to run within a workflow activity. The workflow service needs to wait for the Web service call to complete and then to send a message back to the workflow instance with the response. Another example is a CPU intensive work item that needs to run but because it may take longer than a second it needs to run outside of the workflow activity. Again, you can use a workflow service and create a thread in the workflow service to execute the CPU intensive work item. The new thread can send a message back once it is finished. Both of these examples are implemented with the same pattern. The following walkthrough shows how to create a new SharePoint Sequential Workflow and call a pluggable workflow service that factors prime numbers to identify how many prime numbers there are under 100,000,000. This work takes too long to execute within the main line of an activity. Step 1 Create a Pluggable Workflow Service To create a pluggable workflow service in Visual Studio 2010, you need to implement the service as an interface and class in your project. Figure 17 shows an example of a pluggable workflow service which can be added to your project in a new class file called MyService.cs. In the code, the interface definition is in IMyService, the interface implementation in class MyService and the MessageOut method runs most of the logic through an anonymous method delegate on a separate thread. In the separate thread, the call to RaiseEvent will send the message back to the waiting HandleExternalMessage activity. Figure 17 The Pluggable Workflow Service
// Interface declaration [ExternalDataExchange] public interface IMyService { event EventHandler<MyEventArgs> MessageIn; void MessageOut(string msg); }

// Arguments for event handler [Serializable] public class MyEventArgs : ExternalDataEventArgs { public MyEventArgs(Guid id) : base(id) { } public string sAnswer; }

// Class for state class FactoringState { public SPWeb web; public Guid instanceId; public FactoringState(Guid instanceId, SPWeb web) { this.instanceId = instanceId; this.web = web; } }

// Interface implementation class MyService : Microsoft.SharePoint.Workflow.SPWorkflowExternalDataExchangeService, IMyService { public event EventHandler<MyEventArgs> MessageIn; public void MessageOut(string msg) { ThreadPool.QueueUserWorkItem(delegate(object state) { FactoringState factState = state as FactoringState; DateTime start = DateTime.Now; int topNumber = 100000000; BitArray numbers = new System.Collections.BitArray(topNumber, true);

for (int i = 2; i < topNumber; i++) { if (numbers[i]) { for (int j = i * 2; j < topNumber; j += i) numbers[j] = false; } } int primes = 0; for (int i = 2; i < topNumber; i++)

{ if (numbers[i]) primes++; }

string sAnswer = "Found " + primes + " in " + Math.Round(DateTime.Now.Subtract(start).TotalSeconds, 0) + " seconds";

// Send event back through CallEventHandler RaiseEvent(factState.web, factState.instanceId, typeof(IMyService), "MessageIn", new object[] { sAnswer }); }, new FactoringState(WorkflowEnvironment.WorkflowInstanceId, this.CurrentWorkflow.ParentWeb)); }

// Plumbing that routes the event handler public override void CallEventHandler(Type eventType, string eventName, object[] eventData, SPWorkflow workflow, string identity, System.Workflow.Runtime.IPendingWork workHandler, object workItem) { var msg = new MyEventArgs(workflow.InstanceId); msg.sAnswer = eventData[0].ToString(); msg.WorkHandler = workHandler; msg.WorkItem = workItem; msg.Identity = identity; // If more than one event - you'd need to switch based on parameters this.MessageIn(null, msg); } public override void CreateSubscription(MessageEventSubscription subscription) { throw new NotImplementedException(); } public override void DeleteSubscription(Guid subscriptionId) { throw new NotImplementedException(); }

Step 2 Update the web.config

Once the pluggable workflow service is constructed, it needs to be registered with the workflow runtime that runs in SharePoint. This is done by editing the web.config section for workflow services. The web.config editing required should be done using a feature receiver that calls SPWebApplication.WebConfigModifications.Add. The following code shows the additional configuration entry to be added:
<WorkflowServices><WorkflowService Assembly="WorkflowProject1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=YOURPUBLICKEY" Class="WorkflowProject1.MyService"> </WorkflowService></WorkflowServices>

The assembly name and public key information can be obtained using GACUTIL.EXE /l. Step 3 Create the workflow model The rest of the work is easy. Add Call External Method and Handle External Event activities to the workflow and configure them to point to this service, as shown in Figure 18. The Call External Method activity will call MessageOut in the service and the Handle External Event activity will wait for the event MessageIn. This involves setting the InterfaceType and EventName properties in each of the two activities.

Figure 18 The Completed Workflow Using Pluggable Workflow Services

Figure 19 Completed Prime Calculating Pluggable Workflow Service Step 4 Run the workflow When this workflow is run, it will start a separate thread in the pluggable workflow service to do the prime number calculations. After 10-15 seconds of running, a workflow history item appears as shown in Figure 19. It shows that there are 5,761,455 prime numbers under 100,000,000. As shown, there is some code to write for pluggable workflow services and more code to write for each system you connect to. There are two options for reducing the amount of code required to communicate with external services. One is by interfacing with BizTalk Server and making use of the BizTalk adapter library for connecting other systems. The other is using the business connectivity services in SharePoint 2010 which provide a way to expose data from another system through external lists.