locked
Validate ActivityBuilder in rehosted designer RRS feed

Answers

  • Another approach you can try is load the workflow as a DynamicActivity in order to run validation. This should more closely mimic the runtime validation behavior.

    designer.Flush();
    Activity a = ActivityXamlServices.Load(new StringReader(designer.Text)); //would return a DynamicActivity for your case
    ActivityValidationServices.Validate(a);


    or a more efficient approach might be building the DynamicActivity yourself, in code.

    Tim

    • Marked as answer by MatthewVB Wednesday, February 10, 2010 8:36 PM
    • Edited by Tim Lovell-Smith Wednesday, February 10, 2010 9:31 PM +new StringReader()
    Wednesday, February 10, 2010 3:59 PM

All replies

  • I guess you use ActivityBuild to load the workflowdesigner.
    like
    Activitybuilder builder = new Activitybuilder();
    builder.Implementation = new Sequence();
    so what you can do is to use following code to get the real activity
    ModelItem sequence = Designer.Context.Services.GetService<ModelService>().Root.Properties["Implementation"].ComputedValue;

    then convert this sequence to Activity.
    Now you can use ActivityValidationServices.Validate  to validate the activity.

    • Proposed as answer by Ye Yu - MSFT Wednesday, February 10, 2010 4:54 AM
    Wednesday, February 10, 2010 4:54 AM
  • Hi,

    I tried this but the problem is that the acitivity builder that I pass into the designer has some arguments defined on it.  I then get validation error messages where the sequence tries to use those arguments because it doesn't know about them.

    Is there no way I can validate the activity builder completely?

    Cheers

    Matt
    Wednesday, February 10, 2010 5:12 AM
  • the only way is to convert Arguments to Variables manually.
    if you don't want to manually convert Arguments to Variables, you can call ValidationService.ValidateWorkflow()

    it will handle the activitybuilder with Arguments, and convert arguments to Variables in ValidateWorkflow().
    however, if you call ValidationService.ValidateWorkflow()
     you need to publish following service

    //create the instance
    using System.Activities.Presentation.Validation;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Linq;

    namespace VariableFinderShell
    {
        class DebugValidationErrorService : IValidationErrorService
        {
            public void ShowValidationErrors(IList<ValidationErrorInfo> errors)
            {
                errors.ToList().ForEach(vei => Debug.WriteLine(string.Format("Error: {0} ", vei.Message)));
            }
        }
    }

    //publish the service
    wd.Context.Services.Publish<IValidationErrorService>(new DebugValidationErrorService());

    • Proposed as answer by Ye Yu - MSFT Wednesday, February 10, 2010 6:46 AM
    Wednesday, February 10, 2010 6:46 AM
  • add some code for converting arguments to variable.

    since ActivityValidationServices.Validate just handle the Activity, we need to find some activity which can contain the ActivityBuilder.Implementation and variables converted from arguments.

    so here we use Sequence.

    now begin to convert the whole activity builder to sequence.
     
    //create a sequence
    Sequence holder = new Sequence();
    //get the activitybuilder modelitem
                ModelItem root = designer.Context.Services.GetService<ModelService>().Root;
                VisualBasic.SetSettings(holder, VisualBasic.GetSettings(root));
        //now begin to convert arguments to variables
                List<Variable> variables = new List<Variable>();
               
                foreach (DynamicActivityProperty prop in builder.Properties)
                {
                    if (property != null)
                    {
    //convert the property(argument is created by DynamicActivityProperty) to variable
                        Variable autoVariable = GetVariableFromProperty(prop);
                        if (autoVariable != null)
                        {
                            variables.Add(autoVariable);
                        }
                    }
                }

    //add the variables in list variables to holder(declared above)

    //add implementation to sequence
    holder.Activities.Add(builder.Implementation);

    //now call ActivityValidationServices.Validate to validate sequence
    Wednesday, February 10, 2010 7:32 AM
  • Another approach you can try is load the workflow as a DynamicActivity in order to run validation. This should more closely mimic the runtime validation behavior.

    designer.Flush();
    Activity a = ActivityXamlServices.Load(new StringReader(designer.Text)); //would return a DynamicActivity for your case
    ActivityValidationServices.Validate(a);


    or a more efficient approach might be building the DynamicActivity yourself, in code.

    Tim

    • Marked as answer by MatthewVB Wednesday, February 10, 2010 8:36 PM
    • Edited by Tim Lovell-Smith Wednesday, February 10, 2010 9:31 PM +new StringReader()
    Wednesday, February 10, 2010 3:59 PM
  • Thanks for the help. I went with Tim's suggestion and it is working great.

    Just need to be aware that the middle line of the code sample should be

    Activity a = ActivityXamlServices.Load(new StringReader(designer.Text));


    Otherwise it thinks that you are providing a path to a file location and gets a little upset :-)
    Wednesday, February 10, 2010 8:38 PM
  • Thanks for the correction, I'll edit the post so it doesn't trip anyone else up. :-)
    Tim

    Wednesday, February 10, 2010 9:30 PM