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.


    April 22

    Do you think you know when to call Dispose() in Sharepoint ?

     
    One of the most frequent cause of problems in Sharepoint developement is when developers don't call Dispose() (specially when they traverse collections of objects).
    My reference for this was this excellent whitepaper from Scott Harris and Mike Ammerlaan ; to summarize, call Dispose() all the time except when the object comes from the context (ex SPContext.Web), because Sharepoint will take care of it.
    However the following article from Roger Lamb shows that it is a bit more complex.
     
     
    April 02

    Open XML is now an ISO Standard

     

    in my opinion this is very important and opens the door to many interesting patterns. Oh boy, some of my friends in Redmond must be so happy.

    MVP 2008-2009 renewed

     

    MVPRenewed

    Happy to know that my MVP status has been renewed today...

    March 28

    Enable WCF in Windows Server 2008

     

    Solved some WCF + Windows Server 2008 problems today and the following links helped me :

    1. Don't forget that WCF is a feature-> read this to activate it in ws2008.
    2. Using WCF with WAS in Windows Server 2008 (a bit easier than with Vista)
    March 26

    Upgrading my silverlight "skills" to v2 beta1

     

    I just spent a couple of days with Silverlight v2:

     

    For Silverlight 2 & Sharepoint, if you don't want to waste one day or more, just follow Patrick's instructions to modify the web.config file (+Mime)  and don't forget to recompile your "SL.XAML.HelloSilverlight2 project". Let's repeat it : "recompile you xap project, dude".

    March 20

    Declarative workflows and WSS sp1 bug

    Declarative workflows (like those generated by Sharepoint Designer) don't start automatically anymore when you install Windows Sharepoint Service sp1:
    this is a nasty bug, but there is a workaround .
     
     
     
    February 29

    Speaker for the TechDays 2008 : Workflow Foundation Rules Engine

     

    The next Microsoft Tech Days (Belgium) will take place in less than 2 weeks in Gent; this will be the official launch of brand new versions of Windows Server 2008, SQL Server 2008 and Visual Studio 2008.  Like my U2U colleagues Patrick Tisseghem and Peter Himschoot, I'll be a speaker : my session will be "Externalizing the Business Rules in any .Net application (including Sharepoint) with the Workflow Foundation Rules Engine" (13 March 2008). See ya there !

    image

    January 23

    Hosting a WCF Serviced Workflow in IIS 7 and using the persistence service (Visual Studio 2008)

     

     

    By Serge Luca

    MVP Windows Workflow Foundation

    In the previous post I showed you how to host a "WCF serviced" workflow and how to use a persistence  service in a console application.

    Now, let's move our workflow service to IIS7. Code can be downloaded here.

    1.Download the code of the previous post.

    2.In IIS7 Admin Manager, create a virtual directory that will point to the WFServiceLibrary folder, assign a port number (for instance 8082). Make sure the service dll is in the .bin folder just below the virtual root.

    sshot-185

    3.In the virtual root, add a .svc file (myservice.svc)  with the following code:

    <%@ServiceHost language=c# Debug="true" Service="WFServiceLibrary.Workflow1" Factory="System.ServiceModel.Activation.WorkflowServiceHostFactory" %>

    4.Add a web.config file and configure it like this:

    <configuration>
      <system.web>
        <compilation debug="true" />
      </system.web>
      <system.serviceModel>
        <services>
          <service name="WFServiceLibrary.Workflow1" behaviorConfiguration="WFServiceLibrary.Workflow1Behavior">
            <host>
              <baseAddresses>
                <add baseAddress="/" />
              </baseAddresses>
            </host>
            <endpoint address=""
                      binding="wsHttpContextBinding"
                      contract="WFServiceLibrary.IWorkflow1">
              <!--
                  Upon deployment, the following identity element should be removed or replaced to reflect the
                  identity under which the deployed service runs.  If removed, WCF will infer an appropriate identity
                  automatically.
              -->
              <identity>
                <dns value="localhost"/>
              </identity>
            </endpoint>
            <endpoint address="mex"
                      binding="mexHttpBinding"
                      contract="IMetadataExchange" />
          </service>
        </services>
        <behaviors>
          <serviceBehaviors>
            <behavior name="WFServiceLibrary.Workflow1Behavior"  >
              <serviceMetadata httpGetEnabled="true" />
              <serviceDebug includeExceptionDetailInFaults="false" />
              <serviceCredentials>
                <windowsAuthentication
                    allowAnonymousLogons="false"
                    includeWindowsGroups="true" />
              </serviceCredentials>
            </behavior>
          </serviceBehaviors>
        </behaviors>
      </system.serviceModel>
    </configuration>

    5.Now test the svc file in the browser to verify that you can grab the metadata (wsd):

    you should get this:

     

    image

     

    6.Add a console application project (name it IISClient) in order to invoke the service:

    7.In the IISClient project add a service reference to the WCF service:

    image

    Keep the default name and click on ok. A proxy will be generated.

    8.Add a reference to the System.WorkflowService assembly in the IISclient project .

    9.Implement the client-side code :

    static void Main(string[] args)

    {

    ServiceReference1.

    Workflow1Client proxy= new ServiceReference1.Workflow1Client("WSHttpContextBinding_IWorkflow1");

    // much faster to provide the endpoint directly, I don't know why
    // new ServiceReference1.Workflow1Client(new WSHttpContextBinding(),
    // new EndpointAddress("http://localhost:8082/myservice.svc"));

    Console.WriteLine(proxy.GetData(0));

    }

     

    10.Run the code

     image

    Ok that works !

    11.Let's modify the web.config file to register the persistence service:

    add workflowRuntime setting in the default behavior:

    image

    Here is the workflowRuntime setting:

    <

    workflowRuntime name="WorkflowServiceHostRuntime" validateOnCreate="true" enablePerformanceCounters="true">

    <

    services>

    <

    add type="System.Workflow.Runtime.Hosting.SqlWorkflowPersistenceService, System.Workflow.Runtime, Version=3.0.00000.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"connectionString="Data Source=localhost\sqlexpress;Initial Catalog=PersistenceDB2;Integrated Security=True;Pooling=False"LoadIntervalSeconds="1" UnLoadOnIdle= "true" />

    </

    services>

    </

    workflowRuntime>

    Make sure the persistence database (PersistenceDB2 here has been created, see my previous post for more infos)

    12 (optional)If you want to access the WorkflowRuntime by code even if your service is hosted in IIS (and by the way an .svc file), then your need to create your own WorkflowServiceHost factory by creating a class derived from System.ServiceModel.Activation.WorkflowServiceHostFactory and by overriding its CreateServiceHost method.

     

    • In the WFServiceLibrary project  add a new class called MyCustomServiceHost derived from WorkflowServiceHostFactory (in our case we will register the persistence service in the WorkflowRuntime) :

    public class MyCustomServiceHost : WorkflowServiceHostFactory

    {

    public override ServiceHostBase CreateServiceHost(string constructorString,Uri[] baseAddresses){

    WorkflowServiceHost serviceHost=
    (
    WorkflowServiceHost)base.CreateServiceHost(constructorString, baseAddresses);
    WorkflowRuntime wRuntime =serviceHost.Description.Behaviors.Find<WorkflowRuntimeBehavior>().WorkflowRuntime;

    string connectionString=@"Data Source=localhost\sqlexpress;Initial Catalog=PersistenceDB2;Integrated Security=True;Pooling=False";

    wRuntime.AddService(

    new SqlWorkflowPersistenceService(connectionString,true,new TimeSpan(1,0,0), new TimeSpan(0,0,1)));

    return serviceHost;

    }

    }

    • Modify the .svc file to use our new factory class:

    <%

    @ServiceHost language=c# Debug="true" Service="WFServiceLibrary.Workflow1" Factory="WFServiceLibrary.MyCustomServiceHost" %>
    • Remove the Persistence service definition in the web.config file.

    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.

     

     

     

     

     

    January 15

    Using the persistence service in a WCF 3.5 hosted workflow

     

    Using the persistence service in a WCF 3.5 hosted workflow   

     

    By Serge Luca

    MVP Windows Workflow Foundation

    This morning a  colleague at U2U asked me how to use the persistence service in a workflow hosted in WCF (.Net 3.5 and Visual Studio 2008).

    I've created  a quick (and dirty, sorry) step by step tutorial on how to achieve it.

    Click here to download the code.

    1.Start Visual Studio 2008 and create a new Sequential Workflow Service Library project ; call it WFServiceLibrary.

    sshot-185

    A workflow with a WF-WCF 3.5 Receive activity linked to the GetData method of a IWorkflow interface will be generated:

    sshot-186

    sshot-187

    sshot-188

     

    2.Drag and drop a code activity into the Receive activity and set the ReturnValue to a funny string

    sshot-190

    sshot-189

    3.Create a WCF host for the workflow by generating a Console project

    sshot-191

    ...and add the following references:

    sshot-192

     

    And don't forget to add a reference to the WFServiceLibrary as well...

    4.In the Host project,..host the workflow and don't forget to create the persistence database with the scripts provided with the .Net framework :

    sshot-193

    The second parameter of the persistence service (unloadOnIdle) is set to true, which means the workflow will be persisted by the workflow runtime when it is idle; add a delay activity after the Receive activity to make it idle:

    sshot-194

    Set its timeout duration to 30 secs.

    5.Let's create the client application by adding a Console application to the solution:

    sshot-195

    Don't forget to reference the following .Net assemblies and the library project (just to get the interface definition: I told you it was quick and dirty)

    sshot-201

    Implement the client-side code in the Main() function :

    sshot-196

    6.Start the Host (if your run it Vista, I strongly suggest that you start it with admin privileges):

    sshot-198

    7.Start the client:

    sshot-199

    Ok, the communication works...

    8.Check the persistence database (InstanceState table):

    sshot-200

    yes the workflow is persisted!!! After 30 seconds, it will be removed from the database.

    Click here to download the code.


    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.

    November 20

    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" 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.

    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.

    Train The Trainer OBA(Office Business Applications)-Beijing

     

     
    After Paris, I've been the trainer of another OBA (Office Business Applications) Train The Trainer workshop last week in Bejing for Microsoft.
    This was my first trip in China; almost 70 persons (many Microsoft employees) attended this 3 days course.
    It was a great experience. After Joanna Bichsel and John Graham, I was fortunate to spend the week with Khawar Ahmed and Andrew Toner (both are OBA Product Managers).
     
    obachina
     
    Discussions
     
    Workflow discussion...
     
    Serge&Beiyang
     
    With Beiyang (Microsoft China-Shanghai)
     
    Serge&Keith
     
    With Keith Liu (Microsoft China-Shanghai)
     
    china 2007 020
     
    On the Great Wall with Khawar Ahmed (Microsoft, Oba team)
     
    china 2007 057
     
    In the Forbidden City
     
    china 2007 091
     
    With Khawar Ahmed  and Andrew Toner (Microsoft Oba team)
     
     
    October 03

    Workflow Foundation source code...

     
    According to Scott Guthrie, the source code of the .Net framework libraries 3.5 will be released under Microsoft Reference License.
    This is going to be great for all of us who use Reflector on a daily basis but who don't want to post on the MS code for legal reasons.
    So we'll be able to dig into the .net framework code from within our (VS2008) debugger; by the way , we already did it ten years ago with the C++ Microsoft Foundation Class Library. Great posts in perspective...Thanks MS! mmh what about Sharepoint ? there are some (workflow) obfuscated code parts I would like to see.
     

    Sharepoint Page Processing Model

     

     
     
    When I teach a Sharepoint course for U2U, I like to spend some time on the Page Processing Model (+ the role of IIS, ASP.Net and Sharepoint specific components like the Sharepoint modules, page layout, etc...)
     
    The following URL (from the Sharepoint 2007 sdk 1.2) provides an excellent explanation. I didn't noticed it before...
    More informations can be provided by opening up the Web Application's global.asax (where you'll find a reference to the SPHttpApplication) and the web.config file: you'll find references to  SPRequestModule & others .Net modules...).
     
     
     
     
    October 02

    The Workflow Foundation for Sharepoint series will continue...

    I've received tons of e-mail about the next "episodes" of my "Workflow for Sharepoint " series.
    I've been very busy on other works with U2U and Microsoft these last days (just have to teach a Oba Train the Trainer for U2U & Microsoft in China next week if I can get a visa Beschaamd), I'm also working with Microsoft learning on creating some of the next Workflow Foundation  beta certifications exams questions, and I'll be back on track for the serie.
     
    There are some very interesting of oba patterns where Workflow Foundation can play a important role, so....
    September 26

    Workflow Foundation is "very" single threaded, but...

     

     image

     
    Workflow Foundation is single threaded (one thread at a time will run your workflow instance, but the workflowRuntime is multithreaded : several workflows can run simultaneously), even when we use the ParallelActivity which coordonates execution
    of activities in multiple branches in a round-robin fashion; this doesn't mean the same thread will always run the workflow instance: indeed, if we use the DelayActivity (or if the workflow wait for another kind of message), the running thread is released and after the delay, another thread can be used to run the workflow.
    This is true even in a TransactionScopeActivity !!!
    By the way, you need to know that if you use the SqlWorkflowPersistenceService with the flag UnloadOnIdle set  to true, if your workflow becomes idle in the middle of a TransactionScope activity, your workflow WON'T BE PERSISTED. There is a tight coupling between the TransactionScopeActivity (TSCA) and the workflowRuntime which prevents it to be persisted & unloaded; the workflowRuntime also gives a higher priority to the child activities of the TSCA and this has an impact if we have a TSCA in one branch of a ParallelActivity and a Sequence activity in the other branch of the ParallelActivity.
     
     
     
    September 23

    Teaching the Oba Train the Trainer in Paris with the Redmond Team

     
     
    the last 2 weeks have been very busy : I've prepared the OBA Train the Trainer session that I had to teach last week in Paris for Microsoft.
    This course has  been created by Patrick Tisseghem for Microsoft.
    OBA means Office Business Application (see: www.obacentral.com and Office Business Application Portal) and that is really what I like : building real applications from existing building blocks like Office client, .Net, Sharepoint, Open XML and several nice patterns.
    Very exiting was the fact that some members of the OBA team (Redmond) like Joanna Bichsel and John Graham attended my course (see picture below).
    Thank you all for attending this Oba session. My next Oba session will probably take place in China next month (my first trip in China).
    In the meantime, I'll continue my work with MS learning to finalize the Windows Workflow Foundation (beta) certification exam.
    On the other side, I have many many scenarios in mind about using  Workflow Foundation in OBA apps, I'd really need to work 30 hours a day.
    And this week, I'll be in Denmark  to teach a Sharepoint course for U2U...
     
    August 30

    My live (hotmail) mail account moved to 5 GB !!!!

    here is what I saw this evening in my Windows live mail(hotmail) account: