Zobrazují se příspěvky se štítkemWorkflow. Zobrazit všechny příspěvky
Zobrazují se příspěvky se štítkemWorkflow. Zobrazit všechny příspěvky

pondělí 8. února 2010

Owner activity of CorrelationToken

In approval workflow it is quite common to give the approver possibility to ask for additional information. When I develop sequential workflow I am modeling it the way this picture shows.



In other words first task "managementApproveTask" is creted and when the manager ask for additional information then "addManagementInfoTask" is created. Whene the person adds the information the big WHILE returns and creates new task for the manager to approve the document - this gives the manager the possibility to ask for additional information as many times as he wants and ask different people and so on...

Well then the question is which activity set as the owner of CorrelationToken of the CreateTask activity and also of OnTaskChanged activity - because they are always the same.

If you set the "ManagementApproveActivity" or any other activity PARENT TO THE WHILE loop as the owner of the CorrelationToken, you will get the following error:

System.InvalidOperationException: Correlation value on declaration "TOKEN NAME" is already initialized.
at System.Workflow.Runtime.CorrelationToken.Initialize(Activity activity, ICollection`1 propertyValues)
at System.Workflow.Activities.CorrelationService.InvalidateCorrelationToken(Activity activity, Type interfaceType, String methodName, Object[] messageArgs)...


The problem is as the exception says that the Correlation Token is already initialized. To resolve this you have to set as Owner activity of the CorrelationToken any activity inside the WHILE loop. Then any time the while loop is entered the activities inside are recreated, that means that there will be also new CorrelationToken created for each new task.

neděle 7. února 2010

TargetInvocationException when using CreateTaskWithContentType activity

If you want to use ASP.NET pages with your workflow in SharePoint you need to follow these steps:

1) Create the web page.
2) Create ContentType containing your WebPage.
3) Add the ContentType to the ContentTypes gallery in SharePoint site.
4) Allow ContentTypes on the SharePoint task list, where the task of your workflow will be stored.
5) Add the ContentType to the list where your workflow tasks will be stored.
6) Finally you can use CreteTaskWithContentType activity and specify the GUID of the ContentType which you have created.

For more details of how to develop SharePoint workflows with ASP.NET pages refer to this blog.

If you do not add the ContentType to the gallery or if you forgot to add it to the SharePoint list, you can receive the following exception:

System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.NullReferenceException: Object reference not set to an instance of an object. at Microsoft.SharePoint.Workflow.SPWinOETaskService.CreateTaskWithContentTypeInternal(Guid taskId, SPWorkflowTaskProperties properties, Boolean useDefaultContentType, SPContentTypeId ctid, HybridDictionary specialPermissions) at Microsoft.SharePoint.Workflow.SPWinOETaskService.CreateTaskWithContentType(Guid taskId, SPWorkflowTaskProperties properties, String taskContentTypeId, HybridDictionary specialPermissions)


The best way to add the ContentType to the ContentTypes library is to create Feature containing all your ContentTypes and install and activate the feature on SharePoint. On details pleas follow the part 4 of the above mention blog how-to.

Programatically allow and add ContentTypes on SharePoint list


Here is a method which I am using to programatically alow and add ContentTypes on SharePoint task list, which accepts String representing the GUID of the ContentType and SPList representing the task list.

I've found the code in this method again in part 4 of this great series.


public static void AllowContentType(SPList lTaskList, String lTaskContentType)
{

//make shure that the content types are enabled on the task list
if (lTaskList.ContentTypesEnabled != true)
{
//if not allow them. This can be done also in the SharePoint GUI
lTaskList.ContentTypesEnabled = true;
}

// convert given String representing the GUID to SPContentTypeId
SPContentTypeId myContentTypeID = new SPContentTypeId(lTaskContentType);

// Find the content type in SharePoint site content types library
SPContentType myContentType = lTaskList.ParentWeb.Site.RootWeb.ContentTypes[myContentTypeID];

//if the content type was found
if (myContentType != null)
{

// Check if the content type was already added to the SharePoint task list
bool contenTypeExists = false;
foreach (SPContentType contentType in lTaskList.ContentTypes)
{
if (contentType.Name == myContentType.Name)
{
// This content type was already added
contenTypeExists = true;
break;
}
}

// If I didn't find this content type in the list I will have to add it
if (contenTypeExists != true)
{
lTaskList.ContentTypes.Add(myContentType);
}
}
else
{
throw new Exception("Content type is not register with the web site");
}
}

pondělí 28. prosince 2009

SharePoint - AlterTask method problem

During the development of a simple sequential workflow in SharePoint I came across "OnTaskChanged not firing" issue.

I had this problem already couple times, so I tried to check the usual causes of this problem:

1) Usually in sequential workflow you hava a CreateTask or CreateTaskWithContentType activity, which is followed by OnTaskChanged activity in the loop.

Correlation token, TaskId, TaskProperties of these two activities have to match - so your task can be "wired" together with OnTaskChanged activity.


2)The last time I was having this issue was that one of my assemblies in GAC was not up to date. In that time I found this in my LOG:


System.TypeLoadException: Could not load type 'BaseClassesLibrary.Library.MailLibrary' from assembly 'BaseClassesLibrary, Version=1.0.0.0, Culture=neutral, PublicKeyToken=cfc77ab1c27103f4'. at RequestWorkflowASP.ITApproveActivity.ITApproveTask_MethodInvoking(Object sender, ExternalDataEventArgs e) at System.Workflow.ComponentModel.Activity.RaiseGenericEvent[T](DependencyProperty dependencyEvent, Object sender, T e) at System.Workflow.Activities.HandleExternalEventActivity.RaiseEvent(Object[] args) at System.Workflow.Activities.HandleExternalEventActivity.System.Workflow.ComponentModel.IActivityEventListener.OnEvent(Object sender, QueueEventArgs e) at System.Workflow.ComponentModel.ActivityExecutorDelegateInfo`1.ActivityExec...


So I was searching for something similar(Missing any assemblies)….no result.

So finally after hours of digging I found the solution. The task is displayed as ASP page. In the code-behind of this page I change the SharePoint task item (because taks is a simple SPListItem) by calling the SPWorkflowTask.AlterTask(...) method.


//Create the hashtable which will be populated to ExtendedProperties of task AfterProperties
Hashtable taskHash = new Hashtable();

//Fill the values of the HashTable
taskHash["hwDescription"] = txbHWDescription.Text;
taskHash["swDescription"] = txbSWDescription.Text;
taskHash["částka"] = txbPrice.Text;

//Call the AlterTask method to populate AfterProperties
SPWorkflowTask.AlterTask(_spListItem, taskHash, true);


The problem was in the line: taskHash["částka"] where I have used some Czech alphabet characters to specify the property. SharePoint couldn't alter the task correctly, so my OnTaskChanged event didn't fire.

I try to avoid using the Czech alphabet in my code and this was just "temporary" solution, which somehow stayed there. If I would keep some coding best practices and never left temporary solutions, I could have saved myself couple hours of time :).

Strange is the fact, that I didn't receive any exception in the SharePoint LOG.
Just the OnTaskChanged was not firing.