Fundamental WCF Concepts

At its core, WCF is a development platform for service-oriented applications. As I mentioned earlier, WCF is part of the .NET Framework 3.0, which comprises a set of new assemblies that rely on the .NET Framework 2.0. System.ServiceModel is the assembly that contains core functionality for WCF, which explains why the WCF platform is often called the service model. Any project that exposes or consumes WCF services must reference the System.ServiceModel assembly, and possibly other supporting assemblies.

Before you can begin to do interesting things with the service model, it helps to understand the core features that make it possible to create, host, and consume services. In this section, I will briefly summarize some of the concepts that will be elaborated on in this chapter, to help you on your way.

Message Serialization

All enterprise applications at some point must make remote calls across process and machine boundaries. This is handled by sending messages between applications. The format of the message is what determines an application’s ability to communicate with other applications. Remote procedure calls (RPC) and XML messaging formats are two common ways for applications to communicate.

RPC calls are used to communicate with objects (components) across boundaries—for example, calls from a client application to a remote object living in another process. RPC calls are marshaled by converting them to messages and sending them over a transport protocol such as TCP. When the message reaches its destination, it is un-marshaled and converted into a stack frame that invokes the object. This is all usually handled transparently through a client proxy and stub at the destination. Both proxy and stub know how to construct and deconstruct messages. This process is known as serialization and deserialization.

Figure 1-14 illustrates the serialization and deserialization process (often just called serialization) from a high level. As I mentioned, the transport carries a message according to the agreed-upon format of both the client and remote application. As far as the client is concerned, it is usually working with a proxy that looks like the remote object. When a method is invoked at the client, the proxy invokes underlying plumbing of the technology (for example, Enterprise Services or .NET Remoting) to serialize the outgoing message. The remote application usually listens for messages on a particular port, and as they arrive, deserializes those messages (using the same technology) to build a stack frame and invoke the appropriate method on the remote object. The method return is likewise serialized by the underlying plumbing and returned to the client, at which time the plumbing deserializes the message and constructs a stack frame for the response. RPC communication like this comes in many flavors, and each flavor is generally not compatible with another—that’s why RPC is not interoperable.

RPC serialization and deserialization

Figure 1-14. RPC serialization and deserialization

To achieve interoperability, systems rely on a standard format for messages understood by both ends of the communication. Applications still exchange messages, but they are formatted in XML according to known protocols. The technology used to support this is traditionally associated with web services such as ASMX, WSE, or WCF. As Figure 1-15 illustrates, the serialization process is consistent with RPC, the key difference being the underlying plumbing, the format of the message, and the target object, which is usually a web service. The other difference is in the lifetime of the service. While remote objects are frequently kept alive for the duration of a client session, web services are typically constructed anew for each call.

Web service serialization and deserialization

Figure 1-15. Web service serialization and deserialization

WCF can be used to achieve both RPC-style messaging and web service messaging. In both cases, the type that ultimately processes messages is a service type, but its lifetime can be controlled to behave like traditional client-server components or like web services without the notion of a session. The service model handles all serialization activities based on configuration settings.

Services

WCF applications expose functionality through services. A service is a Common Language Runtime (CLR) type that encapsulates business functionality and exposes a set of methods that can be accessed by remote clients. In order for a regular CLR type to be considered a service it must implement a service contract.

A service contract is defined by applying the ServiceContractAttribute to a class or interface. When applied to a class, the class becomes a service type. When applied to an interface, any class that implements the interface becomes a service type. In either case, methods exposed by the class or interface must be decorated with the OperationContractAttribute to be considered part of the service contract. Methods with this attribute are considered service operations.

A service type must be hosted before clients can invoke service operations.

Hosting

Service functionality is made available at runtime through a host process—any managed process will do the trick. Many hosting options are available for WCF services, including:

Self-hosting

This includes console applications, Windows Forms or WPF applications, or Windows services.

Internet Information Services (IIS)

Services can be hosted alongside other ASP.NET applications, for example.

Windows Activation Service (WAS)

This is similar to IIS hosting but is only available to IIS 7.0.

Tip

Each hosting environment has its benefits and appropriate uses, which will be discussed in Chapter 4.

Although a host process is important, ultimately it is the service model that knows how to process messages targeting a service. For this a ServiceHost instance is associated with each service type. ServiceHost is part of the service model and is responsible for initializing communication channels that receive messages to a service. Basically, to host any service, you construct a ServiceHost, provide it with a service type to activate for incoming messages, provide it with one or more addresses where the service can be located along with the service contract supported by each address, and provide it with the supported communication protocols.

You can think of the ServiceHost as responsible for managing the lifetime of the communication channels for the service.

Endpoints

When the ServiceHost opens a communication channel for a service, it must expose at least one endpoint for the service so that clients can invoke operations. In fact, endpoints are the key to invoking service functionality. An endpoint describes where services can be reached, how they can be reached, and what operations can be reached. Thus, endpoints have three key parts:

Address

Refers to the URI where messages can be sent to the service.

Binding

Bindings indicate the protocols supported when messages are sent to a particular address.

Contract

Each address supports a specific set of operations, as described by a service contract.

The ServiceHost is provided with a list of endpoints before the communication channel is opened. These endpoints each receive messages for their associated operations over the specified protocols.

Addresses

Each endpoint is associated with an address, identified by a URI. An address has a scheme, domain, port, and path in the following format: scheme://domain[:port]/[path].

The scheme indicates the transport protocol being used, such as TCP, named pipes, HTTP, or MSMQ. Respectively, the schemes for these protocols are net.tcp, net.pipe, http, and net.msmq. The domain refers to either a machine name or web domain. Sometimes localhost is used for communications on the same machine. The port can be specified to use a specific communication port other than the default for the protocol identified by the scheme. For example, HTTP defaults to port 80. Here are some examples of valid base addresses before specifying a path:

net.tcp://localhost:9000
net.pipe://mymachinename
http://localhost:8000
http://www.anydomain.com
net.msmq://localhost

A path is usually provided as part of the address to disambiguate service endpoints. The path does not usually include a filename for self-hosting, but with IIS (as you will see later in this chapter) a physical file is implicitly included in the address. These are valid self-hosting addresses that include paths:

net.tcp://localhost:9000/ServiceA
net.pipe://mymachinename/ServiceB
http://localhost:8000/Services/ServiceA
http://www.mydomain.com/ServiceA
net.msmq://localhost/QueuedServices/ServiceA

When you add endpoints to a ServiceHost instance, you must specify a unique address for each endpoint. That means that you must vary at least one of the scheme, domain, port, or path specified.

Bindings

A binding describes the protocols supported by a particular endpoint, specifically, the following:

  • The transport protocol, which can be TCP, named pipes, HTTP, or MSMQ

  • The message encoding format, which determines whether messages are serialized as binary or XML, for example

  • Other messaging protocols related to security and reliability protocols, plus any other custom protocols that affect the contents of the serialized message

There are a number of predefined bindings (called standard bindings) provided by the service model. These standard bindings represent a set of typical protocols representative of common communication scenarios. Bindings are discussed in detail in Chapter 3.

Metadata

Once the ServiceHost is configured for one or more endpoints, and communication channels are open, service operations can be invoked at each endpoint. This is according to the protocols supported by each endpoint. Clients invoke service operations at a particular endpoint. To do so, they need information about the endpoint, including the address, the binding, and the service contract. Information about service endpoints is part of the metadata for a particular service. Clients rely on this metadata to generate proxies to invoke the service.

Metadata can be accessed in two ways. The ServiceHost can expose a metadata exchange endpoint to access metadata at runtime, or it can be used to generate a WSDL document representing the endpoints and protocols supported by the service. In either case, clients use tools to generate proxies to invoke the service.

Tip

You’ll explore different ways to work with service metadata throughout this chapter, and Chapter 2 discusses metadata in further detail.

Proxies

Clients communicate with services using proxies. A proxy is a type that exposes operations representative of a service contract that hides the serialization details from the client application when invoking service operations. For WCF applications, proxies are based on the service contract, so if you have access to the service contract definition, you can create a proxy instance to invoke the service. Before the proxy instance can be used to call service operations, it must be provided with information about one of the endpoints exposed for that service contract—there is a one-to-one relationship between proxy and endpoint.

Tools also exist to generate proxies and endpoint configurations from metadata. In this chapter, you will learn how to create a proxy manually, without generating metadata, and how to use proxy generation tools. In either case, the client must open a communication channel with the service to invoke operations. This channel must be compatible with the channel exposed by the ServiceHost for communications to work.

Channels

Channels facilitate communication between clients and services in WCF. The ServiceHost creates a channel listener for each endpoint, which generates a communication channel. The proxy creates a channel factory, which generates a communication channel for the client. Both communication channels must be compatible for messages between them to be processed effectively. In fact, the communication channel is comprised of a layered channel stack—each channel in the stack is responsible for performing a particular activity while processing a message. The channel stack includes a transport channel, a message-encoding channel, and any number of message processing channels for security, reliability, and other features. Without getting into specifics, the binding controls which channels participate in the channel stack, as shown in Figure 1-16. (The details of channels and bindings are explored in Chapter 3.)

Messages are processed by equivalent channels at the client and service

Figure 1-16. Messages are processed by equivalent channels at the client and service

Behaviors

Behaviors also influence how messages are processed by the service model. While services and endpoints determine the core communication requirements and metadata shared with clients, a behavior modifies the way messages are processed as they flow through the channel stack. Behaviors are local to the client or service—thus, they are not included in metadata.

There are behaviors to control many service model features such as exposing metadata, authentication and authorization, transactions, message throttling, and more. Behaviors are enabled either in configuration or by applying behavior attributes to client proxies and services.

Tip

In this chapter, you’ll learn how to apply the metadata behavior to a service, but other behaviors will be explored throughout this book as they relate to each feature.

Get Learning WCF now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.