Step by Step Tutorial. Creating Workflows for Windows Sharepoint Services and MOSS2007 (part 14/20). Easy ASPX Association Forms-(by using my small generic framework)
By Serge Luca
There are many reasons to associate workflows with aspx forms in Sharepoint instead of Infopath forms (IP):
aspx forms are more robust
more flexible than IP forms
can be debugged
work with Windows Sharepoint Service which is free.
The black sides of aspx forms in Sharepoint workflows are :
they are not integrated in Office 2007 rich client
they are more complex to develop than IP forms
the main sample in the Sharepoint sdk doesn’t work (see my previous post where I show how to fix it).
The first kind of form you need to create is the association form; I’ve encapsulated and abstracted the complexity of association forms in a small framework; this framework will be upgraded in the future to handle other kind of forms and will be available in CodePlex.
There will be 3 parts in this post :
In parts 1 and 2, I will show you how to quickly create an association form by using my framework.
In part 3, I will detail how association forms work under the cover.
Part 1. Creating a basic association form
Creating the workflow
Let’s create a very basic Sharepoint workflow by using the Sharepoint sequential workflow template and name the project DemoAssocFormWorkflow (Fig 1).
[Fig 1. Basic workflow project]
Untick the “Automatically Associate…” option in the third form form” (Fig 2).
[Fig 2. Don’t automatically associate the workflow]
Add a reference to the SergeLuca.WorkflowTools.WorkflowAssociation.dll (Fig 3) (this dll can be grabbed from the startup files).
[Fig 3.Add a reference to my small framework]
Set the Copy Local property of this assembly to true.
Create the classic TEMPLATE-LAYOUTS folder with you custom sub folder: DemoAssocFormWorkflow
[Fig 4.Create the “12 like” folders for the Layout page (association form)]
Add a FEATURES folder with a DemoAssocFormWorkflow custom folder under the TEMPLATE folder and move the feature.xml and workflow.xml over there :
[Fig 5.Add the Features folder and the features files]
Add the file WFAssoc.aspx into this folder; you can get it from my startup code; this page is very primitive WorkflowAssociation page; I’ve kept it simple on purpose. This page just displays an Ok button.
- Add the WFAssoc.cs page(from the startup code) to your project root; this file is the association page code behind (fig 6).
[ Fig 6.Generic Page class]
- GenericWFAssocPage is an abstract class; implements its methods :
[Fig 7.Implementing the Abstract class]
- Remove the generated throw new NotImplementedException() statements and return null in the FromAssocDataToPage member :
[Fig 8.Basic generic page implementation]
[Update 11/24 : in the next release the Function FromAssocDataToPage will only have an AssocFormData parameter]
- Compile the project and use Reflector to retrieve the assembly strong name.Modify the assembly directive of WFAssoc.aspx (Fig 9).
Fig 9.Modify the @Assembly directive to point to your code behind assembly
- You still need to specify somewhere that you want WFAssoc.aspx to become your association form: do it in workflow.xml :
[Fig 10. Defining the association forms in the feature manifest]
That’s it! Now it’s just a matter of installing the workflow, the page layout and the Framework assembly.
Installing the workflow
Add the install.bat file into the project root; double check the file to make sure everything is ok (in the Install.bat file we assume the application pool name is SharepointPool), change the url (which here is http://blog.redwood.com) ; add a Post-Build event to the project :
[Fig 10.Install.bat file in the Post-build event]
Rebuild the project and check the output windows for any error (if you don’t find this window, you can display it from the View menu).
The final code can be found here.
Association forms testing
Normally the install.bat file activates the feature for the whole site collection.
We are going to test the 3 kinds of workflow associations
Association type 1 : workflow associated with a list
Go to a list or document library and add the association.
Since an association form has been provided, the next button will show up :
[Fig 11. Standard workflow association form]
- Click on the Next button and our form will show up :
[Fig 12. Custom workflow association form]
- Click ok and the the association will be created.
- You can modify the association by asking to select new Task and History list (Fig 13):
[Fig 13.Modification of a workflow association]
- Modify the association and View the site content : you will see your new Task and History lists (Fig 13):
[Fig 14.New Task and History lists ]
Association type 2 : workflow associated with a content type
- Create 2 item content types : Vehicule and Car which inherits from Vehicule
- Associate these content types to a generic list named Parking.
- Associate the DemoAssocFormWorkflow with the Vehicule content type (in the Site Content Type gallery)
[Fig 15.Associate a workflow with a content type]
- Add a new Vehicule in the parking list
- Start the workflow in the list item ECB (menu linked to the list item).
- If you add a new Car (not just a Vehicule), the workflow association will aslo show up.
Association type 3 : Workflow associated with a content type in a specific list
- In the parking list, create a new association with the Vehicule content type (Fig 16).
[Fig 16.Workflow associated with a content type in a specific list]
This association will be available on every Vehicule in this list, but not on the cars !
Part 2. Extending the association form
We want to be able to create the following association form (Fig 17) :
[Fig 17.The final association form]
- Add the following control declaration in WFAssoc.aspx (get the code from snippet1.txt in the startup files).
<%@ Register TagPrefix="wssuc" TagName="InputFormSection" src="/_controltemplates/InputFormSection.ascx" %>
<%@ Register TagPrefix="wssuc" TagName="InputFormControl" src="/_controltemplates/InputFormControl.ascx" %>
<%@ Register Tagprefix="wssawc" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=184.108.40.206, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
- In WFAssoc.aspx, replace the existing code in “Placeholdermain” just above the hidden fields with code provided in snippet2.txt in the starter files (keep the hidden fields, remove everything else).
- Rebuild you workflow and test the association form to make sure it can show up.
- In WFAssoc.cs define the form fields as protected members (snippet3.txt).
- Define the fields namespace (Resolve) :
- We need to add a class that will allow data transfer between the association form and the workflow; Add the file AssocFormData to your project from the starter files, and examine the code.
- since AssocData is the data transfer class, replace the <object> generic with <AssocData>:
[Fig 18. specifying the AssocFormData class in the generic]
- by implementing FromAssocDataToPage(), you will transfer your association data from the workflow association to the association form. (snippet4.txt).
- by implementing FromPageToAssocData(), you will transfer your association data from the association form to the workflow association.(snippet5.txt).
- Now you can rebuild the project, your workflow will be deployed and you can test it on a list, on a content type and on a content type on a list.
Part 3.Inside Association Forms
- The concept is pretty simple: when you add a workflow association, the Sharepoint framework provides a first generic page: AddWrkfl.aspx (Fig 19).
[Fig 19.Generic workflow association page (AddWrkfl.aspx)]
- The query string parameters will depend on the association type.
Association on a Content type:
query string : ctype=<cont typeid>
[Fig 20.Query string generated by the association to a Content type]
Association on a List:
query string: List=<list id>
[Fig 21.Query string generated by the association to a list]
Association on a Content type in a List :
query string: ctype=<content typeid>&List=<list id>
- The association form must be a layout page (derived directly or indirectly from Microsoft.SharePoint.WebControls.LayoutsPageBase).
- This query string and others variables described below will be sent to your Association Form and your custom association page must handle them (my small WorkflowAssociationContext class will do that for you).
- The picture below illustrates most variables (in red) you association form will have to manage (for a content type).
[Fig 22.variables generated in the context of the association of a workflow with a content type]
[Fig 23. variables generated in the context of the association of a workflow with a list or with a content type in a specific list]
- If you click on the Next button, the association form specified in your feature manifest file (here workflow.xml, (fig 8) will show up .
- When you click on the Ok button, you will have to create the association by using one of the following methods of the SPWorkflowAssociation class :
public static SPWorkflowAssociation CreateListAssociation
public static SPWorkflowAssociation CreateSiteContentTypeAssociation
public static SPWorkflowAssociation CreateListContentTypeAssociation
The SPWorkflowTemplate is actually a wrapper around the workflow type.
- When you click on the Ok button of your custom association form, you need to make sure the http variables have been stored somewhere; it is mandatory to provide hidden fields that will keep a trace of all variables provided by the Sharepoint framework (AddWrkfl.aspx) between postbacks. That’s reason why I’ve added the hidden fields into the WFAssoc.aspx :
[Fig 24.Hidden field to keep workflow association variables between postbacks]
My WorkflowAssociation class hides all the details of getting/storing these variables values and creating/updating the corresponding Sharepoint objects.
That’s it! Congratulations! Don’t forget that I still have to fully test this code and that I will upgrade the framework to take the other kinds of forms into account.
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.