How to: Creating Sandboxed Workflow Actions

Applies to: SharePoint Server 2010

In this article
Sandboxed Workflow Action Scenario
Common Usage Scenarios for Sandboxed Workflow Actions
Tips for Using Sandboxed Workflow Actions

This topic describes how to create sandboxed workflow actions that read from external lists by using the SharePoint List object model.

This how-to topic corresponds to the Sandboxed Workflow sample, which is part of the Microsoft SharePoint 2010 Software Development Kit (SDK). For more information about how to get this sample, see Code Sample: Sandboxed Workflow Sample.

Sandboxed workflow actions are code functions that can be used in a declarative workflow designer and that are called from a declarative workflow. A sandboxed workflow action is written in Microsoft Visual Studio and uploaded to SharePoint Solution Gallery. These actions run in isolation to ensure that the core system process is protected and boundaries are respected.

By using sandboxed workflow actions, you can read an item from the external list once and store it in a way that this data can be reused. This enables you to decrease the number of read operations performed on an external list that would otherwise have to be performed when working with SharePoint workflow activities. Reading a column from an external list by using the built-in SharePoint workflow activities calls a Read List method (Finder) and a Read Item method (SpecificFinder), which is unnecessary. Sandboxed workflow actions prevent the unnecessary calls and reduce the load on the external system.

Sandboxed Workflow Action Scenario

Typically, you should use a workflow with Microsoft Business Connectivity Services (BCS) in a scenario that needs conditional approval and the condition of the approval is based on a value that is stored in an external system. For the example, consider an expense approval scenario where the expense report is sent for approval to a manager only if the total expense amount is above a safe limit. If the expense amount is below or equal to the safe limit, the expense is a-approved automatically and does not need explicit approval. Because the expense safe limit can vary, it is stored in an external system and is looked up later by the workflow through an external list.

The example in this topic walks you the steps to create an external list that is based on the SafeLimit external content type, a workflow, and the lookup variable.

Note

This scenario assumes you are familiar with using SharePoint Designer List item activities against external lists if you have used them to operate on SharePoint lists. The main difference in how List item activities work is that you do not find an item by identifier (ID), but instead by its identifying column.

To build the safe limit workflow by using SharePoint Designer activities

  1. In SharePoint Designer, create an external content type and name it SafeLimit.

    The external content type should have two fields: EmployeeID, and Limit (for the safe limit value).

  2. Create an external list by using the SafeLimit external content type and name it SafeLimits.

  3. Create a document Library for expense reports and name it ExpenseReports. Then, add a column for EmployeeID.

  4. In SharePoint Designer, in the ExpenseReports document library, click New List Workflow.

  5. Type a workflow name, give it a description, and then click Continue.

    Now, in the workflow designer, you can add new activities.

  6. Insert the Set Workflow variable action.

    1. Click the workflow variable hyperlink, and then click Create New Variable.

      Name this new variable SafeLimit.

    2. Click the value and then on the fx button to create the lookup into the external list.

    3. For Data source, click the SafeLimits external list.

      This is the data source from which to pull the safe limit values.

    4. For Field from source, choose the field that shows the safe limit. In this example, it is named Limit.

  7. Define what to use to look up the item. In this scenario, you want to find the external list item by the Employee ID, so for Field, click the EmployeeID field.

  8. Pick the value to look for. In this scenario, you will pick the EmployeeID field from the current item, so click the fx button in the dialog box.

  9. In the dialog box that opens, for Data source, click Current Item; for Field from source, click EmployeeID.

    Figure 1 shows the lookup dialog box.

    Figure 1. Lookup dialog Box for the safe limit

    Looking up a variable

  10. Click OK to create the lookup variable.

    After you create the lookup variable, a warning appears, such as the one shown in Figure 2. This warning appears because the column picked to find the item in the external list does not have unique values. In this case, the warning informs you that the lookup will return the first value when multiple values are found. You will typically encounter this warning with external list items.

    Figure 2. Lookup warning

    Multiple values lookup warning

The next scenario expands on the previous scenario by adding safe limits for certain budget categories instead of having one safe limit for all expense submissions. For example, you can have safe limits for travel expenses that are different from safe limits for equipment expenses. When an employee submits the expense report, the workflow validates the category and its expense limit to determine the action to take.

