<ns0:RootWorkflowActivityWithData x:Class="Microsoft.SharePoint.Workflow.ROOT" x:Name="ROOT" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/workflow" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 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" />
</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.
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.
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 :
Here is what we get if we click on the collection:
This will initialize the informations the CopyItemActity needs (see later).
Now, let’s take a look at the CopyItemActivity properties :
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 :
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:
Another view of the Workflow Designer will show up:
Drag and drop a FaultHandler activity from the Workflow Foundation toolbox into fautlHandlersActivity1 :
In the property page of this last activity select the FaultType property by browsing the mscrolib assembly:
Select System.Exception:
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) :
Select the logToHistoryListActivity1 and set its HistoryOutcome property to the stack trace value of faultHandlerActivity1:
Rebuild the solution , redeploy (install.bat) and test the workflow.
The trace will show up in the workflow status :
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:
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”:
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:
Select the Expression property, you’ll see something like this:
Replace the whole content of this windows with the following code :
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.