locked
Literal Error when trying to pass custom types to my workflow RRS feed

  • Question

  • Guys,

    I have a simple procedural workflow that determines how to assign a real estate lead to an agent. It takes three input parameters, and 1 output parameter. The only unusual aspect of this activity, (if you call it unusual), is that I'm passing in complex objects rather than types. I've created a lead and agent objects like this:

        public class LeadProxy
        {
            public int PK { get; set; }
            public int Amount { get; set; }

       }

        public class AgentProxy
        {
            public int PK { get; set; }
            public int Senority { get; set; }
            public int CurrentLeadCount { get; set; }
        }

    My current input arguments are:

      <x:Members>
        <x:Property Name="Agents" Type="InArgument(scg:List(local:AgentProxy))" />
        <x:Property Name="Lead" Type="InArgument(local:LeadProxy)" />
        <x:Property Name="AssignToAgent" Type="OutArgument(local:AgentProxy)" />
        <x:Property Name="UseSenority" Type="InArgument(x:Boolean)" />
      </x:Members>

    The odd thing is, I get the following error for each of my custom types:

    {"The following errors were encountered while processing the workflow tree:\r\n'Literal<LeadProxy>': Literal only supports value types and the immutable type System.String.  The type BOWLWFAssigner.LeadProxy cannot be used as a literal."}

    I've even tried creating a simple activity with a console write that doesn't even use the arguments, yet I get the above error at runtime regardless. What am I missing here guys? Am I passing in the types incorrectly, or possibly creating my custom classes inproperly?

    Thanks a bunch,

    Ryan

     

     

    Tuesday, October 12, 2010 3:19 PM

