sharepointsharepoint-designersharepoint-workflow

SharePoint designer errors out with missing required parameters for custom activity


I am making a custom Activity for SharePoint 2010. When I drop the activity in the SharePoint Designer and supply values for the parameters, I get a mysterious validation error that simply says:

This action has required parameters that are missing.

Here's the source code for the action:

using System;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Workflow.ComponentModel;
using System.Workflow.Activities;
using System.Workflow.ComponentModel.Compiler;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WorkflowActions;

namespace SharePoint.Activities.IO
{
    public partial class CopyFile : SequenceActivity
    {
        public CopyFile()
        {
            InitializeComponent();
        }

        public static DependencyProperty SourceDirectoryProperty = DependencyProperty.Register("SourceDirectory", typeof(string), typeof(CopyFile));
        public static DependencyProperty TargetDirectoryProperty = DependencyProperty.Register("TargetDirectory", typeof(string), typeof(CopyFile));
        public static DependencyProperty ActionResultProperty = DependencyProperty.Register("ActionResult", typeof(string), typeof(CopyFile));
        public static DependencyProperty CreateDateProperty = DependencyProperty.Register("CreateDate", typeof(DateTime), typeof(CopyFile));
        public static DependencyProperty CompletionDateProperty = DependencyProperty.Register("CompletionDate", typeof(DateTime), typeof(CopyFile));
        public static DependencyProperty WFContextProperty = DependencyProperty.Register("WFContext", typeof(WorkflowContext), typeof(CopyFile));

