Exercise 9-1: Creating a Workflow Engine


Exercise 9-1: Creating a Workflow Engine

Because SPS lacks any kind of workflow designer and engine, implementing even simple business processes requires writing code. If you custom-code each process, then you will rapidly find that performing maintenance on the code will become time consuming. Therefore, you will want to create some kind of engine that is more generic. In this exercise, you will create a simple workflow engine for approval routing that is programmable using an XML document.

Prerequisites

Before you begin to create the engine, you must perform several operations to prepare the environment. The first thing to do is enable event handling on your virtual server using the steps outlined earlier in the chapter. No document library events are trapped unless they are specifically enabled. After the document library events are enabled, you will need to create a new site with three libraries you can use to simulate routing the document. Your engine will be designed to move a document from a Submit library to a Review library to an Approve library.

Here are the steps to set up the libraries:

  1. Log in to SPS as a member of the Administrator site group .

  2. Navigate to the Site Directory by clicking the Sites link.

  3. In the Site Directory, click the Create Site link under the Actions list.

  4. Create a new blank site named Workflow .

  5. When the new site is created, click the Create link.

  6. On the Create page, select to create a new document library named Submit .

  7. Repeat this to create a second document library named Review and a third named Approve .

The last thing to do before you start writing the engine is configure the Microsoft Single Sign-On (SSO) service with a set of impersonation credentials you can use to run the event handler. You will retrieve these credentials within the event handler. This section assumes that you have already set up SSO in accordance with Chapter 6.

To configure SSO credentials, take these steps:

  1. Log in to SPSPortal as a member of the MSSSOAdmins group.

  2. Select Start All Programs SharePoint Portal Server SharePoint Portal Server Single Sign-On Administration.

  3. On the Manage Settings page select Enterprise Application Definition Settings Manage Settings for Enterprise Application Definitions.

  4. On the Manage Enterprise Application Definitions page, click the New Item link.

  5. On the Create Enterprise Application Definition page, enter Workflow Engine in the Display Name box.

  6. Enter Workflow in the Application Name box.

  7. Enter administrator@sps.local in the Contact E-mail Address box.

  8. Enter UserName in the Field 1: Display Name box.

  9. Enter Domain in the Field 2: Display Name box.

  10. Enter Password in the Field 3: Display Name box.

  11. Select Yes for the Mask option associated with Field 3.

  12. Click OK.

  13. Return to the Manage Settings page and select Enterprise Application Definition Settings Manage Account Information for Enterprise Application Definitions.

  14. In the Account Information section, choose Workflow Engine from the drop-down list.

  15. Type sps\Domain Users in the Group Account Name box.

  16. Click OK.

  17. On the "Provide workflow engine account information" page, type administrator in the UserName box.

  18. Type sps in the Domain box.

  19. Type the administrator password in the Password box.

  20. Click OK.

Building the Workflow Engine

Document library event handlers are built as class library assemblies. For your workflow engine, you will build a class library in C# and implement the IListEventSink interface. This interface traps document approval events for the Submit and Review libraries and routes the document to the next library when it is approved. The routing details will be managed through an XML document.

Here is what to do to start the project:

  1. Log in to SPSPortal as a local administrator.

  2. Start Visual Studio and choose File New Project from the menu.

  3. In the New Project dialog, click the Visual C# Projects folder.

  4. In the Templates window, click Class Library.

  5. Name the new project Workflow and click OK.

  6. When the new project is created, select Project Add Reference from the menu.

  7. In the Add Reference dialog, select to add references to Microsoft.SharePoint.Portal.SingleSignon.dll , System. Windows .Forms.dll , System.Xml.dll , and Windows SharePoint Services.

  8. Click OK.

  9. Rename the Class1.cs file as Engine.cs .

  10. Open the Engine.cs file and rename the namespace to WorkFlow and the class to Engine .

  11. Add code references to the imported assemblies so that your code appears exactly as shown in Listing 9-11.

    Listing 9-11: The WorkFlow.Engine Class

    start example
     using System; using System.Windows.Forms; using System.Xml; using System.Security.Principal; using System.Runtime.InteropServices; using Microsoft.SharePoint; using Microsoft.SharePoint.Portal.SingleSignon; namespace WorkFlow {     public class Engine     {     } } 
    end example
     

Creating the New Identity Helper

Before you code the body of the event handler, you will construct a helper function to establish the identity under which the event handler will run. This helper function is essentially the same in every event-handling class you create. It makes a call to the Windows API to log the impersonation user on to the system. It then returns a WindowsIdentity object to the main code. Add the code in Listing 9-12 to the Engine class to get the impersonation identity.

