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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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 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.)
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.