Step by Step Tutorial. Creating Workflows for Windows Sharepoint Services and MOSS2007 (part 10/20)

 

 

image

Step 10/20. Reuse, Modify and Debug a Sharepoint Designer workflow in Visual Studio  

 

By Serge Luca

 

image

 

1.Scenario

Microsoft Sharepoint Designer 2007 is a very interesting tool that allows developers and users to create workflows  running in Sharepoint 2007 without writing code.
The workflows generated by Sharepoint Designer cannot be debugged and reused in another site unless we import it in Visual Studio.Net.This tutorial will show you how to achieve this.

I assume that your have the correct setup for creating workflows for Sharepoint .

2.Hands-on

• Create a team site. By default a task list ("tasks") is generated.
• Create another task list and call it “Issues”.
• Now start Sharepoint Designer and open your web site (Menu “File-Open Site”).
Let’s create a very simple workflow that will copy a task list item from the "Task" list to the "Issues" list if the Title column of the record contains the word “problem”.
• In Sharepoint Designer, start the Menu “File”-“New Workflow”; keep the default workflow name and select the list you want the workflow to be associated with: Task; unselect the option “allow this workflow to be manually started from an item” and select the two others.

 

image

 

Click on the Next button of the form and the Workflow Designer will show up :

 

image

Click on the Conditions button and select the option Compare Tasks field.

image

In the condition, click on the “field” hyperlink and select Title in the combobox.
In the condition, click on the “value” hyperlink and type “problem” (without the quotes).
In the condition, click on the “equals” hyperlink and select “contains”.

 

image

In the Action, select “Copy List Item”.

image

Click on the Finish button of the form; Sharepoint Designer will  generate the xoml code (which is not xaml activated code !!!) , it will compile the code ( xaml activated code must not be compiled) and it will associate the workflow to the corresponding list.

3.Testing the workflow

Add a new item in the task list: set the Title to “problem in Belgium”: since the Task’s Title column contains the word “problem”, it will be copied to the Issues list by the workflow .

4.Importing the workflow in Visual Studio

In Sharepoint Designer, go to the Workflows folder, select Workflow1 and right click on “Publish Selected Files” : 
 

image

Select the option “File System” (specify a file location) :

image

Click on OK. The following files will be generated  at the selected location:

image

Rename the file Workflow1.xoml.rules to Workflow1.rules.

In our specific case, the .rules file contains the test that will check if the title column contains the word “problem”; this test is expressed in the  CodeDom language.

Create a new Sharepoint Workflow project  that will host the generated files ; name it MySPWorkflow :

 

image

Add the files Workflow1.rules and Workflow1.xoml into the new project and delete Workflow1.cs :

image

Click on Workflow1.xoml and the workflow will show up in the Workflow Designer :

image

  • The first activity (ID1) is a Microsoft.Sharepoint.WorkflowActions.OnWorkflowActivated activity and makes the link between the workflow and the Sharepoint context (like the list and the list item among many other things).
  • The activity ID6 is a Microsoft.Sharepoint.WorkflowActions.CopyItemActivity .
    The workflow itself is derived from Microsoft.SharePoint.WorkflowActions.RootWorkflowActivityWithData which is derived from SequentialWorkflowActivity.
  • The following code shows the real content code of Workflow1.xoml:

 

