Friday 22 February 2013

CreateTaskWithContentType (04)

Let's Make a Workflow 

1.) Open up that workflow you created in the very first post, and let's have a look

Right after the onWorkFlowActivated activity add the following:
  • LogToHistoryListActivity
  • CreateTaskWithContentType
  • create a WhileActivity
    • Inside the while activity add a onTaskChanged activity
  • right outside the while activity add a complete task activity
  • finally create another Log To History Activity
2.) Now don't panic you should have four red Exclamation marks on your workflow, this is normal; all you've done was drag and drop some shapes onto a canvas. This isn't Visio and you're not a Business Analyst, you're actually going to have to do some real work and not draw shapes with a crayon calling it a career.


Lets get started, click on the createTaskWithContentType1 activity and hit the F4 key to bring up the properties.

Create a correlationToken, type in the value TaskToken and pick Workflow1 as the OwnerActivity Name. That should get rid of your Exclamation mark, but we're not done we're going to have to do some binding.

First bind the ContentTypeId to a custom field, how you ask?

click on the property to give it focus, this should bring up three little dots on the left of the value field, click that

this will bring up the "Bind 'Content TypeId' to an Activity's Property" dialogue box, select the "Bind to a new member" tab, Change the name to something meaningful, switch the type to Create Field or don't, it doesn't really matter.

with that complete hit OK, you have two more properties to bind, follow the same procedure as above

  • For the TaskId property, I set the field name to Task_Id
  • For the TaskProperties property, I set the field name to Task_Properties

Now for the MethodInvoking property just type in createTask and hit enter, that should bring you to the bound function createTask, here you're going to set your task properties, the value for your task id field.
the three task properties you're going to set are:
  • Assigned to - who does the task
  • Title - what the task is called
  • TaskType - which task form to use (it'll become clearer later on)

so here's what you're function is suppose to look like when complete as well as the fields you created

public String Task_ContentTypeId = default(System.String);
public Guid Task_Id = default(System.Guid);
public SPWorkflowTaskProperties Task_Properties = new Microsoft.SharePoint.Workflow.SPWorkflowTaskProperties();
private void CreateTask(object sender, EventArgs e)
    Task_Id = Guid.NewGuid();
    Task_Properties.AssignedTo = @"domain\SPtest3";
    Task_Properties.Title = "Magical Task";
    Task_Properties.TaskType = 0;

and here's what the properties of your activity should be

Next we're going to tackle the onTaskChanged activity

Set your CorrelationToken property to the same one as for createTaskWithContentType1, TaskToken.

When it comes to binding your TaskId property, do NOT create a new field, bind to the existing one from before.

Next you have to bind the BeforeProperties property to a new field, I call it Task_beforeProperties, it's good practice to bind the AfterProperties as well, but not necessary for an example this simplistic.

With your on task changed activity wrapped up lets focus on that while loop.

Click on your while loop, hit F4 to see the properties, change the Condition property to Code Condition and call the Condition CheckText and hit enter.

once you hit enter you should see the function in the code behind, now this function has a ConditionalEventArgs that can be set to a boolean value representing if it should loop or not.
  • True = loop
  • False = exit loop
As the name of our function suggests we're going to ensure that our task user provides us with a value and we're going to accomplish this by checking our kiwiMango Field. the code to do this is as follows.

private void CheckText(object sender, ConditionalEventArgs e)
    e.Result = Task_BeforeProperties.ExtendedProperties["KiwiMango"] == null ? true : 

Or if you prefer

private void CheckText(object sender, ConditionalEventArgs e)
    if (Task_BeforeProperties.ExtendedProperties["KiwiMango"] == null)
        e.Result = true;       
    else if (Task_BeforeProperties.ExtendedProperties["KiwiMango"].ToString() == string.Empty)
        e.Result = true;
        e.Result = false;

We're going to set up our complete task.

  • Again set the correlation Token to TaskToken
  • Bind the task Id like you did before
  • Now you could set your TaskOutcome property to static text such as Task complete, but let's do something more interesting. instead in the methodInvoking property type in completeTask and hit enter; this should bring you back to your code behind an here we'll set the task outcome to include our value from our form.

private void completeTask(object sender, EventArgs e)
    ((CompleteTask)sender).TaskOutcome = 
        string.Format("KiwiMango = {0}", task_BeforeProperties.ExtendedProperties["KiwiMango"].ToString());

now what you've done is cast the sender argument to a CompleteTask activity and then set the taskOutcome property in code to include the parameter passed back from the user form.

Log activities

To wrap this post up lets set up our two log activities, so that we can know what on earth is going on, the first one lets set it to let us know that:
  • the work flow has started
  • we're about to create a task
the second one:
  • the task is complete
  • workflow is complete
to do this, right click on the first one and select Generate handlers, this will bring you to the code behind where, we'll add our code. As with the complete task activity we're going to cast our sender as a LogToHistoryActivity object and set our history description and history outcome properties
the code for the first log is

private void logToHistoryListActivity1_MethodInvoking(object sender, EventArgs e)
    ((LogToHistoryListActivity)sender).HistoryDescription = "workflow initiated";
    ((LogToHistoryListActivity)sender).HistoryOutcome = "about to create task";

and for the second log is

private void logToHistoryListActivity2_MethodInvoking(object sender, EventArgs e)
    ((LogToHistoryListActivity)sender).HistoryDescription = "Task Complete";
    ((LogToHistoryListActivity)sender).HistoryOutcome = "about to Complete workflow";

and there you go, if you deploy and attach your workflow it's going to fail, but that's cause we're not done yet; it's now time for the real pain in the ass part, making the damn thing work. but that's in the next post.