Search code examples
c#argumentsworkflow-foundation-4default-valueworkflow-activity

default value for required arguments of custom activities in Workflow Foundation


In writing Custom Activities for a re-hosted Workflow Designer, it gives me an error that there is a value required for the Required Argument if I don't have one, so I either use a null as seen below or "ALL". It does not accept null or "ALL" or anything else for a default argument. Please note that my required argument is of type string.

[RequiredArgument]
[DefaultValue(null)]
[Description(@"The status of the job to perform")]
public InArgument<string> JobStatus { get; set; }

[RequiredArgument]
[DefaultValue("All")]
[Description(@"The status of the job to perform")]
public InArgument<string> JobStatus { get; set; }

Error Message when Running the Workflow :

Workflow Console: Starting Workflow...

Could not start workflow.

Message: Failed to start workflow DynamicActivity.

Exception message: The following errors were encountered while processing the workflow tree: 'DynamicActivity': The private implementation of activity '1: DynamicActivity' has the following validation error: Value for a required activity argument 'JobStatus' was not supplied.

Stack trace: at System.Activities.Validation.ActivityValidationServices.ThrowIfViolationsExist(IList`1 validationErrors) at System.Activities.Hosting.WorkflowInstance.ValidateWorkflow(WorkflowInstanceExtensionManager extensionManager) at System.Activities.Hosting.WorkflowInstance.RegisterExtensionManager(WorkflowInstanceExtensionManager extensionManager) at System.Activities.WorkflowApplication.EnsureInitialized() at System.Activities.WorkflowApplication.Enqueue(InstanceOperation operation, Boolean push) at System.Activities.WorkflowApplication.WaitForTurn(InstanceOperation operation, TimeSpan timeout) at System.Activities.WorkflowApplication.InternalRun(TimeSpan timeout, Boolean isUserRun) at System.Activities.WorkflowApplication.Run()

Thanks for your help


Solution

  • Neither workflow runtime nor workflow designer will look into DefaultValueAttribute. Searching attributes requires reflection which might be costly on performance. Moreover that's not the purpose of the attribute.

    Anyway, you can either initialize the variable with a default value. On constructor, for example:

    public class MyCodeActivity : CodeActivity
    {
        public MyCodeActivity()
        {
            JobStatus = "All";
        }
    }
    

    or force a value through accessor. Something like this:

    private InArgument<string> text = "All";
    
    [RequiredArgument]
    public InArgument<string> Text
    {
        get { return text ?? "All"; }
        set { text = value; }
    }
    

    These are different approaches, use the one that fits into the behavior you want. In both cases the value can always be modified through XAML so a small check on runtime might be good:

    protected override void Execute(CodeActivityContext context)
    {
        string text = context.GetValue(this.Text);
        if (text == null) 
        {
            text = "All";
        }
    
        Console.WriteLine(text);
    }