
Pro CSharp 2008 And The .NET 3.5 Platform [eng]-1
.pdf
912 CHAPTER 25 ■ INTRODUCING WINDOWS COMMUNICATION FOUNDATION
This interface defines three methods, one of which returns an array of the (yet-to-be-created)
InventoryRecord type. You may recall that the GetInventory() method of InventoryDAL simply returned a DataTable object, which might make you question why our service’s GetInventory() method does not do the same.
While it would work to return a DataTable from a WCF service method, recall that WCF was built to honor the use of SOA principles, one of which is to program against contracts, not implementations. Therefore, rather than returning the .NET-specific DataTable type to an external caller, we will return a custom data contract (InventoryRecord) that will be correctly expressed in the contained WSDL document in an agnostic manner.
Also note that this interface defines an overloaded method named InsertCar(). The first version takes four incoming parameters, while the second version takes an InventoryRecord type as input. This data contract can be defined as so:
[DataContract]
public class InventoryRecord
{
[DataMember] public int ID; [DataMember] public string Make; [DataMember]
public string Color; [DataMember]
public string PetName;
}
If you were to implement this interface as it now stands, build a host, and attempt to call these methods from a client, you might be surprised to find a runtime exception. The reason has to do with the fact that one of the requirements of a WSDL description is that each method exposed from a given endpoint is uniquely named. Thus, while method overloading works just fine as far as C# is concerned, the current web service specifications do not permit two identically named InsertCar() methods.
Thankfully, the [OperationContract] attribute supports a named property (Name) that allows you to specify how the C# method will be represented within a WSDL description. Given this, update the second version of InsertCar() as so:
public interface IAutoLotService
{
...
[OperationContract(Name = "InsertCarWithDetails")] void InsertCar(InventoryRecord car);
}
Implementing the Service Contract
The AutoLotService type implements this interface as follows (be sure to import the
AutoLotConnectedLayer and System.Data namespaces in this code file):
using AutoLotConnectedLayer; using System.Data;
public class AutoLotService : IAutoLotService
{
private const string ConnString =
@"Data Source=(local)\SQLEXPRESS;Initial Catalog=AutoLot"+ ";Integrated Security=True";


914CHAPTER 25 ■ INTRODUCING WINDOWS COMMUNICATION FOUNDATION
the name and location of the service implementation within the install point. Because we have changed the names of our starter files and WCF types, we must now update the contents of the
Service.svc file as so:
<%@ ServiceHost Language="C#" Debug="true"
Service="AutoLotService" CodeBehind="~/App_Code/AutoLotService.cs" %>
Updating the Web.config File
Before we can take this service out for a test drive, the final task is to update the <system. serviceModel> section of the Web.config file. As described in more detail during our examination of ASP.NET later in this book, the Web.config file serves a similar purpose to an executable’s *.config file; however, it also controls a number of web-specific settings. For this example, all we need to do is update the WCF-specific section of the file as follows:
<system.serviceModel>
<services>
<service name="AutoLotService" behaviorConfiguration="ServiceBehavior"> <endpoint address="" binding="wsHttpBinding" contract="IAutoLotService"/>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceBehavior"> <serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/> </behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
Testing the Service
Now you are free to build any sort of client to test your service, including passing in the endpoint of the *.svc file to the WcfTestClient.exe application:
WcfTestClient http://localhost/AutoLotWCFService/Service.svc
Consider Figure 25-21, which illustrates the result of invoking GetInventory().
■Source Code The AutoLotService project is located under the Chapter 25 subdirectory.

CHAPTER 25 ■ INTRODUCING WINDOWS COMMUNICATION FOUNDATION |
915 |
Figure 25-21. Creating a web-centric WCF service
If you wish to build a custom client application, simply use the Add Service Reference dialog box as you did for the MagicEightBallServiceClient and MathClient project examples earlier in this chapter.
Summary
This chapter introduced you to the Windows Communication Foundation (WCF) API, which has been part of the base class libraries since .NET 3.0. As explained, the major motivation behind WCF is to provide a unified object model that exposes a number of (previously unrelated) distributed computing APIs under a single umbrella. Furthermore, as you saw at the onset of this chapter, a WCF service is represented by specified addresses, bindings, and contracts (easily remembered by the friendly abbreviation ABC).
As you have seen, a typical WCF application involves the use of three interrelated assemblies. The first assembly defines the service contracts and service types that represent the services functionality. This assembly is then hosted by a custom executable, an IIS virtual directory, or a Windows service. Finally, the client assembly makes use of a generated code file defining a proxy type (and settings within the application configuration file) to communicate with the remote type.
The chapter also examined using a number of WCF programming tools such as
SvcConfigEditor.exe (which allows you to modify *.config files), the WcfTestClient.exe application (to quickly test a WCF service), and various Visual Studio 2008 WCF project templates.



918CHAPTER 26 ■ INTRODUCING WINDOWS WORKFLOW FOUNDATION
and whatnot. As you may know firsthand, building this sort of infrastructure from scratch entails a great deal of time and manual labor.
Assuming that a development team did, in fact, build a custom business process framework for their applications, their work was not yet complete. Simply put, a raw C# code base cannot be easily explained to nonprogrammers on the team who also need to understand the business process. The truth of the matter is that subject matter experts (SMEs), managers, salespeople, and members of a graphical design team often do not speak the language of code. Given this, we were required to make use of other modeling tools (such as Microsoft Visio) to graphically represent our processes using skill set–neutral terms. The obvious problem here is we now have two entities to keep in sync: If we change the code, we need to update the diagram. If we change the diagram, we need to update the code.
Furthermore, when building a sophisticated software application using the 100% code approach, the code base has very little trace of the internal “flow” of the application. For example, a typical .NET program might be composed of hundreds of custom types (not to mention the numerous types used by the base class libraries). While programmers may have a feel for which objects are making calls on other objects, the code itself is a far cry from a living document that explains the overall sequence of activity. While the development team may build external documentation and workflow charts, again we run into the problem of multiple representations of the same process.
The Role of WF
Since the release of .NET 3.0, we were provided with the Windows Workflow Foundation API. In essence, WF allows programmers to declaratively design business processes using a prefabricated set of activities. Thus, rather than building a custom set of assemblies to represent a given business activity and the necessary infrastructure, we can make use of the WF designers of Visual Studio 2008 to create our business process at design time. In this respect, WF allows us to build the skeleton of a business process, which can be fleshed out through code.
When programming with the WF API, a single entity can then be used to represent the overall business process as well as the code that defines it. Since a single WF document is used to represent the code driving the process in addition to being a friendly visual representation of the process, we no longer need to worry about multiple documents falling out of sync. Better yet, this WF document will clearly illustrate the process itself.
The Building Blocks of WF
As you build a workflow-enabled application, you will undoubtedly notice that it “feels different” from building a typical .NET application. For example, up until this point in the text, every code example began by creating a new project workspace (most often a Console Application project) and involved authoring code to represent the program at large. A WF application also consists of custom code; however, in addition, you are building directly into the assembly the business process itself. Consider Figure 26-1, which illustrates the initial workflow diagram generated by Visual Studio 2008 when selecting a new Sequential Workflow Console Application project workspace.
Using this designer (and the various WF-centric tools integrated into Visual Studio) you are able to model your process and eventually author code to execute it under the appropriate circumstances. You’ll examine these tools in more detail a bit later in this chapter.
Understand that WF is far more than a pretty designer that allows you to model the activities of a business process. As you are building your WF diagram, the designer tools are authoring code to represent the skeleton of your process. Thus, the first thing to be aware of is that a visual WF diagram is executable code, not just simply a Visio-like static image. As such, WF is represented by a set of .NET assemblies, namespaces, and types, just like any other .NET technology.

CHAPTER 26 ■ INTRODUCING WINDOWS WORKFLOW FOUNDATION |
919 |
Figure 26-1. An empty sequential workflow diagram designer
The WF Runtime
Given the fact that a WF diagram equates to real types and custom code, the next thing to understand is that the WF API also consists of a runtime engine to load, execute, unload, and in other ways manipulate a workflow process. The WF runtime engine can be hosted within any .NET application domain; however, be aware that a single application domain can only have one running instance of the WF engine.
Recall from Chapter 17 that an AppDomain is a partition within a Win32 process that plays host to a .NET application and any external code libraries. As such, the WF engine can be embedded within a simple console program, a GUI desktop application (Windows Forms or Windows Presentation Foundation [WPF]), or exposed from a WCF service or XML web service.
If you are modeling a business process that needs to be used by a wide variety of systems, you also have the option of authoring your WF within a C# Class Library project. In this way, new applications can simply reference your *.dll to reuse a predefined collection of business processes. This is obviously helpful in that you would not want to have to re-create the same WF multiple times.
In any case, at this point understand that the WF API provides a full-blown object model that allows you to programmatically interact with the runtime engine as well as the workflows you have designed.
The Core Services of WF
In addition to designer tools, activities, and a runtime engine, WF provides a set of out-of-the-box services that complete the overall framework of a workflow-enabled application. Using these services we can “inherit” a good deal of commonly required WF infrastructure, rather than having to commit time and resources to build this infrastructure by hand. Table 26-1 documents the intrinsic services baked into the WF API.
Collectively, the four intrinsic services seen in Table 26-1 are termed the core services. The WF APIs provide default implementations of each of these services, two of which are mandatory (scheduling and transactions), while tracking and persistence services are optional and not registered with the runtime by default. While the .NET base class libraries do provide types that support each core service, you are able to exchange them with your own custom implementations. Thus, if you wish to customize the way in which a long-running workflow should be persisted, you can do so. As well, if you wish to extend the basic functionality of a service with new functionality, it is possible to do so.


CHAPTER 26 ■ INTRODUCING WINDOWS WORKFLOW FOUNDATION |
921 |
■Note Visual Studio 2008 divides the Activities Toolbox into .NET 3.0 and .NET 3.5 activity categories. The activities under the Windows Workflow v3.5 node allow you to interact with Windows Communication Foundation (WCF) services.
.NET 3.5 provides numerous out-of-the-box activities that you can use to model your business process, each of which maps to real types within the System.Workflow.Activities namespace and therefore can be represented by, and driven from, code. You’ll make use of several of these baked-in activities over the course of this chapter. Table 26-2 describes the high-level functionality of some useful activities, grouped by related functionality.
Table 26-2. A Sampling of Intrinsic WF Activities
Activities |
Meaning in Life |
CodeActivity |
This activity represents a unit of custom code to execute |
|
within the workflow. |
IfElseActivity, WhileActivity |
These activities provide basic looping and decision |
|
support within a workflow. |
InvokeWebServiceActivity, |
These activities allow your workflow to interact with |
WebServiceInputActivity, |
XML web services. |
WebServiceOutputActivity, |
|
WebServiceFaultActivity |
|
SendActivity, ReceiveActivity |
These activities allow you to interact with Windows |
|
Communication Foundation services. Be aware that these |
|
two activities are .NET 3.5 specific. |
ConditionedActivity, GroupActivity |
These activities allow you to define a group of related |
|
activities that execute when a given condition is true. |
DelayActivity, SuspendActivity, |
These activities allow you to define wait periods as well |
TerminateActivity |
as pause or terminate a course of action within a |
|
workflow. |
EventDrivenActivity, |
These activities allow you to associate CLR events to a |
EventHandlingScopeActivity |
given activity within the workflow. |
ThrowActivity, FaultHandlerActivity |
These activities allow you to raise and handle exceptions |
|
within a workflow. |
ParallelActivity, SequenceActivity |
These activities allow you to execute a set of activities in |
|
parallel or in sequence. |
|
|
While the current number of intrinsic activities is impressive and provides a solid foundation for many WF-enabled applications, you are also able to create custom activities that seamlessly integrate into the Visual Studio IDE and the WF runtime engine.
Sequential and State Machine Workflows
The WF API provides support for modeling two flavors of business process workflows: sequential workflows and state machine workflows. Ultimately, both categories are constructed by piecing together any number of related activities; however, exactly how they execute is what sets them apart.