<ns0:RootWorkflowActivityWithData x:Class="Microsoft.SharePoint.Workflow.ROOT" x:Name="ROOT" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/workflow&quot; xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml&quot; xmlns:ns0="clr-namespace:Microsoft.SharePoint.WorkflowActions;Assembly=Microsoft.SharePoint.WorkflowActions, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c">

      <ns0:RootWorkflowActivityWithData.WorkflowFields>

            <ns0:WorkflowDataField Name="__list" Type="System.String" />

            <ns0:WorkflowDataField Name="__item" Type="System.Int32" />

            <ns0:WorkflowDataField Name="__context" Type="Microsoft.SharePoint.WorkflowActions.WorkflowContext" />

            <ns0:WorkflowDataField Name="__initParams" Type="Microsoft.SharePoint.Workflow.SPWorkflowActivationProperties" />

            <ns0:WorkflowDataField Name="__workflowId" Type="System.Guid" />

      </ns0:RootWorkflowActivityWithData.WorkflowFields>

      <ns0:OnWorkflowActivated WorkflowProperties="{ActivityBind ROOT,Path=__initParams}" x:Name="ID1" EventName="OnWorkflowActivated">

            <ns0:OnWorkflowActivated.CorrelationToken>

                  <wf0:CorrelationToken Name="refObject" OwnerActivityName="ROOT" xmlns:wf0="http://schemas.microsoft.com/winfx/2006/xaml/workflow&quot; />

            </ns0:OnWorkflowActivated.CorrelationToken>

      </ns0:OnWorkflowActivated>

      <IfElseActivity x:Name="ID4" Description="Step 1">

            <IfElseBranchActivity x:Name="ID3">

                  <IfElseBranchActivity.Condition>

                        <RuleConditionReference ConditionName="__Rule_ID3" />

                  </IfElseBranchActivity.Condition>

                  <ns0:CopyItemActivity ListId="{}{7DC0CBDB-1A73-4A9A-8F7C-7FF3EFC3807B}" x:Name="ID6" Overwrite="False" ToListId="{}{A3EBF037-9BAA-49DC-A8B6-87A8795DA41F}" __Context="{ActivityBind ROOT,Path=__context}" ListItem="{ActivityBind ROOT,Path=__item}" />

            </IfElseBranchActivity>

      </IfElseActivity>

</ns0:RootWorkflowActivityWithData>

 

5.Xoml code

1.We can notice that this not what Workflow Foundation afficionados called “xaml activated” code which is xaml code that can  run on the fly without having to be compiled. This code must be compiled: indeed the x:class attribute provides the compiler with a class name for the workflow :

 

<ns0:RootWorkflowActivityWithData x:Class="Microsoft.SharePoint.Workflow.ROOT" x:Name="ROOT"

The workflow itself is an activity named Root and derived from the class RootWorkflowActivityWithData.

image 

2. According to the Sharepoint sdk, the RootWorkflowActivityWithData class has a WorkflowFields  property which is a collection of key-object pairs where the key is a string (describing the property name) and the object a type (the type of the property); this is an handy way to dynamically add properties of any type to a class.

image

The following  xoml fragment shows how Sharepoint Designer feeds this WorkflowFields property :

 

<ns0:RootWorkflowActivityWithData>

      <ns0:RootWorkflowActivityWithData.WorkflowFields>

            <ns0:WorkflowDataField Name="__list" Type="System.String" />

            <ns0:WorkflowDataField Name="__item" Type="System.Int32" />

            <ns0:WorkflowDataField Name="__context" Type="Microsoft.SharePoint.WorkflowActions.WorkflowContext" />

            <ns0:WorkflowDataField Name="__initParams" Type="Microsoft.SharePoint.Workflow.SPWorkflowActivationProperties" />

            <ns0:WorkflowDataField Name="__workflowId" Type="System.Guid" />

      </ns0:RootWorkflowActivityWithData.WorkflowFields>

 

  • __list: the list Guid.
  • __item: the index of the ListItem.
  • __context: a Microsoft.SharePoint.WorkflowActions.WorkflowContext which is a class that will encapsulate some elements of the well known SPWorkflowActivationProperties (stored in the __initParams field). In our example, the instance of this class will be used internally by the CopyItem activity to provide some necessary information like the SPWeb for instance.
  • __initParams: a Microsoft.SharePoint.Workflow.SPWorkflowActivationProperties ; this class provides many information like the SPWeb, the SPList, the SPListItem etc…

The reason for using a WorkflowContext instead of directly a SPWorkflowActivationProperties object is not clear here.

