serge's profileSerge Luca (Sharepoint M...PhotosBlogLists Tools Help

Blog


    May 08

    Step by Step Tutorial. Creating Workflows for Windows Sharepoint Services and MOSS2007 (part 12/20). Managing several approvers/reviewers

    image

    Step by Step Tutorial. Creating Workflows for Windows Sharepoint Services and MOSS2007 (part 12/20). Managing several approvers/reviewers

     

    By Serge Luca

    MVP Connected System 

    image

     

     

    Introduction

    The Out-of the box approval workflow provided with MOSS allows to specify several approvers. In this post, I will illustrate how to do this. In a first time (part 1) , I will show you how to use the Replicator activity that you will need, and in a second time (part 2), you will apply this knowledge to our Sharepoint problem. If you know how the Replicator activity works you can directly go to part 2.

     

    Part 1. Using the Replicator activity

    The Replicator activity is part of the Workflow Foundation Base Activity Library, is somewhat similar to the While activity.

    • Create a  Sequential Workflow console application project.
    • Add a Replicator activity into the workflow surface

    image

    • Add a custom Activity to the project; call it "ManageTask":

     

    image

    • Define a public string member  called Approver in the custom activity :

     

    image

    • Drag and drop a Code activity in the custom activity

    image

    • Display the Approver member in its Event handler:

    image

    Recompile the project and drag & drop the custom activity into the Replicator:

    image

    • In the workflow code add an ArrayList data member and name it Approvers :

    image

    • In the Workflow constructor, add 2 users to the ArrayList

    image

    • In the Replicator activity, databind the InitialChildData property to the ArrayList:

    image

    In the Replicator activity, double click on the ChildInitialized event to generate an event handler :

    image

    • Each item in the collection will be associated with a child activity (the child activity here is ManageTask): each time a child activity will be created, the ChildInitialized event will be triggered, which give us the possibility to pass the associated data :

    image

    Run the application:

    image

    You can download the code here.

    Part 2. Using the Replicator activity in the Approval workflow

     

    • as I did in the previous post, I will start by using the HelloWorldSequential sample  provided with the MOSS sdk. Don't forget to replace the string http://locahost in the install.bat file with you own web site/site collection url. (See step 11 of this tutorial for more infos about this sample).

     

    • The strategy is to replicate the following selected activities in a Replicator activity :

     

    image

    We will group these activities in a custom sequential activity.

    • Add a new project (Sharepoint-Sequential Workflow Library ) to the current solution

    image

    • Remove the following files from the project :

    image

    • In the same project, add a new custom activity, name it ManageApproval:

    image

    • You can either drag & drop the activities from Workflow1 to the new custom activity or adding new activities in the ManageApproval activity (my option) :

     image

    • Link each of these activity to the same correlation token : TaskToken and ManagerApproval for the OwnerActivityName

    image

    • Select the CreateTask activity and databind its TaskId and TaskProperties property to  new fields :

    TaskId and TaskProperties

    • Databind the TaskId prperty of the OnTaskChanged and CompleteTask activities to the newly created taskId member.

    On the OnTaskChanged activity, databind the AfterProperties and BeforeProperties to new fields:

    AfterProperties and BeforeProperties

    image

    • Define the following members (make sure Assignee is public since it will get the task owner from the Replicator activity) :

    image 

    • Double click on the CreateTask activity to generate a handler and add the following code:

    (most of the code can be copied from Workflow1.cs)

    image

    • Set the Condition property of the WhileActivity to Code Condition and name the function TaskNotFinished :

    image

    • Define a bool data member, isFinished , and check its status in the TaskNotFinished function:

    image

    • Double click on the TaskChanged activity to generate a handler and add the following code:

    image

    • Sign you assembly
    • Get back to the workflow project and double click on the workflow code to display it in the designer; clean it up by deleting the activities you don't need anymore; you must have something like this:

    image

    • Recompile the solution to make sure your custom activity will show up in the toolbox.
    • Add a Replicator activity just after the OnWorkflowActivated activity and drag & drop you custom activity in it.

    image

    • In the workflow code, define a new member to host the assignees:

    image

    • Store the assignees into this ArrayList: click on the OnWorkflowActivated activity and add the following code in the handler:

    image

    • Bind the Replicator activity to the Assignee member.
    • Add a handler to the ChildInitialized event of the Replicator and insert the following code:

    image

    • Modify the install.bat file in order to register the custom activity in the Gac :

    "%programfiles%\Microsoft Visual Studio 8\SDK\v2.0\Bin\gacutil.exe" -uf MyApprovalActivities
    "%programfiles%\Microsoft Visual Studio 8\SDK\v2.0\Bin\gacutil.exe" -if bin\Debug\MyApprovalActivities.dll

     

    • Test the workflow: rebuild, install the workflow, add the association and start a workflow ; assign to user separated with a ";" , for instance  U2UCOURSE\Administrator;U2UCOURSE\serge, like this :

    image

    A first task will be created for the user "Administrator":

    image

    • If the Administrator clicks on its task :

    image

    • Then, if the user "Administrator" select the "I am finished reviewing" and click the Submit button, a new task will be created for the user "serge":

    image

     

    • The reason  Serge's tasks is created after the Administrator's task completes is that the ExecutionType property of the Replicator activity was set to Sequence. Let's change it to parallel, rebuild and test the workflow .

    image

    Congratulations !!!!


    This hands-on training is the property of Redwood S.L sprl and may not be organized in class or in group without the prior written permission of Serge Luca. Should you wish to organize this hands-on training in your company or institution, please contact Serge Luca  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 Serge Luca whether he or she has entered into a licence agreement with Redwood S.L sprl.

    The hyperlink to this hands-on training may be placed on your website for free, on the condition that the name Serge Luca is clearly mentioned in the reference. Please send us a mail containing the link to the web page our reference is used on.


    May 07

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

     

     

    image

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

     

    By Serge Luca

    MVP Connected System 

    image

     

     

     

     

    Introduction

    Modification forms allow us to reassign a workflow task to another user.

    3 parts in this article:

    1. What are Modification Forms
    2. Introduction to the EventHandlingScope activity
    3. Adding a Modification form to an existing workflow

    Part 1. What are Modification Forms

    To illustrate this concept, I will run a workflow provided with the downloadable version of the Sharepoint Sdk (1.3 in my case).

    By default, the samples are installed in the following location :

     

    image

     

    • Try to open the ModificationSample project;if you try to compile it, you will get a compilation exception since this project references another assembly provided with the sdk as well: ECMActivities; recompile the ECMActivities project and resolve the reference in ModificationSample.

     

    • If you doubleclick on the Workflow1 class you'll get the following model(I will describe the different elements of this workflow in the second part of this post, don't worry).

    image

     

    • If we compare this model to the workflows we did in the previous tutorials, we'll notice 2 new activities: EnableWorkflowModification (a Sharepoint activity) and EventHandlingScopeActivity (which is part of the base activity library of Workflow Foundation).

     

    • Let's click on the manifest file (workflow.xml), you will notice a couple of new tags :

    image

    Several Infopath forms are also provided with this example and one of them which is referenced in the Modification element of the manifest is the Modification form:

    image

     

    • In the Install.bat file, replace http://localhost with our site collection url and run it.
    • Associate the workflow with a Sharepoint list and start the workflow. You'll notice that the Reviewer is U2UCOURSE\serge :

    image

    The workflow is in progress; if you click on its status:

    image

    You'll be redirected to this form where you have the option to reassign the task:

    image

    A task has been created and assigned to serge:

    image

    • Let's reassign the task to john by clicking on the "Update task owner" hyperlink described above:

    image

     

    • If you get back to the task list, you will notice that the task owner has been changed appropriately:

    image

     

    • Now, if John click on its task, the task form will show up; if he clicks in the "completes" field, the workflow will complete; there is a small bug in the application, however : john's task doesn't complete, it is still necessary to add a Sharepoint  "CompleteTask" activity :

    image

    ..and to link it to the task Id

    image

    ...and the correlation token to "taskToken1" :

    image

    Recompile, and (re)install the workflow.

     

    Part 2. Understanding the EventHandlingScopeActivity

    The EventHandlingScopeActivity is an activity that allows a workflow (or part of a workflow) to run while listening to events; it is a kind of (but just a kind of) ListenActivity or ParrallelActivity.

    Ok, I'll give you a quick tutorial on it:

     

    • Create a Workflow Console application (Sequential workflow) and drag and drop a EventHandlingScopeActivity from the toolbox into the workflow surface:

    image

     

    • Drag and drop a Sequence activity into the EventHandlingScope activity

    image

     

    • Drag and drop a Delay activity followed by a code activity:

     

    image

     

    • Set the TimeoutDuration of the delayActivity to 20 seconds and in the codeActivity1 associated code, display "Main Application Completed".

    These activities can be considered as part of the main flow of the workflow sequence.

    In the background however, the workflow can listen to events while the main flow is not completed: in the case of our Sharepoint workflow the potential event that could come up is the OnWorkflowModified event which is triggered when a task is reassigned to another owner for instance.

     

    • To keep it simple, I will use another delay activity (it must be any activity implementing the IEventActivity interface and that's the case of the delay activity but also the case of all  "green" Sharepoint activities : these green activites are derived from HandleExternalEvent activity, which implement IEventActivity). The activity must be encapsulated in an EventDriven activity (the first activity of an EventDriven activity must implement IEventActivity); it is like a catch for an event (instead of a catch for an exception). Lets go for it.

     

    • To show the event side of the EventHandlingScope activity, right click on it and select "view Event Handlers" as following:

     

    image

    You'll see this :

    image

    • Drag and drop an EventDriven activity (or several if you need to listen to several events).

    image

     

    • Lets drag and drop a Delay activity (and set its timeout property to 10 seconds, to make sure the event will fire before the main flow completes).
    • Just after the Delay activity, add a code activity and display the message "delay event fired in the background" in the associated code:

    image

     

    • Run the application and you will get something like this

    image

     

    Part 3. Using a Modification form in an existing workflow

     

    • I will assume that you know how to create sharepoint workflows and how to link Infopath Forms to the workflow association, Initiation and task changing state; if it is not the case, follow the previous versions of my sharepoint workflow tutorials.
    • Add an existing Sharepoint workflow project to the current solution

     

    Step 1.Add to your solution the HelloWorldSequential workflow provided with the sdk ; in its install.bat file, replace http://localhost with your site collection url, deploy it and play with it.

    Step 2.Add the ModSimpleModificationForm.xsn Infopath Form of ModificationSample (sdk)  to the location of the HelloWorldSequential project.

    Step 3.Register the Modification forms in workflow.xml:

     

    -generate a Guid with Guidgen (Visual Studio-Tools-Create GUId menu)

    -after the <Task0_FormURN> elements, add 2 elements: <Modification_xxx_FormURN> and <Modification_xxx_Name> where xxx is the generated Guid like this:

           <Modification_bf35e820-5070-4e33-bc91-de30388e0b7e_FormURN>

              urn:schemas-microsoft-com:office:infopath:ModSampleModificationForm:-myXSD-          2006-05-17T01-22-06

          </Modification_bf35e820-5070-4e33-bc91-de30388e0b7e_FormURN>

          <Modification_bf35e820-5070-4e33-bc91-de30388e0b7e_Name>

                  Update task owner

          </Modification_bf35e820-5070-4e33-bc91-de30388e0b7e_Name>

     

     

    Step 4.Run Install.bat, associate the workflow with a list and run it on a list item. If you click on the workflow status (when the workflow is "in progress", you will notice that the "update task owner" message is not visible; we need to add another functionality (next step).

     

    Step 5.Add the EnableWorkflowModification activity just before the CreateTask activity :

     

    image

     

    • set its correlation token to the current token, "modifToken" and the OwnerActivityName to HelloWorldSequential.
    • set its ModificationId property to the Guid defined before: bf35e820-5070-4e33-bc91-de30388e0b7e
    • compile, install and test the workflow : the workflow will crash and you will get an "an error has occured" message.
    • try to visualize the error message by setting up a FaultHandler activity in the Fault Handler view of the workflow and  log the error message in the workflow history by using a LogToHistoryList activity :

     

    image

    • Set the FaultType property of the FaultHandler activity to System.Exception and the HistoryOutCome property of the LogToHistoryList activity to the exception message property as following:

    image

    You will get a rather unclear exception (if you click on the workflow completed status hyperlink):

    image

    Step 6. Add a sequence activity in yhe EventhandlingScope activity and move the EnableWorkflowModification activity and the other  activities that follow (disable the SendMail, LogToHistoryList and CodeActivity) into an EventHandlingScope activity (group them all in a sequence activity):

    image 

    • in the CorrelationToken property of the grouped activities, set the owner activity property to the EventHandlingScope activity name
    • Build and test, you will get the following (same) error:

     image

    • In the EventHandlingScope activity Event Handler, add an EventDriven activity and a OnWorkflowActivated activity like this:

     

     image

    • Set the OnWorkflowModified activity CorrelationToken property to "modifToken".
    • Set the ModificationId to the value defined above.
    • Build, run and test the  workflow, and this time the workflow status will be "in progress" which is a good sign ! 
    • If you click on the workflow status, you will see the "Update task owner" hyperlink:

    image

    • However, if you click on the "Update Task owner" hyperlink, you will get an Infopath Form exception; indeed the contextData, which is supposed to contain the data to be transferred to/from the modification form is not yet ready. We will manage this in the next step.

    Step 7. Sending data to the modification form

    As we did it in one of the  the tutorial, let's use xsd.exe to generate a class that will be mapped to the modification form.

    • Open the modification form with Infopath and use the "save as source"  menu; this will generate (among others), an .xsd file.
    • generate the mapping .net class : xsd.exe myschema.xsd /c
    • rename the generated class file as  "modificationForm.cs"
    • add the file to the workflow project
    • create an helper function to serialize an Infopath form schema:

            private string SerializeModificationData(ModificationForm form)

            {

                using (MemoryStream stream = new MemoryStream())

                {

                    XmlSerializer serializer = new XmlSerializer(typeof

                                                     (ModificationForm));

                    serializer.Serialize(stream, form);

                    return Encoding.UTF8.GetString(stream.GetBuffer());

                }

            }

    • select the EnableWorkflowModifcation actvity and bind its ContextDate property to a new workflow field that we will call _ContextData.
    • at the end of the OnWorkflowActivated event handler, add the following lines :

                ModificationForm modifForm = new ModificationForm();

                modifForm.taskOwner = assignee;

                this._ContextData = this.SerializeModificationData(modifForm);

     

    • Build, install and test the workflow : click on the "Update Task owner" link and the modification form will show up:

    image

    We still need to be able to take the modification data into account.

    Step 8. Sending data from the modification form

    • Everytime the modification form data will be submitted, the OnWorkflowModified activity will be triggered.
    • To get the new task owner, we need to deserialize to data from the Modification form.
    • To manage this, create a function to deserialize Infopath form data:

            private ModificationForm DeserializeFormData(string xmlString)

            {

                using (MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes

                                                                        (xmlString)))

                {

                    XmlSerializer serializer = new XmlSerializer(typeof

                                                            (ModificationForm));

                    ModificationForm data = (ModificationForm)serializer.Deserialize

                                                            (stream);

                    return data;

                }

            }

    • Define a newAssignee data member in the workflow class :

             private string newAssignee = default(string);

    • Switch to the EventHandler of the EventHandlingScope activity
    • Add an eventHandler to the Invoked event of the OnWorkflowModified activity
    • Deserialize the Infopath form as following:

         private void onWorkflowModified1_Invoked(object sender, ExternalDataEventArgs e)

         {

                ModificationForm modForm = this.DeserializeFormData(this._ContextData);

                this.newAssignee = modForm.taskOwner;

         }

    • We still need to update the existing task(s) by using an UpdateTask activity: drag & drop an Update Task activity just after the onWorkflowModified1 activity:

    image

    • Link the UpdateTask activity to the created task activity by "databinding" its TaskId property to the workflow taskId property and by "databinding" its TaskProperties to the workflow member afterProps (which is databound to the afterProperties property of the onTaskChanged1 activity).
    • Set also its correlation token to modifToken.
    • Set an event handler to the updateTask1 activity with the following code that will modify the Assigned to user :

           private void updateTask1_MethodInvoking(object sender, EventArgs e)

            {

                afterProps.AssignedTo = this.newAssignee;

     

            }

    step 9. Testing

    • Build deploy and test the workflow; it is very important to make sure the task data are updated even when you redirect the form to another user:

     

     image

    image

    Get to the Tasks list

    image

    Click on the title hyperlink and modify the instructions in the form as following (here I've added "modified by admin") :

     image

    Click on the Submit button.

    Get back to the original list, click on the workflow status ("in Progress)

    image

    Update the task owner ("here to Serge)

    image

    Go to the Tasks list, make sure the task owner has been modified

    image

    Click on the Title hyperlink, should get the modified data in the form :

    image
     

    Congratulations !!!


    This hands-on training is the property of Redwood S.L sprl and may not be organized in class or in group without the prior written permission of Serge Luca. Should you wish to organize this hands-on training in your company or institution, please contact Serge Luca  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 Serge Luca whether he or she has entered into a licence agreement with Redwood S.L sprl.

    The hyperlink to this hands-on training may be placed on your website for free, on the condition that the name Serge Luca is clearly mentioned in the reference. Please send us a mail containing the link to the web page our reference is used on.