text: 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.
  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.
  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)
  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)
  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
  To use the attached sample, you will need to do the following
  And that’s it. I hope you found these articles useful and good luck with workflow and BCS!
  - JD Klaka