        [Description("Path the files to perform the operation on")]
        [Browsable(true)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        [ValidationOption(ValidationOption.Required)]
        public string SourceDirectory
        {
            get { return (string)GetValue(SourceDirectoryProperty); }
            set { SetValue(SourceDirectoryProperty, value); }
        }
        [Description("Path the files are copied to")]
        [Browsable(true)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        [ValidationOption(ValidationOption.Required)]
        public string TargetDirectory
        {
            get { return (string)GetValue(TargetDirectoryProperty); }
            set { SetValue(TargetDirectoryProperty, value); }
        }
        [Description("Once the the operation completes, this is set to OK or the exception information")]
        [Browsable(true)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        [ValidationOption(ValidationOption.Optional)]
        public string ActionResult
        {
            get { return (string)GetValue(ActionResultProperty); }
            set { SetValue(ActionResultProperty, value); }
        }
        [Description("When the request was created")]
        [Browsable(true)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        [ValidationOption(ValidationOption.Optional)]
        public DateTime CreateDate
        {
            get { return (DateTime)GetValue(CreateDateProperty); }
            set { SetValue(CreateDateProperty, value); }
        }
        [Description("When execution stoped")]
        [Browsable(true)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        [ValidationOption(ValidationOption.Optional)]
        public DateTime CompletionDate
        {
            get { return (DateTime)GetValue(CompletionDateProperty); }
            set { SetValue(CompletionDateProperty, value); }
        }

        [Browsable(true)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        public WorkflowContext WFContext
        {
            get { return (WorkflowContext)GetValue(WFContextProperty); }
            set { SetValue(WFContextProperty, value); }
        }

        //protected override void Initialize(IServiceProvider provider)
        //{
        //    TraceIn();
        //    base.Initialize(provider);
        //    TraceOut();
        //}

        protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
        {
            TraceIn();

            Debugger.Break();

            var isSiteAdmin = false;
            CreateDate = DateTime.Now;
            try
            {
                // Needs administrative credentials to get the web application properties ino
                SPSecurity.RunWithElevatedPrivileges(delegate
                {
                    using (var site = new SPSite(WFContext.Site.ID))
                    {
                        using (var web = site.AllWebs[WFContext.Web.ID])
                        {
                            isSiteAdmin = web.CurrentUser.IsSiteAdmin;
                            if (string.IsNullOrEmpty(SourceDirectory)) throw new ArgumentException("SourceDirectory cannot be null or empty");
                            if (!Directory.Exists(SourceDirectory)) throw new DirectoryNotFoundException("Could not find source directory: \"" + SourceDirectory + "\"");

                            if (string.IsNullOrEmpty(TargetDirectory)) throw new ArgumentException("TargetDirectory cannot be null or empty");
                            if (!Directory.Exists(TargetDirectory)) throw new DirectoryNotFoundException("Could not find target directory: \"" + TargetDirectory + "\"");
                            // Do something 
                            Debug.WriteLine(string.Format("Doing something amazing from {0} and moving it to {1}", SourceDirectory, TargetDirectory));
                        }
                    }
                });

                ActionResult = "OK";
            }
            catch (Exception ex)
            {
                ActionResult = isSiteAdmin ? ex.ToString() : ex.Message;
            }
            CompletionDate = DateTime.Now;

            var result = base.Execute(executionContext);

            TraceOut();

            return result;
        }

        private static void TraceIn()
        {
            Trace("Entering");
        }

        private static void TraceOut()
        {
            Trace("Exiting");
        }

        private static void Trace(string direction)
        {
            Debugger.Launch();
            var stackTrace = new StackTrace(2, false);
            var frame = stackTrace.GetFrame(0);
            Debug.WriteLine(direction + " " + frame.GetMethod().Name);
        }
    }
}

Here is the .action file.

<?xml version="1.0" encoding="utf-8" ?>
<WorkflowInfo>
    <Actions
        Sequential="then"
        Parallel="and">
        <Action
            Name="IO Activities"
            ClassName="SharePoint.Activities.IO.CopyFile"
            Assembly="SharePoint.Activities.IO, Version=1.0.0.0, Culture=neutral, PublicKeyToken=abfb622251cf6982"
            Category="Custom Actions"
            AppliesTo="all">
            <RuleDesigner
                Sentence="CopyFiles from %1 to %2">
                <FieldBind
                    Field="SourceDirectory"
                    DesignerType="String"
                    Id="1"/>
                <FieldBind
                    Field="TargetDirectory"
                    DesignerType="String"
                    Id="2"/>
            </RuleDesigner>
            <Parameters>
                <Parameter
                    Name="SourceDirectory"
                    Type="System.String, mscorlib"
                    Direction="In"
                    DesignerType="StringBuilder"
                    Description="Directory where the source files are to move" />
                <Parameter
                    Name="TargetDirectory"
                    Type="System.String, mscorlib"
                    Direction="In"
                    DesignerType="StringBuilder"
                    Description="Directory where the files will be placed" />
                <Parameter
                    Name="ActionResult"
                    Type="System.String, mscorlib"
                    Direction="Optional" 
                    DesignerType="Hide" />
                <Parameter
                    Name="CreateDate"
                    Type="System.DateTime, mscorlib"
                    Direction="Optional" 
                    DesignerType="Hide" />
                <Parameter
                    Name="CompletionDate"
                    Type="System.DateTime, mscorlib"
                    Direction="Optional" 
                    DesignerType="Hide" />

                <Parameter 
                    Name="WFContext" 
                    Type="Microsoft.SharePoint.WorkflowActions.WorkflowContext, Microsoft.SharePoint.WorkflowActions" 
                    DesignerType="Hide" />
            </Parameters>
        </Action>
    </Actions>
</WorkflowInfo>

Here's a link to my post on social.msdn.microsoft.com.

Update

I've even tried removing all of the parameters by commenting out the parameters in the .actions files, the properties in the class, and commenting out the DependencyProperties. I still get the same error.


Solution

  • Ultimately, it looks like the issue (after I tore the project down and started over) was an incorrect designer type and a missing .

    Here is the old code:

    <FieldBind Field="Result" DesignerType="TextArea" Text="Action result message; returns OK on success" Id="3" />
    

    Here is the correct code:

    <FieldBind Field="Result" DesignerType="ParameterNames" Text="Action result message; returns OK on success" Id="3" />
    

    Once that change was made, everything seems to be working.