
Pro CSharp 2008 And The .NET 3.5 Platform [eng]
.pdf
882 CHAPTER 25 ■ INTRODUCING WINDOWS COMMUNICATION FOUNDATION
In Table 25-3, note that a WCF binding can be represented in code (via class types within the System.ServiceModel namespace) or as XML attributes defined within *.config files.
Table 25-3. The HTTP-Centric WCF Bindings
Binding Class |
Binding Element |
Meaning in Life |
BasicHttpBinding |
<basicHttpBinding> |
Used to build a WS-Basic Profile (WS-I |
|
|
Basic Profile 1.1)–conformant WCF |
|
|
service. This binding uses HTTP as the |
|
|
transport and Text/XML as the default |
|
|
message encoding. |
WSHttpBinding |
<wsHttpBinding> |
Similar to BasicHttpBinding, but |
|
|
provides more web service features. |
|
|
This binding adds support for |
|
|
transactions, reliable messaging, |
|
|
and WS-Addressing. |
WSDualHttpBinding |
<wsDualHttpBinding> |
Similar to WSHttpBinding, but for use |
|
|
with duplex contracts (e.g., the service |
|
|
and client can send messages back |
|
|
and forth). This binding supports only |
|
|
SOAP security and requires reliable |
|
|
messaging. |
WSFederationHttpBinding |
<wsFederationHttpBinding> |
A secure and interoperable binding |
|
|
that supports the WS-Federation |
|
|
protocol, enabling organizations that |
|
|
are in a federation to efficiently |
|
|
authenticate and authorize users. |
|
|
|
As the name suggests, BasicHttpBinding is the simplest of all web service–centric protocols. Specifically, this binding will ensure that your WCF service conforms to a specification named WS-I Basic Profile 1.1 defined by WS-I. The main reason to use this binding is to maintain backward compatibility with applications that were previously built to communicate with ASP.NET web services (which have been part of the .NET libraries since version 1.0).
The WSHttpBinding protocol not only incorporates support for a subset of the WS-* specification (transactions, security, and reliable sessions), but also supports the ability to handle binary data encoding using Message Transmission Optimization Mechanism (MTOM).
The main benefit of WSDualHttpBinding is that it adds the ability to allow the caller and sender to communicate using duplex messaging, which is just a fancy way of saying they can engage in a two-way conversation. When selecting WSDualHttpBinding, you can hook into the WCF publish/ subscribe event model.
Finally, WSFederationHttpBinding is the web service–based protocol you may wish to consider when security is of the utmost importance. This binding supports the WS-Trust, WS-Security, and WS-SecureConversation specifications, which are represented by the WCF CardSpace APIs.
TCP-Based Bindings
If you are building a distributed application involving machines that are configured with the .NET 3.0/3.5 libraries (in other words, all machines are running Windows XP, Windows Server 2003, or Windows Vista), you can gain performance benefits bypassing web service bindings and opting for a TCP binding, which ensures all data is encoded in a compact binary format rather than XML. Again, when using the bindings shown in Table 25-4, the client and host must be .NET applications.

|
CHAPTER 25 ■ INTRODUCING WINDOWS COMMUNICATION FOUNDATION |
883 |
||
Table 25-4. The TCP-Centric WCF Bindings |
|
|
|
|
|
|
|
|
|
Binding Class |
Binding Element |
Meaning in Life |
|
|
NetNamedPipeBinding |
<netNamedPipeBinding> |
A secure, reliable, optimized binding for on- |
|
|
|
|
the-same-machine communication between |
|
|
|
|
.NET applications |
|
|
NetPeerTcpBinding |
<netPeerTcpBinding> |
Provides a secure binding for P2P network |
|
|
|
|
applications |
|
|
NetTcpBinding |
<netTcpBinding> |
A secure and optimized binding suitable for |
|
|
|
|
cross-machine communication between .NET |
|
|
|
|
applications |
|
|
|
|
|
|
|
The NetTcpBinding class uses TCP to move binary data between the client and WCF service. As mentioned, this will result in higher performance than the web service protocols, but you are limited to an in-house Windows solution. On the plus side, NetTcpBinding does support transactions, reliable sessions, and secure communications.
Like NetTcpBinding, NetNamedPipeBinding supports transactions, reliable sessions, and secure communications, but it has no ability to make cross-machine calls. If you are looking for the fastest way to push data between WCF applications on the same machine (e.g., cross-application domain communications), NetNamedPipeBinding is the binding choice of champions. As far as NetPeerTcpBinding is concerned, consult the .NET Framework 3.5 documentation for details regarding P2P networking.
MSMQ-Based Bindings
Finally, if you are attempting to integrate with a Microsoft MSMQ server, the NetMsmqBinding and MsmqIntegrationBinding bindings are of immediate interest. We will not examine the details of using MSMQ bindings in this chapter, but Table 25-5 documents the basic role of each.
Table 25-5. The MSMQ-Centric WCF Bindings
Binding Class |
Binding Element |
Meaning in Life |
MsmqIntegrationBinding |
<msmqIntegrationBinding> |
This binding can be used to enable |
|
|
WCF applications to send and receive |
|
|
messages to and from existing MSMQ |
|
|
applications that use COM, native C++, |
|
|
or the types defined in the System. |
|
|
Messaging namespace. |
NetMsmqBinding |
<netMsmqBinding> |
This queued binding is suitable for |
|
|
cross-machine communication between |
|
|
.NET applications. |
|
|
|
A BRIEF NOTE ON COMMUNICATING WITH COM+ OBJECTS
Notice that there is not a specific binding to interact with COM+ objects. Communicating with COM+ components via WCF is entirely possible; however, doing so involves exposing the COM+ types through an XML web service binding via the ComSvcConfig.exe command-line tool that ships with the .NET Framework 3.5 SDK or by using the SvcConfigEditor.exe utility (which we will examine later in this chapter).

884 CHAPTER 25 ■ INTRODUCING WINDOWS COMMUNICATION FOUNDATION
Understanding WCF Addresses
Once the contracts and bindings have been established, the final piece of the puzzle is to specify an address for the WCF service. This is obviously quite important, in that remote callers will be unable to communicate with the remote types if they cannot locate them! Like most aspects of WCF, an address can be hard-coded in an assembly (via the System.Uri type) or offloaded to a *.config file.
In either case, the exact format of the WCF address will differ based on your choice of binding (HTTP based, named pipes, TCP based, or MSMQ based). From a high level, WCF addresses can specify the following bits of information:
•Scheme: The transport protocol (HTTP, etc.).
•MachineName: Fully qualified domain of the machine.
•Port: This is optional in many cases. For example, the default for HTTP bindings is port 80.
•Path: The path to the WCF service.
This information can be represented by the following generalized template (the Port value is optional, as some bindings make no use of them):
scheme://<MachineName>[:Port]/Path
When you are using a web service–based binding (basicHttpBinding, wsHttpBinding, wsDualHttpBinding, or wsFederationHttpBinding), the address breaks down as so (recall that if you do not specify a port number, HTTP-based protocols will default to port 80):
http://localhost:8080/MyWCFService
■Note If you wish to make use of Secure Sockets Layer (SSL), simply replace http with https.
If you are making use of TCP-centric bindings (such as NetTcpBinding or NetPeerTcpBinding), the URI takes the following format:
net.tcp://localhost:8080/MyWCFService
The MSMQ-centric bindings (NetMsmqBinding and MsmqIntegrationBinding) are a bit unique in their URI format, given that MSMQ can make use of public or private queues (which are available only on the local machine) and port numbers have no meaning within an MSMQ-centric URI. Consider the following URI, which describes a private queue named MyPrivateQ:
net.msmq://localhost/private$/MyPrivateQ
Last but not least, the address format used for the named-pipe binding, NetNamedPipeBinding, breaks down as so (recall that named pipes allow for interprocess communication for applications on the same physical machine):
net.pipe://localhost/MyWCFService
While a single WCF service might expose only a single address (based on a single binding), it is possible to configure a collection of unique addresses (with different bindings). This can be done within a *.config file by defining multiple <endpoint> elements. Here, you can specify any number of ABCs for the same service. This approach can be helpful when you want to allow callers to select which protocol they would like to use when communicating with the service.