Another way to visualize these properties is to select the workflow object in the workflow designer and to display the associated property page :

image

Here is what we get if we click on the collection:

image

This will initialize the informations the CopyItemActity needs (see later).

 

Now, let’s take a look at the CopyItemActivity properties :

image

In order to copy one ListItem to an other list, the CopyItemActivity needs some informations:

1.       The original list Guid: ListId property .

2.       The destination list Guid: ToListid property.

3.       The list item index: ListItem property ;  databinding from the __item property of the workflow.

4.       The SPWeb object : __Context property; databinding from the __context member of the workflow.

 

6.Deployment and test of the workflow

 

We will deploy the workflow as a feature, therefore we need to modify the install.bat file :

1.       Sign the project

2.       Retrieve the strong name

3.       In  install.bat , replace http://localhost with your site collection url

4.       in install.bat, replace myFeature with the assembly name

5.       run install.bat

6.       test the workfow

7.Error

This workflow generates an error :

image

8.Fault Handler

To get more detailed information about this error, it is necessary to add a Fault Activity (equivalent of a catch block) and to log it.

Select the workflow in the (Visual Studio) Workflow Designer, click on the lower left side of the Designer and click on the Fault Handler:

image

Another view of the Workflow Designer will show up:

image

Drag and drop a FaultHandler activity from the Workflow Foundation toolbox into  fautlHandlersActivity1 :

image

In the property page of this last activity select the FaultType property by browsing the mscrolib assembly:

image

Select System.Exception:

image

Now we will log the StackTrace into the workflow history log: drag and drop a LogHistoryList activity into the handler (if you don’t find this activity drag and drop the microsoft.Sharepoint.WorkflowAction.dll assembly to a new Visual Studio toolbox tab) :

image

Select the logToHistoryListActivity1 and set its HistoryOutcome property to the stack trace value of faultHandlerActivity1:

image

image

Rebuild the solution , redeploy (install.bat) and test the workflow.

The trace will show up in the workflow status :

image

Remove the activity ID2 : this activity (class ApplyActivation) is the source of the error.

Let’s Click on the ID1 activity to generate the code behind and paste the following code in the generated handler:

        private void ID1_Invoked(object sender, ExternalDataEventArgs e)

        {

            __context = new WorkflowContext();

            __context.Initialize(__initParams);

            __list = __initParams.List.ToString();

            __item = __initParams.ItemId;

            __workflowId = __initParams.WorkflowId;

        }

 

Recompile the workflow, and test it.

9.Debugging our workflow

Reset the web server, refresh the web site, open the project in Visual Studio, set a breakpoint in ID1_Invoked and attach the browser to the w3wp.exe host:

image

Invoke the workflow by changing a value in the title property, you should hit your breakpoint.

Reusing the workflow in another site

The good news is that the CopyItemActivity can use both list Guid or list name.

Select its property page and set the ListId and ToListId properties respectively  to “Tasks” and “Issues”:

image

Recompile the workflow, deploy and test it to make sure it works again 😉

The same workflow can be reused in another site if the appropriate list (“Tasks” and “Issues”) are present.

 

10.Modify the .rules files

The condition that evaluates if the list item contains the word "problem" is stored in a rule file which is compiled with the application (in another post I will show you how to store and retrieve it dynamically from a database, and how a user can create this rules). The rules generated by Sharepoint Designer are rather cryptic.

Select the activity ID3 in the Workflow designer and click on the Condition property in the property page:

image

Select the Expression property, you’ll see something like this:

image

Replace the whole content of this windows with the following code :

image

That’s it ! Recompile, deploy and test the application .

 


This hands-on training is the property of U2U and may not be organized in class or in group without the prior written permission of U2U. Should you wish to organize this hands-on training in your company or institution, please contact U2U first to enter into a licence agreement. Each trainer or teacher using this hands-on training should have a licence agreement. Please ask your trainer or U2U whether he or she has entered into a licence agreement with U2U.

