In 2006, Microsoft released .NET Framework 3.0, which basically consisted of extensions to .NET Framework 2.0. WCF was the biggest hit back then and gained the most attention. That even continued with the 3.5 release of the framework.
With .NET Framework 4.0, Microsoft made WF the major focus, and with the many enhancements they have in place, it is evident the importance that WF 4.0 will have for building .NET-based applications.
What is WF?
Well, answering this question is not the scope of this article. Understanding what WF is and when to use it is something you can get from various online resources – or even books. For example, one of the great early publications on WF 4.0 is David Chappell’s paper on MSDN; reading it will be more than enough to understand what is and when to use WF 4.0. You can find it here: http://msdn.microsoft.com/en-us/library/dd851337.aspx.
So what is this article about?
In summary, this article has two main objectives:
- Gives a first look on WF 4.0 (beta1 as of this writing).
- Shows how we can use WF 4.0 to build distributed applications via WF 4.0 Services.
- Using .NET 4.0 Data Services for performing data access.
Note: A nice post about the differences between WF 4.0 and WF 3.5 can be found here: http://bloggingabout.net/blogs/pascal/archive/2009/05/20/wf-4-0-what-is-different-from-3-x.aspx.
The application demonstrates a demo-worthy Car Rental system. The image below shows the design of the application.
The scenario is as follows: A car rental company has its information in a SQL Server database. They need to build an application which allows employees to check car prices and then book cars to clients based on the client input. For that, a WF 4.0 Service which contains the business logic is hosted over HTTP where clients can ask it to do two operations: CheckPrice and BookCar. The WF 4.0 Service – being a business process – is not allowed to access the database directly; instead, it communicates with an ADO.NET Data Service which performs database CRUD operations (more on that later). What client types does the system support? The answer is just about any client. In this example, we will see a .NET Windows client, and more interestingly, a WF 4.0 client.
Any similarities spotted…?
Examining the above architecture should definitely trigger in your development sense the concept of n-tier applications. In fact, the above design is nothing more than the traditional and beloved three tier design. Let’s do the matching:
- Data Access Layer: ADO.NET Data Services is used instead of the traditional DAL class libraries with the famous
- Business Layer: A WF 4.0 Service is used as the business layer instead of the BAL class libraries we used to write.
- Presentation Layer: A WF 4.0 console client application is used instead of a .NET console application. Now, this is tricky; in this example, no user interface is required, so a console WF application was sufficient. However, in cases where a GUI is needed, a Windows (or web) client application is used easily…after all, the business logic is hosted in a WF Service, and can be consumed by any client just as if you were using an XML Web Service, for example.
So in a more traditional design, the architecture would be like something in the figure below:
So, the advent of the new technologies allowed for better designs. How the new WF-based design tops the old traditional one is something you will see as we go in this article…
The source code can be downloaded from the link above. I will use the solution components as we go through the article. It would have been impossible to show a step by step approach on how I built the application, so as we go, I will refer to the various components of the solution and explain each and every one of those components.
The sample is built on top of .NET 4.0 and VS 2010 Beta1 release. You can download them from here: http://www.microsoft.com/downloads/details.aspx?familyid=3296BB4F-D8BA-4CFD-AA95-A424C5913F6B&displaylang=en. You will also need SQL Server 2000/2005. Let’s roll…
Part 1: The database
As with any data-centric approach, the application design usually starts with the database and then goes up through layers. We will follow the concept here. Luckily, for our example, the database is as simple as a single table called Cars, shown below:
The CarId column holds the names of some famous manufacturers like Honda and Mercedes. The Day_UnitPrice column holds the daily renting amount fee, and finally, the Quantity column holds the available number of cars for renting.
In the attached files, you will find a file called CarStore.bak; restore that to your SQL Server.
Part 2: The ADO.NET Data Service
Data Services follow the Representational State Transfer (REST) design paradigms. This design depends entirely on the plain HTTP verbs: POST, GET, PUT, and DELETE to perform Create, Read, Update, and Delete (CRUD) operations, respectively. With REST, you enjoy simplicity and ease, and is most suitable when you are in no need to the complexity (yet sometimes absolute must) of SOAP with XML Web Services or WCF. When you do not need SOAP encryption, WS-routing, WS-addressing, and any other WS-* standards, then Data Services can be the best choice for performing CRUD operations.
There are many great sources online debating the REST vs. SOAP subject, which I encourage you to read and get more insights about when to use each.
First thing to do when creating an ADO.NET Data Service is exposing the data source. I used the Entity Framework to do just that. So, follow these steps to set up the Data Service project:
- Create an empty VS 2010 solution and call it “CarRentalDemo”.
- In the attached files, you will find a folder “CarRentalDataService“. Copy this file into your intepub/wwwroot folder, and from within IIS, create its application.
- Add the “CarRentalDataService” project as an existing web site into the “CarRentalDemo” solution.
Now, let’s examine what makes the Data Service project. From within VS, you will see the following files:
- CarRental.edmx: This will create an object representation of the CarStore database. Before exposing a database via REST style in a Data Service, we need to have the object model of that database. This object model is best represented using the ADO.NET Entity Framework.
- CarRentalService.svc and CarRentalService.cs: Now with the object model ready, we need to create the Data Service itself. CarRentalService.cs is used to indicate what the Entity Model is which we are exposing, and CarRentalService.svc is the physical Data Service pointing to the
That’s all that is required in order to build a Data Service. Now, from within Visual Studio, you can right click CarRentalService.svc and select Browse, and you will be able to query the data source in a REST style. For example, to select the car with ID “Honda”, use the following URL: http://localhost/CarRentalDataService/CarRentalService.svc/Cars('Honda').
Using the browser is enough only for browsing; however, in order to make the Data Service usable in our sample, we will have to do the CRUD operations using .NET code. This will be shown next.
Part 3: Custom Activities
Following the architecture diagram, we should now be seeing the WF 4.0 Service. Prior to that, let's discuss the custom activities. Activities are the building blocks of WF. Every shape you drag from the toolbox into the WF designer is an Activity. Custom Activities allow the developer to extend the existing activities with new ones written especially for the problem in hand; it is a kind of a Domain Specific Language (DSL).
WF 4.0, in particular, encourages the use of custom activities. Prior to 4.0, WF had the Code Activity shape which allowed the developer to write code directly into the WF process. In WF 4.0, the Code Activity shape is gone, and now developers will have to create custom activities to build their components.
In our example, there are a set of custom activities that we will need to use in both the WF 4.0 Service and the WF 4.0 Client. In the attached files, you will find a project named “CustomActivities”; this is a Class Library were all activities are compiled. Add this project to your solution “CarRentalDemo”. Let’s examine its contents:
GetInput.cs: This activity collects input from a user via console, and assigns it to an output argument. Arguments are the way in WF 4.0 to get data in and out of a process. There are input arguments and output arguments. Below is the code of the activity: