This is the first post in a series about Building an Enterprise Workflow system with WF4.
Hosting our Workflows
When we were building our enterprise workflow solution at our company, it was during the development of .Net 4 and we were heavily involved in the Microsoft TAP (early adopters) program. We looked at all the features for WF4 and realised (along with advice from the workflow team) that the best hosting story was using the WorkflowServiceHost (WSH) in IIS as opposed to a roll-your-own host approach with WorkflowApplication etc. There are many reasons for this but the primary one is AppFabric and the services it provides on top of the WF runtime. Here is a list of some of the benefits those features provide.
- IIS management console UI for tracking instances and controlling them (Suspend, Terminate, Cancel)
- Management of tracking level for workflow and WCF services via the tracking level slider bar
- The WorkflowManagementService that comes with IIS would wake up our instances when they have an expired timer (delay). This was a big plus as we wouldn’t have to write another service to monitor timer expirations.
- Powershell management API.
- IIS horizontal scalability and lock configuration through web farm management, along with consolidated tracking logging.
Having decided that the WSH was the key to getting what we wanted hosting-wise, we started looking at the built in service templates and the samples that we were given. The store then was pretty much the same as it is today, you create a new project using the project template “WCF Workflow Service Application”.
Having done that, we are presented with a project structure that has a Service1.xamlx file and a web.config file.
The Service1.xamlx file is our workflow which is quite similar to a workflow activity but it has some major differences.
There are no arguments to define, in fact the arguments option usually present in activity authoring is not present in our workflow service. Instead we get 2 activities already on our surface, a Receive and a SendReply.
So what are these things?
Well, these are the 2 main activities used to expose a WCF service from WF4. There is also the combination of Send and ReceiveReply which is used to consume a WCF service in WF4. On the Content (View Message) section you add message parameters or a message type and map them to variables in your workflow, this forms the parameters on your WCF operation contract.
Introducing the Magic Eight Ball
The sample for this blog post series will be that we are a website offering a magic eight ball service, users can ask a question, choose an eight ball to ask and we will send them back a response.
We want ordinary users of our website to be able to create their own magic eight ball implementations that we will host for them. We will provide them activities to help them do this but they are not coders and they shouldn’t have to understand WCF/WF/C# etc.
For example, below is a workflow service I have written which is a Magic Eight Ball service, you give it a question and your email address and it will email you a response.
The message parameters on the ReceiveRequest activity are defined as follows:
As you may be able to tell, this is simply defining a WCF Service contract.
Remember from our requirements, the sample that we are going to create in this blog series will be an enterprise workflow system where a business user could create their own workflows using a simple authoring experience.
Already this workflow code example I have above is starting to seem a little complicated for an ordinary user, if we look at the properties on the Receive activity we are asked for namespaces, which serializer should we use, correlation, known types etc. These are not things that a business user should be concerned about.
Users don’t / shouldn’t care about WCF configuration
When building our company’s solution we started to ponder how we could avoid the business user having to see this stuff and you should ask yourself the same question. Should your users have to be presented with options that they should never understand? It’s not a very reassuring experience to say to your end users: “Don’t touch that stuff there or it will break”. Therefore we didn’t want them messing with this WCF stuff.
We knew we would probably supply our users a project template that would start them off and the subsequent experience we wanted for them was basically the activity authoring experience. A blank canvas, no messing around with things that shouldn’t concern them.
If you look at the XAML for a Workflow Service (xamlx) by using “View Code” from solution explorer you will see that the root element is a “WorkflowService”. If you look at a composite activity (.xaml) you will see that it’s root is an “Activity”. This tells us that fundamentally, our XAML is creating 2 different types of objects in these scenarios.
How then did we do this? How do we host a normal workflow activity as a service? Well that is where the WorkflowServiceHostFactory comes in to play. As we will see in the next post, it allows us to host an ordinary activity as a service, and to customize all the features we want on the Workflow Service Host, e.g. tracking, persistence, idle behavior etc.