Introduction
The first days of networking and communications, system developers used to employ concrete Network APIs such as Sockets, MSMQ , Remoting, and traditional web services to implement distributed systems. WCF came into the field and filled all the gaps uniting those functionalities into one integrated solution. WCF is a must for every system that needs communication between nodes– it is standard, well designed, and is an excellent fit for any distribution scenario that you may think about. This paper starts with an overview of SOA architecture and covers basic and essential WCF concepts.
It is expected that you are familiar with OO programming, Web Services, WSDL, Advanced C#, SOAP, SOA, and related Network concepts.
In a very general view, a WCF service can be seen as an advanced web service; meaning it has a lot of options and possibilities to get configured, designed and extended. But the way you define it differs from traditional web services.
We’re going to deal with the following basic concepts:
SOA in WCF
- SOA in WCF
- Contracts [Service, Data]
- Communication Directions [Duplex, Paired, …]
- Complex Data Types
- Endpoints and basic Preconfigured Bindings
- WCF Projects [In-Process, Syndication, …]
SOA in WCF
SOA is all about having a standard base architecture in which services can be integrated, deployed in a loosely coupled manner, and because they are platform-neutral they can communicate with each other easily– thus improving the interoperability. Therefore every service inside SOA must be well-defined and comply with existing SOA standards. SOA uses a message-based approach over common protocols that all platforms would be able to deal with. In SOA, each service acts like a component that provides a part of services that other client nodes or services might need; therefore you can imagine it as a network of distributed components that are implemented and provide services complying with SOA principles. In SOA, a service exposes its service contract to clients, and because the data layer is connected to the interface layer in a loosely coupled manner the service can provide many options and possibilities; therefore the client can choose the desired interface from the available service interfaces to communicate and send/receive data through.
Some important constraints of SOA architecture:
- Messages must be self-descriptive and should enable service extendibility; they should expose the required characteristics and enough information of a service or the message itself, and should contain the related information to get easily processed by any kind of client over different channels and platforms.
- User simpler and lighter message structures; message elements such as data types should be simple and platform-neutral.
- Messages should contain discovery information through which a service can be discovered and other available services identified.
Note that because services are distributed, chances are that some services fail or stop responding for a moment thus making problems, exceptions, and etc. In such situations, the following solutions should be taken into consideration:
- Services, especially some real-time critical services, need availability and reliability, therefore enhance availability and reliability in a system that the service resides in.
- The business logic of the system employing the service should be able to handle such exceptions. There are different approaches like transactions, back-up servers and etc.
Endpoints and Bindings
Each of the WCF nodes needs to know the other party’s endpoint to initiate communication. Let’s first define what an endpoint means. An endpoint is the address of a client or a server node making it possible for nodes to communicate and send and receive messages. Suppose that a client is going to send a message to the server; it should have the address (endpoint) of the server and format the sending message according to the service contract of the server so that the server can understand the message and respond to the message appropriately. In order for a WCF node to become a message receiver and be able to respond to incoming messages, it should be hosted inside IIS or WAS, or ultimately it can implement a stand-alone host itself in its own app process.
An endpoint has three important components:
1) Address
It is simply the location of the service and consists of an IP address or a DNS plus the WCF service name.
Protocol://SERVER/SERVICE-NAME
Or in case that a virtual directory is used:
Protocol://SERVER/VIRTUAL-DIR/SERVICE-NAME
2) Binding
Message-passing between nodes is done through a communication channel, binding defines the type of the channel for communication; it could be TCP, HTTP, MSMQ and some others. In other words, a binding is a collection of binding elements that each portraits the characteristics of a communication channel. WCF has several pre-configured bindings, and they all have their own binding elements that define their behaviors. As an example, wsHttpBinding contains the binding elements for HTTP protocol and complies with WS-* standard protocols.
Note that the bindings that start with ws, are standard and designed for interoperability scenarios; for example a Java application would use wsHttpBinding to communicate with a WCF service. Bindings that start with net are used only for .NET; therefore in this case both the client and the server must be a .NET application.
There are also other bindings but for the case of simplicity and practicality, the following bindings are recommended:
- basicHttpBinding
It is a binding for WS-I Basic Profile 1.1 Web Services such as ASMX web services. Use this binding if the client doesn’t have features to employ wsHttpBinding or webHttpBinding.
- wsHttpBinding
Use this binding when you need to provide interoperability; a WCF service with a non-WCF client application.
- ws2007HttpBinding
This is the same as wsHttpBinding but supports the latest WS-* specifications and is based on newer standards. If the client supports this binding then use it instead of wsHttpBinding.
- wsDualHttpBinding
This binding provides a two-way communication; from service to client, and client to service. We’ll implement a sample application on this in later sections. This binding uses two channels to implement a two-way communication.
- webHttpBinding
Use this binding when you need to provide interoperability. It Supports REST and POX-based services using XML/JSON.
- netTcpBinding
Use this binding when both of the communication nodes are .NET applications. It provides the best performance over the rest of the bindings listed here. This binding uses only one channel and does not need two channels to implement a two-way communication, because the internal layers of TCP implicitly support it.
3) Contract
The contract defines the operations of a service and the incoming and outgoing message format that each operation requires and etc. and the endpoint then exposes the operations and behaviors defined by the contract.
Contracts are the important building blocks of WCF. There are about five types of contracts that are available for the developer to leverage and use to customize or implement a specific functionality of a service.
There are five types of contracts:
- ServiceContract
- OperationContract
- DataContract
- MessageContract
- FaultContract
- ServiceContract
- OperationContract
- DataContract
- MessageContract
- FaultContract
We will cover Service, Operation, and Data contracts and leave the last two contracts since they are related to advanced topics witch will be covered in a separate paper related to advanced topics of WCF.
Service Contract
The high level contract in WCF is the ServiceContract and it defines general and high level policies and semantics; how messages are correlated and exchanged, communication directions, and etc. First let’s take a look at the asynchronous model. Don’t forget to set the namespace parameter on the ServiceContract attribute so that it fully represents a unique service so that it prevents service name conflicts.
The high level contract in WCF is the ServiceContract and it defines general and high level policies and semantics; how messages are correlated and exchanged, communication directions, and etc. First let’s take a look at the asynchronous model. Don’t forget to set the namespace parameter on the ServiceContract attribute so that it fully represents a unique service so that it prevents service name conflicts.
Asynchronous Model
Some operations need time to complete and return the results, or might be time-consuming and long-running operations. An asynchronous programming model can be used to communicate with the service asynchronously.
The following steps illustrate how an asynchronous service request is initiated:
The callback function will be executed as soon as the results arrive from the service:
Communication Directions
The service contract can provide different direction configurations:
- One-Way with Acknowledge
- One-Way with Response
- Duplex
- Paired Contracts
One-Way with Acknowledge
One Way direction is the simplest form of communication, it is like ‘fire and forget’ but actually the client is notified of the receipt (acknowledge) of the message by the server. So what does that mean in practice? You define a parameter in OperationContract attribute as:
After setting the attribute parameter, what happens in the client side is that when the client invokes the ClientBeat method, the control directly returns to the client from the server and the client just receives an acknowledge (execution without any error or exception) of receiving the message but won’t wait for the result (if any) of the method being invoked and that is why we say ‘fire and forget’. The return data type of the method should be of type Void.
One-Way with Response
This is the default method that is used in WCF. The client simply invokes an operation on the service and gets the related response, and it can be done synchronously or asynchronously. In a one-way communication, only one party can initiate the request; in other words, if a client initiates a request, then the server can’t initiate a request at a later time. In this method, the server cannot initiate an independent request because it is not configured by default to do so although the server may have the client’s endpoint; the server just responses to client’s requests. An example of one-way communication can be found is the example provided earlier in the In-Process Service Application section.
Duplex
In Duplex (bidirectional) communication, the client and server communicate by sending and receiving messages. It is a two-way communication where the client can initiate a request to the server, and also the server can initiate a request to the client. Because the contract is shared between the client and server, they are both bound to certain common binding, and contract details. The owner of the contract, and the only one which is responsible for the contract and binding is the server; therefore the server maintains them (this include versioning and etc.) and if anything change in the contract or the binding, the client should update to accommodate itself to the changes.
For this communication method to work both the client and the server must have their own endpoints and each of them needs the other party’s endpoint in order to initiate an independent request. You might ask that how the client’s endpoint can be defined? WCF channel is responsible for creating the endpoint of a client that has initiated a request to the server.
Duplex Implementation
Let’s first implement the server-side:
Apply a CallbackContract attribute parameter on ServiceContract attribute passing in the type of the client’s interface which is INewsClient. In service contract specify the operations that the client would invoke, in this case, the Subscribe method is invoked by client to register for receiving news about a specific news category. In client contract specify the operations that the service would invoke, in this case, the Notify method is invoked by service to submit news and update the client on this. As you see the communication is made one-way (with acknowledge) by setting the IsOneWay attribute parameter on the Notify method implying that there is no need to wait for the output; therefore it is of type Void. Next, we are going to implement the service class:
The GetCallbackChannel method gets each client’s contract and adds it to the list of clients so that later the service part uses this list to initiate requests to the clients and update them. Here is the last part and the host implementation:
Now let’s take a look at the client part:
After adding a service reference named NewsServiceReference, we’ll use the classes made available by this service proxy. As you see we implemented the INewsServiceCallback interface, and made an instance of the service context so that we would be able to initiate a request to the service through this reference. In order to be able to call a method on the service, this instance is passed to the NewsServiceClient. The following figure shows the result window:
Paired Contracts
The Paired Contracts method is another way to initiate a two-way communication and each party is an independent WCF host itself; meaning that they expose their own custom bindings and contracts and can expose multiple endpoints. Unlike other types of communications, this method is about the service to service communication. This type of communication is actually made up of two one-way contracts that are configured to simulate a two-way communication. It has its own advantages because it has some flexibility in the configuration that you may not find in other similar two-way configurations like Duplex. The Duplex method needs fewer configurations than Paired Contracts method. Because each of the parties has its own service and can customize and use different bindings and contracts, each of them can use different protocols, different encryption, compression, security, encoding, message structure and several other features.
Channels in Communication
A channel, as its name implies is like a tunnel where data between the client and server endpoints are transmitted through and is made based on what is defined the contract and binding settings. The one-way communications use only one channel; it could be HTTP or TCP or other types. In two-way communication, for bindings that employ TCP or Named Pipes, a single channel is used –one common bidirectional channel for both client and the server. For bindings that use HTTP, one channel is not enough to maintain a two-way communication because HTTP does not support bidirectional communication, therefore the communication should be simulated over two channels –one for client to server direction and another for server to client direction. This dual channel over HTTP uses wsDualHttpBinding of pre-configured .NET bindings.
Note that in each of the communication directions, whether one-way or two-way, it is the client that should initiate the request first (first-time initiation) because the service doesn't know if any client exists.
Data Contract
Data Contracts provide a way to map service data types to client data types. The service data types are .NET data types and the client could be a .NET client, a Java or other types of clients. A data contract, translates the source data types into an intermediary data type in WSDL file, and this intermediary data file contains XML elements and are understandable by all clients and platforms. For primitive data types there is no need to apply any data contract because it is being done implicitly by the framework. For complex data types such as class, collection and some others, there should be much done than a simple definition. Data contract elements are applied on the complex types to prepare them to be translated into the intermediary representation. Important attributes of data contract are DataContract attribute and DataMember attribute. The following complex data type shows the attributes in action:
Let’s see what is going on here. The ComplexType class is the complex type we’re talking about. A complex type should have a namespace and name to make it unique and therefore prevent probable conflicts with other types. If you fill in the name parameter in DataContract attribute, then the data contract engine would pick the defined name for the target representation, otherwise the class name itself is used for the target representation. It is the same for the names of data members. As you see here, the DataContract attribute is used on the class and the DataMember attribute is used on the class members. The Order parameter defines the order in which data members appear in the representation; note that some complex types may be dependent on the order in which the data members appear. The IsRequired parameter denotes the necessity of presence of a data member in a representation when it is read or deserialized by the target node; therefore if the IsRequired parameter is set to true for a complex type data member and the source node doesn’t include it in the message sent to the target, then based on the schema the target node finds out that the attribute is not passed and consequently will generate exceptions. Note that if a data member is of other complex data types, define the desired complex data type and decorate it with data contract attributes. The following code shows how to do this:
Inheritance in Complex Types
Some complex types may appear as an inheritance relation. Let’s convey it through the famous example, the relation of person, student, and teacher.
Note that the Namespace definition is required for the class hierarchy to behave as expected.
Passing Derived Classes
Derived classes can be passed instead of a base class where the method return type or the method parameter is expected to be of type Base Class. An example of this situation is covered later in Syndication Implementation section. So how would the target act when it receives a derived type while it expected a base type? We can instruct the target about the derived data type so it can accept it instead of base class. This is done by setting KnownType attribute on the base class definition.
Now you are able to implement a method that can return derived types instead of expected base type:
Collections
In order to prepare a collection to be serialized by WCF into an appropriate WSDL equivalent, apply CollectionDataContract attribute on a class and inherit the needed collection data type:
Message Contract
Message Contracts are used when an implementation of a customized SOAP message is required. They give much control than Data Contracts because they give you the ability to alter SOAP header and body. You may find it more appropriate to implement some communication details inside the header rather than implementing operations and methods -for any reason, such as security. When the demands of the current system require this depth of detail in message processing, then both the client and the server must do much in order to handle messages and relations.
Service Discovery
In order for a service be discoverable by clients, its WCF node must have a MEX endpoint. Then this endpoint is used to generate the WSDL in order for the client to be able to use the service. The IDE then uses the WSDL file to generate required proxies and related service bindings. The proxy class has the operations that were exposed by the endpoint of the service. The proxy class uses the binding defined in the configuration file to invoke the operations on the service.
In order to use the service, clients have two options to set up the service reference:
- Use the WCF service utility (svcutil.exe) to generate the proxy class and related configuration file.
- In their IDE, try to add a service reference and then the IDE automatically generates classes and relations.
Suppose that you are using VS, first make sure the service is running by running the application you made in the previous step. In the target client project, right click on References folder and choose Add Service Reference to open the related discovery window:
Then type in your service URI, and hit the Go button. What happens next is called the discovery process; it queries for the WSDL of the service. Remember you defined MEX endpoint for the service and that way the service can respond to discovery queries and deliver its own WSDL to the client’s endpoint. In this window name the Namespace field appropriately to what the service implies, and hit the OK button. This is how you may use the service reference in the client application:
What if we want to connect to a service from client without doing any of the above steps and just use code? Well, we have to know the service contract and the service address as well as the service binding. The following code demonstrates it:
As you see, we have to know about the contract; therefore the interface above is the contract of our service. Next we will include information about the binding and address of the service:
The ChannelFactory class takes a service contract and the address and binding of the service and prepares everything for channel creation. The CreateChannel method provides a proxy class of the service that the client can use to invoke the exposed operations of the service.
By now, you probably understand what is discovery all about and the relations. The WSDL file prepared by the MEX endpoint of the service does the same thing as we did in latter discovery method; it delivers the address, binding, and contract of the service to the client and the client uses the generated proxy to invoke operations on the service.
Visual Studio supports the following project types:
- WCF Service Library
- WCF Service Application
- WCF Workflow Service Application
- Syndication Service Library
- In-Process Service Application
WCF Service Library
WCF service library project allows implementing a host-independent service so that the service does not necessarily need an application service or IIS/WAS. The result of the service can be run as a windows service.
WCF Service Application
WCF service application project allows creating a WCF service that can be hosted in IIS/WAS.
WCF service application project allows creating a WCF service that can be hosted in IIS/WAS.
WCF Workflow Service Application
CSF workflow service application projects are hosted in IIS/WAS and managed by AppFabric in windows server. Workflow projects are designed for asynchronous long-running workflows. One of the characteristics of such services is that the workflow service goes into idle mode when no request arrives from a specific client and therefore the workflow service is saved into a repository and leaves the memory. Once the client resumes the workflow by requesting a specific operation, then the service resumes and comes into memory and continues its flow and this cycle continues. Another advantage of workflow service is that most of the service logic is implemented using workflow diagrams without doing any special coding.
Syndication Service Library
WCF syndication service project supports exposing services to work with syndication feeds in RSS, Atom, and other custom formats. WCF supports RSS 2.0 and Atom 1.0 syndications. There are general syndication classes common for RSS and Atom in a format-neutral manner. We will now go through a syndication service to understand how to employ such a feed service so that the clients will be able to subscribe to it.
Syndication Elements:
- SyndicationCategory
- SyndicationFeed
- SyndicationItem
- SyndicationLink
- SyndicationPerson
Synd. Feed Formatters :
- Rss20FeedFormatter
- Atom10FeedFormatter
Implementation
Now we are going to implement a base syndication service that can be generalized based on your needs. First of all, add the service address to the ACL as is described in In-Process Service App section. Then make sure namespaces like System.ServiceModel, System.ServiceModel.Description, and System.ServiceModel.Syndication are referenced.
1) Add the service contract:
Because we have two different outputs depending on the input request parameter, and that the output of the feed is of general type SyndicationFeedFormatter which itself can contain one of two formatters Atom10FeedFormatter and Rss20FeedFormatter, we define the possible output formats using ServiceKnownType attribute for the service so it would know how to resolve the appropriate output which is specified by the type of the object that resides implicitly inside the SyndicationFeedFormatter object. The body style WebMessageBodyStyle.Bare specifies that the service’s response is raw XML/text.
Here is the implementation of service class using IFeed interface:
The output type of Feed method is SyndicationFeedFormatter and this data type can contain either Atom10FeedFormatter or Rss20FeedFormatter. The top element is SyndicationFeed which is a container for the whole feed document and as you see an instance of this type is made passing the feed title, feed description, and the feed URI. Then the feed metadata can be attached to the feed, things like some feed authors, some feed categories, and one feed description. A feed is made up of several feed items, known as syndication items. Each syndication item has an item title, item content, item URI, item ID, and the date-time information about the item. After making the feed and feed items, then based on the request parameter Format, the method decides whether to format the feed structure conforming to a RSS2 or an Atom1 format.
Synd. Client
Up to now we have explained how to implement syndication services. Now we are going to call and use a syndication service. The simplest form of using the service is by entering the address in a web browser to get the raw XML feed. First run the syndication service and then in the client implement the feed reader code as you see here.
If you are going to retrieve a RSS feed, then:
Notice a subtle difference in iterating the feed items; RSS uses summary property as the syndication content while Atom uses the Content property. The differences are due to the differences in specifications.
Now, host the implemented service:
Note that Syndication service has some subtle differences than other WCF services; one is that since it is a typical publisher-subscriber scenario and mostly because the output is raw xml over HTTP rather than being encrypted, compressed, serialized or etc. it does not need any endpoint be defined because there is no need to do message-passing between the nodes; it’s just a simple web feed. Of course in some advanced scenarios you may have to define appropriate channels, apply needed security or have to implement the required endpoints. Because this service deals with simple XML and no message is used, as a result it is based on raw HTTP protocol and thus it can only be applied in web context; meaning that you have to use a HTTP web server or a self-hosted WebServiceHost alternative.
In-Process Service Application
There is no template in VS for this kind of project in WCF template category because you just set up the environment inside source code. An in-process WCF service can be implemented in a windows console application and this type of service is self-hosted.
To implement this kind of application, first add a reference to System.ServiceModel .NET framework assembly.
1) Before publishing the service, you’ll have to give the URL enough permissions by adding it to ACL:
Our target address is “http://localhost:8000/SelfHostableService”, Change the netsh command parameters based on the pattern of your URI, and domain-name/computer-name and username. First run Command Prompt as administrator and then execute the modified version of netsh command:
netsh http add urlacl url=http://+:8000/SelfHostableService user=Sonic-Laptop\Sonic
2) Add using System.ServiceModel; and using System.ServiceModel.Description; namespace references.
3) Define the interface of the service and implement it on a class:
4) Add a service host and then assign some endpoints to it to be able to send/receive messages through the endpoint.
5) Clients need to get access to the service. Therefore Add a Metadata behavior and create a MetadataExchange endpoint so that clients are able to locate and use the service.
6) Opening the service and implement the related logic:
Client Diversity
Clients are not limited to windows platform; other platforms and non-dot-net languages can still leverage the benefits of WCF services. In most cases clients use basic bindings that they can understand. The enterprise usually use REST with JSON as its architecture data format. There are some tools and libraries that can generate service proxies for many languages that they can use to communicate with the service.
More on WCF
Message Contracts, Behaviors and other advanced related topics will be covered in another paper which is dedicated to advanced topics on WCF.
Conclusion
WCF has a broad usage in communications enabling the implementation of complex SOA and dynamic services with noticeable performance advantages than its counterpart old ASMX Web Services. We’ve covered SOA architecture in WCF, Different kinds of WCF projects such as In-Process, Syndication services, service contracts, data contracts, how they map to complex data types, and communication directions such as duplex and paired, implemented the most important concepts in practice, and had a review on their applications. This paper covered mostly the basic and practical aspects of WCF and we will cover advanced topics in another dedicated paper.






























