Clean paths with WCF Hosted Workflows


I am a big fan of the things added to WCF 4.0. One of those things is the deep integration with ASP.NET routes. Today, I was writing a service in WF and hosting the workflow with WCF. I really didn’t like the service URL-yeah, I’m a picky developer who doesn’t like exposing implementation details in the URL.

I knew a few things:

1. WF/WCF integration provides a ServiceHostFactory named WorkflowServiceHostFactory for hosting XAMLX files in WCF.

2. WorfklowServiceHostFactory will see CreateServiceHost called with some constructorString plus a bunch of baseAddresses.

3. I wanted the host to work on HTTP only-I don’t care about goofy URLs for net.tcp.

4. XAMLX services do not have a runtime defined type- they exist only in XAML.

My goal was to create a new route type, like ServiceRoute, that allowed me to pass in the desired path and the path to the XAMLX to instantiate. After a few minutes of thinking and hacking, I had the following:

 

public class WorkflowServiceRoute : ServiceRoute
{
  public class HostedWorkflowServiceHostFactory : 
    WorkflowServiceHostFactory
  {
    public HostedWorkflowServiceHostFactory(string xamlxPath)
    {
      XamlxPath = xamlxPath;
    }

    string XamlxPath { get; set; }

    public override System.ServiceModel.ServiceHostBase CreateServiceHost(
      string constructorString, Uri[] baseAddresses)
    {
      return base.CreateServiceHost(XamlxPath, baseAddresses);
    }
  }

  public WorkflowServiceRoute(string routePrefix, string xamlxPath)
    : base(routePrefix, 
           new HostedWorkflowServiceHostFactory(xamlxPath), 
           typeof(object))
  {
  }
}

I’m pretty happy with the succinctness of the class and the fact that it works on the few use cases I have at hand. Requests are directed to the correct locations and integration seems to be just fine. Use of the WorkflowServiceRoute is just:

routes.Add(new WorkflowServiceRoute("helloWorld", "SimpleWorkflow.xamlx"));

Frankly, this is the first implementation I thought to write, and it works. The code size is small. I don’t like a few things about it, but I’ll live. Things I don’t like:

1. Passing typeof(object) to the base constructor from the route seems wrong. The receiver code thinks it needs a reference to the service type at all times. I’m just lying to the ServiceRoute so that I can take advantage of everything good about it.

2. Custom ServiceHost just so the code can remember the path to the XAMLX. This bothers me until I think that this is the same thing that happens with each .SVC or other XAMLX file.

 

As a benefit, I get URLs that look like this:

http://scottseely-xps/WfHostApp/helloWorld
instead of:
 
http://scottseely-xps/WfHostApp/SimpleWorkflow.xamlx

 

This serves as yet another example of how good it is that WCF is super extensible and what a great design decision it was to build WCF on top of the extensibility points instead of along side them.

%d bloggers like this: