akjha

Hi,

I am hosting a WWF designer inside an ASP.NET project to design and execue workflows totally from the hands of a user.

I have built lots of custom activities and they run fine alone when included in the workflow.

I have to keep some parameters in the workflow activity and then the custom activities will need to get those parameters from the workflow. The custom activities also need to get the parameters among them pass around.

I am building workflow execution task using xoml file which is convenient so that I pass this xoml to the runtime and it excutes it.

All these work inside a Windows application where you can pass parameters using the Properties window.

How can I do it in ASP.NET I don't want to modify the xoml just by parsing it and keeping the activity param using text modification.

I know the syntax to pass the parameters like Activity=Workflow1, Path=Password.

But how to get it modified in xoml.

Thanks

Achintya




Re: Windows Workflow Foundation Setting and passing parameters in XOML when Hosting WWF designer in ASP.NET

Jonathan Davlin

What's happening in VS:

You say "bind", and you select a binding. VS assigns a new ActivityBind for the property. When the Xoml serializer goes to work, it serializes the property like "{ActivityBind ActivityName,Path=PropertyName} " (note the brackets... but you can't set it manually in the property window in that format.)

What you need to do:


The same way the designer adds child activities, you need to add the ActivityBinds through code before handing off to the Xoml serializer. To see an example, creat an all cs workflow and check the code in intializecomponent. You need to have the same code for any properties you want automatically bound. In terms of how you implement that in the designer you are rehosting, you can pick whatever syntax you want because you will be parsing it to and from based on either a property's real value or an ActivityBind attached to that property.






Re: Windows Workflow Foundation Setting and passing parameters in XOML when Hosting WWF designer in ASP.NET

akjha

Jonathan,

Thanks for your answer.

How can I define the parameters in the workflow activity which is hosted in the designer

I know how to pass parameters when starting a workflow instance, but again the parameters should be defined in xoml.

How do I set the parameters in XOML

Achintya






Re: Windows Workflow Foundation Setting and passing parameters in XOML when Hosting WWF designer in ASP.NET

Jonathan Davlin

In your Xoml, set the baseclass like so
MyCustomizableWorkflow : MyWorkFlowBase
{
}

declare a class that can be referenced by the designer properties (it excludes new properties because it is a new type the way we do it by default)


MyWorkFlowBase: SequentialWorkflow
{
Static DependencyProperty MyPropertyProperty =.....

public string MyProperty
{
get{ return base.GetValue(MyPropertyProperty}






Re: Windows Workflow Foundation Setting and passing parameters in XOML when Hosting WWF designer in ASP.NET

Tom Lake - MSFT

You cannot define parameters within the xoml file, they must be declared in code. For how to do this in the rehosted designer take a look at the post at http://forums.microsoft.com/MSDN/ShowPost.aspx PostID=971933&SiteID=1.




Re: Windows Workflow Foundation Setting and passing parameters in XOML when Hosting WWF designer in ASP.NET

akjha

Hi Jon,

Thanks for your prompt replies.

I don't have any basic file for xoml.

I have based my code upon Jon Flanders AtlasDesigner at http://www.masteringbiztalk.com/atlasworkflowdesigner

I still don't get where should I add the properties

Achintya






Re: Windows Workflow Foundation Setting and passing parameters in XOML when Hosting WWF designer in ASP.NET

Jonathan Davlin

1. In a separate assembly, define a class like I said, just an empty CS workflow, no activities.

2. In Jon Flanders' example, he is using SequentialWorkflowActivity as his base class when he creates a new "template" like below

XomlExample = @"<SequentialWorkflowActivity x:Class=""HelloWorld.HelloWorldWorkflow"" x:Name=""HelloWorldWorkflow"" xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/workflow"" xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"">

<CodeActivity x:Name=""CodeActivity1"" ExecuteCode=""CodeActivity1_ExecuteCode""/>

<x:Code>

<![CDATA[

void CodeActivity1_ExecuteCode(object o,EventArgs e)

{

System.Console.WriteLine(""Hello World"");

}

]]>

</x:Code>

</SequentialWorkflowActivity>";

Just replace SequentialWorkflowActivity with your class you defined elsewhere. Also make sure you are qualifying the XClassProperty with a namespace, and not just the class name. There may be a few little tweaks elswhere to make sure you aren't referencing a different base class anywhere (like when generating the compile unit).


Now, if you want to get totally crazy: You can also use a trick so that, you can use simple Xoml to allow the users to declaratively alter the type's definition in the designer. Each time the designer flushes, the compiled code is updated, so the user's changes will be reflected. All that's involved is overriding the ActivityCodeGenerator attribute and supplying it an implementation less than 40 lines worth of code.






Re: Windows Workflow Foundation Setting and passing parameters in XOML when Hosting WWF designer in ASP.NET

akjha

Hi Jonathon,

I am really thankful to the help you are providing me.

I am sure the answers which your are providing me should be correct, but I might be doing something wrong.

I changed the xoml initialization using this code

internal static readonly string XomlExample = @"<MySequentialWorkflowActivity xmlns='http://schemas.microsoft.com/winfx/2006/xaml/workflow' xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'></MySequentialWorkflowActivity>";

This MySequentialWorkflowActivity is deriving from SequentialWorkflowActivity.

But when I run my app, my app never gets the workflow image.

It is not getting the rootActivity, in the performload function in Loader.cs in WorkflowDesignerControl assembly.

When I change the xoml to just SequentialWorkflowActivity, it gets the SequentialWorkflowActivity as the rootActivity.

using (XmlReader xmlReader = XmlReader.Create(reader))

{

WorkflowMarkupSerializer xomlSerializer = new WorkflowMarkupSerializer();

rootActivity = xomlSerializer.Deserialize(xmlReader) as Activity;

}

Thanks in advance for your help.

Achintya






Re: Windows Workflow Foundation Setting and passing parameters in XOML when Hosting WWF designer in ASP.NET

Jonathan Davlin

damnit, I just typed all this out and it logged me out...

OK, make sure you add the assembly to your typeprovider

Code Snippet

host.AddService(typeof(IToolboxService), new ToolboxService(host));

TypeProvider typeProvider = (TypeProvider)host.GetService(typeof(ITypeProvider));

typeProvider.AddAssembly(typeof(MySequentialWorkflowActivity).Assembly);

you may also want to use these services:


Code Snippet

using System;

using System.Collections.Generic;

using System.Text;

namespace WorkflowDesignerControl

{

public class TypeDiscoveryService : System.ComponentModel.Design.ITypeDiscoveryService

{

System.ComponentModel.Design.ITypeDiscoveryService _InnerService;

public TypeDiscoveryService()

{

}

public TypeDiscoveryService(System.ComponentModel.Design.ITypeDiscoveryService innerService)

{

_InnerService = innerService;

}

#region ITypeDiscoveryService Members

public System.Collections.ICollection GetTypes(Type baseType, bool excludeGlobalTypes)

{

return _InnerService.GetTypes(baseType, excludeGlobalTypes);

}

#endregion

}

public class TypeResolutionService : System.ComponentModel.Design.ITypeResolutionService

{

System.Workflow.ComponentModel.Compiler.TypeProvider _InnerService;

public TypeResolutionService()

{

}

public TypeResolutionService(System.Workflow.ComponentModel.Compiler.TypeProvider innerService)

{

_InnerService = innerService;

}

#region ITypeResolutionService Members

public System.Reflection.Assembly GetAssembly(System.Reflection.AssemblyName name, bool throwOnError)

{

System.Reflection.Assembly assembly = null;

try

{

assembly = System.Reflection.Assembly.Load(name, new System.Security.Policy.Evidence());

}

catch { }

foreach (System.Reflection.Assembly refAssembly in _InnerService.ReferencedAssemblies)

{

if (refAssembly.GetName() == name)

{

assembly = refAssembly;

break;

}

}

return assembly;

}

public System.Reflection.Assembly GetAssembly(System.Reflection.AssemblyName name)

{

return GetAssembly(name, false);

}

public string GetPathOfAssembly(System.Reflection.AssemblyName name)

{

return "";//_InnerService.GetPathOfAssembly(name.);

}

public Type GetType(string name, bool throwOnError, bool ignoreCase)

{

return _InnerService.GetType(name, throwOnError);//, ignoreCase);

}

public Type GetType(string name, bool throwOnError)

{

return _InnerService.GetType(name, throwOnError);

}

public Type GetType(string name)

{

Type type = null;

try

{

type = _InnerService.GetType(name.Substring(0,name.IndexOf(',')));

}

catch { }

if (type == null)

{

try

{

type = Type.GetType(name);

}

catch { }

}

return type;

}

public void ReferenceAssembly(System.Reflection.AssemblyName name)

{

_InnerService.AddAssembly(System.Reflection.Assembly.Load(name));

}

#endregion

}

}

to replace them, use the following:

Code Snippet

public static void ReplaceTypeDiscovery(IServiceContainer serviceContainer)

{

ITypeDiscoveryService oldService = (ITypeDiscoveryService)serviceContainer.GetService(typeof(ITypeDiscoveryService));

ITypeDiscoveryService newService = null;

if (oldService != null)

{

newService = new TypeDiscoveryService((ITypeDiscoveryService)oldService);

serviceContainer.RemoveService(typeof(ITypeDiscoveryService));

}

else

{

newService = new TypeDiscoveryService();

}

serviceContainer.AddService(typeof(ITypeDiscoveryService), newService);

}

public static void ReplaceTypeResolution(IServiceContainer serviceContainer)

{

TypeResolutionService oldService = (TypeResolutionService)serviceContainer.GetService(typeof(ITypeResolutionService));

ITypeResolutionService newService = null;

if (oldService != null)

{

serviceContainer.RemoveService(typeof(ITypeResolutionService));

}

else

{

newService = new TypeResolutionService((TypeProvider)serviceContainer.GetService(typeof(TypeProvider)));

}

serviceContainer.AddService(typeof(ITypeResolutionService), newService);

}






Re: Windows Workflow Foundation Setting and passing parameters in XOML when Hosting WWF designer in ASP.NET

Jonathan Davlin

Also, in case I wasn't clear enough on the new base class.

1. It needs to be in a separate, preferably referenced assembly.
2. It must be a C# activity, not Xoml, should not have any activities in it(until you get it working),



OH.... your XAML was missing a little detail. Here's an example I did real quick.

Code Snippet

<ns0:MyBaseWorkflowActivity x:Class="WorkflowLibrary1.Workflow2" x:Name="Workflow2" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/workflow" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:ns0="clr-namespace:ActivityLibrary1;Assembly=ActivityLibrary1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">


</
ns0:MyBaseWorkflowActivity>






Re: Windows Workflow Foundation Setting and passing parameters in XOML when Hosting WWF designer in ASP.NET

Jonathan Davlin

Note the namespace in the XOML above. Duh, I should've caught that right away.




Re: Windows Workflow Foundation Setting and passing parameters in XOML when Hosting WWF designer in ASP.NET

akjha

Thanks Jonathan,

I updated the namespace and it worked...I am so excited now...

I am sure going to ask you many more questions....

Achintya






Re: Windows Workflow Foundation Setting and passing parameters in XOML when Hosting WWF designer in ASP.NET

akjha

Hi Jonathan,

I am moving to my next step where I can pass parameters from one activity to another.

I know the code you gave me which gets generated when we do a C# workflow project and bind one property of one activity to that of another one.

Again my problem is where to add this code.

How difficult is to make the same binding dialog boxes as we get it in the C# projects. I know it will require ajax or so, but has somebody implemented that kind of functionality

Many Thanks...

Achintya






Re: Windows Workflow Foundation Setting and passing parameters in XOML when Hosting WWF designer in ASP.NET

akjha

My dear friend Jonathan,

Where are you

Achintya