Expression Translation using Workflow Manager Tools 1.0

 

Updated: April 10, 2013

Workflows hosted in Workflow Manager 1.0 are fully declarative and therefore can only be authored using activities, expressions and variables from the trusted surface. (For more information about the Workflow Manager trusted surface, see Authoring Declarative Workflows for Workflow Manager 1.0.) Any expressions in the workflows are translated into expression activities before the workflow is uploaded to Workflow Manager. In order to provide a better authoring experience, Workflow Manager Tools 1.0 for Visual Studio 2012 includes an Expression Translation Build Task and an Expression Translation API. Developers can choose to use either the build task or the API to validate the expressions in a workflow during build-time. For instructions on installing Workflow Manager Tools, see Workflow Manager Tools 1.0 for Visual Studio 2012 installation.

To use the build task, add the following Import element to the csproj (or vbproj) file for your project.

<Import Project=
"C:\Program Files (x86)\MSBuild\Microsoft\Workflow Service\1.0\Microsoft.WorkflowServiceBuildExtensions.targets"/>
  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />

For an example project file that contains the previous Import element, see the ActivityLibrary1.csproj file from the Using Workflow Tools sample.

To explore the behavior of the build task, add an unsupported expression, for example a WriteLine activity with new Guid().ToString() as the Text argument and build the project. Note the errors that are displayed before and after importing the expression translation build task targets file.

To programmatically validate the expressions in workflow, the following helper method can be used.

public static string TranslateWorkflow(string originalWorkflow)
{
    string translatedWorkflowString = null;

    using (TextReader inputWorkflowReader = new StringReader(originalWorkflow))
    {
        using (XamlReader xamlReader = new XamlXmlReader(inputWorkflowReader))
        {
            try
            {
                TranslationResults result = ExpressionTranslator.Translate(xamlReader);
                if (result.Errors.Count == 0)
                {
                    translatedWorkflowString = CreateXamlString(result.Output);
                }
                else
                {
                    string errorMessage = string.Format(
                        "Error: Failed to translate workflow with {0} errors",
                         result.Errors.Count);
                    foreach (TranslationError error in result.Errors)
                    {
                        errorMessage += string.Format(
                            "\n Expression: {0}, Message: {1}",
                              error.ExpressionText, error.Message);
                    }

                    return errorMessage;
                }
            }
            catch (Exception e)
            {
                return "Error: " + e.Message;
            }
        }
    }

    return translatedWorkflowString;
}

static string CreateXamlString(XamlReader reader)
{
    StringBuilder stringBuilder = new StringBuilder();
    using (XmlWriter xmlWriter = XmlWriter.Create(stringBuilder, 
        new XmlWriterSettings { Indent = true, OmitXmlDeclaration = true }))
    {
        using (XamlXmlWriter writer = new XamlXmlWriter(xmlWriter, reader.SchemaContext))
        {
            XamlServices.Transform(reader, writer);
        }
    }
    return stringBuilder.ToString();
}

Community Additions

ADD
Show: