WCF Tutorial
Activation and Hosting:
WCF service can be hosted by following mechanism
IIS: It does not
require Host code to activate the service, it automatically activates
service code. It will automatically launch the host service when it gets
first request from the client. The disadvantage is that it will support
only HTTP.
Windows Activation Service: (WAS)
is the new process activation mechanism that ships with IIS 7.0. It is
available with IIS 7.0 and it is more powerful compared to IIS 6.0
because it supports Http, TCP and named pipes where IIS 6.0 supports
only Http. It can be installed and configured separately.
Hosting WCF in
Activation service takes many advantages such as process recycling,
isolation, idle time management and common configuration system. WAS
hosted service can be created using following steps
-Enable WCF for non-http protocols
-Create WAS hosted service
-Enable different binding to the hosted service
Self-Hosting: WCF service can be self hosted as console application, Win Forms or WPF application with graphical UI.
ServiceHost is the core
class use to host the WCF service. It will accept implemented contract
class and base address as contractor parameter. You can register
multiple base addresses separated by commas, but address should not use
same transport schema.
Windows Service: WCF can also be hosted as a Windows Service, so that it is under control of the Service Control Manager (SCM).
advantage of hosting service in Windows service:
-The service will be hosted, when system starts
-Process life time of the service can be controlled by Service Control Manager for windows service
-All versions of Windows will support hosting WCF service.
There are different ways of creating the proxy:
-Using SvcUtil.exe, we can create the proxy class and configuration file with end points.
-Adding Service reference to the client application.
-Implementing ClientBase<T> class : it will create the proxy only at runtime.
WCF:
WCF is a combined features of Web Service, Remoting, MSMQ and COM+. WCF provides a common platform for all .NET communication.
Advantage:
-WCF is interoperable with other services when compared to .Net Remoting,where the client and service have to be .Net.
-WCF services provide better reliability and security in compared to ASMX web services.
-In WCF, there is no
need to make much change in code for implementing the security model and
changing the binding. Small changes in the configuration will make your
requirements.
-WCF has integrated
logging mechanism, changing the configuration file settings will provide
this functionality. In other technology developer has to write the
code.
WCF services can be
debugged now in Visual Studio 2008. Wcfsvchost.exe will do it for you
because service will be self hosted when you start debugging.
Difference between Web Service and WCF:
Features -- Web Service -- WCF :
Hosting:
It can be hosted in IIS It
can be hosted in IIS, windows activation service, Self-hosting, Windows service
Programming:
[WebService] attribute has to be added to the class
[ServiceContraact] attribute has to be added to the class
Model:
[WebMethod] attribute represents the method exposed to client
[OperationContract] attribute represents the method exposed to client
Operation:
One-way, Request- Response are the different operations supported in web service
one-Way, Request-Response, Duplex are different type of operations supported in WCF
XML:
System.Xml.serialization name space is used for serialization
System.Runtime.Serialization namespace is used for serialization
Encoding:
XML 1.0, MTOM(Message Transmission Optimization Mechanism), DIME, Custom
XML 1.0, MTOM, Binary, Custom
Transports:
Can be accessed through HTTP, TCP, Custom
Can be accessed through HTTP, TCP, Named pipes, MSMQ,P2P, Custom
Protocols:
Security
Security, Reliable messaging, Transactions
A service is a class
that exposes functionality available to clients at one or more
endpoints. To create a service, write a class that implements a WCF
contract. You can do this in one of 2 ways.
You can define the contract separately as an interface and then create a class that implements that interface.
// Define the IMath contract.
[ServiceContract]
public interface IMath
{
[OperationContract]
double Add(double A, double B);
[OperationContract]
double Multiply (double A, double B);
}
// Implement the IMath contract in the MathService class.
public class MathService : IMath
{
public double Add (double A, double B) { return A + B; }
public double Multiply (double A, double B) { return A * B; }
Alternatively, you can create the class and contract directly by placing the ServiceContractAttribute attribute on the class
itself and the OperationContractAttribute attribute on the methods available to the clients of the service.
// Define the MathService contract directly on the service class.
[ServiceContract]class MathService
{
[OperationContract] public double Add(double A, double B) { return A + B; }
[OperationContract]
private double Multiply (double A, double B) { return A * B; }
}
WCF is an SDK for
developing and deploying services on Windows. WCF provides a runtime
environment for your services, enabling you to expose CLR types as
services, and to consume other services as CLR types.
WCF provides interoperability between services.
Most all of the WCF
functionality is included in a single assembly called
System.ServiceModel.dll in the System.ServiceModel namespace.
The basic tasks to perform are, in order:
1. Define the service
contract.A service contract specifies the signature of a service, the
data it exchanges, and other contractually required data.
2. To implement a
service contract, create the class that implements the contract and
specify custom behaviors that the runtime should have.
3. Configure the service by specifying endpoint information and other behavior information.
4. Host the service in an application.
5. Build a client application.
With WCF, all messages
are SOAP messages. The 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.
With WCF, the client
never interacts with the service directly. Instead, the client always
uses a proxy to forward the call to the service. The proxy exposes the
same operations as the service, plus some proxy-management methods.
WCF allows the client to
communicate with the 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.
It is possible for two TCP addresses (from the same host) to share a port:
net.tcp://localhost:8002/MyService
net.tcp://localhost:8002/MyOtherService
Similar to TCP addresses, two HTTP addresses from the same host can share a port, even on the same machine.
IPC addresses use net.pipe for transport, to indicate the use of the Windows named pipe mechanism.
net.pipe://localhost/MyPipe
You can only open a
named pipe once per machine, and therefore it is not possible for two
named pipe addresses to share a pipe name on the same machine.
MSMQ addresses use
net.msmq for transport, to indicate the use of the Microsoft Message
Queue (MSMQ). You must specify the queue name. When you're dealing with
private queues, you must specify the queue type, but that can be omitted
for public queues:
net.msmq://localhost/private/MyService
net.msmq://localhost/MyService
WCF defines 4 types of contracts.
1. Service contracts: Describe which operations the client can perform on the service.
2. Data contracts:
Define which data types are passed to and from the service. Data
Contract attribute defines the data type that will be exchanged between
the client and the service.
3. Fault contracts:
Define which errors are raised by the service, and how the service
handles and propagates errors to its clients.
4. Message contracts:
Allow the service to interact directly with messages. Message contracts
can be typed or untyped, and are useful in interoperability cases and
when there is an existing message format you have to comply with.
WCF Hosting:
WCF service cannot exist
on its own; it has to be hosted in windows process called as host
process. Single host process can host multiple servers and same service
type can be hosted in multiple host process. There are mainly 4
different way of hosting the WCF service.
-IIS hosting
-Self hosting
-Windows Activation Service
-Windows Service
Hosting Environment Supported protocol
Windows console and form application -HTTP,net.tcp,net.pipe,net.msmq
Windows service application -HTTP,net.tcp,net.pipe,net.msmq
Web server IIS6 -http, wshttp
Web server IIS7 - WAS, HTTP, net.tcp, net.pipe, net.msmq
A summary of hosting options and supported features.
Feature Self-Hosting IIS Hosting WAS Hosting
Executable Process/ App Domain Yes Yes Yes
Configuration App.config Web.config Web.config
Activation Manual at startup Message-based Message-based
Idle-Time Management No Yes Yes
Health Monitoring No Yes Yes
Process Recycling No Yes Yes
Management Tools No Yes Yes
IIS Hosting:
The main advantage of
hosting a service in IIS web server is that the host process is launched
automatically upon the first client request, and you rely on IIS to
manage the life cycle of the host process. It uses the features of IIS
such as process recycling, idle shutdown, process health monitoring and
message based activation. The main disadvantage of IIS hosting is that
it will support only HTTP protocol. With IIS5, you are further
restricted to having all services use the same port number.
Example 1-2. A .svc file
<%@ ServiceHost
Language = "C#"
Debug = "true"
CodeBehind = "~/App_Code/MyService.cs"
Service = "MyService"
%>
When configuring a service in Visual Studio, use either a Web.config or an App.config file to specify the settings.
If you are using IIS to
host your service, use a Web.config file. If you are using any other
hosting environment, use an App.config file.
SELF Hosting: WCF provides the user to host the service in any application (e.g. console application, Windows form).
WAS Hosting:
WAS is a system service
available with Windows Vista and Windows Server 2008. WAS is part of
IIS7, but can be installed and configured separately. To use the WAS for
hosting your WCF service, you need to supply a .svc file, just as with
IIS.
The main difference
between IIS and WAS is that the WAS is not limited to HTTP and can be
used with any of the available WCF transports, ports, and queues.
WAS offers advantages
over self-hosting, including application pooling, process recycling,
idle time management, identity management, and isolation, and is the
host process of choice when available; that is, when you can target
either a Vista Server machine for scalability or a Vista client machine
used as a server machine for a handful of clients only.
WAS hosted service can be created using following steps:
-Enable WCF for non-http protocols
-Create WAS hosted service
-Enable different binding to the hosted service
Service Host
Service Host object is
in the process of hosting the WCF service and registering endpoints. It
loads the service configuration endpoints, apply the settings and start
the listeners to handle the incoming request.
System.ServiceModel.ServiceHost namespace hold this object. This object is created while self hosting the WCF service.
In the below example you can find that WCF service is self hosted using console application.
//Creating uri for the hosting the service
Uri uri = new Uri("http://localhost/CategoryService");
//Creating the host object for MathService
ServiceHost host = new ServiceHost(typeof(CategoryService), uri);
//Adding endpoint to the Host object
host.AddServiceEndpoint(typeof(ICategoryService),new WSHttpBinding(), uri);
host.Open(); //Hosting the Service
Console.WriteLine("Waiting for client invocations");
Console.ReadLine();
host.Close();
EndPoint:
Each endpoint consists of four properties:
-An address that indicates where the endpoint can be found.
-A binding that specifies how a client can communicate with the endpoint.
-A contract that identifies the operations available.
-A set of behaviors that specify local implementation details of the endpoint.
Address:
Every endpoint must have
a unique address. The endpoint address is represented by the
EndpointAddress class, which contains a Uniform Resource Identifier
(URI) that represents the address of the service, an Identity, which
represents the security identity of the service, and a collection of
optional Headers. The optional headers provide more detailed addressing
information to identify or interact with the endpoint. For example,
headers can indicate how to process an incoming message, where the
endpoint should send a reply message, or which instance of a service to
use to process an incoming message from a
particular user when multiple instances are available.
Binding:
The binding specifies how to communicate with the endpoint. This includes:
-The transport protocol to use ( TCP or HTTP)
-The encoding to use for the messages (text or binary)
-The necessary security requirements (SSL or SOAP message security)
There are different
protocols available for the WCF to communicate to the Client. You can
mention the protocol type based on your requirements.
A binding has several characteristics, including the following:
Transport -Defines the base protocol to be used like HTTP, Named Pipes, TCP, and MSMQ are some type of protocols.
Encoding (Optional) -
Three types of encoding are available-Text, Binary,or Message
Transmission Optimization Mechanism (MTOM). MTOM is an interoperable
message format that allows the effective transmission of attachments or
large messages (greater than 64K).
Protocol(Optional) - Defines information to be used in the binding such as Security, transaction or reliable messaging capability
A binding is represented in the WCF object model by the abstract base class Binding.
BasicHttpBinding - Basic Web service communication. No security by default
WSHttpBinding - Web services with WS-* support. Supports transactions
WSDualHttpBinding - Web services with duplex contract and transaction support
WSFederationHttpBinding - Web services with federated security. Supports transactions
MsmqIntegrationBinding - Communication directly with MSMQ applications. Supports transactions
NetMsmqBinding - Communication between WCF applications by using queuing. Supports transactions
NetNamedPipeBinding - Communication between WCF applications on same computer. Supports duplex contracts and transactions
NetPeerTcpBinding - Communication between computers across peer-to-peer services. Supports duplex contracts
NetTcpBinding - Communication between WCF applications across computers. Supports duplex contracts and transactions
Basic binding:
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. When used by the client, this binding enables new WCF
clients to work with old ASMX services. An HTTP protocol binding
suitable for connecting to Web services that conforms to the WS-I Basic
Profile specification (for example, ASP.NET Web services-based
services).
TCP binding:
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.
Peer network binding:
Offered by the NetPeerTcpBinding class, this uses peer networking as a transport.
IPC binding: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 and it supports a variety
of features
similar to the TCP binding.
Web Service (WS) 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.
An interoperable binding suitable for connecting to endpoints that conform to the WS-* protocols.
Federated WS binding:
Offered by the WSFederationHttpBinding class, this is a specialization of the WS binding
MSMQ binding:Offered by
the NetMsmqBinding class, this uses MSMQ for transport and is designed
to offer support for disconnected queued calls.
MSMQ integration binding:
Offered by the MsmqIntegrationBinding class, this converts WCF messages to and from MSMQ messages,
NetMsmqBinding:
Uses the .NET Framework to create queued message connections with other WCF endpoints.
Name Transport Encoding Interoperable
asicHttpBinding HTTP/HTTPS Text, MTOM Yes
NetTcpBinding TCP Binary No
NetPeerTcpBinding P2P Binary No
NetNamedPipeBinding IPC Binary No
WSHttpBinding HTTP/HTTPS Text, MTOM Yes
WSFederationHttpBinding HTTP/HTTPS Text, MTOM Yes
WSDualHttpBinding HTTP Text, MTOM Yes
NetMsmqBinding MSMQ Binary No
MsmqIntegrationBinding MSMQ Binary Yes
Binding Configuration Element Description
BasicHttpBinding
<basicHttpBinding> A binding that is suitable for
communicating with WS-Basic Profile conformant Web services, for
example, ASP.NET Web services (ASMX)-based services. This binding uses
HTTP as the transport and text/XML as the default message encoding.
WSHttpBinding
<wsHttpBinding> A secure and interoperable binding
that is suitable for non-duplex service contracts.
NetTcpBinding
<netTcpBinding> A secure and optimized binding
suitable for cross-machine communication between WCF applications.
NetPeerTcpBinding <netPeerTcpBinding> A binding that enables secure, multiple machine communication.
MsmqIntegrationBinding
<msmqIntegrationBinding> A binding that is suitable for
cross-machine communication between a WCF application and existing
Message Queuing applications.
WSDualHttpBinding
<wsDualHttpBinding> A secure and interoperable binding that
is suitable for duplex service contracts or communication through SOAP
intermediaries.
Contracts:
What operations can be called by a client.
The form of the message.
The type of input parameters or data required to call the operation.
What type of processing or response message the client can expect.
service contract is a statement that provides information about:
-The grouping of operations in a service.
-The signature of the operations in terms of messages exchanged.
-The data types of these messages.
-The location of the operations.
-The specific protocols and serialization formats that are used to support successful communication with the service.
A duplex contract consists of two interfaces.
-The primary interface is used to send messages from client to service.
-The callback interface is used to send messages from service back to client.
A duplex contract allows
clients and servers to communicate with each other independently so
that either can initiate calls to the other. The duplex contract is one
of 3 message patterns available to WCF services. The other two message
patterns are one-way and request-reply.
A duplex contract
consists of two one-way contracts between the client and the server and
does not require that the method calls be correlated. Use this kind of
contract when your service must query the client for more information or
explicitly raise events on the client.
sample program: http://msdn.microsoft.com/en-us/library/ms731184(v=VS.100).aspx
Use the ServiceModel
Metadata Utility Tool (Svcutil.exe) to retrieve the WSDL document and
(optional) code and configuration for a client.
IIS bindings provide two pieces of information: a binding protocol, and binding information.
The binding protocol
defines the scheme over which communication occurs, and binding
information is the information used to access the site.
The following example shows the components that can be present in an IIS binding:
Binding protocol: HTTP
binding Information: IP Address, Port, Host header
IIS can specify multiple
bindings for each site, which results in multiple base addresses for
each scheme. Prior to .NET Framework 3.5, WCF did not support multiple
addresses for a schema
With .NET Framework 3.5,
you specify a prefix filter at the AppDomain level in the configuration
file. You do this with the <baseAddressPrefixFilters> element,
which contains a list of prefixes. The incoming base addresses, supplied
by IIS, are filtered based on the optional prefix list. By default,
when a prefix is not specified, all addresses are passed through.
Specifying the prefix results in only the matching base address for that scheme to be passed through.
The following is an example of configuration code that uses the prefix filters.
<system.serviceModel>
<serviceHostingEnvironment>
<baseAddressPrefixFilters>
<add prefix="net.tcp://payroll.myorg.com:8000"/>
<add prefix="http://shipping.myorg.com:8000"/>
</baseAddressPrefixFilters>
</serviceHostingEnvironment>
</system.serviceModel>
net.tcp://payroll.myorg.com:8000
and http://shipping.myorg.com:9000 are the only base addresses, for
their respective schemes, which are passed through.
The baseAddressPrefixFilter does not support wildcards.
Binding and Behavior:
Binding -- how the client will communicate with service.
Consider a scenario say,
I am creating a service that has to be used by two type of client. One
of the client will access SOAP using http and other client will access
Binary using TCP. How it can be done? With Web service it is very
difficult to achieve, but in WCF its just we need to add extra endpoint
in the configuration file.
<system.serviceModel>
<services>
<service name="MathService" behaviorConfiguration="MathServiceBehavior">
<endpoint address="http://localhost:8090/MyService/MathService.svc"
contract="IMathService" binding="wsHttpBinding"/>
<endpoint address="net.tcp://localhost:8080/MyService/MathService.svc"
contract="IMathService" binding="netTcpBinding"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="MathServiceBehavior">
<serviceMetadata httpGetEnabled="True"/>
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
cording to its scope:
common behaviors affect all endpoints globally, service behaviors affect
only service-related aspects, endpoint behaviors affect only
endpoint-related properties, and operation-level behaviors affect
particular operations.
Example:
In the below
configuration information, I have mentioned the Behavior at Service
level. In the service behavior I have mention the servieMetadata node
with attribute httGetEnabled='true'. This attribute will specifies the
publication of the
service metadata. Similarly we can add more behavior to the service.
<system.serviceModel>
<services>
<service name="MathService"
behaviorConfiguration="MathServiceBehavior">
<endpoint address="" contract="IMathService"
binding="wsHttpBinding"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="MathServiceBehavior">
<serviceMetadata httpGetEnabled="True"/>
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
Note:
Application can be
controlled either through coding, configuring or through combination of
both. Specification mention in the configuration can also be overwritten
in code.
Binding
Binding means how the
client will communicate with service. There are different protocols
available for the WCF to communicate to the Client. You can mention the
protocol type based on your requirements.
Binding has several characteristics, including the following:
Transport-Defines the base protocol to be used like HTTP, Named Pipes, TCP, and MSMQ are some type of protocols.
Encoding (Optional)--Three
types of encoding are available-Text, Binary, or Message Transmission
Optimization Mechanism (MTOM). MTOM is an interoperable message format
that allows the effective transmission of attachments or large messages
(greater than 64K).
Protocol(Optional)--Defines information to be used in the binding such as Security, transaction or reliable messaging capability
Message and Channel:
Message: WCF Message is
the unit of data exchange between client and service. It consists of
several parts, including a body and headers.
WCF Runtime: WCF
runtime is the set of object responsible for sending and receiving
message. For example formatting the message, applying security and
transmitting and receiving message using various protocol.
Channels: Channels
are the core abstraction for sending message to and receiving message
from an Endpoint. Broadly we can categories channels as
Transport Channels: Handles sending and receiving message from network. Protocols like HTTP, TCP name pipes and MSMQ.
Protocol Channels: Implements SOAP based protocol by processing and possibly modifying message. e.g. WS-Security and WS-Reliability.
WCF Client and Metadata:
WCF Client:
WCF client is a client
application creates to expose the service operations as method. Any
application can host a WCF client, including an application that host a
service. Therefore it is possible to create a service that includes WCF
clients of other services.
A client application is a
managed application that uses a WCF client to communicate with another
application. To create a client application for a WCF service requires
the following steps:
1. Get the Proxy class and service end point information:
Using SvcUtil.exe we can
create proxy class for the service and configuration information for
endpoints. Example type the following sentence in the Visual studio
command prompt, this will generate the class file and configuration file
which
contain information about the endpoints.
svcutil /language:vb /out:ClientCode.vb /config:app.config http://localhost:8090/MyService/SimpleCalculator.svc?wsdl
2. Call operations.
Add this class files in the client application. Then create the object for this class and invoke the service operation.
Configuration
information we got from the above step has to be added to the client
application configuration file. When the client application calls the
first operation, WCF automatically opens the underlying channel. This
underlying channel is
closed, when the object is recycled.
//Creating the proxy on client side
MyCalculatorServiceProxy.MyServiceProxy proxy = new MyCalculatorServiceProxy.MyServiceProxy();
Console.WriteLine("Counter: " + proxy.MyMethod());
3. Close the WCF client object.
After using the object
created in the above steps, we have to dispose the object. Channel will
be closed with the service, when the object is cleared.
Metadata:
Characteristics of the service are described by the metadata. This metadata can be exposed to the client to understand the
communication with
service. Metadata can be set in the service by enabling the
ServiceMetadata node inside the servcieBehaviour node of the service
configuration file.
<system.serviceModel>
<services>
<service name="MathService" behaviorConfiguration="MathServiceBehavior">
<endpoint address="" contract="IMathService"
binding="wsHttpBinding"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="MathServiceBehavior">
<serviceMetadata httpGetEnabled="True"/>
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
This metadata can be viewed while creating WCF client application using SvcUtil.exe
Contracts and Service Host:
Contracts
In WCF, all services are
exposed as contracts. Contract is a platform-neutral and standard way
of describing what the service does. WCF defines 4 types of contracts:
1. Service Contract 2. Data Contract
3. Message Contract 4. Fault Contract
1. Service Contract:
Service contracts describe the operation that service can provide. For
Eg, a Service provide to know the temperature of the city based on the
zip code, this service is called as Service contract. It will be created
using Service and Operational Contract attribute.
It describes the client-callable operations (functions) exposed by the service
It maps the interface and methods of your service to a platform-independent description
2. Data Contract:
Data contract describes the custom data type which is exposed to the
client. This defines the data types, that are passed to and from
service. Data types like int, string are identified by the client
because it is already mention in XML schema definition language
document, but custom created class or data types cannot be identified by
the client e.g. Employee data type. By using DataContract we can make
client to be aware of Employee data type that are returning or passing
parameter to the method.
A data contract is a formal agreement between a service and a client that abstractly describes the data to be exchanged.
Data contract can be
explicit or implicit. Simple type such as int, string etc has an
implicit data contract. User defined object are explicit or Complex
type, for which you have to define a Data contract using [DataContract]
and [DataMember] attribute.
A data contract can be defined as follows:
-It describes the external format of data passed to and from service operations
-It defines the structure and types of data exchanged in service messages
-It maps a CLR type to an XML Schema
-It defines how data
types are serialized and deserialized. Through serialization, you
convert an object into a sequence of bytes that can be transmitted over a
network. Through deserialization, you reassemble an object from a
sequence of bytes that
you receive from a calling application.
-It is a versioning system that allows you to manage changes to structured data
We need to include
System.Runtime.Serialization reference to the project. This assembly
holds the DataContract and DataMember attribute.
Create user defined data
type called Employee. This data type should be identified for
serialization and deserialization by mentioning with [DataContract] and
[DataMember] attribute.
[ServiceContract]
public interface IEmployeeService
{
[OperationContract]
Employee GetEmployeeDetails(int EmpId);
}
[DataContract]
public class Employee
{
private string m_Name;
private int m_Age;
private int m_Salary;
private string m_Designation;
private string m_Manager;
[DataMember]
public string Name
{ get { return m_Name; }
set { m_Name = value; }
}
[DataMember]
public int Age
{
get { return m_Age; } set { m_Age = value; }
}
[DataMember]
public int Salary
{
get { return m_Salary; } set { m_Salary = value; }
}
[DataMember]
public string Designation
{
get { return m_Designation; } set { m_Designation = value; }
}
[DataMember]
public string Manager
{
get { return m_Manager; } set { m_Manager = value; }
}
}
Implementation of the
service class is shown below. In GetEmployee method we have created the
Employee instance and return to the client. Since we have created the
data contract for the Employee class, client will aware of this instance
whenever he
creates proxy for the service.
public class EmployeeService : IEmployeeService
{
public Employee GetEmployeeDetails(int empId)
{
Employee empDetail = new Employee();
//Do something to get employee details and assign to 'empDetail' properties
return empDetail;
}
}
Client side:
On client side we can create the proxy for the service and make use of it. The client side code is shown below.
protected void btnGetDetails_Click(object sender, EventArgs e)
{
EmployeeServiceClient objEmployeeClient = new EmployeeServiceClient();
Employee empDetails;
empDetails = objEmployeeClient.GetEmployeeDetails(empId);
//Do something on employee details
3. Message Contract:
Default SOAP message
format is provided by the WCF runtime for communication between Client
and service. If it is not meeting your requirements then we can create
our own message format. This can be achieved by using Message Contract
attribute.
Message is the packet of
data which contains important information. WCF uses these messages to
transfer information from Source to destination.
Transport Channels: Handles sending and receiving message from network. Protocols like HTTP, TCP name pipes and MSMQ.
Protocol Channels: - Implements SOAP based protocol by processing and modifying message.
e.g. WS-Security and WS-Reliability.
WCF uses SOAP Message
format for communication. SOAP message contain Envelope, Header and
Body.SOAP envelope contails name, namespace,header and body element.
SOAP Hear contain important information which are not directly related
to message. SOAP
body contains information which is used by the target.
Message Pattern: It
describes how the programs will exchange message each other. There are
three way of communication between source and destination
1. Simplex - It is one way communication. Source will send message to target, but target will not respond to the message.
Request/Replay - It is
two way communications, when source send message to the target, it will
resend response message to the source. But at a time only one can send a
message
2. Duplex - It is two way communication, both source and target can send and receive message simultaniouly.
Message contract?
WCF uses SOAP message
for communication. Most of the time developer will concentrate more on
developing the DataContract, Serializing the data, etc. WCF will
automatically take care of message. On Some critical issue, developer will
also require control over the SOAP message format. In that case WCF
provides Message Contract to customize the message as per requirement.
WCF supports either
RPC(Remote Procedure Call) or Message style operation model. In the RPC
model, you can develop operation with Ref and out parameter. WCF will
automatically create the message for operation at run time. In Message
style operation
WCF allows to customize the message header and define the security for header and body of the message.
Message Contract:
Message contract can be
applied to type using MessageContract attribute. Custom Header and Body
can be included to message using 'MessageHeader' and
'MessageBodyMember'atttribute. Let us see the sample message contract
definition.
[MessageContract]
public class EmployeeDetails
{
[MessageHeader]
public string EmpID;
[MessageBodyMember]
public string Name;
[MessageBodyMember]
public string Designation;
[MessageBodyMember]
public int Salary;
[MessageBodyMember]
public string Location;
}
When I use this
EmployeeDeatils type in the service operation as parameter. WCF will add
extra header call 'EmpID' to the SOAP envelope. It also add Name,
Designation, Salary, Location as extra member to the SOAP Body.
Rules:
-You have to follow certain rules while working with Message contract
-When using Message contract type as parameter, Only one parameter can be used in servicie Operation
[OperationContract]
void SaveEmployeeDetails(EmployeeDetails emp);
-Service operation either should return Messagecontract type or it should not return any value
[OperationContract]
EmployeeDetails GetEmployeeDetails();
-Service operation will accept and return only message contract type. Other data types are not allowed.
[OperationContract]
EmployeeDetails ModifyEmployeeDetails(EmployeeDetails emp);
Note: If a type has both Message and Data contract, service operation will accept only message contract
Metadata Exchange:
WCF provides rich
infrastructure for Exporting, Publishing, retrieving and Importing the
metadata. WCF uses the Metadata to describe how to interact with the
service endpoint. Using the metadata, client will create the proxy class
for the service
using SvcUtil.exe
Exporting Service Metadata:
It is the process of describing the service endpoint so that client can understand how to use the service.
Publishing Service Metadata:
It is the process
publishing metadata. It involves converting CLR type and binding
information into WSDL or some other low level representation.
Retrieving Service Metadata:
It is the process of retrieving the metadata. It uses WS-MetadataExcahge or HTTP protocol for retrieving the metadata.
Importing Service Metadata - It is the process of generating the abstract representation of the service using metadata.
There are two way to
publish metadata, either we can use HTTP-GET or through message exchange
endpoint. By default service metadata is turn-off due to security
reason. WCF metadata infrastructure resides in
System.ServiceModel.Description namespace. Service metadata can be used
for following purpose
-Automatically generating the client for consuming service
-Implementing the service description
-Updating the binding for a client
1. HTTP_GET Enabled Metadata
Administrative (Configuration file):
In the below mention configuration information, you can find the behavior section in the ServiceBehavior. You can expose the metadata using ServiceMetadata node with httpGetEnable='True'.
<system.serviceModel>
Using ServiceMetadataBehavior you can enable the metadata exchange. In the following code, I have created the ServiceMetadataBehavior object and assigned HttpGetEnabled property to true. Then you have to add the behavior to host description as shown. This set of code will publish the metadata using HTTP-GET.
//Create a URI to serve as the base address
//Enable metadata exchange using HTTP-GET
host.Description.Behaviors.Add(smb);
2. Metadata Exchange Endpoint
2. Metadata Exchange Endpoint
You can create the Metadata Exchange Endpoint either Administrative (configuration file) or programmatically.
<system.serviceModel>
Programming Model:
Create the ServiceMetadataBehavior object and add to Service host description.
Create the metadata binding object using MetadataExchangeBinding
3. Add the endpoint to the service host with address, binding and contract.
Complete code for hosting the service with metadata exchange endpoint is shown below.
//Create a URI to serve as the base address
Console.WriteLine("Service is host at " + DateTime.Now.ToString());
4. Fault Contract:
WCF provides the option to handle and convey the error message to client from service using SOAP Fault contract.
Step 1: I have created simple calculator service with Add operation which will throw general exception as shown below
//Service interface
try
Define a type using the data contract and specify the fields you want to return.
Step 1:
When the client creates new proxy to particular service instance, a dedicated service instance will be provided to the client. It is independent of all other instance.
Console.WriteLine("Client 2 making call to service...");
Instance Deactivation:
ReleaseInstanceMode property of the OberationalBehavior attribute used to control the instance in relation to the method call.
List of Release modes available in the ReleaseInstanceMode:
[ServiceContract()]
Explicit Deactivate:
[ServiceContract()]
Defining the Durable Service:
CanCreateInstance = true: creats the serialization and inserting it into the datastore.
How to Create Durable Service:
[OperationContract]
using System.Runtime.Serialization;
[Serializable]
Step 4:
SqlPersistenceProviderSchema.sql
Step 5:
<system.serviceModel>
Step 7: Add following reference to client application
Step 8: Add WCF service as Service Reference to the project and name it as SimpleCalculatorService
<services>
<service behaviorConfiguration="ServiceBehavior" name="MyService">
<endpoint address="http://localhost/IISHostedService/MyService.svc"
binding="wsHttpBinding" contract="IMyService">
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceBehavior">
<!-Setting httpGetEnabled you can publish the metadata -->
<serviceMetadata httpGetEnabled="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
Progarmming Model:
Uri httpUrl = new Uri("http://localhost:8090/MyService/SimpleCalculator");
//Create ServiceHost
ServiceHost host = new
ServiceHost(typeof(MyCalculatorService.SimpleCalculator), httpUrl);
//Add a service endpoint
host.AddServiceEndpoint
(typeof(MyCalculatorService.ISimpleCalculator), new WSHttpBinding(), "");
//Enable metadata exchange
ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
smb.HttpGetEnabled = true;
//Start the Service
host.Open();
Console.WriteLine("Service is host at " + DateTime.Now.ToString());
Console.WriteLine("Host is running... Press key to stop");
Console.ReadLine();
Exposing the metadata
using HTTP-GET has a disadvantage, ie there is no guarantee that other
platforms you interact will support it. There is other way of exposing
the using special endpoint is called as Metadata Exchange Endpoint. You
can have
as many metadata exchange endpoints as you want.
Address:
It is basically Uri to
identify the metadata. You can specify as address in the endpoint but
append with "mex" keyword. For example
"http://localhost:9090/MyCalulatorService/mex"
Binding:
There are four types of
bindings supported for metadata exchange. They are mexHttpBinding,
mexHttpsBinding, mexNamedPipesBinding, mexTcpBinding.
Contract:
IMetadataExchange is the
contract used for MEX endpoint. WCF service host automatically provides
the implementation for this IMetadataExcahnge while hosting the
service.
Administrative (Configuration file):
In the configuration file of the hosting application, you can add metadata exchange endpoint as shown below.
<services>
<service name="MyService">
<endpoint address="http://localhost/IISHostedService/MyService.svc"
binding="wsHttpBinding" contract="IMyService">
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
</system.serviceModel>
Steps to create the metadata endpoint through coding are:
ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
host.Description.Behaviors.Add(smb);
Binding mexBinding = MetadataExchangeBindings.CreateMexHttpBinding ();
host.AddServiceEndpoint(typeof(IMetadataExchange), mexBinding, "mex");
Uri httpUrl = new Uri("http://localhost:8090/MyService/SimpleCalculator");
//Create ServiceHost
ServiceHost host = new
ServiceHost(typeof(MyCalculatorService.SimpleCalculator), httpUrl);
//Add a service endpoint
host.AddServiceEndpoint
(typeof(MyCalculatorService.ISimpleCalculator), new WSHttpBinding(), "");
//Enable metadata exchange
ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
host.Description.Behaviors.Add(smb);
Binding mexBinding = MetadataExchangeBindings.CreateMexHttpBinding ();
//Adding metadata exchange endpoint
host.AddServiceEndpoint(typeof(IMetadataExchange), mexBinding, "mex");
//Start the Service
host.Open();
Console.WriteLine("Host is running... Press key to stop");
Console.ReadLine();
Suppose the service I
consumed is not working in the client application. I want to know the
real cause of the problem. How I can know the error? For this we are
having Fault Contract. Fault Contract provides documented view for error
occurred in the
service to client. This helps us to easy identity, what error has occurred.
[ServiceContract()]
public interface ISimpleCalculator
{
[OperationContract()]
int Add(int num1, int num2);
}
//Service implementation
public class SimpleCalculator : ISimpleCalculator
{
public int Add(int num1, int num2)
{
//Do something
throw new Exception("Error while adding number");
}
}
Step 2: On client side
code. Exceptions are handled using try-Catch block. Even though I have
capture the exception when I run the application. I got the message that
exceptions are not handled properly.
{
MyCalculatorServiceProxy.MyCalculatorServiceProxy proxy
= new MyCalculatorServiceProxy.MyCalculatorServiceProxy();
Console.WriteLine("Client is running at " + DateTime.Now.ToString());
Console.WriteLine("Sum of two numbers... 5+5 =" + proxy.Add(5, 5));
Console.ReadLine();
}
catch (Exception ex)
{ Console.WriteLine(ex.Message);
Console.ReadLine();
}
Step 3: Now if you want to send exception information form service to client, you have to use FaultException as shown below.
public int Add(int num1, int num2)
{
//Do something
throw new FaultException("Error while adding number");
}
Step 4: Output window on the client side is show below.
Step 5: You can
also create your own Custom type and send the error information to the
client using FaultContract. These are the steps to be followed to create
the fault contract.
Decorate the service operation with the FaultContract attribute and specify the type name.
Raise the exception from the service by creating an instance and assigning properties of the custom exception.
Step 6: Defining the type using Data Contract
[DataContract()]
public class CustomException
{
[DataMember()]
public string Title;
[DataMember()]
public string ExceptionMessage;
[DataMember()]
public string InnerException;
[DataMember()]
public string StackTrace;
}
Step 7: Decorate the service operation with the FaultContract
[ServiceContract()]
public interface ISimpleCalculator
{
[OperationContract()]
[FaultContract(typeof(CustomException))]
int Add(int num1, int num2);
}
Step 8: Raise the exception from the service
public int Add(int num1, int num2)
{
//Do something
CustomException ex = new CustomException();
ex.Title = "Error Funtion:Add()";
ex.ExceptionMessage = "Error occur while doing add function.";
ex.InnerException = "Inner exception message from serice";
ex.StackTrace = "Stack Trace message from service.";
throw new FaultException(ex,"Reason: Testing the Fault contract") ;
}
Step 9: On client side, you can capture the service exception and process the information, as shown below.
try
{
MyCalculatorServiceProxy.MyCalculatorServiceProxy proxy
= new MyCalculatorServiceProxy.MyCalculatorServiceProxy();
Console.WriteLine("Client is running at " + DateTime.Now.ToString());
Console.WriteLine("Sum of two numbers... 5+5 =" + proxy.Add(5, 5));
Console.ReadLine();
}
catch (FaultException<MyCalculatorService.CustomException> ex)
{
//Process the Exception
}
Instance Management:
Instance management refers to the way a service handles a request from a client.
Basically there are 3 instance modes in WCF:
Per-Call instance mode
Per-Session instance mode
Singleton Instance Mode
Instance mode can be configured using ServiceBehavior attribute.
[ServiceContract()]
public interface IMyService
{
[OperationContract]
int MyMethod();
}
[ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)]
public class MyService:IMyService
{
public int MyMethod()
{
//Do something
}
}
Per-Call Instance:
A Service instance will
be created for each client request. This Service instance will be
disposed after response is sent back to client.
1. Client call the proxy
2. Proxy forward the call to service
3. WCF create service instance.
4. Service Instance calls the method
5. Method returns value to the client
6. WCF call IDisposable on service instance.
Create the service
contract called IMyService and implement the interface. Add service
behavior attribute to the service class and set the InstanceContextMode
property to PerCall as show below.
[ServiceContract()]
public interface IMyService
{
[OperationContract]
int MyMethod();
}
Step 2:
In this implementation
of MyMethod operation, increment the static variable(m_Counter). Each
time while making call to the service, m_Counter variable is incremented
and return the value to the client.
[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerCall)]
public class MyService:IMyService
{
static int m_Counter = 0;
public int MyMethod()
{
m_Counter++;
return m_Counter;
}
}
Step 3:
Client side, create the proxy for the service and call "myMethod" operation multiple time.
static void Main(string[] args)
{
Console.WriteLine("Service Instance mode: Per-Call");
Console.WriteLine("Client making call to service...");
//Creating the proxy on client side
MyCalculatorServiceProxy.MyServiceProxy proxy =
new MyCalculatorServiceProxy.MyServiceProxy();
Console.WriteLine("Counter: " + proxy.MyMethod());
Console.WriteLine("Counter: " + proxy.MyMethod());
Console.WriteLine("Counter: " + proxy.MyMethod());
Console.WriteLine("Counter: " + proxy.MyMethod());
Console.ReadLine();
}
All requests to service
return '1', because we configured the Instance mode to Per-Call. Service
instance will created for each request and value of static variable
will be set to one. While return back, service instance will be
disposed.
Per-Session Service:
When WCF service is configured for Per-Session instance mode, logical session between client and service will be maintained.
Step 1:
Create the service
contract called IMyService and implement the interface. Add service
behavior attribute to the service class and set the InstanceContextMode
property to PerSession as show below.
[ServiceContract()]
public interface IMyService
{
[OperationContract]
int MyMethod();
}
Step 2:
In this implementation
of MyMethod operation, increment the static variable (m_Counter). Each
time while making call to the service, m_Counter variable will be
incremented and return the value to the client.
[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerSession)]
public class MyService:IMyService
{
static int m_Counter = 0;
public int MyMethod()
{
m_Counter++;
return m_Counter;
}
}
Step 3:
Client side, create the proxy for the service and call "myMethod" operation multiple time.
static void Main(string[] args)
{
Console.WriteLine("Service Instance mode: Per-Session");
Console.WriteLine("Client making call to service...");
//Creating the proxy on client side
MyCalculatorServiceProxy.MyServiceProxy proxy =
new MyCalculatorServiceProxy.MyServiceProxy();
Console.WriteLine("Counter: " + proxy.MyMethod());
Console.WriteLine("Counter: " + proxy.MyMethod());
Console.WriteLine("Counter: " + proxy.MyMethod());
Console.WriteLine("Counter: " + proxy.MyMethod());
Console.ReadLine();
}
All request to service
return incremented value (1, 2, 3, 4), because we configured the
instance mode to Per-Session. Service instance will be created once the
proxy is created at client side. So each time request is made to the
service, static
variable is incremented. So each call to MyMethod return incremented value.
Singleton Service:
When WCF service is
configured for Singleton instance mode, all clients are independently
connected to the same single instance. This singleton instance will be
created when service is hosted and, it is disposed when host shuts down.
Step 1:
Create the service
contract called IMyService and implement the interface. Add service
behavior attribute to the service class and set the InstanceContextMode
property to Single as show below.
[ServiceContract()]
public interface IMyService
{
[OperationContract]
int MyMethod();
}
Step 2:
In this implementation
of MyMethod operation, increment the static variable(m_Counter). Each
time while making call to the service, m_Counter variable is incremented
and return the value to the client
[ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)]
public class MyService:IMyService
{
static int m_Counter = 0;
public int MyMethod()
{
m_Counter++;
return m_Counter;
}
}
Step 3:
Client side, create the two proxies for the service and made a multiple call to MyMethod.
static void Main(string[] args)
{
Console.WriteLine("Service Instance mode: Singleton");
Console.WriteLine("Client 1 making call to service...");
//Creating the proxy on client side
MyCalculatorServiceProxy.MyServiceProxy proxy =
new MyCalculatorServiceProxy.MyServiceProxy();
Console.WriteLine("Counter: " + proxy.MyMethod());
Console.WriteLine("Counter: " + proxy.MyMethod());
Console.WriteLine("Counter: " + proxy.MyMethod());
//Creating new proxy to act as new client
MyCalculatorServiceProxy.MyServiceProxy proxy2 =
new MyCalculatorServiceProxy.MyServiceProxy();
Console.WriteLine("Counter: " + proxy2.MyMethod());
Console.WriteLine("Counter: " + proxy2.MyMethod());
Console.ReadLine();
}
When two proxy class
made a request to service, single instance at service will handle it and
it return incremented value (1, 2, 3, 4), because instance mode is
configured to 'Single'. Service instance is created when it is hosted.
So this instance will remain till host is shutdown.
Basically service
instance is hosted in a context.When session starts, context is created
and when it closes, context is terminated. WCF provides the option of
separating the two lifetimes and deactivating the instance separately
from its context.
RealeaseInstanceMode.None
RealeaseInstanceMode.BeforeCall
RealeaseInstanceMode.AfterCall
RealeaseInstanceMode.BeforeAndAfterCall
public interface ISimpleCalculator
{
[OperationContract()]
int Add(int num1, int num2);
}
[OperationBehavior(ReleaseInstanceMode=ReleaseInstanceMode.BeforeCall]
public int Add(int num1, int num2)
{
return num1 + num2;
}
ReleaseInstanceMode.None:It will not affect the instance lifetime. By default ReleaseInstanceMode property is set to 'None'.
ReleaseInstanceMode.BeforeCall:
It will create new
instance before a call is made to the operation.If the instance is
already exist,WCF deactivates the instance and calls Dispose() before
the call is done.
ReleaseInstanceMode.AfterCall:
It will deactivate the instance after call is made to the method.
ReleaseInstanceMode.BeforeAndAfterCall:
It will create new
instance of object before a call and deactivates the instance after
call. It has combined effect of using ReleaseInstanceMode.BeforeCall and
ReleaseInstanceMode.AfterCall
We can also explicitly deactivate instance using InstanceContext object as shown below.
public interface IMyService
{
[OperationContract]
void MyMethod();
}
[ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)]
public class MyService:IMyService
{
public void MyMethod()
{
//Do something
OperationContext.Current.InstanceContext.ReleaseServiceInstance();
}
}
Durable Service:
Durable services persist
service state information even after service host is restarted or
Client. Durable services have the capability to restore their own state
when they are recycled. It can use SQL database for maintaining
instance state.
We can also maintain
session using WCF sessions, but content in the session environment is
not persisted by default. If the service is shut down or client closes
the proxy, data will be lost. But in case of Durable service it is still
maintained.
When a client make a
request to the service, instance of the service is serialized, a new
GUID is generated. This serialized instance xml and key will be saved in
the database. We will call this GUID as instanceID. Service will send
the instanceID to
the client, so later it can use this id to get the instance state back.
Even when client is shut down, instanceId will be saved at the client
side. So when ever client opening the proxy, it can get back the
previous state.
Durable service can be implemented using [DurableService()] attribute. It takes 'CanCreateInstance' and 'CompletesInstance'
property to mention on which operation instance state has to be saved and destroyed.
CompletesInstance = true: Deletes the persisted instance from the datastore.
[Serializable]
[DurableService()]
public class MyService :IMyservice
{
[DurableOperation(CanCreateInstance = true)]
public int StartPersistance()
{
//Do Something
}
[DurableOperation(CompletesInstance = true)]
public void EndPersistence()
{
//Do Something
}
}
Let us understand more
about the durable service by creating Simple Calculator service which
persist the instance state in SQL server database.
Step 1:
Start the Visual Studio 2008 and click File->New->Web Site. Select the 'WCF Service' as shown below.
Step 2:
Create interface and decorate with Service and Operation contract.
[ServiceContract()]
public interface ISimpleCalculator
{
[OperationContract]
int Add(int num);
int Subtract(int num);
[OperationContract]
int Multiply(int num);
[OperationContract]
void EndPersistence();
}
Step 3:
You need to add [Serializable] And [DurableService()] attribute to the service implementation. Set CanCreateInstance = true
property to the
operation in which instance state has to be persisted and set
CompletesInstance = true when state has to be destroyed. In this
implementation, we are going to persist the 'currentValue' variable
value to the database.
using System.ServiceModel;
using System.Text;
using System.ServiceModel.Description;
[DurableService()]
public class SimpleCalculator :ISimpleCalculator
{
int currentValue = default(int);
[DurableOperation(CanCreateInstance = true)]
public int Add(int num)
{
return (currentValue += num);
}
[DurableOperation()]
public int Subtract(int num)
{
return (currentValue -= num);
}
[DurableOperation()]
public int Multiply(int num)
{
return (currentValue *= num);
}
[DurableOperation(CompletesInstance = true)]
public void EndPersistence()
{
}
Before configuring the
database information in the durable service, you need to set up
DataStore environment. Microsoft provides inbuilt sqlPersistance
provider. To set up the database environment, run the these sql query
located at following
location 'C:\Windows\Microsoft.NET\Framework\v3.5\SQL\EN'
SqlPersistenceProviderLogic.sql
In order to support
durable service, you need to use Context binding type.
<persistenceProvider> tag is used to configure the persistence
provider.
<services>
<service name="SimpleCalculator" behaviorConfiguration="ServiceBehavior">
<!-- Service Endpoints -->
<endpoint address="" binding="wsHttpContextBinding"
bindingConfiguration="browConfig" contract="ISimpleCalculator">
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding"
contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceBehavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
<persistenceProvider type="System.ServiceModel.Persistence.SqlPersistenceProviderFactory,
System.WorkflowServices, Version=3.5.0.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35" connectionStringName="DurableServiceStore"
persistenceOperationTimeout="00:00:10" lockTimeout="00:01:00" serializeAsText="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<wsHttpContextBinding >
<binding name="browConfig" >
<security mode="None"></security>
</binding>
</wsHttpContextBinding>
</bindings>
</system.serviceModel>
<connectionStrings>
<add name="DurableServiceStore" connectionString="Data Source=saravanakumar;Initial Catalog
=DurableServiceStore;Integrated Security=True"/>
</connectionStrings>
Create the console client application and name it as DurableServiceClient
System.ServiceModel
System.WorkflowService
Step 9:
Create the Helper class
called it as Helper.cs. This helper class is used to Store, Retrieve and
set the context at the client side. Context information will be saved
in 'token_context.bin' file. Copy and paste the below code to your
helper file.
Helper.cs:
using System.ServiceModel.Channels;
using System.ServiceModel;
using System.Net;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
public class Helper
{
static readonly String TokenContextFileName = "token_context.bin";
public static IDictionary<String, String> LoadContext()
{
IDictionary<String, String> ctx = null;
try
{
using (FileStream fs = new
FileStream(TokenContextFileName, FileMode.Open, FileAccess.Read))
{
BinaryFormatter bf = new BinaryFormatter();
ctx = bf.Deserialize(fs) as IDictionary<String, String>;
fs.Close();
}
}
catch (Exception ex)
{ }
return ctx;
}
public static void SaveContext(IClientChannel channel)
{
IDictionary<String, String> ctx = null;
IContextManager cm = channel.GetProperty<IContextManager>();
if (cm != null)
{
ctx = cm.GetContext() as IDictionary<String, String>;
try
{
using (FileStream fs
= new FileStream(TokenContextFileName, FileMode.CreateNew))
{
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(fs, ctx);
fs.Close();
}
}
catch (Exception ex)
{ }
}
}
public static void DeleteContext()
{
try
{
File.Delete(TokenContextFileName);
}
catch (Exception ex)
{ }
}
public static void SetContext(IClientChannel channel,
IDictionary<String, String> ctx)
{
IContextManager cm = channel.GetProperty<IContextManager>();
if (cm != null)
{
cm.SetContext(ctx);
}
}
}
Step 10:
In the main method, I
was creating the proxy for the service and calling the Add operation.
Call to this method will add instance state to the database. Now I have
closed the proxy and creating new proxy instance. When I call the
Subtract and
Multiply operation, it will operate on the previously saved value (instance state).
static void Main(string[] args)
{
//Create the proxy for the service
SimpleCalculatorService.SimpleCalculatorClient client= new SimpleCalculatorService.SimpleCalculatorClient
"WSHttpContextBinding_ISimpleCalculator");
int currentValue = 0;
//Call the Add method from the service
currentValue = client.Add(10000);
Console.WriteLine("The current value is {0}", currentValue);
//Save the Context from the service to the client
Helper.SaveContext(client.InnerChannel);
//Close the proxy
client.Close();
//Create new Instance of the proxy for the service
client = new SimpleCalculatorService.SimpleCalculatorClient("WSHttpContextBinding_ISimpleCalculator");
//Load the context from the client to start from saved state
IDictionary<string,string> cntx=Helper.LoadContext();
//Set Context to context manager
Helper.SetContext(client.InnerChannel, cntx);
//Call the Subtract and Multiply method from service
currentValue = client.Subtract(2);
Console.WriteLine("The current value is {0}", currentValue);
currentValue = client.Multiply(5);
Console.WriteLine("The current value is {0}", currentValue);
//Delete the context from the client
Helper.DeleteContext();
//Remove persistance state from the server
client.EndPersistence();
Console.WriteLine("Press <ENTER> to shut down the client.");
Console.ReadLine();
client.Close();
}
Throttling:
WCF throttling provides
some properties that you can use to limit how many instances or sessions
are created at the application level. Performance of the WCF service
can be improved by creating proper instance.
Attribute Description
maxConcurrentCalls -
Limits the total number of calls that can currently be in progress
across all service instances. The default is 16.
maxConcurrentInstances -
The number of InstanceContext objects that execute at one time across a
ServiceHost. The default is Int32.MaxValue.
maxConcurrentSessions - A
positive integer that limits the number of sessions a ServiceHost
object can accept. The default is 10.
Service Throttling can be configured either Adminstractive or Programatically
Administrative (configuration file)
Using
<serviceThrottling> tag of the Service Behavior, you can configure
the maxConcurrentCalls, maxConcurrentInstances , maxConcurrentSessions
property as shown below.
<system.serviceModel>
<services >
<service behaviorConfiguration="ServiceBehavior" name="MyService">
<endpoint address="" binding="wsHttpBinding" contract="IMyService">
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceBehavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true "/>
<serviceThrottling maxConcurrentCalls="500"
maxConcurrentInstances ="100" maxConcurrentSessions ="200"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
Programming Model
Use ServiceThrottlingBehavior object to set concurrent calls, session and instance property.
ServiceHost host = new ServiceHost(typeof(MyService));
ServiceThrottlingBehavior throttle = host.Description.Behaviors.Find();
if (throttle == null)
{
throttle = new ServiceThrottlingBehavior();
throttle.MaxConcurrentCalls = 500;
throttle.MaxConcurrentSessions = 200;
throttle.MaxConcurrentInstances = 100;
host.Description.Behaviors.Add(throttle);
}
host.Open();
Transfer mode
If data transfer is
taking place through WCF service, message size will play major role in
performance of the data transfer. Based on the size and other condition
of the data transfer, WCF supports two modes for transferring messages
Buffer transfer
When the client and the
service exchange messages, these messages are buffered on the receiving
end and delivered only once the entire message has been received. This
is true whether it is the client sending a message to the service or the
service returning a message to the client. As a result, when the client
calls the service, the service is invoked only after the client's
message has been received in its entirety; likewise, the client is
unblocked only once the returned message with the results of the
invocation has been received in its entirety.
Stream transfer
When client and Service
exchange message using Streaming transfer mode, receiver can start
processing the message before it is completely delivered. Streamed
transfers can improve the scalability of a service by eliminating the
requirement for large memory buffers. If you want to transfer large
message, streaming is the best method.
StreamRequest
In this mode of configuration, message send from client to service will be streamed
StreamRespone
In this mode of configuration, message send from service to client will be streamed.
Configuration
<system.serviceModel>
<services >
<service behaviorConfiguration="ServiceBehavior" name="MyService">
<endpoint address="" binding="netTcpBinding"
bindingConfiguration="MyService.netTcpBinding" contract="IMyService">
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceBehavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true "/>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings >
<netTcpBinding>
<binding
name="MyService.netTcpBinding" transferMode="Buffered" closeTimeout
="0:01:00" openTimeout="0:01:00"></binding>
</netTcpBinding>
</bindings>
</system.serviceModel>
Differences between Buffered and Streamed Transfers
Buffered:
Target can process the message once it is completely received.
Performance will be good when message size is small
Native channel shape is IDuplexSessionChannel
Streamed:
Target can start processing the data when it is partially received
Performance will be good when message size is larger(more than 64K)
Native channels are IRequestChannel and IReplyChannel
Operations:
Three modes of communication between client and service are
1. Request- Replay:
By default all WCF will
operated in the Request-Replay mode. It means that, when client make a
request to the WCF service and client will wait to get response from
service (till receiveTimeout). After getting the response it will start
executing the
rest of the statement. If service doesn't respond to the service within receiveTimeout, client will receive TimeOutException.
Apart from NetPeerTcpBinding and the NetMsmqBinding all other bindings will support request-reply operations.
2. One-Way:
In One-Way operation
mode, client will send a request to the server and does not care whether
it is success or failure of service execution. There is no return from
the server side, it is one-way communication.
Client will be blocked
only for a moment till it dispatches its call to service. If any
exception thrown by service will not reach the server.
Client can continue to
execute its statement, after making one-way call to server. There is no
need to wait, till server execute. Sometime when one-way calls reach the
service, they may not be dispatched all at once but may instead be
queued up
on the service side to
be dispatched one at a time, according to the service's configured
concurrency mode behavior. If the number of queued messages has exceeded
the queue's capacity, the client will be blocked even if it's issued a
one-way call.
However, once the call
is queued, the client will be unblocked and can continue executing,
while the service processes the operation in the background.
Definition:
One-way operation can be enabled by setting IsOneWay property to true in Operation contract attribute.
[ServiceContract]
public interface IMyService
{
[OperationContract(IsOneWay=true)]
void MyMethod(EmployeeDetails emp);
}
One-Way Operations and Sessionful Services:
Let us see the example, what will happen when you use the one-way communication with Sessionful service.
[ServiceContract(SessionMode = SessionMode.Required)]
interface IMyContract
{
[OperationContract(IsOneWay = true)]
void MyMethod();
}
As per above
configuration, when client makes one-way call using MyMethod() operation
and if it close the proxy. Client will be blocked until operation
completes. It will be good practice, that one-way operation should be
applied on per-call and singleton service.
Suppose If you want to
make use of One-way operation in Sessionful service, use in the last
operation of the service which will terminate the session. This
operation should not return any value.
[ServiceContract(SessionMode = SessionMode.Required)]
interface IMyContract
{
[OperationContract]
void MyMethod1();
[OperationContract]
string MyMethod2();
[OperationContract(IsOneWay = true, IsInitiating = false,
IsTerminating = true)]
string CloseSessionService(int id);
}
One-Way Operations and Exceptions:
Suppose when we are
using BasicHttpBinding or WSHttpBinding, i.e. no transport session is
used, if any exception throw by service will not affect the client.
Client can make a call to the service using same proxy
[ServiceContract]
interface IMyContract
{
[OperationContract(IsOneWay = true)]
void MethodWithError( );
[OperationContract]
void MethodWithoutError( );
}
//Client side without transport session
MyContractClient proxy = new MyContractClient( );
proxy.MethodWithError( ); //No exception is thrown from serivce
proxy.MethodWithoutError( ); //Operation will execute properly
proxy.Close( );
In the presence of
transport session, any exception thrown by service will fault the client
channel. Client will not be able to make new call using same proxy
instance.
//Client side transport session
MyContractClient proxy = new MyContractClient( );
proxy.MethodWithError( );
proxy.MethodWithoutError( ); //Can not executre because channel is faulted
proxy.Close( );
3. Callback:
Till now we have seen
that the all clients will call the service to get the things done. But
WCF also provides the service to call the client. In which, service will
act as client and client will act as service.
HTTP protocols are
connectionless nature, so it is not supported for callback operation. So
BasicHttpBinding and WSHttpBinding cannot be used for this operation.
WCF support WSDualHttpBinding for call back operation.
All TCP and IPC protocols support Duplex communication. So all these binding will be used for callback operation.
Defining and configuring a callback contract:
Callback service can be
enabled by using CallbackContract property in the ServiceContract
attribute. In the below example you can find the decalration of the
callback contract and it is configured in the ServiceContract attribute.
public interface IMyContractCallback
{
[OperationContract]
void OnCallback();
}
[ServiceContract(CallbackContract = typeof(IMyContractCallback))]
public interface IMyContract
{
[OperationContract()]
void MyMethod();
}
Client Callback Setup:
As I said earlier, in
callback operation client will act as service and service will act as
client. So client has to expose a callback endpoint to the service to
call. In the earlier part of the tutorial I have mention that
InstanceContext is the execution scope of inner most service instance.
It provides a constructor that takes the service instance to the host.
IMyContractCallback callback=new MyCallback();
InstanceContext cntx=new InstanceContext(callback);
MyServiceClient proxy = new MyServiceClient(cntx);
proxy.MyMethod();
The client must use a
proxy that will set up the bidirectional communication and pass the
callback endpoint reference to the service. This can be achieved by
creating the proxy using DuplexClientBase
class MyServiceClient:DuplexClientBase,IMyContract
{
public MyServiceClient(InstanceContext callbackCntx)
: base(callbackCntx)
{
}
public void MyMethod()
{
base.Channel.MyMethod();
}
}
Service-Side Callback Invocation:
The client-side callback endpoint reference is passed along with every
call the client makes to the service, and it is part of the incoming
message. The OperationContext class provides the service with easy
access to the callback reference via the
generic method GetCallbackChannel<T>( ). Service can call the
client side callback method using reference e to the client side
callback instance. The following code shows the callback method
invocation.
IMyContractCallback
callbackInstance=OperationContext.Current.GetCallbackChannel();
callbackInstance.OnCallback();
one way Operation:
One way calls are useful for scenarios where you want to sure that the
message was delivered, but don't care whether the message was processed
or not.
Once the Client issues the call , WCF generates the request message and
there is no corresponding response message for that. No Service side
Exception will make their way to client.
A one way service call doesn't wait the call to be processed, only to be
delivered - where delivery includes deserialization of the request.
Once this has happened WCF send the response and start processing the
operation on a separate thread.
When there is no transport session; means when BasicHttpBinding or
wsHttpBinding is used; if an Exception takes place during the invocation
of one-way operation, the client is unaffected and can continue to
issue call on the same proxy
instance.
One-way property could only be set true to the operations that are
returning Void. On any other return type it would throw error while
loading the service.
Exception Handling:
The following options are provided to handle exceptions in WCF:
Using returnUnknownExceptionsAsFaults
Using FaultException
Using IErrorHandler
WCF provides an option to raise the exception automatically as a Soap
Fault. To enable this option, set returnUnknownExceptionsAsFaults=‘True’
in the service behavior setting in the application configuration file
under system.servicemodel.
<behaviors>
<behavior name="OrderingServiceBehavior"
returnUnknownExceptionsAsFaults="True">
</behavior>
</behaviors>
When you use the returnUnknownExceptionsAsFaults option, the client will
receive an UnknownFaultException instead of a CommuncationException.
The returnUnknownExceptionsAsFaults option should only be used during
debugging.
http://www.wcftutorial.net/Fault-Contract.aspx
FaultContract is an attribute in WCF used to specify the type of exception that can be raised by that service.
FaultException is used in WCF to create a Soap Fault. Using the Fault
Exception, you can wrap .NET exception or any custom object into a Soap
Fault.
If the FaultContract contract is not specified, the clients receive all
the exceptions as unknowfaultexceptions even if the exception is raised
as a FaultException for an ApplicationException.
[OperationContract()]
[FaultContract(typeof(ApplicationException))]
void CreateOrderWithFaultException(Order order);
FaultException approach is the best approach for handling exception in
WCF. In this approach,we have 2 options, one is to raise the .Net
exception and the other is to raise it with custom object. You should
always opt for the custom object option, as it would not expose all the
details of .Net exception to the client, instead it sends only the
required information to the client as a custom object. Another advantage
of this option is that it will work well in other platform clients, as
custom object type is described in WSDL.
In the case of .Net exception type, it is not described in WSDL and
hence other platform clients would not understand it. You should use
.Net exception option only when you know that both the client and
service are using WCF and the client needs to get the exact .Net
exception that occurred in the WCF service.
Using IErrorHandler:
With IErrorHandler approach, you can intercept all the exceptions raised
inside a service using IErrorHandler. If you implement IErrorHandler
interface methods in your service, you can intercept all the exceptions
and you can “log and suppress” the exceptions or you can “log and throw”
them as FaultException.
No comments:
Post a Comment