Answered by:
Validate ActivityBuilder in rehosted designer

Question
-
Hi,
I am using a rehosted designer and want to be able to validate that the workflow is valid so that I can prevent users from saving an invalid workflow. I am attempting to use the solution suggested at: http://social.msdn.microsoft.com/Forums/en-US/wfprerelease/thread/caf14927-bc4c-4c61-ac28-5551a11975b5/
However I am having problem as the ActivityValidationServices.Validate method only takes in an Activity and the root of my workflow is an ActivityBuilder. Does anyone have any suggestions on how I can validate this?
Cheers
MattWednesday, February 10, 2010 3:40 AM
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
MattWednesday, 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 sequenceWednesday, 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. :-)
TimWednesday, February 10, 2010 9:30 PM