CHAPTER 25 ■ INTRODUCING WINDOWS COMMUNICATION FOUNDATION |
885 |
Building a WCF Service
Now that you have a better understanding about the building blocks of a WCF application, let’s create our first sample application to see how the ABCs are accounted for in code. Our first step is to define our WCF service library consisting of the contracts and their implementations.
This first example will not use the Visual Studio WCF project templates, in order to keep focused on the specific steps involved in making a WCF service. To begin, create a new C# Class Library project named MagicEightBallServiceLib. Once you have done so, rename your initial file from Class1.cs to MagicEightBallService.cs and add a reference to the System.ServiceModel.dll assembly. In the initial code file, specify that you are using the System.ServiceModel namespace. At this point, your C# file should look like so:
using System;
using System.Collections.Generic; using System.Linq;
using System.Text;
// The key WCF namespace. using System.ServiceModel;
namespace MagicEightBallServiceLib
{
public class MagicEightBallService
{
}
}
Our class type will implement a single WCF service contract represented by a strongly typed CLR interface named IEightBall. As you most likely know, the Magic 8-Ball is a toy that allows you to view one of a handful of fixed answers to a question you may ask. Our interface will define a single method that allows the caller to pose a question to the Magic 8-Ball to obtain a random answer.
WCF service interfaces are adorned with the [ServiceContract] attribute, while each interface member is decorated with the [OperationContract] attribute (more details regarding these two attributes in just a moment). Here is the definition of the IEightBall interface:
[ServiceContract]
public interface IEightBall
{
// Ask a question, receive an answer!
[OperationContract]
string ObtainAnswerToQuestion(string userQuestion);
}
■Note It is permissible to define a service contract interface that contains methods not adorned with the [OperationContract] attribute. However, such members will not be exposed through the WCF runtime.
As you know from your study of the interface type (see Chapter 9), interfaces are quite useless until they are implemented by a class or structure, in order to flesh out their functionality. Like a real Magic 8-Ball, the implementation of our service type (MagicEightBallService) will randomly return a canned answer from an array of strings. Also, our default constructor will display an information message that will be (eventually) displayed within the host’s console window (for diagnostic purposes):

886 CHAPTER 25 ■ INTRODUCING WINDOWS COMMUNICATION FOUNDATION
public class MagicEightBallService : IEightBall
{
// Just for display purposes on the host. public MagicEightBallService()
{
Console.WriteLine("The 8-Ball awaits your question...");
}
public string ObtainAnswerToQuestion(string userQuestion)
{
string[] answers = { "Future Uncertain", "Yes", "No", "Hazy", "Ask again later", "Definitely" };
// Return a random response.
Random r = new Random();
return string.Format("{0}? {1}.",
userQuestion, answers[r.Next(answers.Length)]);
}
}
At this point, our WCF service library is complete. However, before we construct a host for this service, let’s examine some additional details of the [ServiceContract] and [OperationContract] attributes.
The [ServiceContract] Attribute
In order for a CLR interface to participate in the services provided by WCF, it must be adorned with the [ServiceContract] attribute. Like many other .NET attributes, the ServiceContractAttribute type supports a number of properties to further qualify its intension. Two properties, Name and Namespace, can be set to control the name of the service type and the name of the XML namespace defining the service type. If you are using a web service–specific binding, these values are used to define the <portType> elements of the related WSDL document.
Here, we have not bothered to assign a Name value, given that the default name of the service type is directly based on the C# class name. However, the default name for the underlying XML namespace is simply http://tempuri.org (which really should be changed for all of your WCF services).
When you are building a WCF service that will send and receive custom data types (which we are currently not doing), it is important to establish a meaningful value to the underlying XML namespace, as this will make sure that your custom types are unique. As you may know from your experience building XML web services, XML namespaces provide a way to wrap your custom types in a unique container to ensure that your types do not clash with types in another organization.
For this reason, we can update our interface definition with a more fitting definition, which, much like the process of defining an XML namespace in a .NET Web Service project, is typically the URI of the service’s point of origin, for example:
[ServiceContract(Namespace = "http://Intertech.com")] public interface IEightBall
{
...
}
Beyond Namespace and Name, the [ServiceContract] attribute can be configured with the additional properties shown in Table 25-6. Be aware that some of these settings will be ignored depending on your selection of binding.

