Friday, May 8, 2009

TaskItemId on Workflows

When we create new task on a workflow, after its being created, if we access the TaskProperties.TaskItemId property, we receive -1 but not the real new TaskItemId corresponding to the new item ID recently created on the TaskList assigned to the workflow.

Unfortunately after the workflow finishes the createTask event, the TaskItemId remains on -1 value, and it never being set to the proper value.
Why this is happening? Really seems to be a WSS bug...

But there is a way to find this ID with a few lines of code.
The first idea should be to access the TaskList and get the last item Id and increase it on one unit, then we will get the next Item id.
But this is not the good way because the Item ID property on a TaskList library is auto-incremental. And what does this mind? This mind that if we have 5 items created with each ID assigned (1,2,...,5) if we delete the last 2 items (4 and 5), next time we create new item the ID assigned to this item will be 6 and not 4.

How can we know the proper NextItemID of the TaskList?
Well this simple code executes a query how returns the next available item ID on a List getting by parameter the SPSite object where the list belongs and the GUID of the list.

Therefore we can get the nextItemId that will be assigned to the new task and then set the TaskItemId property with this value.
Since this moment every time we access to this property everywhere on the workflow process, we will get the proper ItemID corresponding to the Task we have created.



private int GetNextAvailableIdFromList(SPSite site, Guid listId)
{
int NextAvailableId = -1;

if (site.WebApplication.ContentDatabases.Count > 0)
{
foreach (SPContentDatabase contentDB in site.WebApplication.ContentDatabases)
{
string DBConnString = contentDB.DatabaseConnectionString;
SqlConnection con = new SqlConnection(DBConnString);
try
{
con.Open();
SqlCommand com = con.CreateCommand();
com.CommandText = String.Format("select tp_NextAvailableId from AllLists where tp_ID = '{0}'", listId.ToString());
NextAvailableId = (int)com.ExecuteScalar();

if (NextAvailableId <> -1){
con.Close();
return NextAvailableId;
}
}
catch { }
finally
{
con.Close();
}
}
}

return NextAvailableId;
}


This is an example of how can we use this function.


TaskProperties.TaskItemId = GetNextAvailableIdFromList(workflowProperties.Site, WorkflowProperties.TaskListId);

1 comment:

  1. The createTask Activity works asyncronous so you cant access the TaskItemID before the task item is actually created.
    You should propably prefer to use OnTaskCreated activity instead and then access the TaskItemID on.

    it TaskitemID = OnTaskCreated_AfterProperties.TaskItemId;

    I don't think it is a good idea to access contentdatabase

    ReplyDelete