More on Managing Windows Workflow Events in ASP.NET

In the last post I pointed out problems you can experience trying to handle workflow events in an ASP.NET page. Before we get to a working solution, let's take a look at another pitfall.

We know the default WF scheduling service will select a thread from the CLR thread pool to execute workflows asynchronously. Generally speaking, this isn't a good approach for server side applications because we can tie up too many threads. Instead, we use the ManualWorkflowSchedulerService. The manual scheduler lets us run workflows on the same thread that is processing the HTTP request. We just need to call RunWorkflow on the service whenever we need a workflow to execute.

It's tempting to think the manual scheduler can make life easier since we don't have to worry about threads. For instance, let's suppose we want any unhandled faults originating from inside a workflow to bring the current request to a screeching halt. We want unhandled exceptions! When a workflow faults and throws an exception, WF will catch the exception and raise a WorkflowTerminated event. This event will fire on the same thread as the request that ran the faulty workflow.

Knowing that we want to end requests with an error, we could try to use global.asax like the following. After all, if we throw an exception on the current request thread, we should create the yellow screen of death (assuming the Page doesn't have an exception handler). Note: I'm using global.asax just to make this simple.

void Application_Start(object sender, EventArgs e)
{
    _workflowRuntime =
new WorkflowRuntime("wfConfiguration");

    _workflowRuntime.WorkflowTerminated +=
        
new EventHandler<WorkflowTerminatedEventArgs>
            (_workflowRuntime_WorkflowTerminated);

    _workflowRuntime.StartRuntime();

}
  
void _workflowRuntime_WorkflowTerminated
        (
object sender, WorkflowTerminatedEventArgs e)
{
    
throw e.Exception;        
}
        
private static WorkflowRuntime _workflowRuntime;

The problem is that the WorkflowRuntime is dedicated to its job. The runtime is tasked with telling all the event subscribers that a workflow terminated, and it is not going to let some unhandled exception prevent the rest of the subscribers from missing events. The WF runtime swallows our exception. See Ken Getz's article for how to use GetInvocationList to achieve this behavior.

How can we communicate the exception back to the Page? Consider the following code.

void _workflowRuntime_WorkflowTerminated
        (
object sender, WorkflowTerminatedEventArgs e)
{
    
HttpContext.Current.Items["WorkflowResult"] = e.Exception;
}

Now the web form can pull the exception out of the HTTP request context. Problem solved!

Oh, but wait - we are spiraling out of control. Now the ASP.NET developer has to remember to start workflows with the manual scheduler, and check the request context for exceptions, and use such and such a communication service to raise events to the workflow.

If you are going to the trouble to use Windows Workflow in an ASP.NET application, then you have an architectural responsibility to abstract away these problematic and sometimes dangerous scenarios to the point that the ASP.NET developer doesn't even know there is a workflow driving the process. Bring a mediator to the party.

posted on Wednesday, January 24, 2007 12:00 AM by scott

Comments

Tuesday, January 23, 2007 10:01 PM by Mike

# re: More on Managing Windows Workflow Events in ASP.NET

What are your thoughts on Web Client Factory? Will you be doing an article about it soon?
Wednesday, January 24, 2007 4:54 AM by scott

# re: More on Managing Windows Workflow Events in ASP.NET

Mike:

I am hoping to get into WCSF and also AJAX over the coming months. No promises, though :)
Wednesday, January 24, 2007 6:33 AM by Sam Gentile

# New and Notable 137

We finally saw some snow here but it was under an inch. Today, my team has a release party. After 14
Wednesday, January 24, 2007 6:53 PM by Christopher Steen

# Link Listing - January 24, 2007

Accessing and Updating Data in ASP.NET 2.0: Declaratively Caching Data [Via: ] Transforms, Opacity Masks...
Tuesday, January 30, 2007 6:39 AM by Sam Gentile

# New and Notable 137

We finally saw some snow here but it was under an inch. Today, my team has a release party. After 14
Sunday, February 25, 2007 11:49 PM by Luke's Blog

# Workflow Foundation in ASP.NET

Tuesday, May 15, 2007 8:33 PM by Web Form

# ASP.NET and Windows Workflows Foundation

Combining ASP.NET 2.0 and Windows Workflow Foundation (WF) will provide us with all the essential tools

# WF Persistence - Where [DataContract] != [Serializable]

Let&amp;#39;s say you were using Workflow Foundation (WF) and Windows Communication Foundation (WCF). Assume