locked
Loading Xoml Workflows in re hosted Designer WF 4.0 RRS feed

  • Question

  • Hi,

    I am having problem loading an xoml workflow into the new WorkflowDesigner in WF 4.0.
    Here is the code I am using as suggested in this post.

    Assembly a = Assembly.LoadFrom(Environment.CurrentDirectory + @"\FilesCopierWorkflow.dll");
    string name = Environment.CurrentDirectory + @"\FilesCopierWorkflow.xoml";

     IList<Assembly> assem = new List<Assembly>();
               
    assem.Add(a);
               
    XmlReader xmlREader = XmlReader.Create(name);
               
    XamlSchemaContext context = new XamlSchemaContext();
               
               
    XamlReader reader = new XamlXmlReader(xmlREader, context);
               
    WorkflowElement workflow = XamlServices.Load(name) as WorkflowElement;
               
    wd.Load(workflow);

    I get an error at the second last line, saying:
    "Cannot create unknown Type '{clr-namespace:FilesCopierWorkflow;Assembly=FilesCopierWorkflow, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null}FilesCopierWorkflow'. Line:1 Offset:40".
    Thursday, August 13, 2009 8:36 AM

Answers

  • Well, if you can deploy to a machine using 4.0, then you can have the team working on the designer build the designer and any 4.0 activities.  If they get some 3.5 activities from some other team, have a separate Visual Studio project just for wrappers and create a 4.0 declarative activity that just wraps the WF3 activity with the interop activity.  Then you can even hook up a custom WF4 activity designer for it.  The developers using .NET 3.5 can keep using that, and those using WF4 can use that with no problem.  A little more work to get the two connected, but may be worth it if you don't want your teams moving to .NET 4 just yet. 

    Matt

    Check out Pluralsight On Demand! http://www.pluralsight.com/main/olt/
    Monday, August 17, 2009 2:23 PM

All replies

  • you didn't provide the list of assemblies in the constructor to the XamlSchemaContext - did you mean to? 

    matt
    Check out Pluralsight On Demand! http://www.pluralsight.com/main/olt/
    Thursday, August 13, 2009 3:27 PM
  • Sorry i posted the wrong code. I was having so much trouble, I tried everything. Even when i pass the assemblies, it does not work.
    When i debug it, I can see referenced assemblies count = 1 in the 'context' variable, but it still does not work.
    Here is the updated code.

    Assembly a = Assembly.LoadFrom(Environment.CurrentDirectory + @"\FilesCopierWorkflow.dll");
    string name = Environment.CurrentDirectory + @"\FilesCopierWorkflow.xoml";

     IList<Assembly> assem = new List<Assembly>();
               
    assem.Add(a);
               
    XmlReader xmlREader = XmlReader.Create(name);
               
    XamlSchemaContext context = new XamlSchemaContext(assem);
               
               
    XamlReader reader = new XamlXmlReader(xmlREader, context);
               
    WorkflowElement workflow = XamlServices.Load(name) as WorkflowElement;
               
    wd.Load(workflow);

    I get an error at the second last line, saying:
    "Cannot create unknown Type '{clr-namespace:FilesCopierWorkflow;Assembly=FilesCopierWorkflow, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null}FilesCopierWorkflow'. Line:1 Offset:40".
    Thursday, August 13, 2009 3:30 PM
  • here you are passing the Load method of XamlServices the path to the file and not the XamlReader you created with the context information.  So it is bypassing all of the context information you built up with the assemblies.  Change that last line to:

    WorkflowElement workflow = XamlServices.Load(reader) as WorkflowElement;
    



    HTH,
    Matt


    Check out Pluralsight On Demand! http://www.pluralsight.com/main/olt/
    Thursday, August 13, 2009 3:36 PM
  • Did that as well, still does not work :(
    Thursday, August 13, 2009 3:45 PM
  • Ok, just to step back and make sure I understand this - it looks like your exception is complaining that it can't find the Type FilesCopierWorkflow, is that the name of your workflow?  If so, I have a couple of follow up questions / points.  First, your type name and namespace name are the same which often causes all sorts of wonkiness in .NET so I'd change the type name to be different and try this again.  Second, if you are trying to load the XAML from the XML, you don't really need it compiled into a type in your assembly, so you can change the build action on that file to NONE to keep it from being compiled. 

    I'd guess that the namespace/typename conflict may be the culprit here though. 

    Matt


    Check out Pluralsight On Demand! http://www.pluralsight.com/main/olt/
    Thursday, August 13, 2009 4:03 PM
  • Here is my latest code, I am trying with a new dll now.
    // create the workflow designer
    WorkflowDesigner wd = new WorkflowDesigner();

    Assembly a = Assembly.LoadFrom(Environment.CurrentDirectory + @"\SampleNoCodeWorkflow.dll");
    string name = Environment.CurrentDirectory + @"\SampleNoCode.xoml";

    IList<Assembly> assem = new List<Assembly>();

    assem.Add(a);

    XmlReader xmlREader = XmlReader.Create(name);

    XamlSchemaContext context = new XamlSchemaContext(assem);

    XamlReader reader = new XamlXmlReader(xmlREader, context);

    object workflow = XamlServices.Load(reader);

    wd.Load(workflow);


    My XOML
    <?xml version="1.0" encoding="utf-8"?><ns0:NoCodeWorkflowBaseActivity x:Name="samplenocode" Number="0" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/workflow" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:ns0="clr-namespace:SampleNoCodeWorkflow;Assembly=SampleNoCodeWorkflow, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">
        <IfElseActivity x:Name="ifElseActivity1">
            <IfElseBranchActivity x:Name="ifElseBranchActivity1">
                <IfElseBranchActivity.Condition>
                    <CodeCondition Condition="{ActivityBind samplenocode,Path=IsPositive}" />
                </IfElseBranchActivity.Condition>
                <ns0:WriteMessageActivity Message="The number is positive" x:Name="writeMessageActivity1" />
            </IfElseBranchActivity>
            <IfElseBranchActivity x:Name="ifElseBranchActivity2">
                <ns0:WriteMessageActivity Message="The number is negative" x:Name="writeMessageActivity2" />
            </IfElseBranchActivity>
        </IfElseActivity>
    </ns0:NoCodeWorkflowBaseActivity>

    PS: This time the namespace and type name is not the same.
    Thursday, August 13, 2009 5:07 PM

  • - try to add an AssemblyResolve handler into your AppDomain.

     
    System.AppDomain.CurrentDomain.AssemblyResolve += delegate(object sender, ResolveEventArgs args)
     {
          string assemblyName = args.Name.Split(',')[0].Trim();
          
          // create filename
      
          // check if the file exist
    
          // if exist:  return System.Reflection.Assembly.LoadFrom(filename);
          
          // else: return null;
     };



    Thanks

    Roman


    Roman Kiss, MVP Connected System Developer
    Thursday, August 13, 2009 6:10 PM
  • If I do something similar, but with one change, it works.  Remove the "Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" from the clr-namespace declaration and see if that helps.  It seems to cause the Xaml stack to get confused for your assembly that isn't in the GAC. 

    So you would just have:
    xmlns:ns0="clr-namespace:SampleNoCodeWorkflow;Assembly=SampleNoCodeWorkflow


    Matt

    Check out Pluralsight On Demand! http://www.pluralsight.com/main/olt/
    Thursday, August 13, 2009 8:19 PM
  • So that would be equivalent to setting "Specific Version" to false in the visual studio. However, it would be a problem in my case, because I am trying to create the XOML from the designer too. Any Suggestions?
    Friday, August 14, 2009 9:10 AM
  • @Matt:
    So that would be equivalent to setting "Specific Version" to false in the visual studio. However, it would be a problem in my case, because I am trying to create the XOML from the designer too. Any Suggestions?
    @Roman:
    I added the code but it does not get called :(
    Friday, August 14, 2009 9:28 AM
  • What is the base class for your NoCodeWorkflowBaseActivity activity? 
    Check out Pluralsight On Demand! http://www.pluralsight.com/main/olt/
    Friday, August 14, 2009 2:31 PM
  • It derives from System.Workflow.Activities.SequentialWorkflowActivity.
    Is there a way for me to send you the dll?
    Friday, August 14, 2009 5:15 PM
  • Are you sure? this is a 3.5 class



    Thanks


    Roman


    Roman Kiss, MVP Connected System Developer
    Friday, August 14, 2009 5:18 PM
  • Yes I am sure. Actually the dll is 3.5. I am able to use it with my old designer, even when i upgrade it to target network 4.0.
    Actually the use case I have requires me to use a 3.5 dll with a 4.0 re hosted designer.
    Friday, August 14, 2009 5:21 PM
  • In the WF4 Model (beta1), the Custom activity must be derived from the WorkflowElement


    Roman Kiss, MVP Connected System Developer
    Friday, August 14, 2009 5:36 PM
  • Is that a reason for the type to show up as not referenced? Shouldn't there be another error?
    Why does this work when I convert my old re hosted designer to target framework 4.0?
    Does this mean that a WF 4.0 re hosted designer would not be able to use .NET 3.5 dlls, in the context that I am using them?
    Friday, August 14, 2009 5:39 PM
  • Correct, your old designer still works built against .NET 4, because it knows how to deal with the old Activity base class.  the new designer only works against workflow element, as Roman said, so it won't directly work with activities in the System.Workflow.* namespaces. you have to use the Interop activity to wrap activities built against that old model, but you don't get any custom designer support for those activities. 

    Matt

    Check out Pluralsight On Demand! http://www.pluralsight.com/main/olt/
    Friday, August 14, 2009 5:44 PM
  • xoml => WF3 Model
    xaml => WF4 Model

    you can not have the following:
    xoml => WF4 Model


    Roman Kiss, MVP Connected System Developer
    Friday, August 14, 2009 5:46 PM
  • So, If I want to use WF designer application that is 4.0 that allows my user to create workflows using custom activities that are .NET 3.5 what do I do?
    Friday, August 14, 2009 5:49 PM
  • If they are using your 3.5 activities you have a couple of choices:

    1) have the user add an interop activity to their workflow and point to the workflow type (probably not the best)
    2) create a WF 4 activity (XAML/Declarative activity) and have it wrap the interop activity pointed to your old activity (gives you control over the wrapper and simpler for your users). 
    3) Rewrite your activity as a WF 4 activity - this may not be as hard as you imagine. 

    Matt

    Check out Pluralsight On Demand! http://www.pluralsight.com/main/olt/
    Friday, August 14, 2009 5:52 PM

  • the answer is this
    Roman Kiss, MVP Connected System Developer
    Friday, August 14, 2009 5:52 PM
  • Well Matt, I think I am in a bit of trouble here.
    Let me tell you the whole scenario and perhaps then you would be able to give me a yes of no answer.
    I plan to have a workflow designed using the new 4.0 Re Hosted Designer.
    And I Plan to run this workflow from an application that is constrained to be .NET 3.5, that is why i want to keep the custom activities in a .NET 3.5 dll.
    Is this scenario even possible?
    Friday, August 14, 2009 5:55 PM
  • If you are constrained by the client having only 3.5 on machine, then you can't, by definition, use .NET 4 on the box.  Is it that you won't have .NET 3.5 on the box, or the application developers are only going to be using Visual Studio 2008 and .NET 3.5? 

    Matt


    Check out Pluralsight On Demand! http://www.pluralsight.com/main/olt/
    Friday, August 14, 2009 6:03 PM
  • Well, its far more complicated than that, the components used in the use case are all developed by different teams. Some teams have moved to .NET 4.0 some have not.
    Friday, August 14, 2009 8:03 PM
  • Well, if you can deploy to a machine using 4.0, then you can have the team working on the designer build the designer and any 4.0 activities.  If they get some 3.5 activities from some other team, have a separate Visual Studio project just for wrappers and create a 4.0 declarative activity that just wraps the WF3 activity with the interop activity.  Then you can even hook up a custom WF4 activity designer for it.  The developers using .NET 3.5 can keep using that, and those using WF4 can use that with no problem.  A little more work to get the two connected, but may be worth it if you don't want your teams moving to .NET 4 just yet. 

    Matt

    Check out Pluralsight On Demand! http://www.pluralsight.com/main/olt/
    Monday, August 17, 2009 2:23 PM