CHAPTER 25 ■ INTRODUCING WINDOWS COMMUNICATION FOUNDATION |
887 |
Table 25-6. Various Named Properties of the [ServiceContract] Attribute
Property |
Meaning in Life |
CallbackContract |
Establishes if this service contract requires callback functionality for two- |
|
way message exchange. |
ConfigurationName |
The name used to locate the service element in an application configuration |
|
file. The default is the name of the service implementation class. |
ProtectionLevel |
Allows you to specify the degree to which the contract binding requires |
|
encryption, digital signatures, or both for endpoints that expose the |
|
contract. |
SessionMode |
Used to establish if sessions are allowed, not allowed, or required by this |
|
service contract. |
|
|
The [OperationContract] Attribute
Methods that you wish to be used within the WCF framework must be attributed with the [OperationContract] attribute, which may also be configured with various named properties. Using the properties shown in Table 25-7, you are able to declare that a given method is intended to be one-way in nature, supports asynchronous invocation, requires encrypted message data, and so forth (again, many of these values may be ignored based on your binding selection).
Table 25-7. Various Named Properties of the [OperationContract] Attribute
Property |
Meaning in Life |
Action |
Gets or sets the WS-Addressing action of the request message. |
AsyncPattern |
Indicates if the operation is implemented asynchronously using a Begin/End |
|
method pair on the service. This allows the service to offload processing to |
|
another server-side thread; this has nothing to do with the client calling the |
|
method asynchronously! |
IsInitiating |
Specifies if this operation can be the initial operation in a session. |
IsOneWay |
Indicates if the operation consists of only a single input message (and no |
|
associated output). |
IsTerminating |
Specifies if the WCF runtime should attempt to terminate the current session |
|
after the operation completes. |
|
|
For this initial example, we don’t need to configure the ObtainAnswerToQuestion() method with additional traits, so the [OperationContract] attribute can be used as currently defined.
Service Types As Operational Contracts
Finally, recall that the use of interfaces is not required when building WCF service types. It is in fact possible to apply the [ServiceContract] and [OperationContract] attributes directly on the service type itself:
//This is only for illustrative purposes
//and not used for the current example.
[ServiceContract(Namespace = "http://Intertech.com")] public class ServiceTypeAsContract
{
[OperationContract] void SomeMethod() { }

888 CHAPTER 25 ■ INTRODUCING WINDOWS COMMUNICATION FOUNDATION
[OperationContract] void AnotherMethod() { }
}
Although this approach is possible, there are many benefits to explicitly defining an interface type to represent the service contract. The most obvious benefit is that a given interface can be applied to multiple service types (authored in a variety of languages and architectures) to achieve a high degree of polymorphism. Another benefit is that a service contract interface can be used as the basis of new contracts (via interface inheritance), without having to carry any implementation baggage.
In any case, at this point our first WCF service library is complete. Compile your project to ensure you do not have any typos.
■Source Code The MagicEightBallServiceLib project is located under the Chapter 25 subdirectory.
Hosting the WCF Service
We are now ready to define a host. Although a production-level service would be hosted from a Windows service or an IIS virtual directory, our first host will be a simple console named MagicEightBallServiceHost.
Once you have created this new Console Application project, add a reference to the System. ServiceModel.dll and MagicEightBallServiceLib.dll assemblies, and update your initial code file by importing the System.ServiceModel and MagicEightBallServiceLib namespaces:
using System;
using System.Collections.Generic; using System.Linq;
using System.Text;
using System.ServiceModel; using MagicEightBallServiceLib;
namespace MagicEightBallServiceHost
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("***** Console Based WCF Host *****");
Console.ReadLine();
}
}
}
The first step you must take when building a host for a WCF service type is to decide whether you want to define the necessary hosting logic completely in code or to relegate several low-level details to an application configuration file. As mentioned, the benefit of *.config files is that the host is able to change the underlying plumbing without requiring you to recompile and redeploy the executable. However, always remember this is strictly optional, as you can hard-code the hosting logic using the types within the System.ServiceModel.dll assembly.

