Posts mit dem Label Correlation Token werden angezeigt. Alle Posts anzeigen
Posts mit dem Label Correlation Token werden angezeigt. Alle Posts anzeigen

02 November 2009

How to set a Correlation Token Property on a Custom Activity


I like to break up my sharepoint workflows into several custom activities, especially when there are many repetitive tasks involved. But I've always struggeld with one thing: when I needed to send an email from such an activity, I had to pass the correlation token of the onWorkflowActivated activity manually in the constructor of my workflow to my custom activity, which assigned it in turn to the SendEmail activity. As one doesn't get workflow validation using this approach, it makes for an easy to oversee failure if in a hurry. And additionally, the compiler produces a warning that the correlation token of you SendEmail Activity may be uninitialized.

After a little digging around with Reflector.NET, I finally found out that one can declare a Type Converter of the type CorrelationTokenTypeConverter on the correlation token property of the custom activity. As this type converter is an internal class, the type property of the attribute has to be set by its full qualified class name.

[DefaultValue((string)null),
TypeConverter("System.Workflow.Activities.CorrelationTokenTypeConverter, System.Workflow.Activities, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35")]
public CorrelationToken WorkflowCorrelationToken
{
get { return (CorrelationToken)base.GetValue(WorkflowCorrelationTokenProperty); }
set
{
base.SetValue(WorkflowCorrelationTokenProperty, value);
sendEmail.CorrelationToken = value;
}
}

(The code snippets above assumes assumes that a “CorrelationToken” dependency property is registered for the custom activity class.)

Now that we can set the correlation token using the designer, we are also able to use a validator class on the custom activity, so the compiler will throw an error if the correlation token is not set. Doing this is quite easy, just add the ActivityValidator attriubte to the activity class definition and implement an activityvalidator class which validates that the correlation token property of the custom activity is set.

[ActivityValidator(typeof(MyActivityValidator))]
public partial class MyActivity : SequenceActivity
{

private class MyActivityValidator : ActivityValidator
{
/// <summary>
/// Verifies that the MyActivity activity is valid.
/// </summary>
/// <param name="manager">The <see cref="T:System.Workflow.ComponentModel.Compiler.ValidationManager"/> associated with validation.</param>
/// <param name="obj">The <see cref="T:System.Workflow.ComponentModel.Activity"/> to be validated.</param>
/// <returns>
/// A <see cref="T:System.Workflow.ComponentModel.Compiler.ValidationErrorCollection"/> object containing any errors or warnings that occurred during validation.
/// </returns>
public override ValidationErrorCollection Validate(ValidationManager manager, object obj)
{
ValidationErrorCollection errors = new ValidationErrorCollection();
MyActivity activity = obj as MyActivity;
if (activity == null)
{
throw new InvalidOperationException();
}
if (activity.Parent != null)
{
if (activity.WorkflowCorrelationToken == null)
{
Hashtable hashtable = activity.GetValue(WorkflowMarkupSerializer.ClrNamespacesProperty) as Hashtable;
if ((hashtable == null) (hashtable["WorkflowCorrelationToken"] == null))
{
errors.Add(ValidationError.GetNotSetValidationError("WorkflowCorrelationToken"));
}
}
}
errors.AddRange(base.Validate(manager, obj));
return errors;
}
}
// SNIP: MyActivity code...
}