The hyperlink "www.u2u.be/msdna" to this hands-on training may be placed on your website for free, on the condition that the name and the logo of U2U are clearly mentioned in the reference. Please send us a mail containing the link to the web page our reference is used on.

8 responses to “Step by Step Tutorial. Creating Workflows for Windows Sharepoint Services and MOSS2007 (part 10/20)

  1. I deploy my workflows with the CodeBesideClass property in the Workflow tag of the Workflow.xml file that comes with WSS Sequential Workflow projects.It points to the class in the default workflow\’s code behind. (CodeBesideClass="SharePointWorkflowLibrary_Test.Workflow1"). If I remove that line, the workflow fails.In your example, you say that we should delete the Workflow.cs file. How then would you go about it to make your workflow run without failing?I\’ve tried linking to the workflow on Workflow 1.xoml  from the one on Workflow1.cs, but couldn\’t find a way to do so.Any assistance would be much appreciated

  2. I deploy my workflows with the CodeBesideClass property in the Workflow tag of the Workflow.xml file that comes with WSS Sequential Workflow projects.It points to the class in the default workflow\’s code behind. (CodeBesideClass="SharePointWorkflowLibrary_Test.Workflow1"). If I remove that line, the workflow fails.In your example, you say that we should delete the Workflow.cs file. How then would you go about it to make your workflow run without failing?I\’ve tried linking to the workflow on Workflow 1.xoml  from the one on Workflow1.cs, but couldn\’t find a way to do so.Any assistance would be much appreciated

  3. I deploy my workflows with the CodeBesideClass property in the Workflow tag of the Workflow.xml file that comes with WSS Sequential Workflow projects.It points to the class in the default workflow\’s code behind. (CodeBesideClass="SharePointWorkflowLibrary_Test.Workflow1"). If I remove that line, the workflow fails.In your example, you say that we should delete the Workflow.cs file. How then would you go about it to make your workflow run without failing?I\’ve tried linking to the workflow on Workflow 1.xoml  from the one on Workflow1.cs, but couldn\’t find a way to do so.Any assistance would be much appreciated

  4. I deploy my workflows with the CodeBesideClass property in the Workflow tag of the Workflow.xml file that comes with WSS Sequential Workflow projects.It points to the class in the default workflow\’s code behind. (CodeBesideClass="SharePointWorkflowLibrary_Test.Workflow1"). If I remove that line, the workflow fails.In your example, you say that we should delete the Workflow.cs file. How then would you go about it to make your workflow run without failing?I\’ve tried linking to the workflow on Workflow 1.xoml  from the one on Workflow1.cs, but couldn\’t find a way to do so.Any assistance would be much appreciated

  5. I deploy my workflows with the CodeBesideClass property in the Workflow tag of the Workflow.xml file that comes with WSS Sequential Workflow projects.It points to the class in the default workflow\’s code behind. (CodeBesideClass="SharePointWorkflowLibrary_Test.Workflow1"). If I remove that line, the workflow fails.In your example, you say that we should delete the Workflow.cs file. How then would you go about it to make your workflow run without failing?I\’ve tried linking to the workflow on Workflow 1.xoml  from the one on Workflow1.cs, but couldn\’t find a way to do so.Any assistance would be much appreciated

  6. I deploy my workflows with the CodeBesideClass property in the Workflow tag of the Workflow.xml file that comes with WSS Sequential Workflow projects.It points to the class in the default workflow\’s code behind. (CodeBesideClass="SharePointWorkflowLibrary_Test.Workflow1"). If I remove that line, the workflow fails.In your example, you say that we should delete the Workflow.cs file. How then would you go about it to make your workflow run without failing?I\’ve tried linking to the workflow on Workflow 1.xoml  from the one on Workflow1.cs, but couldn\’t find a way to do so.Any assistance would be much appreciated

Leave a comment