In the last post, we covered how to use Sandboxed Workflow Actions to lessen the stress on your external system. In this post, we will cover the final option for writing activities that surface BCS data to be used in SharePoint Designer (SPD): Full Trust Activities. These activities can be generic, but to build complex scenarios they will most likely be specific to a given scenario. In this post, I will show you how to write a simple Full Trust Activity that implements the same scenario as the last post. This time, it will be targeted to the SafeLimits external context type and will not require an external list.

Full Trust Activities are written in Visual Studio and need to be installed in the GAC. They also need an actions file to be placed in the workflow template folder on each farm machine’s file system and an AuthorizedTypes entry in the web.config files on each machine to allow the assembly to execute. These have to be deployed on each farm machine, and therefore require much higher permissions and scrutiny.

Tips on Action Usage and Common Mistakes

Use Full Trust Workflow Activities for BCS if:
  • You have permission to deploy full trust activities
  • You want to do any of the following:
    • Read, Create, and Update data in an external system from a workflow with or without having an external list already provisioned.
    • Make as few calls to the external system as possible.
    • Have complex logic that requires looping over multiple items or associations to other external content types without using the Sandboxed Code Service.
Things to keep in mind:
  • Full trust activities, as their name implies, will run in full trust. This means that you should know exactly what the activity does and trust the author of the activity as though they were an administrator before you deploy the activity.
  • If you are using this activity in SPD, you need to return a fixed number of items as SPD does not support looping.

Building the Scenario- Full Trust Workflow activity

For this post, the activity we are building will return the approver and safe limit for a given type of expense and employee ID. Information about the external content type is already built into the activity, and the activity will only work on that external content type.

Create the Workflow Activity

I’ve attached a Visual Studio project to this post for the activity we will be talking about. Overall, we want to accomplish the same scenario as before, except this time we are not dealing with an external list; we are going to achieve the scenario solely using the Business Data Connectivity (BDC) APIs. This is a little more complex than just reading an item in a list, since the BDC APIs offer much more flexibility than just a flat list. Before we dive into the code, let’s first look at the properties that are exposed by this activity. Although I have exposed all of the activity’s properties so that they can be edited in SPD, I am building in some defaults so that we do not have to enter the information for those that should be consistent across my deployments.

Name

Description

EntityName

The name of the external content type. We will hardcode this in the sample to a default, but allow you to override the value in the property grid. In production you may not want to allow EntityName, EntityNamespace and LobSystemIsntanceName to be passed in to the activity at all, as any user of SPD can change the workflow to point to a different entity and possibly get information they should not. These properties are here mostly so you can easily see how the code works.

EntityNamespace

The namespace of the external content type. We will hardcode this in the sample to a default, but allow you to override the value in the property grid.

LobSystemInstanceName

The External Systems Instance Name. All of the Instance Names in SPD are the names you type in when discovering the external system. However external content types made outside of SPD can have multiple names, which is why we need to specify one. We will hardcode this in the sample to a default, but allow you to override the value in the property grid.

EmployeeID

This is the Employee ID we are looking up.

Category

The Category of expenses. The implementation in the sample supports Morale, Equipment and Travel as the only valid inputs for this parameter.

Approver

This is returned to the user from the external system. It is the user who should approve the expense.

SafeLimit

This is returned to the user from the external system. It is the limit for that particular user, and for that type of expense.

The next step is to look at the activity code itself. I am not going to go into any real depth into general workflow activity design and instead will just be going over the BCS specific parts of the code. The first thing to notice is that all of the code is contained in the Execute method, which is what the workflow host calls to execute the activity. In this call, the first BDC action we need to do is to get the metadata catalog that contains the “SafeLimits” external content type, as seen in the function below:

private IMetadataCatalog GetMetadataCatalog(SPSite site, ISharePointService hostInterface)

The code may look simple, but there are a few things to note. First, the catalog is farm scoped, not site scoped. This means that this activity will work on any site that is using the same BDC service. The second thing to notice is that the SharePoint APIs we are using to get the metadata catalog will return null if the item is not found. This is different than the BDC APIs, which will throw exceptions if items are not found (more on this later).

Now that we have the metadata catalog, we have to find the external content type and return the correct data. This code is in this function:

private void GetSafeLimits(IMetadataCatalog catalog, ISharePointService hostInterface)

Notice in the code sample that GetEntity is in a try catch block. This is because if the external content type was deleted, or was just not in this catalog, a MetadataObjectNotFoundException will be thrown. Instead of just crashing the workflow right there, I wanted to add an entry into the workflow history list to inform us of this, and then re-throw the exception (which would allow the workflow to fail).

Once we have an external content type, we need to find a specific instance of that external content type. To do this, we use the FindSpecific method of IEntity. This function takes two parameters. First it requires the Identity of the specific instance. In our example, EmployeeID was set as the identifier, so we need to pass the EmployeeID as the Identity. You can see at this point how this has to be targeting this particular external content type. Another entity may have a different identifier with a different name and even a different type. The second parameter is the Lob System Instance that we use to find the item. As stated before, in our case, since we are using SPD, there will be only one Lob System Instance, and we will use the name that is stored in the code for that. You will also notice that FindSpecific will throw a different exception if the item is not found: an ObjectNotFoundException. Again, we will want to catch this and give a nice error to the user before re-throwing the exception so the workflow can fail. Once we have the Entity Instance, the rest is pretty simple. We can use the field names in the square brackets to get the values of the instance.

Now let’s see it in action. J

Setup Instructions

To use the attached sample, you will need to do the following

  1. Unzip the attached file
  2. Open in Visual Studio 2010
  3. Rebuild the solution
    • Before you rebuild, make sure the defaults for entity name, namespace and lob system instance name are updated to match your setting. These are defined in the GetSafeLimits function.
  4. Deploy the solution
    1. See http://blogs.msdn.com/sharepointdesigner/archive/2007/03/15/adding-activities-to-spd.aspx and look at steps 2-4 on how to deploy the dll, actions file(BCSReadActivity.Actions in the zip) and how to update the web.config
Building the Workflow
  1. In SPD, go to the ExpenseReports document library you created in the last post
  2. Click on New List Workflow
  3. Give the workflow a name and description and continue
    • Note: At this point, you are in the workflow designer, and you can start to add your actions.
  4. Insert the “Get Safe Limits for Employee” Action
    • For the first two parameters, you can leave them alone. These are the output variables from the function for Approver and SafeLimit.
    • For the third parameter, we want to specify the Category. This is already defined on our list, so as before, pick the ExpenseType column using the CurrentItem by using the clip_image002 button
    • For the last parameter, pick the EmployeeID column using the CurrentItem by using the clip_image002[1] button
    • You should end up with something that looks like this:

clip_image004

And that’s it. I hope you found these articles useful and good luck with workflow and BCS!

- JD Klaka