To create the sandboxed workflow action

  1. The Code Sample: Sandboxed Workflow Sample implements the actions that this topic describes. At a high level, the action should read an item once and then read other properties out of that one transaction to the external system. We also want this action to appear in Microsoft SharePoint Designer 2010 so that more users can write workflows against the list. Because SharePoint Designer does not support looping, the action cannot return an array of items. Instead, you can create an action to read an item and store its properties in an XML string. Then, we will create another action to read a specific field value out of this XML string into a SharePoint Designer variable. You can optimize this action, for example, to store only the values you need to read, but this example is implemented to be the most generic and reusable way to return properties for an item with any set of properties.

    The method with the following signature reads values from the external list.

    public static Hashtable GetExternalListItemByField(SPUserCodeWorkflowContext context, String externalListId, string fieldName, string fieldValue)
    

    This method takes an external list identifier (ID) and then finds an item in that list by locating the first item that has "fieldValue" for a field named "fieldname". After finding the item, it puts each field into a data table and saves it as XML so that you can parse it later. The function is generic enough to work on SharePoint list items also. This can help us improve performance because it calls the finder and the specific finder only once and gets all of the properties; however, you will still call the finder. You can optimize this action to call the finder only twice, however, that is explored later in the topic.

  2. After the item is read, call the method with the following signature to look up the field specified by the value parameter.

    public static Hashtable GetItemDataFromString(SPUserCodeWorkflowContext context, string itemData, string value) 
    

    This method takes the XML string with all the item properties in the itemData parameter, reconstructs the data table, and looks up the field specified by the value parameter. This does involve reloading the data table on every call of the function, but can be much faster than going to the external system for every call. It also enables the SharePoint Designer user to pick which columns they want to look at instead of hardcoding it into the method.

    The other file of interest in the project is the elements.xml file in the BCSWorkflowActivities directory. This file tells SharePoint Designer how the sandboxed action should be presented in SharePoint Designer and how the user can map the properties. The details of this file are out of the scope of this topic, but the file has the same basic structure as the ACTIONS.xml file used in Office SharePoint Designer 2007.

To use the BCS Sandboxed Activities sample

  1. Download and unzip the BCS Sandboxed Activities sample from the Microsoft Download Center (see SharePoint 2010 Reference: Software Development Kit.)

  2. Open the sample in Visual Studio 2010.

  3. Press F6 to build the solution.

  4. Deploy the solution.

    If you are deploying the solution to another computer, you can use the solution package (.wsp file) created in step 3 and do the following:

    1. In Site Settings, under Galleries, select Solutions.

    2. Upload the .wsp file and activate it.

To create the workflow

  1. In SharePoint Designer, create an external content type and name it SafeLimit.

    The external content type should have the following seven fields: EmployeeID, EquipmentLimit, EquipmentApprover, MoraleLimit, MoralApprover, TravelLimit, and TravelApprover.

  2. Create an external list for the SafeLimit external content type and name it SafeLimits.

  3. Create a document library for expense reports and name it ExpenseReports.

  4. Add two columns for EmployeeID and ExpenseType.

    ExpenseType should be a choice field with the following choices: Morale, Equipment, Travel.

  5. In SharePoint Designer, in the ExpenseReports document library, click New List Workflow.

  6. Type a workflow name and description, and then click Continue.

    At this point, you are in the workflow designer and can add new actions.

  7. Insert the Get External List Item by Field (Sandboxed Function).

    1. Pick your SafeLimits external list for the first parameter.

    2. Pick the EmployeeID column using the CurrentItem by using the fx button for the second parameter.

    3. Type EmployeeID for the third parameter.

    4. You can leave the output parameter the same (it defaults to ItemString).

  8. To read a column of data from that item you stored in ItemString, insert the Read External List Item Data (Sandboxed Function).

    1. For the first parameter, type in a field you want to see. For this scenario, use the value stored in the choice field ExpenseType and append Limit to it.

    2. For the second parameter, choose the ItemString variable.

    3. The last parameter is the value that is found; name it limit.

  9. Repeat step 8 and append Approver to the ExpenseType value (instead of Limit), and change the output to approver.

    Figure 1 shows the workflow you should now have.

    Figure 1. Sandboxed workflow

    Sandboxed workflow

Common Usage Scenarios for Sandboxed Workflow Actions

Use sandboxed workflow actions for external lists if you do not have permission to deploy full-trust activities and want to do any of the following:

  • Read many values from an external list.

  • Write a simple function that will work on SharePoint lists and external lists.

Tips for Using Sandboxed Workflow Actions

Sandboxed workflow actions can cause your workflow to fail if it cannot obtain a sandboxed worker process application domain. The number of application domains that are configured by an administrator is fixed, and the application domains are shared with all sandboxed code, such as actions, Web Parts, and event receivers. For this reason, be cautious when using sandboxed actions in the following situations:

  • Complex sandboxed code actions that take time to complete.

  • Slow external lists.

  • An environment where many workflows will run at about the same time.

  • Scenarios that cannot handle workflow failures.

The sandboxed code service can run these calls with an account that is different from the application pool account, so you must ensure that this account is set up in the Secure Store Service.

If you are storing a local copy of the data you have read from an external list item, as in this sample, you need to ensure that your data is fresh.