A service is a unit of functionality exposed to the world. In that respect, it is the next evolutionary step in the long journey from functions to objects to components to services. Service orientation (SO) is an abstract set of principles and best practices for building service-oriented applications. Appendix A provides a concise overview and outlines the motivation for using this methodology. The rest of this book assumes you are familiar with these principles. A service-oriented application aggregates services into a single logical application, similar to the way a component-oriented application aggregates components and an object-oriented application aggregates objects, as shown in Figure 1-1.
The services can be local or remote, can be developed by multiple parties using any technology, can be versioned independently, and can even execute on different timelines. Inside a service, you will find concepts such as languages, technologies, platforms, versions, and frameworks, yet between services, only prescribed communication patterns are allowed.
The client of a service is merely the party consuming its functionality. The client can be literally anything—for instance, a Windows Forms, WPF, or Silverlight class, an ASP.NET page, or another service.
Clients and services interact by sending and receiving messages. Messages may be transferred directly from the client to the service or be sent via an intermediary such as the Windows Azure AppFabric Service Bus. With WCF, messages are usually SOAP messages. These messages are independent of transport protocols—unlike web services, WCF services may communicate over a variety of transports (not just HTTP). WCF clients may interoperate with non-WCF services, and WCF services can interact with non-WCF clients. That said, if you develop both the client and the service, you can typically construct the application so that both ends require WCF in order to utilize WCF-specific advantages.
Because the making of the service is opaque from the outside, a WCF service typically exposes metadata describing the available functionality and possible ways of communicating with the service. The metadata is published in a predefined, technology-neutral way, such as using WSDL (Web Services Description Language) over HTTP-GET or an industry standard for metadata exchange over any protocol. A non-WCF client can import the metadata to its native environment as native types. Similarly, a WCF client can import the metadata of a non-WCF service and consume it as native CLR classes and interfaces.
With WCF, the client never interacts with a service directly, even when dealing with a local, in-memory service. Instead, the client always uses a proxy to forward calls to the service. The proxy exposes the same operations as the service, plus some proxy-management methods.
WCF allows the client to communicate with a service across all execution boundaries. On the same machine, the client can consume services in the same app domain, across app domains in the same process, or across processes (see Figure 1-2).
Across machine boundaries (Figure 1-3), the client can interact with services in its intranet or across the Internet.
In the past, distributed computing technologies such as DCOM and .NET remoting aspired to provide the same programming model to the client regardless of whether the object was local or remote. In the case of a local call, the client used a direct reference, and when dealing with a remote object, the client used a proxy. The problem with trying to use the local programming model as the remote programming model was that there is much more to a remote call than an object with a wire. Complex issues such as lifecycle management, reliability, state management, and security reared their heads, making the remote programming model significantly more complex. Numerous problems arose, all because the remote object was trying to be what it is not—a local object.
WCF also strives to provide the client with the same programming model regardless of the location of the service. However, the WCF approach is the exact opposite: it takes the remote programming model of instantiating and using a proxy and uses it even in the most local case. Because all interactions are done via a proxy, requiring the same configuration and hosting, WCF maintains the same programming model for the local and remote cases; thus, it not only enables you to switch locations without affecting the client, but also significantly simplifies the application programming model. Another important benefit of always using a proxy is that it enables WCF to intercept the calls and add its value, as you will see later on.