views:

546

answers:

3

I'm working with a state machine workflow and using the ExternalDataExchange service to handle events in the host and get data into the workflow via eventargs.

However, now I need to get data out of the workflow and I'm having difficulties.

The outputparameters are only available in the workflow completed event, but my workflow isn't complete. The host fires an event with some data and is basically waiting for the workflow to finish processing the event (manual scheduler). In my particular handling of the event in the workflow, it's doing some validation and should that validation fail, it does NOT move to the next state but I need to be able to send the validation results back to the host application.

An example of what I'm trying to accomplish would look like this:

OrderWorkflow
    PendingOrderState
        ImportOrderEvent
            - If the order passes validation move to CompletedState
            - Else return the validation results to the host (how?)
    CompletedState

It should also be noted that my host is in fact an ASP.NET MVC application, so I'm trying to avoid wiring up events on my controller/page directly to handle local services from the workflow calling out but am not totally opposed to it if that's the way it needs to be done.

+3  A: 

Looks like I've got a working solution for this.

Basically my WorkflowRuntimeManager is more or less the same as the one presented by Bruce Bukovics in his book Pro WF Windows Workflow in .NET 3.5.

I ended up creating a new service and adding it to the workflow runtime. This service allows my workflow to fire an event in my application that allows it to pass any IDictionary back to my host application.

This event is in turn picked up by the WorkflowRuntimeManager where it then in turn takes the results and associates them with the appropriate WorkflowInstance and where it becomes available to the application itself once the Workflow method returns.

I've attached the service implementation here for anyone else that may want to duplicate this functionality. Or even better, if someone can find a better way to do this, please let me know.

public interface ISendDataService
{
    event EventHandler<ReceivedDataEventArgs> ReceivedDataEvent;
    void SendData(Guid instanceId, IDictionary<string, object> data);
}

public class SendDataService : ISendDataService
{
    public event EventHandler<ReceivedDataEventArgs> ReceivedDataEvent;

    private void OnReceivedDataEvent(Guid instanceId, IDictionary<string, object> data)
    {
        if (ReceivedDataEvent != null)
            ReceivedDataEvent(null, new ReceivedDataEventArgs(instanceId, data));
    }

    public void SendData(Guid instanceId, IDictionary<string, object> data)
    {
        OnReceivedDataEvent(instanceId, data);
    }
}

public class ReceivedDataEventArgs : EventArgs
{
    public ReceivedDataEventArgs()
    {
    }

    public ReceivedDataEventArgs(Guid instanceId, IDictionary<string, object> data)
    {
        InstanceId = instanceId;
        Data = data;
    }

    public Guid InstanceId { get; set; }
    public IDictionary<string, object> Data { get; set; }
}
Chris Stavropoulos
Cool! I like the fact that you used IDictionary as one of the weaknesses that I see with WF Interace service from the WF Pro book is that parameter lists can get get quite long if you have to move data in and out.
David Robbins
A: 

Above solution workable for ManuakWorkflowScheduler Service - Synchronous execution?

Yes. That is precisely how I was using it. The issue was more to do with how to get data out of a state machine workflow mid-stream.I recommend Bruce Bukovics book if you're interested in running workflows as it has a pretty good implementation of a runtime wrapper.
Chris Stavropoulos
A: 

Hi Chris, Would you mind posting an example of how you use the service to send data back to the host from the state activity? I'm having a hard time getting my brain around your solution.