There are multiple aspects of communication with any given service, and there are many possible communication patterns: messages can follow a synchronous request-reply or asynchronous fire-and-forget pattern, messages can be bidirectional, messages can be delivered immediately or queued, and the queues can be durable or volatile. As discussed previously, there are many possible transport protocols for the messages, such as HTTP (or HTTPS), TCP, IPC, and MSMQ. There are also a few possible message encoding options: you can choose plain text to enable interoperability, binary encoding to optimize performance, or the Message Transport Optimization Mechanism (MTOM) for large payloads. Finally, there are multiple options for securing messages: you can choose not to secure them at all, to provide transport-level security only, or to provide message-level privacy and security, and of course there are numerous ways to authenticate and authorize the clients. Message delivery might be unreliable or reliable end-to-end across intermediaries and dropped connections, and the messages might be processed in the order they were sent or in the order they were received. Your service might need to interoperate with other services or clients that are aware of only the basic web service protocol, or with clients and services capable of using the score of WS-* modern protocols, such as WS-Security and WS-Atomic Transactions. Your service may need to be able to interoperate with any client, or you may want to restrict your service to interoperate only with another WCF service or client.
If you were to count all the possible communication and interaction options, you'd probably find that the number of permutations is in the tens of thousands. Some of those choices may be mutually exclusive, and some may mandate other choices. Clearly, both the client and the service must be aligned on all these options in order to communicate properly. Managing this level of complexity adds no business value to most applications, and yet the productivity and quality implications of making the wrong decisions are severe.
To simplify these choices and make them manageable, WCF groups together sets of such communication aspects in bindings. A binding is merely a consistent, canned set of choices regarding the transport protocol, message encoding, communication pattern, reliability, security, transaction propagation, and interoperability. All you need to do is decide on the target scenario for your service, and WCF makes a correct multidimensional decision for you regarding all the aspects of the communication. Ideally, you would extract all these "plumbing" aspects from your service code and allow the service to focus solely on the implementation of the business logic. Bindings enable you to use the same service logic over drastically different plumbing.
You can use the WCF-provided bindings out-of-the-box, you can tweak their properties, or you can write your own custom bindings from scratch. The service publishes its choice of binding in its metadata, enabling clients to query for the type and specific properties of the binding. This is important because the client must use the exact same binding values as the service. A single service can support multiple bindings on separate addresses.
WCF defines six frequently used bindings:
Offered by the BasicHttpBinding
class, this
is designed to expose a WCF service as a legacy ASMX web service, so that old
clients can work with new services. The basic binding makes your service look, on
the wire, like a legacy web service that communicates over the basic web service
profile. When used by clients, this binding enables new WCF clients to work with old
ASMX services.
Offered by the NetTcpBinding
class, this uses
TCP for cross-machine communication on the intranet. It supports a variety of
features, including reliability, transactions, and security, and is optimized for
WCF-to-WCF communication. As a result, it requires both the client and the service
to use WCF.
Offered by the NetNamedPipeBinding
class,
this uses named pipes as a transport for same-machine communication. It is the most
secure binding, since it cannot accept calls from outside the machine. The IPC
binding supports a variety of features, similar to the TCP binding. It is also the
most performant binding, since IPC is a lighter protocol than TCP.
The NetNamedPipeBinding
class is named
incorrectly, since the binding naming convention is to refer to the protocol, not
the communication mechanism (thus, we have NetTcpBinding
rather than NetSocketBinding
). The correct name for this binding should have been
NetIpcBinding
. Throughout this book, I will
refer to the NetNamedPipeBinding
as the IPC
binding.
Offered by the WSHttpBinding
class, this uses
HTTP or HTTPS for transport, and is designed to offer a variety of features (such as
reliability, transactions, and security) over the Internet, all using the WS-*
standards. This binding is designed to interoperate with any party that supports the
WS-* standards.
Offered by the WSDualHttpBinding
class, this
is similar to the WS binding except it also supports bidirectional duplex
communication from the service to the client, as discussed in Chapter 5. While this binding does use industry standards (it is
nothing more than two WSHttpBinding
bindings
wired up against each other to support callbacks), there is no industry standard for
setting up the callback, and therefore the WSDualHttpBinding
is not interoperable.
Offered by the NetMsmqBinding
class, this
uses MSMQ for transport and is designed to offer support for disconnected queued
calls. Using this binding is the subject of Chapter 9.
Each of the frequently used bindings uses a different transport schema and encoding, as listed in Table 1-1. Where multiple encodings are possible, the defaults are shown in bold.
Table 1-1. Transport and encoding for common bindings
Name |
Transport |
Encoding |
Interoperable |
---|---|---|---|
|
HTTP/HTTPS |
Text, MTOM |
Yes |
|
TCP |
Binary |
No |
|
IPC |
Binary |
No |
|
HTTP/HTTPS |
Text, MTOM |
Yes |
|
HTTP |
Text, MTOM |
No |
|
MSMQ |
Binary |
No |
Having a text-based encoding typically enables a WCF service (or client) to communicate over HTTP with any other service (or client), regardless of its technology and across firewalls. Binary encoding over TCP, IPC, or MSMQ yields the best performance, but at the expense of interoperability, because it mandates WCF-to-WCF communication. That said, with the TCP, IPC, and MSMQ bindings, interoperability is often not required. In the case of IPC, since the call can never leave the client machine, the client can rest assured that the target machine is running Windows and has WCF installed on it. In the case of the TCP binding, while your application may need to interoperate with other applications written in other technologies, internally applications themselves do tend to be homogeneous. As such, as long as your application spans only the local intranet, you can typically assume a homogenous Windows environment, without internal firewalls between machines. Finally, the MSMQ binding requires the use of MSMQ server, which of course is Windows-specific.
This binary encoder used by the TCP, IPC, and MSMQ bindings is proprietary to WCF. Do not attempt to write a custom parser for it on other platforms. Microsoft reserves the right to change its format over time, in order to keep optimizing and evolving it.
When choosing a binding for your service, you should follow the decision diagram shown in Figure 1-4.
The first question you should ask yourself is whether your service needs to interact
with non-WCF clients. If the answer is yes, and those clients expect the basic web service
protocol (ASMX web services), choose the BasicHttpBinding
, which exposes your WCF service to the outside world as if
it were an ASMX web service (that is, a WSI-basic profile). The downside of this choice is
that you cannot take advantage of most of the modern WS-* protocols. If, however, the
non-WCF client can understand these standards, you can instead choose one of the WS
bindings (WSHttpBinding
or WSDualHttpBinding
). If you can assume that the client is a WCF client and yet
requires offline or disconnected interaction, choose the NetMsmqBinding
, which uses MSMQ for transporting the messages. If the client
requires connected communication but could be calling across machine boundaries, choose
the NetTcpBinding
, which communicates over TCP. If the
client is on the same machine as the service, choose the NetNamedPipeBinding
, which uses IPC to maximize performance.
Most bindings work well even outside their target scenarios. For example, you could use the TCP binding for same-machine or even in-proc communication, and you could use the basic binding for intranet WCF-to-WCF communication. However, do try to choose a binding according to Figure 1-4.
In addition to the six frequently used bindings described so far, WCF provides three
specializations of these bindings: the BasicHttpContextBinding
, the WSHttpContextBinding
, and the NetTcpContextBinding
. The context bindings (described in Appendix B) all derive from their respective regular bindings,
adding support for a context protocol. The context protocol allows you to pass out-of-band
parameters to the service. The context bindings can also be used for durable services
support, as described in Chapter 4.
Finally, WCF defines six infrequently used bindings. These bindings (listed next) are each designed for a specific target scenario and cannot easily be used outside that scenario. This book makes no use of these bindings, due to their somewhat esoteric nature:
Offered by the NetPeerTcpBinding
class, this
uses peer networking as a transport: the peer-network-enabled client and services
all subscribe to the same grid and broadcast messages to it. Peer networking is
beyond the scope of this book, since it requires an understanding of grid topology
and mesh computing strategies.
Offered by the WSFederationHttpBinding
class,
this is a specialization of the WS binding that offers support for federated
security. Federated security is beyond the scope of this book, since by and large,
the industry presently lacks good support (both in technology and in business
models) for true federated scenarios. I do expect federation to become mainstream as
time goes by.
Offered by the WS2007FederationHttpBinding
class, this is an update of WSFederationHttpBinding
.
Offered by the MsmqIntegrationBinding
class,
this is the analogous queued-world binding to the basic binding. The integration
binding converts WCF messages to and from MSMQ messages and is designed to
interoperate with legacy MSMQ clients.
Offered by the WebHttpBinding
class, this
binding allows your service to accept simple calls over web protocols such as
HTTP-GET using the REST/POX/JSON patterns. This binding could be useful for a
web-scripting client such as an AJAX page.
Offered by the WS2007HttpBinding
class, this
binding derives from the WSHttpBinding
class; it
adds support for the emerging coordination standard, as well as updates for the
transaction, security, and reliability standards.
Each binding offers literally dozens of configurable properties. There are three ways of working with bindings: you can use the built-in bindings as they are, if they fit your requirements; you can tweak and configure some of their properties, such as transaction propagation, reliability, and security; or you can write your own custom bindings. The most common scenario is using an existing binding mostly as it is, and merely configuring two or three of its aspects. Application developers will hardly ever need to write a custom binding, but framework developers may need to.
52.15.176.80