Creating SharePoint State Machine Workflow
State machine workflow is the powerful feature of SharePoint, which can be easily done using Visual Studio.
click here to read my previous tutorial for Creating a SharePoint Sequential Visual Studio Workflow (2 or n Level)
click here to read my previous tutorial on Creating a SharePoint Sequential Visual Studio Workflow (1 Level)
Let me explain how to create a state machine workflow with a example scenario.
Scenario:
Let's consider a scenario in college.
1.Open Visual studio (Run as administrator).
Select State Machine Workflow under SharePoint 2010 template. Enter the project name
2. Enter your site address and select farm solution and click next
3. Select List workflow and click next
4. Select the list , in our case Shared Documents.
5. A workflow can be started (triggered) in 3 ways:
a) Manually
b) When item is created
c) When item is updated
Select 'when an item created' and click finish
6. Now you can see the screen as below with your workflow design and toolbox at left side.
7. Use the toolbox and drag and drop 2 State Activities to your workflow design, so your final design will look as below.
8. Select the Workflow1InitialState and press F4 to open its properties. Rename this to InitialState as shown below
9. Similarly rename the other 2 stateActivities to stateApproval and stateComplete.
10. Right click on InitialState and select Set as Initial State
11. Right click stateComplete and select Set as Completed State
12. Double click on EventDrivenActivity1 in Initial state. Below screen would appear.
13. Drag and drop SetState Activity below onWorkflowActivated1
14. Select setStateActivity1 press F4, in the properties panel set stateApproval as TargetStateName
15. Click on Workflow1 to go back to the main design window.
16. Now your design would look like this
17. Right click on stateApproval, select Add StateInitialization
18. Below screen would appear,
19. Drag and drop Create Task from the toolbox
20. Select CreateTask1, press F4, in the properties window type Correlation token as task token and OwnerActivityName as stateApproval.
21. Click TaskId, click on the small bubble that appears at the end or double click on small yellow box. Below screen would appear and select "Bind to a new member" and hit "Create Field". click OK
22. Repeat the above process for TaskProperties.
23 . Now right click on stateApproval and select Add EventDriven
24. Now below the eventdriveActivity drag and drop OnTaskChanged, 2 IfElse (one inside another), and 3 SetState activities and make your design look like below.
25. select setStateActivity2 , press F4, and Choose the TargetStateName as stetComplete.
26. Repeat the above process for setStateActivity3 and setStateActivity4 by giving TargetStateName as stateApproval. Now the design will look like below.
27. select OntaskChanged1 and press F4, in the properties panel, double click on the small bubble appearing at the end of textbox for AfterProperties and choose Bind to a new member, select create field.
28. repeat above step for BeforeProperties as well.
29. select correlation token as task token, Click the bubble near Taskd and select Bind to existing member, select CreateTask1_TaskId1, click OK.
30. Now we are done with the design part and go back to main design window, your design should look like this.
31. In the InitialState, double click on EventDrivenActivity1 and now double click on onWorkflowActivated1:
33. Now go back to main design and double click on eventDrivenActivity2 and now double click on onTaskChanged1, enter the below code.
36. Repeat above procedure for IfElseBranchActivity3 and select codition as isApprovalSequenceComplete
37. Now we are done with the code, build the solution, and then deploy
38. Go to Shared Documents and upload some document
39. Now you can see your workflow showing in a new column with status as InProgress Since we have selected workflow to begin "when an item created"
40. Click on InProgress and it will open the WorkFlow properties. Edit the created task as shown.
41. Enter 100 for %Complete field and Save
42. As you can see, the task has been created for the next approver.
43. Edit it as we have done previously, make the %complete to 100 and save.
Now go back to the list. As you can see the workflow is Completed.
You can check this for our scenario where,
click here to read my previous tutorial for Creating a SharePoint Sequential Visual Studio Workflow (2 or n Level)
click here to read my previous tutorial on Creating a SharePoint Sequential Visual Studio Workflow (1 Level)
Let me explain how to create a state machine workflow with a example scenario.
Scenario:
Let's consider a scenario in college.
- When a student requests for some document with the Administration office, first it goes to an officer, when he approves, it goes to higher officer for approval.
- When first officer approves, it has to go to next officer and when the 2nd officer approves, the workflow is complete.
- When first officer rejects, it has to go back to student for re-submission.
- When first officer approves, and second officer rejects, it has to go back to the first officer for re-approval.
1.Open Visual studio (Run as administrator).
Select State Machine Workflow under SharePoint 2010 template. Enter the project name
2. Enter your site address and select farm solution and click next
3. Select List workflow and click next
4. Select the list , in our case Shared Documents.
5. A workflow can be started (triggered) in 3 ways:
a) Manually
b) When item is created
c) When item is updated
Select 'when an item created' and click finish
6. Now you can see the screen as below with your workflow design and toolbox at left side.
7. Use the toolbox and drag and drop 2 State Activities to your workflow design, so your final design will look as below.
8. Select the Workflow1InitialState and press F4 to open its properties. Rename this to InitialState as shown below
9. Similarly rename the other 2 stateActivities to stateApproval and stateComplete.
10. Right click on InitialState and select Set as Initial State
11. Right click stateComplete and select Set as Completed State
12. Double click on EventDrivenActivity1 in Initial state. Below screen would appear.
13. Drag and drop SetState Activity below onWorkflowActivated1
14. Select setStateActivity1 press F4, in the properties panel set stateApproval as TargetStateName
15. Click on Workflow1 to go back to the main design window.
16. Now your design would look like this
17. Right click on stateApproval, select Add StateInitialization
18. Below screen would appear,
19. Drag and drop Create Task from the toolbox
20. Select CreateTask1, press F4, in the properties window type Correlation token as task token and OwnerActivityName as stateApproval.
21. Click TaskId, click on the small bubble that appears at the end or double click on small yellow box. Below screen would appear and select "Bind to a new member" and hit "Create Field". click OK
22. Repeat the above process for TaskProperties.
23 . Now right click on stateApproval and select Add EventDriven
24. Now below the eventdriveActivity drag and drop OnTaskChanged, 2 IfElse (one inside another), and 3 SetState activities and make your design look like below.
25. select setStateActivity2 , press F4, and Choose the TargetStateName as stetComplete.
26. Repeat the above process for setStateActivity3 and setStateActivity4 by giving TargetStateName as stateApproval. Now the design will look like below.
27. select OntaskChanged1 and press F4, in the properties panel, double click on the small bubble appearing at the end of textbox for AfterProperties and choose Bind to a new member, select create field.
28. repeat above step for BeforeProperties as well.
29. select correlation token as task token, Click the bubble near Taskd and select Bind to existing member, select CreateTask1_TaskId1, click OK.
30. Now we are done with the design part and go back to main design window, your design should look like this.
31. In the InitialState, double click on EventDrivenActivity1 and now double click on onWorkflowActivated1:
List<string> approverList = new List<string>();add these 2 lines above the method
int currentLevel;
private void onWorkflowActivated1_Invoked(object sender, ExternalDataEventArgs e)
{
//you can read approvers from sharepoint list as well and save to approverList
approverList.Add(@"domain\user1");
approverList.Add(@"domain\user2");
currentLevel = 1;
}
List<string> approverList = new List<string>();32. Now go back to main design window, double click on stateInitializationActivity1 under stateApproval and now double click on createTask1. and enter below code.
int currentLevel;
private void createTask1_MethodInvoking(object sender, EventArgs e)
{
createTask1_TaskId1 = Guid.NewGuid();
if (currentLevel == 0)
{
string user = workflowProperties.Item["Author"].ToString();
if (user.Contains("#"))
{
user = user.Substring(user.IndexOf("#"));
}
SPUser user1 = workflowProperties.Web.EnsureUser(user);
createTask1_TaskProperties1.AssignedTo = user1.LoginName;
}
else
{
SPUser user = workflowProperties.Web.EnsureUser(approverList[currentLevel - 1]);
createTask1_TaskProperties1.AssignedTo = user.LoginName;
}
createTask1_TaskProperties1.Title = "please Approve";
}
33. Now go back to main design and double click on eventDrivenActivity2 and now double click on onTaskChanged1, enter the below code.
private void onTaskChanged1_Invoked(object sender, ExternalDataEventArgs e)34. Now copy below 2 methods
{
onTaskChanged1_AfterProperties1 = onTaskChanged1.AfterProperties;
onTaskChanged1_BeforeProperties1 = onTaskChanged1.BeforeProperties;
}
private void isApproved(object sender, ConditionalEventArgs e)e.Result = false;
{
if (onTaskChanged1_AfterProperties1.PercentComplete == 1.0)
{
currentLevel++;
e.Result = true;
}
else
{
if (currentLevel == 1)
{
//assign to requestor
currentLevel = 0;
}
else
if (currentLevel > 1)
{
currentLevel--;
e.Result = false;
}
}
}
private void isApprovalSequenceComplete(object sender, ConditionalEventArgs e)35. Now select IfElseBranchActivity1, press F4, in the properties panel, choose CodeCondition for Condition, and select isApproved method for condition.
{
if (currentLevel > approverList.Count)
{
//Approval complete
e.Result = true;
}
else
{
//goto to next approver
e.Result = false;
}
}
36. Repeat above procedure for IfElseBranchActivity3 and select codition as isApprovalSequenceComplete
37. Now we are done with the code, build the solution, and then deploy
38. Go to Shared Documents and upload some document
39. Now you can see your workflow showing in a new column with status as InProgress Since we have selected workflow to begin "when an item created"
40. Click on InProgress and it will open the WorkFlow properties. Edit the created task as shown.
41. Enter 100 for %Complete field and Save
42. As you can see, the task has been created for the next approver.
43. Edit it as we have done previously, make the %complete to 100 and save.
Now go back to the list. As you can see the workflow is Completed.
You can check this for our scenario where,
- If 1st person approves, goes to 2nd person, 2nd person approves, workflow complete
- 1st person rejects, task goes to document requestor
- 2nd person rejects task assigns to 1st person
namespace StateMWF.Workflow1e.Result = false;
{
public sealed partial class Workflow1 : StateMachineWorkflowActivity
{
public Workflow1()
{
InitializeComponent();
}
public SPWorkflowActivationProperties workflowProperties = new SPWorkflowActivationProperties();
public Guid createTask1_TaskId1 = default(System.Guid);
public SPWorkflowTaskProperties createTask1_TaskProperties1 = new Microsoft.SharePoint.Workflow.SPWorkflowTaskProperties();
public SPWorkflowTaskProperties onTaskChanged1_AfterProperties1 = new Microsoft.SharePoint.Workflow.SPWorkflowTaskProperties();
public SPWorkflowTaskProperties onTaskChanged1_BeforeProperties1 = new Microsoft.SharePoint.Workflow.SPWorkflowTaskProperties();
List<string> approverList = new List<string>();
int currentLevel;
private void onWorkflowActivated1_Invoked(object sender, ExternalDataEventArgs e)
{
//you can read approvers from sharepoint list as well and save to approverList
approverList.Add(@"domain\user");
approverList.Add(@"domain\user");
currentLevel = 1;
}
private void createTask1_MethodInvoking(object sender, EventArgs e)
{
createTask1_TaskId1 = Guid.NewGuid();
if (currentLevel == 0)
{
string user = workflowProperties.Item["Author"].ToString();
if (user.Contains("#"))
{
user = user.Substring(user.IndexOf("#"));
}
SPUser user1 = workflowProperties.Web.EnsureUser(user);
createTask1_TaskProperties1.AssignedTo = user1.LoginName;
}
else
{
SPUser user = workflowProperties.Web.EnsureUser(approverList[currentLevel - 1]);
createTask1_TaskProperties1.AssignedTo = user.LoginName;
}
createTask1_TaskProperties1.Title = "please Approve";
}
private void onTaskChanged1_Invoked(object sender, ExternalDataEventArgs e)
{
onTaskChanged1_AfterProperties1 = onTaskChanged1.AfterProperties;
onTaskChanged1_BeforeProperties1 = onTaskChanged1.BeforeProperties;
}
private void isApproved(object sender, ConditionalEventArgs e)
{
if (onTaskChanged1_AfterProperties1.PercentComplete == 1.0)
{
currentLevel++;
e.Result = true;
}
else
{
if (currentLevel == 1)
{
//assign to requestor
currentLevel = 0;
}Explanation:
else
if (currentLevel > 1)
{
currentLevel--;
e.Result = false;
}
}
}
private void isApprovalSequenceComplete(object sender, ConditionalEventArgs e)
{
if (currentLevel > approverList.Count)
{
//Approval complete
e.Result = true;
}
else
{
//goto to next approver
e.Result = false;
}
}
}
}
- When an item in Shared Document is created, the workflow is triggered.
- Initially when workflow is activated, we are getting data for list of approvers. Here you can modify the code to get the approvers from sharepoint list as well.
- Task is created for the first approver.
- onTaskChanged will assign the task after properties and before properties to global variables.
- Then using IfElse condition we will check if the currect task is approved, by checking the percent complete. If complete we will move to the next approval level and create task for next approver. If not we will go back to previous level. (if task is rejected by 1st approver, it goes to the requestor, i.e. creates task for requestor).
- It repeats until the approval sequence is complete.
Comments
Post a Comment