C# – How to get data out of a state machine workflow before the workflow enters its completed state

asp.net-mvccworkflow-foundation

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.

Best Answer

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; }
}