Listing 9-12: Creating the Impersonation Identity
start example
 protected static WindowsIdentity CreateIdentity (string userName, string domain, string password) {     IntPtr tokenHandle = new IntPtr(0);     tokenHandle=IntPtr.Zero;     const int LOGON32_PROVIDER_DEFAULT=0;     const int LOGON32_LOGON_NETWORK=3;     //Logon the new user     bool returnValue = LogonUser(userName,domain,password,         LOGON32_LOGON_NETWORK,LOGON32_PROVIDER_DEFAULT,         ref tokenHandle);     if(returnValue==false)     {         int returnError = Marshal.GetLastWin32Error();         throw new Exception("Log on failed: " + returnError);     }     //return new identity     WindowsIdentity id = new WindowsIdentity(tokenHandle);     CloseHandle(tokenHandle);     return id; } [DllImport("advapi32.dll", SetLastError=true)] private static extern bool LogonUser (String lpszUsername, String lpszDomain, String lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken); [DllImport("kernel32.dll", CharSet=CharSet.Auto)] private extern static bool CloseHandle(IntPtr handle); 
end example
 

Creating the XML Document

The last task to perform before you build the body of the event handler is to create the XML document that will contain the routing instructions. Your strategy is to use the SinkData property to identify which of the libraries has triggered the event and then route the document to the next library. To make your solution more flexible, you will build an XML file that contains elements based on the SinkData property and the addresses of the libraries.

To create the XML routing document, follow these steps:

  1. In Visual Studio, select Project Add New Item from the menu.

  2. In the Add New Item dialog, select to add an XML file.

  3. Name the new file Workflow.xml and click Open.

  4. Open Workflow.xml in Visual Studio and modify it to appear as follows :

     <?xml version="1.0" encoding="utf-8" ?> <Workflow xmlns="urn:DataLan.SharePoint.WorkFlow.Engine">     <Submit></Submit>     <Review></Review> </Workflow> 
  5. Open SPS in Internet Explorer and navigate to the Review library you created earlier.

  6. From the document library page, copy the URL associated with the root of the library.

  7. Copy this fragment between the <Submit></Submit> elements in the XML file so that approved documents from the Submit library will be moved to the address of the Review library.

  8. Repeat this action to route approved documents in the Review library to the Approve library. The following code shows an example of how the final XML file might appear.

     <?xml version="1.0" encoding="utf-8" ?> <Workflow xmlns="urn:DataLan.SharePoint.WorkFlow.Engine">     <Submit>http://spsportal/sites/workflow/Review</Submit>     <Review>http://spsportal/sites/workflow/Approve</Review> </Workflow> 
  9. Copy the XML file into the root of the C: drive.

Coding the IListEventSink Interface

Now that the supporting elements are prepared, you can code the main body of the event handler in the IListEventSink interface. Add this interface to your class by typing a colon after the class name followed by the interface name. You should then be able to press the Tab key and have Visual Studio automatically insert the interface stubs for you so the beginning of your class will appear as follows:

 public class Engine:IListEventSink     {          public void OnEvent(SPListEvent listEvent)          { 

In the body of the OnEvent method, you will retrieve the credentials for the impersonation identity from SSO and create the new identity context. Then you will determine if an approval event has occurred in the connected library. If an approval event has occurred, then you will read the XML file to determine the destination of the approved file. Finally, you will move the file to the destination library. Add the code necessary to make your final implementation of the OnEvent method as shown in Listing 9-13.

Listing 9-13: The OnEvent Method
start example
 public void OnEvent(SPListEvent listEvent) {     //Call MSSSO     string[] strCredentials=null;     Credentials.GetCredentials         (Convert.ToUInt32(1),"Workflow",ref strCredentials);     string userName = strCredentials[0];     string domain = strCredentials[1];     string password = strCredentials[2];     //Create new context     WindowsImpersonationContext windowsContext =         CreateIdentity(userName,domain,password).Impersonate();     //Get event objects     SPWeb eventSite = listEvent.Site.OpenWeb();     SPFile eventFile = eventSite.GetFile(listEvent.UrlAfter);     SPListItem eventItem = eventFile.Item;     //Determine if an approval event fired     if((listEvent.Type == SPListEventType.Update) &&         ((string)eventItem["Approval Status"]=="0"))     {         //Load the XML document         string xmlPath ="C:\Workflow.xml";         XmlDocument xmlDoc = new XmlDocument();         xmlDoc.Load(xmlPath);         //Prepare to parse XML         XmlNamespaceManager manager = new XmlNamespaceManager(xmlDoc.NameTable);     manager.AddNamespace("ns","urn:DataLan.SharePoint.WorkFlow.Engine");         //Find the target library for the move         string targetPath = xmlDoc.SelectSingleNode               ("//ns:" + listEvent.SinkData,manager).InnerText;         //Move the document         eventFile.MoveTo(targetPath + "/" + eventFile.Name,false);     }     //Tear down context     windowsContext.Undo(); } 
end example
 

Compiling the Engine

Event-handling classes must be placed in the GAC in order to function. Assemblies placed in the GAC must have a strong name; therefore, you must create a strong name for your assembly before you compile it. Additionally, you must ensure that the version attribute of your assembly is fixed and not changed dynamically each time the assembly is compiled. Both of these changes are essential to properly deploying an assembly to the GAC.

Here is what you need to do to compile the assembly:

  1. Open a command window by selecting Start All Programs Accessories Command Prompt.

  2. In the command window, navigate to \Program Files\Microsoft Visual Studio .NET 2003\SDK\v1.1\bin .

  3. In the command-line window, create a key file by executing the following line:

     sn.exe -k c:\workflow.snk 
  4. In Visual Studio .NET, open the AssemblyInfo.cs file.

  5. In the AssemblyInfo.cs file, scroll to the bottom of the file and add a reference to the key file by editing the AssemblyKeyFile entry to read as follows:

     [assembly: AssemblyKeyFile("c:\workflow.snk")] 
  6. Locate and modify the AssemblyVersion attribute to remove the wild cards and create a static version number as shown in the following code:

     [assembly: AssemblyVersion("1.0.0.0")] 
  7. Save and close the AssemblyInfo.cs file.

  8. Compile your assembly by selecting Build Build Workflow.

  9. Once the assembly is compiled, drag it from your project directory into the folder c:\windows\assembly to add it to the GAC.

Connecting the Libraries

Your workflow engine is designed to react to approval events in the Submit and Review libraries. Therefore, you must connect your assembly to both of these libraries. Additionally, you must enable document approval on all three libraries to complete the process.

To connect the event handler, take these steps:

  1. Log in to SPSPortal as the local administrator.

  2. Open Windows Explorer and navigate to C:\Windows\Assembly .

  3. Locate the Workflow assembly, right-click it, and select Properties from the pop-up menu.

  4. Note the Version , Culture , and PublicKeyToken information for the assembly.

  5. Log in to SPS as a member of the Administrator site group.

  6. Navigate to the Submit library you created earlier.

  7. Click the Modify Settings and Columns link under the Actions list.

  8. On the Customize page, select General Settings Change Advanced Settings.

  9. In the Assembly Name box, type the full strong name of the assembly. An example is shown here:

     WorkFlow,Version=1.0.0.0,Culture=Neutral, PublicKeyToken=5959aab8a976a104 
  10. In the Class Name box, type the fully qualified class name as shown here:

     WorkFlow.Engine 
  11. In the Properties box, type Submit .

  12. Click OK.

  13. On the Customize page, select General Settings Change General Settings.

  14. On the Document Library Settings page, select to require content approval for submitted items.

  15. Click OK.

  16. Navigate to the Review library you created earlier.

  17. Click the Modify Settings and Columns link under the Actions list.

  18. On the Customize page, select General Settings Change Advanced Settings.

  19. In the Assembly Name box, type the full strong name of the assembly. Here is an example:

     WorkFlow,Version=1.0.0.0,Culture=Neutral, PublicKeyToken=5959aab8a976a104 
  20. In the Class Name box, type the fully qualified class name as shown here:

     WorkFlow.Engine 
  21. In the Properties box, type Review .

  22. Click OK.

  23. On the Customize page, select General Settings Change General Settings.

  24. On the Document Library Settings page, select to require content approval for submitted items.

  25. Click OK.

  26. Navigate to the Approve library you created earlier.

  27. Click the Modify Settings and Columns link under the Actions list.

  28. On the Customize page, select General Settings Change General settings.

  29. On the Document Library Settings page, select to require content approval for submitted items.

  30. Click OK.

  31. Restart IIS to make your changes take effect.

If you have successfully created the solution, you should now be able to create a new document in the Submit library and approve it. Once you have approved the document, it should automatically move to the Review library. Once approved in the Review library, the document should automatically move to the Approve library.

Debugging the Solution

This project is moderately difficult, and chances are that you will not get it all correct the first time through. Therefore, you will likely have to debug the solution. Because the event handler is created as a class library, you can use standard debugging techniques to set breakpoints and walk through the code.

To debug the project, follow these steps:

  1. In Visual Studio, change the solution configuration to Debug .

  2. Rebuild the project by selecting Build Rebuild WorkFlow.

  3. Open Windows Explorer and navigate to C:\Windows\Assembly .

  4. Locate the WorkFlow assembly, right-click it, and select Delete from the pop-up menu.

  5. Drag the debug version of your assembly into the GAC.

  6. Restart IIS to unload the old version of the assembly from memory.

  7. Open the SPS home page in Internet Explorer.

  8. In Visual Studio, set breakpoints in your project code at the desired locations.

  9. Select Debug Processes.

  10. In the Processes dialog, select w3wp.exe from the list of Available Processes.

    Note

    The w3wp.exe process will not be visible until you open a portal web page in the browser. You should also be sure that the "Show processes in all sessions" box is checked on the Processes dialog.

  11. Click Attach.

  12. In the Attach to Process dialog, check the Common Language Runtime box.

  13. Click OK.

  14. Return to Internet Explorer and navigate to the Submit library. When you approve a document, your code should break in Visual Studio.




Microsoft SharePoint[c] Building Office 2003 Solutions
Microsoft SharePoint[c] Building Office 2003 Solutions
ISBN: 1590593383
EAN: N/A
Year: 2006
Pages: 92

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net