CHAPTER 25 ■ INTRODUCING WINDOWS COMMUNICATION FOUNDATION |
889 |
This console-based host will indeed make use of an application configuration file, so insert a new Application Configuration File into your current project using the Project Add New Item menu option.
Establishing the ABCs Within an App.config File
When you are building a host for a WCF service type, you will follow a very predictable set of steps— some via configuration and some via code:
1.Define the endpoint for the WCF service being hosted within the host’s configuration file.
2.Programmatically make use of the ServiceHost type to expose the service types available from this endpoint.
3.Ensure the host remains running to service incoming client requests. Obviously, this step is not required if you are hosting your service types using a Windows service or IIS.
In the world of WCF, the term “endpoint” simply represents the address, binding, and contract rolled together in a nice tidy package. In XML, an endpoint is expressed using the <endpoint> element and the address, binding, and contract elements. Update your *.config file to specify a single endpoint (reachable via port 8080) exposed by this host:
<?xml version="1.0" encoding="utf-8" ?> <configuration>
<system.serviceModel>
<services>
<service name="MagicEightBallServiceLib.MagicEightBallService"> <endpoint address ="http://localhost:8080/MagicEightBallService"
binding="basicHttpBinding"
contract="MagicEightBallServiceLib.IEightBall"/>
</service>
</services>
</system.serviceModel>
</configuration>
Notice that the <system.serviceModel> element is the root for all of a host’s WCF settings. Each service exposed by the host is represented by a <service> element, wrapped within the <services> base element. Here, our single <service> element makes use of the (optional) name attribute to specify the friendly name of the service type.
The nested <endpoint> element handles the task of defining the address, the binding model (basicHttpBinding in this example), and the fully qualified name of the interface type defining the WCF service contract (IEightBall). Because we are using an HTTP-based binding, we make use of the http:// scheme, specifying an arbitrary port ID.
Coding Against the ServiceHost Type
With the current configuration file in place, the actual programming logic required to complete the host is painfully simple. When our executable starts up, we will create an instance of the ServiceHost type. At runtime, this object will automatically read the data within the scope of the <system.serviceModel> element of the host’s *.config file to determine the correct address, binding, and contract, and create the necessary plumbing:
static void Main(string[] args)
{
Console.WriteLine("***** Console Based WCF Host *****");

890 CHAPTER 25 ■ INTRODUCING WINDOWS COMMUNICATION FOUNDATION
using (ServiceHost serviceHost = new ServiceHost(typeof(MagicEightBallService)))
{
//Open the host and start listening for incoming messages. serviceHost.Open();
//Keep the service running until the Enter key is pressed.
Console.WriteLine("The service is ready."); Console.WriteLine("Press the Enter key to terminate service."); Console.ReadLine();
}
}
If you now run this application, you will find that the host is alive in memory, ready to take incoming requests from remote clients (see Figure 25-6).
Figure 25-6. Our host, ready for external calls via basic HTTP binding
Host Coding Options
Currently, we are creating our ServiceHost using a constructor that simply requires the service’s type information. However, it is also possible to pass in an array of System.Uri types as a constructor argument to represent the collection of addresses this service is accessible from. Currently, the address is found via the *.config file; however, if we were to update the using scope as so:
using (ServiceHost serviceHost = new ServiceHost(typeof(MagicEightBallService), new Uri[]{new Uri("http://localhost:8080/MagicEightBallService")}))
{
...
}
we would be able to define our endpoint as so:
<endpoint address ="" binding="basicHttpBinding"
contract="MagicEightBallServiceLib.IEightBall"/>
Of course, too much hard-coding within a host’s code base decreases flexibility, so for the purposes of this current host example, I’ll assume you are creating the service host simply by supplying the type information as we did before:
using (ServiceHost serviceHost = new ServiceHost(typeof(MagicEightBallService)))
{
...
}
One of the (slightly frustrating) aspects of authoring host *.config files is that you have a number of ways to construct the XML descriptors, based on the amount of hard-coding you have in the code base (as you have just seen in the case of the optional Uri array). To show yet another way to author *.config files, consider the following reworking:

CHAPTER 25 ■ INTRODUCING WINDOWS COMMUNICATION FOUNDATION |
891 |
<?xml version="1.0" encoding="utf-8" ?> <configuration>
<system.serviceModel>
<services>
<service name="MagicEightBallServiceLib.MagicEightBallService">
<!-- Address obtained from <baseAddresses> -->
<endpoint address ="" binding="basicHttpBinding"
contract="MagicEightBallServiceLib.IEightBall"/>
<!-- List all of the base addresses in a dedicated section-->
<host>
<baseAddresses>
<add baseAddress ="http://localhost:8080/MagicEightBallService"/> </baseAddresses>
</host>
</service>
</services>
</system.serviceModel>
</configuration>
In this case, the address attribute of the <endpoint> element is still empty, and regardless of the fact that we are not specifying an array of Uri objects in code when creating the ServiceHost, the application runs as before as the value is pulled from the baseAddresses scope. The benefit of storing the base address in a <host>’s <baseAddresses> region is that other parts of a *.config file (such as MEX, described shortly) also need to know the address of the service’s endpoint. Thus, rather than having to copy and pass address values within a single *.config file, we can isolate the single value as shown here.
■Note In a later example, I’ll introduce you to a graphical configuration tool that allows you to author configuration files in a less tedious manner.
In any case, before we build a client application to communicate with our service, let’s dig a bit deeper into the role of the ServiceHost class type and <service.serviceModel> element as well as the role of metadata exchange (MEX) services.
Details of the ServiceHost Type
The ServiceHost class type is used to configure and expose a WCF service from the hosting executable. However, be aware that you will only make direct use of this type when building a custom *.exe to host your services. If you are using IIS (or the Vista-specific WAS) to expose a service, the ServiceHost object is created automatically on your behalf.
As you have seen, this type requires a complete service description, which is obtained dynamically through the configuration settings of the host’s *.config file. While this happens automatically upon object creation, it is possible to manually configure the state of your ServiceHost object using a number of members. In addition to Open() and Close() (which communicate with your service in a synchronous manner), Table 25-8 illustrates some further members of interest.