Answers

  • When you assign the leadProxy to the Lead argument (is it a property or an argument?) of the workflow instance, you are binding that input argument to a literal expression. If Lead is an argument, you can pass it in as part of the dictionary of input arguments. If you want to directly assign it like you are doing, you can wrap it up in a Lambda expression, like (well similar, I don't have your exact code but it should be similar to the code below) this:

    // workFlow.Lead = leadProxy;
    // Something similar to this
    workFlow.Lead = new LambdaValue<LeadProxy>(context=>new LeadProxy());
    

    Here is a wiki post that has a little more detail about this:

    http://social.technet.microsoft.com/wiki/contents/articles/using-reference-type-arguments-in-a-workflow-wf.aspx

    Steve Danielson [Microsoft]
    This posting is provided "AS IS" with no warranties, and confers no rights.
    Use of included script samples are subject to the terms specified at http://www.microsoft.com/info/cpyright.htm

     

    • Marked as answer by RynBev Wednesday, October 13, 2010 4:04 PM
    Wednesday, October 13, 2010 1:09 AM

All replies

  • In your activity, are you newing up instances of your custom types and assigning them to any arguments inside your activity? Or newing up any instances of these in any expressions within your activity?

    The following assign activity will give the same error that you mention. This is a validation error because creating a literal expression with a reference type does not create a new instance of the reference type for each instance of the workflow.

    new Assign
    {
      To = new OutArgument<List<string>>(items),
      Value = new InArgument<List<string>>(new List<string>())
    },
    

    To resolve this, replace the literal expression with one that creates and returns a new instance of the reference type. In this example, it can be fixed by using a visualBasic expression to new up the List<string>

    new Assign
    {
      To = new OutArgument<List<string>>(items),
      Value = new InArgument<List<string>>(new VisualBasicValue<List<string>>("New List(Of String)"))
    },
    

    You can check out the following topic for more details on this (scroll down to about 2/3 of the way down the topic)

    http://msdn.microsoft.com/en-us/library/ee358749.aspx

    If this doesn't work for you can you post the code of your simple activity with the Console.WriteLine and we can see if we can spot the issue.

    Thanks,

     Steve Danielson [Microsoft]
    This posting is provided "AS IS" with no warranties, and confers no rights.
    Use of included script samples are subject to the terms specified at http://www.microsoft.com/info/cpyright.htm

     

    Tuesday, October 12, 2010 6:51 PM
  • Hmm, I'm not newing anything really. I'm simply passing in already populated complex objects, and working on them. Here is my little sample code:

    The wpf client code:

            private void button1_Click(object sender, RoutedEventArgs e)
            {
                try
                {
                    TestWorkFlow workFlow = new TestWorkFlow();
                   
                    LeadProxy leadProxy = RetrieveLeadProxy();
                    workFlow.Lead = leadProxy;
                   
                    IDictionary<string, object> result = WorkflowInvoker.Invoke(workFlow);

                }
                catch (Exception ex)
                {
                    System.Diagnostics.Debug.WriteLine(ex.Message);

                }
            }

            private LeadProxy RetrieveLeadProxy()
            {
                LeadProxy leadProxy = new LeadProxy();
                leadProxy.Amount = 500000;
                leadProxy.PK = 5;
                return leadProxy;

            }

    The xaml of the activity:

    <Activity mc:Ignorable="sap" x:Class="BOWLWFAssigner.TestWorkFlow" xmlns="http://schemas.microsoft.com/netfx/2009/xaml/activities" xmlns:local="clr-namespace:BOWLWFAssigner" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mv="clr-namespace:Microsoft.VisualBasic;assembly=System" xmlns:mva="clr-namespace:Microsoft.VisualBasic.Activities;assembly=System.Activities" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:s1="clr-namespace:System;assembly=System" xmlns:s2="clr-namespace:System;assembly=System.Xml" xmlns:s3="clr-namespace:System;assembly=System.Core" xmlns:s4="clr-namespace:System;assembly=System.ServiceModel" xmlns:sa="clr-namespace:System.Activities;assembly=System.Activities" xmlns:sad="clr-namespace:System.Activities.Debugger;assembly=System.Activities" xmlns:sap="http://schemas.microsoft.com/netfx/2009/xaml/activities/presentation" xmlns:scg="clr-namespace:System.Collections.Generic;assembly=mscorlib" xmlns:scg1="clr-namespace:System.Collections.Generic;assembly=System" xmlns:scg2="clr-namespace:System.Collections.Generic;assembly=System.ServiceModel" xmlns:scg3="clr-namespace:System.Collections.Generic;assembly=System.Core" xmlns:sd="clr-namespace:System.Data;assembly=System.Data" xmlns:sl="clr-namespace:System.Linq;assembly=System.Core" xmlns:st="clr-namespace:System.Text;assembly=mscorlib" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
      <x:Members>
        <x:Property Name="Lead" Type="InArgument(local:LeadProxy)" />
      </x:Members>
      <sap:VirtualizedContainerService.HintSize>273,240</sap:VirtualizedContainerService.HintSize>
      <mva:VisualBasic.Settings>Assembly references and imported namespaces for internal implementation</mva:VisualBasic.Settings>
      <Sequence sad:XamlDebuggerXmlReader.FileName="C:\Projects\QOCLight\BOWL\BOWLWFAssigner\BOWLWFAssigner\TestWorkFlow.xaml" sap:VirtualizedContainerService.HintSize="233,200">
        <sap:WorkflowViewStateService.ViewState>
          <scg:Dictionary x:TypeArguments="x:String, x:Object">
            <x:Boolean x:Key="IsExpanded">True</x:Boolean>
          </scg:Dictionary>
        </sap:WorkflowViewStateService.ViewState>
        <WriteLine sap:VirtualizedContainerService.HintSize="211,61" Text="[String.Format(&quot;{0}&quot;, Lead.Amount)]" />
      </Sequence>
    </Activity>

     

    Thanks a bunch for the reply and any further help Steve.

    Ryan

     

    Tuesday, October 12, 2010 8:27 PM
  • When you assign the leadProxy to the Lead argument (is it a property or an argument?) of the workflow instance, you are binding that input argument to a literal expression. If Lead is an argument, you can pass it in as part of the dictionary of input arguments. If you want to directly assign it like you are doing, you can wrap it up in a Lambda expression, like (well similar, I don't have your exact code but it should be similar to the code below) this:

    // workFlow.Lead = leadProxy;
    // Something similar to this
    workFlow.Lead = new LambdaValue<LeadProxy>(context=>new LeadProxy());
    

    Here is a wiki post that has a little more detail about this:

    http://social.technet.microsoft.com/wiki/contents/articles/using-reference-type-arguments-in-a-workflow-wf.aspx

    Steve Danielson [Microsoft]
    This posting is provided "AS IS" with no warranties, and confers no rights.
    Use of included script samples are subject to the terms specified at http://www.microsoft.com/info/cpyright.htm

     

    • Marked as answer by RynBev Wednesday, October 13, 2010 4:04 PM
    Wednesday, October 13, 2010 1:09 AM
  • That worked like a champ steve, thanks a bunch. I just didn't consider the context of the reference objects.

    Thanks again,

    Ryan

    Wednesday, October 13, 2010 4:04 PM