Providing workflow extensions to a workflow service - WF 4.0

3.4k views Asked by At

Greetings one and all!

I'm new to WF 4.0 and WWF in general so forgive me if this seems like a newbie type of question, but believe me I've scoured the depths of the Internet for a solution to this problem, but to no avail.

I have created a sample WF application with a custom CodeActivity that requires an extension be provided, as per below:

public sealed class PreparePizza : CodeActivity
{
    public InArgument<Order> Order { get; set; }

    protected override void CacheMetadata(CodeActivityMetadata metadata)
    {
        base.CacheMetadata(metadata);

        if (this.Order == null)
            metadata.AddValidationError("You must supply an Order.");

        metadata.RequireExtension<IPreparePizzaExtension>();
    }
    // If your activity returns a value, derive from CodeActivity<TResult>
    // and return the value from the Execute method.
    protected override void Execute(CodeActivityContext context)
    {
        // Obtain the runtime value of the Text input argument
        Order order = context.GetValue(this.Order);
        var extension = context.GetExtension<IPreparePizzaExtension>();
        extension.Prepare(order);
    }
}

public interface IPreparePizzaExtension
{
    void Prepare(Order order);
}

I then slot this activity into a workflow service and attempt to consume via my web app by adding a service reference. However, when I add the reference I get:

System.Activities.ValidationException: An extension of type 'PizzaMan.ActivityLibrary.IPreparePizzaExtension' must be configured in order to run this workflow.

Fair enough - of course my activity requires that I pass it an implementation of IPreparePizzaExtension - after all, I've told it to!

So my question is, how on earth do I pass this to the service? I can manage this easily enough in a console app scenario, using the WorkflowInvoker, but I cannot see any obvious way to do this via the service approach. I would assume that obviously a programmatic approach to adding the reference is what's needed, but again I'm at a loss as to precisely how to go about this.

Any help would be greatly appreciated.

Best regards Ian

4

There are 4 answers

2
Maurice On BEST ANSWER

The WorkflowServiceHost has a WorkflowExtensions property where you can add the workflow extenstion. There are several ways you can do that. If you are self hosting this is easy as you create the WorkflowServiceHost. If you are usign IIS you need to create a ServiceHostFactory to configure you WorkflowServiceHost. Finally there is an option to add the workflow extension in the CacheMetadata of your activity using the metadata.AddDefaultExtensionProvider() function.

0
Ian On

Solved it as follows, self-hosting style:

    static void Main(string[] args)
    {
        Workflow1 workflow = new Workflow1();
        // Provide some default values; note: these will be overriden once method on the service is called.
        workflow.productID = -1;

        Uri address = new Uri("http://localhost:1234/WorkflowService1");
        WorkflowServiceHost host = new WorkflowServiceHost(workflow, address);

        // Behaviours
        host.Description.Behaviors.Add(new ServiceMetadataBehavior { HttpGetEnabled = true });
        host.Description.Behaviors.Remove(typeof(ServiceDebugBehavior));
        host.Description.Behaviors.Add(new ServiceDebugBehavior { IncludeExceptionDetailInFaults = true });

        // Persistence
        var connStr = @"";
        var behavior = new SqlWorkflowInstanceStoreBehavior(connStr);
        behavior.InstanceCompletionAction = InstanceCompletionAction.DeleteNothing;
        behavior.InstanceLockedExceptionAction = InstanceLockedExceptionAction.AggressiveRetry;
        behavior.InstanceEncodingOption = InstanceEncodingOption.None;
        host.Description.Behaviors.Add(behavior);

        // Add extension implementations
        if (!TEST_MODE)
        {
            host.WorkflowExtensions.Add(new MyExtension());                
        }
        else
        {
            host.WorkflowExtensions.Add(new MyExtensionTest());
        }

        host.Faulted += new EventHandler(host_Faulted);

        host.Open();

        foreach (System.ServiceModel.Description.ServiceEndpoint endpoint in host.Description.Endpoints)
        {
            Console.WriteLine(endpoint.Address);
        }

        Console.WriteLine("Listening...");
        Console.ReadLine();
        host.Close();
    }
0
Rory Primrose On
0
Sentinel On