WCF
(Windows Communication Foundation) :-
WCF is flexible because its services
can be hosted in different types of applications. The following lists several
common scenarios for hosting WCF services:
IIS
WAS (Windows Activation Service)
Self-hosting
Managed Windows Service
3 major points in WCF :-
Address :- Specifies the location of
the service which will be like http://Myserver/MyService.Clients will use this
location to communicate with our service.
Binding :- Specifies how the two
parties will communicate in term of transport and encoding and protocols
Contract :- Specifies the interface
between client and the server. It's a simple interface with some attribute
Web services can only be invoked by
HTTP (traditional webservice with .asmx). While WCF Service or a WCF component
can be invoked by any protocol (like http, tcp etc.) and any transport type.
Second web services are not flexible. However, WCF Services are flexible. If
you make a new version of the service then you need to just expose a new end.
The
main components of WCF are :-
1. Service class
2. Hosting environment
3. End point
WCF is a unification of .NET framework
communication technologies, NET remoting, MSMQ, Web services, COM+.
How
to deal with operation overloading while exposing the WCF services :-
By default overload operations
(methods) are not supported in WSDL based operation. However by using Name
property of OperationContract attribute, we can deal with operation overloading
scenario.
[ServiceContract]
interface ICalculator
{
[OperationContract(Name = "AddInt")]
int Add(int arg1,int arg2);
[OperationContract(Name = "AddDouble")]
double Add(double arg1,double arg2);
}
What
is Proxy and how to generate proxy for WCF Services :-
The proxy is a CLR class that exposes
a single CLR interface representing the service contract. The proxy provides
the same operations as service's contract, but also has additional methods for
managing the proxy life cycle and the connection to the service.
The proxy can be generated using
Visual Studio by right clicking Reference and clicking on Add Service
Reference.
Proxy can also be generated by using
SvcUtil.exe command-line utility.
Endpoint
:-
Every service must have Address that
defines where the service resides, Contract that defines what the service does
and a Binding that defines how to communicate with the service. In WCF the
relationship between Address, Contract and Binding is called Endpoint. The
Endpoint is the combination of Address, Contract and Binding.
Binding:-
A binding defines how an endpoint
communicates to the world. A binding defines the transport (such as HTTP or
TCP) and the encoding being used (such as text or binary). A binding can
contain binding elements that specify details like the security mechanisms used
to secure messages, or the message pattern used by an endpoint.
WCF supports nine types of bindings :-
Basic binding
TCP binding
Peer network binding
IPC binding
Web Service (WS) binding
Federated WS binding
Duplex WS binding
MSMQ binding
MSMQ integration binding
Contracts:-
In WCF, all services expose contracts.
The contract is a platform-neutral and standard way of describing what the
service does.
Service contracts: Describe which
operations the client can perform on the service.
There are two types of Service
Contracts.
ServiceContract - This attribute is
used to define the Interface.
OperationContract - This attribute is
used to define the method inside Interface.
[ServiceContract]
interface IMyContract
{
[OperationContract]
string MyMethod( );
}
class MyService : IMyContract
{
public string MyMethod( )
{
return "Hello World";
}
}
Data contracts: Define which data
types are passed to and from the service.
There are two types of Data Contracts.
DataContract - attribute used to
define the class
DataMember - attribute used to define
the properties.
[DataContract]
class Contact
{
[DataMember]
public string FirstName;
[DataMember]
public string LastName;
}
Fault contracts: Define which errors are
raised by the service, and how the service handles and propagates errors to its
clients.
Message contracts: Allow the service
to interact directly with messages. Message contracts can be typed or untyped.
WCF
supports following transport schemas :-
HTTP
TCP
Peer network
IPC (Inter-Process Communication over
named pipes)
MSMQ
Difference
between WCF and Web services?
Web Services,
1.It Can be accessed only over HTTP
2.It works in stateless environment
WCF,
WCF is flexible because its services
can be hosted in different types of applications. The following lists several
common scenarios for hosting WCF services:
IIS
WAS
Self-hosting
Managed Windows Service
Web services are not flexible.
However, WCF Services are flexible. If you make a new version of the service
then you need to just expose a new end.
Various
ways of hosting WCF Services :-
Self-hosting the service in his own
application domain.
Host in application domain or process
provided by IIS Server.
Host in Application domain and process
provided by WAS (Windows Activation Service) Server.
Code
name for WCF :-
The code name of WCF was Indigo. WCF
is a unification of .NET framework communication technologies which unites the
following technologies:-
NET remoting
MSMQ
Web services
COM+
How
to set the timeout property for the WCF Service client call :-
The timeout property can be set for
the WCF Service client call using binding tag.
<client>
<endpoint
...
binding = "wsHttpBinding"
bindingConfiguration = "LongTimeout"
...
/>
</client>
<bindings>
<wsHttpBinding>
<binding name = "LongTimeout" sendTimeout = "00:04:00"/>
</wsHttpBinding>
</bindings>
If no timeout has been specified, the
default is considered as 1 minute.
How
to configure Reliability while communicating with WCF Services :-
Reliability can be configured in the
client config file by adding reliableSession under binding tag.
<system.serviceModel>
<services>
<service name = "MyService">
<endpoint
address = "net.tcp://localhost:8888/MyService"
binding = "netTcpBinding"
bindingConfiguration = "ReliableCommunication"
contract = "IMyContract"
/>
</service>
</services>
<bindings>
<netTcpBinding>
<binding name = "ReliableCommunication">
<reliableSession enabled = "true"/>
</binding>
</netTcpBinding>
</bindings>
</system.serviceModel>
Reliability is supported by following
bindings only
NetTcpBinding
WSHttpBinding
WSFederationHttpBinding
WSDualHttpBinding
Transport
and Message Reliability :-
Transport reliability (such as the one
offered by TCP) offers point-to-point guaranteed delivery at the network packet
level, as well as guarantees the order of the packets. Transport reliability is
not resilient to dropping network connections and a variety of other
communication problems.
Message reliability deals with
reliability at the message level independent of how many packets are required
to deliver the message. Message reliability provides for end-to-end guaranteed
delivery and order of messages, regardless of how many intermediaries are
involved, and how many network hops are required to deliver the message from
the client to the service.
Different
elements of WCF Srevices Client configuration file :-
WCF Services client configuration file
contains endpoint, address, binding and contract. A sample client config file
looks like
<system.serviceModel>
<client>
<endpoint name = "MyEndpoint"
address = "http://localhost:8000/MyService/"
binding = "wsHttpBinding"
contract = "IMyContract"
/>
</client>
</system.serviceModel>
Address
formats of the WCF transport schemas :-
Address format of WCF transport schema
always follow
[transport]://[machine or
domain][:optional port] format.
HTTP Address Format,
http://localhost:8888
"Using HTTP, go to the machine
called localhost, where on port 8888 someone is waiting"
When the port number is not specified,
the default port is 80.
TCP Address Format,
net.tcp://localhost:8888/MyService
When a port number is not specified,
the default port is 808:
net.tcp://localhost/MyService
IPC Address Format,
net.pipe://localhost/MyPipe
We 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 Address Format,
net.msmq://localhost/private/MyService
net.msmq://localhost/MyService
Define
a service as REST based service in WCF :-
WCF 3.5 provides explicit support for
RESTful communication using a new binding named WebHttpBinding.
The below code shows how to expose a
RESTful service
[ServiceContract]
interface IStock
{
[OperationContract]
[WebGet]
int GetStock(string StockId);
}
By adding the WebGetAttribute, we can
define a service as REST based service that can be accessible using HTTP GET
operation.
Service
and client in perspective of data communication :-
A service is a unit of functionality
exposed to the world.
The client of a service is merely the
party consuming the service.
Namespace
is used to access WCF service :-
Service
level message and transport level message :-
You can log WCF message at two levels
one is service level and the other is transport level. Service level:-In this
the messages are logged as they enter the user code or leave the user code.
Transport level: - In this the messages are logged as they are ready to be
encoded / decoded. You specify the message levels in the diagnostics node as
shown in the below code snippet.
<system.serviceModel>
<diagnostics>
<messageLogging
logEntireMessage="true"
logMalformedMessages="false"
logMessagesAtServiceLevel="false"
logMessagesAtTransportLevel="true"
maxMessagesToLog="3000"
maxSizeOfMessageToLog="10000"/>
</diagnostics>
</system.serviceModel>
‘Messagelogging’ also has other attributes , below is the short description about the same.
Concept
of tracelevel in trace listeners :-
This value indicates what type and
level of tracing information you want to record.
Trace level value is specified in
‘source’ tag in switch value. For instance the below ‘web.config’ snippet
indicates the trace type as ‘Information’.
<system.diagnostics>
<sources>
<source name="System.ServiceModel"
switchValue="Information, ActivityTracing">
Enable
tracing on the readymade tracing WCF objects :-
We will enable tracing on
‘System.ServiceModel’ tracing object. To enable tracing we need to enable the
‘system.diagnostics’ XML node in the ‘web.config’ file of the WCF service. We
need to also define the type of listeners for the ‘System.ServiceModel’
listener object. So we add the ‘listeners’ tag with the type as
‘System.Diagnostics.XmlWriterTraceListener’. We need to also define the file
and path where the file is created. For the current scenario we have defined
the file as ‘Traces.svclog’ and the folder as ‘c:\’ drive.
<system.diagnostics>
<sources>
<source name="System.ServiceModel"
switchValue="Information, ActivityTracing">
<listeners>
<add name="log"
type="System.Diagnostics.XmlWriterTraceListener"
initializeData="c:\Traces.svclog" />
</listeners>
</source>
</sources>
</system.diagnostics>
Now
if you run the WCF service you can see a XML file created as shown below.
#<E2ETraceEvent xmlns="http://schemas.microsoft.com/2004/06/E2ETraceEvent">
<System xmlns="http://schemas.microsoft.com/2004/06/windows/eventlog/system">
<EventID>0</EventID>
<Type>3</Type>
<SubType Name="Transfer">0</SubType>
<Level>255</Level>
<TimeCreated SystemTime="2009-04-30T03:21:09.5625000Z" />
<Source Name="System.ServiceModel" />
<Correlation ActivityID="{00000000-0000-0000-0000-000000000000}" RelatedActivityID="{d11829b7-d2db-46d5-a4ac-49a37a56376e}" />
<Execution ProcessName="WebDev.WebServer" ProcessID="2660" ThreadID="8" />
<Channel/>
<Computer>COMPAQ-JZP37MD0</Computer>
</System>
<ApplicationData></ApplicationData>
</E2ETraceEvent>
Concept
of trace listener :-
‘Tracelistener’ are objects that get
tracing information from the trace class and they output the data to some
medium. For instance you can see from the figure ‘TraceListener’ how it listens
to the trace object and outputs the same to UI, File or a windows event log.
There are three different types of ‘tracelistener’ first is the
‘defaulttracelistener’ (this outputs the data to UI), second is
‘textwritertracelistener’ (this outputs to a file) and the final one is
‘Eventlogtracelistener’ which outputs the same to a windows event log.
Below
is a code snippet for ‘textwritertracelistener’ and ‘eventlogtracelistener’.
Using ‘textwritertracelistener’ we have forwarded the trace’s to ‘ErrorLog.txt’
file and in the second snippet we have used the ‘Eventlogtracelistener’ to
forward the trace’s to windows event log.
Figure:-
Tracelistener in action
Security differences between
BasicHttpBinding VS WsHttpBinding :-
In order to understand the security
differences between both these entities we will do a small project. In this
project we will create two WCF service one service using ‘BasicHttpBinding’ and
the second service using ‘WsHttpBinding’.
Step1:-
So
let’s first create a simple service using ‘BasicHttpBinding’. For that we just
a create a simple WCF project and then modify the ‘ServiceModel’ element as
shown below. You can see in the ‘endpoint’ tag we have specified
‘basicHttpBinding’ as the protocol.
<system.serviceModel>
<services>
<service name="WCFBasicHttpBinding.Service1" behaviorConfiguration="WCFBasicHttpBinding.Service1Behavior">
<!-- Service Endpoints -->
<endpoint address="" binding="basicHttpBinding" contract="WCFBasicHttpBinding.IService1">
<!--
Upon deployment, the following identity element should be removed or replaced to reflect the identity under which the deployed service runs. If removed, WCF will infer an appropriate identity automatically.
-->
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="WCFBasicHttpBinding.Service1Behavior">
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="true"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
Step
2 :-
We also need to create one more service using ‘WsHttpBinding’. For that you do
not need to anything special as such. By default WCF project is created using
‘WsHttpBinding’. Below is how the Web.config file looks like. You can see how
the endpoint tag is using ‘wsHttpBinding’.
<system.serviceModel>
<services>
<service name="WCFWsHttpBindingHttps.Service1" behaviorConfiguration="WCFWsHttpBindingHttps.Service1Behavior">
<!-- Service Endpoints -->
<endpoint address="" binding="wsHttpBinding" contract="WCFWsHttpBindingHttps.IService1">
<!--
Upon deployment, the following identity element should be removed or replaced to reflect the identity under which the deployed service runs. If removed, WCF will infer an appropriate identity automatically.
-->
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="WCFWsHttpBindingHttps.Service1Behavior">
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="true"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
Step
3 :-
We will not be creating any new methods in both the services. We will just use
the default code created by the WCF template. So both these services will have
a ‘GetData’ function which returns a string. The ‘GetData’ function is a
default function created WCF project.
public class Service1 : IService1
{
public string GetData(int value)
{
return string.Format("You entered: {0}", value);
}
public CompositeType GetDataUsingDataContract(CompositeType composite)
{
if (composite.BoolValue)
{
composite.StringValue += "Suffix";
}
return composite;
}
}
Step
4 :- Now that out services are created we need to create a
client which will consume this service. So we have created a simple web
application and we have added two references one is a service reference i.e.
‘WsHttpBinding’ and the second is a web reference i.e. ‘BasicHttpBinding’.
Please note when you right click to add reference you need to use the ‘Add
service reference’ to add ‘WsHttpService’ and you need to add web reference for
‘BasicHttpBinding’.
We
will add two buttons on the default aspx page. One button will call the http
service and the other will call the wshttp service. Below is how the function
‘GetData’ is called in both the button clicks.
Step
5 :- So now we are ready with the complete project it is time to sniff and see
how data is transported between client and the service in both the scenarios.
So let’s download a simple http data recorder from http://www.ieinspector.com/httpanalyzer/download.html
. We will then click both the buttons one by one and record the data transfer
using httpanalyzer. You can see the posted data is in simple plain XML format
for basic http protocol and it’s in an encrypted format for wshttp protocol.
Enable
windows authentication on WCF using ‘BasicHttpBinding’ :-
Step 6:- We need to host our service
in the IIS. So make the directory as an IIS application so that your service
can be hosted. Now if you try to browse the service i.e. the SVC file you will
see that it pops up the authentication authorization security dialog box. So
this service cannot be executed with windows authentication.
Step
7:- So
let’s consume this WCF services. So add an ASP.NET webapplication and do a add
webreference. You will be popped up with a dialog box as shown below. Click on
add reference so that a proxy is generated for the WCF service.
Step
8:-
Type in the following code snippet in your page load. So add the namespace
reference and call the method ‘GetData’. The most important step to note is the
credential supplied. ‘DefaultCredentials’ passes the current windows identity
to the WCF service.
If
you execute the service you should get the following display as shown below.
You
can try commenting the below code in your client in other words we are not
passing any credentials.
obj.Credentials =
System.Net.CredentialCache.DefaultCredentials;
Now
if you execute you should get the below error stating that this is a
unauthorized call.
Enable
windows authentication on WCF using ‘BasicHttpBinding’ :-
Step 1:-
Create a project of WCF service application as shown in the below figure.
Circle
WCF service application ?Select this
By
default the WCF project creates a class file which has ‘GetData’ function. This
function takes in a number values and displays a explanatory sentence like ‘You
entered 1 value’ , in case you have entered ‘1’.
public class Service1 : IService1
{
public string GetData(int value)
{
return string.Format("You entered: {0}", value);
}
}
Step
2:- When
we create a WCF service application it also has a web.config file associated
with it. So open the web.config file and ensure that authentication mode is
windows.
<authentication mode="Windows" />
Step
3:-
The third step is to define the bindings and the transport type. To define the
bindings we need to enter ‘basicHttpBinding’ element inside the ‘bindings’ XML
tag. We also need to define the ‘clientCredentialType’ as windows.
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpEndpointBinding">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Windows" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<services>
.........
.........
</system.serviceModel>
Step
4:-
Now the bindings defined needs to be associated with service interface i.e.
‘service1’. So we need to modify the services elements as shown below. You can
note that we have defined a end point which has the binding association.
<system.serviceModel>
........
........
........
<services>
<service behaviorConfiguration="WCFWindowsBasicHttpBinding.Service1Behavior" name="WCFWindowsBasicHttpBinding.Service1">
<endpoint address="" binding="basicHttpBinding"
bindingConfiguration="BasicHttpEndpointBinding"
name="BasicHttpEndpoint" contract="WCFWindowsBasicHttpBinding.IService1">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
</service>
</services>
.........
.........
.........
.........
</system.serviceModel>
So
over all your <system.serviceModel> XML part as whole with bindings and
services is a shown below.
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpEndpointBinding">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Windows" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<services>
<service behaviorConfiguration="WCFWindowsBasicHttpBinding.Service1Behavior" name="WCFWindowsBasicHttpBinding.Service1">
<endpoint address="" binding="basicHttpBinding"
bindingConfiguration="BasicHttpEndpointBinding"
name="BasicHttpEndpoint" contract="WCFWindowsBasicHttpBinding.IService1">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="WCFWindowsBasicHttpBinding.Service1Behavior">
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="true"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
Step 5 :- Go to IIS properties and
click on security tab and ensure that anonymous access is disabled and only
windows authentication is enabled.
Transport
level and message level security :-
When we talk about WCF security there
are two aspects, the first is the data and the second is the medium on which
the data travels i.e. the protocol. WCF has the ability to apply security at
the transport level (i.e. protocol level) and also at message level (i.e.
data).
Figure:
- Transport and Message level security
Transport
level security happens at the channel level. Transport level security is the
easiest to implement as it happens at the communication level. WCF uses
transport protocols like TCP, HTTP, MSMQ etc and every of these protocols have
their own security mechanisms. One of the common implementation of transport
level security is HTTPS. HTTPS is implemented over HTTP protocols with SSL
providing the security mechanism. No coding change is required it’s more of
using the existing security mechanism provided by the protocol.
Message level security is implemented with message data itself. Due to this it
is independent of the protocol. Some of the common ways of implementing message
level security is by encrypting data using some standard encryption algorithm.
Core
security features that WCF addresses :-
There are four core security features
that WCF addresses:-
Confidentiality: This feature ensures that the information does not go
in wrong hands when it travels from the sender to the receiver.
Integrity: This feature ensures that the receiver of the message gets
the same information that the sender sends without any data tampering.
Authentication: This feature verifies who the sender is and who the
receiver is.
Authorization: This feature verifies whether the user is authorized to
perform the action they are requesting from the application.
Different
transaction options :-
We can specify transaction in 3 ways
in WCF:-
1. TransactionFlowOption.NotAllowed,
This is a default option. Using this option no transaction will be propagated
across the binding. If any client attempts to call the WCF service in a
transaction it will be ignored for this option.
2. TransactionFlowOption.Allowed,
This option specifies that client can call this WCF service in a transaction.
It’s not compulsory that the service needs to be called in a transaction. You
can call without the transaction also.
3. TransactionFlowOption.Mandatory,
This option specifies that client must call the WCF service in a transaction
mode. If the WCF service is called without transaction, ‘FaultException’ will
be raised.
Simple
WCF example of transactions using SQL Server database :-
To enable WCF transaction is a 6 step
procedure. So let’s create two WCF services and let’s try to call them in one
transaction.
Step 1 :- Create two WCF service
The first step is to create two WCF service projects which will participate in
one transaction. In both of these WCF services we will do database transactions
and we will try to understand how a WCF transaction unifies them. We have also
created a web application with name ‘WCFTransactions’ which will consume both
the service in one transaction scope.
Step 2:- Attribute
interface methods with TransactionFlow
In both the WCF service we will create
a method called as ‘UpdateData’ which will do insert in to the database. So the
first thing is to create the interface class with ‘ServiceContract’ attribute
and the method ‘UpdateData’ with ‘OperationContract’ attribute. In order to enable
transaction in ‘UpdateData’ method we need to attribute it with
‘TransactionFlow’ and we have specified that transactions are allowed for this
method using ‘TransactionFlowOption.Allowed’ enum.
[ServiceContract]
public interface IService1
{
[OperationContract]
[TransactionFlow(TransactionFlowOption.Allowed)]
void UpdateData();
}
Step 3:- Attribute
the implementation with ‘TransactionScopeRequired’
The 3rd step is to attribute the
implementation of the WCF services with ‘TransactionScopeRequired’ as true.
Below is the code snippet which has a simple database inserting function i.e.
‘UpdateData’ which is attributed by ‘TransactionScopeRequired’ attribute.
[OperationBehavior(TransactionScopeRequired = true)]
public void UpdateData()
{
SqlConnection objConnection = new SqlConnection(strConnection);
objConnection.Open();
SqlCommand objCommand = new SqlCommand("insert into Customer(CustomerName,CustomerCode) values('sss','sss')",objConnection);
objCommand.ExecuteNonQuery();
objConnection.Close();
}
Step 4:- Enable
transaction flow using WCF service config file
We also need to enable transactions
for ‘wsHttpBinding’ by setting the ‘transactionFlow’ attribute to true.
<bindings>
<wsHttpBinding>
<binding name="TransactionalBind" transactionFlow="true"/>
</wsHttpBinding>
</bindings>
The transaction enabled binding we
need to attach with the end point through which our WCF service is
exposed.
<endpoint address="" binding="wsHttpBinding" bindingConfiguration="TransactionalBind" contract="WcfService1.IService1">
Step 5:- Call the 2
services in one transaction
Now that we are done with our server
side transaction enablement, it’s time to call the above 2 services in 1
transaction. We need to use the ‘TransactionScope’ object to group the above 2
WCF services in one transaction. To commit all the WCF transactions we call the
‘Complete’ method of the ‘Transactionscope’ object. To rollback we need to call
the ‘Dispose’ method.
using (TransactionScope ts = new TransactionScope(TransactionScopeOption.RequiresNew))
{
try
{
// Call your webservice transactions here
ts.Complete();
}
catch (Exception ex)
{
ts.Dispose();
}
}
Below is the complete code snippet
in which we have grouped both the WCF transactions in one scope as shown
below.
using (TransactionScope ts = new TransactionScope(TransactionScopeOption.RequiresNew))
{
try
{
ServiceReference1.Service1Client obj = new ServiceReference1.Service1Client();
obj.UpdateData();
ServiceReference2.Service1Client obj1 = new ServiceReference2.Service1Client();
obj1.UpdateData();
ts.Complete();
}
catch (Exception ex)
{
ts.Dispose();
}
}
Step 6:- Test does
your transaction work
It’s time to test if the transactions
really work. We are calling two services both of these services are doing an
insert. After the first WCF service call we are forcing an exception. In other
words the data insert of the first WCF service should revert back. If you check
the database records you will see no records are inserted by the WCF service.
Can we implement transactions in
one-way WCF service calls :-
WCF transactions are 2-phase commits.
In other words for every commit you need to get a confirmation response, saying
is the commit successful. In one-way WCF services we do not get any response
back , so WCF transactions are not possible with 1 way WCF service calls.
How
prepare and commit phases work :-
Let’s consider 3
computers as shown in the below figure. The client consuming the WCF service
resides in computer ‘A’ while computer ‘B’ and ‘C’ have the WCF services. The
transaction is initiated from the computer ‘A’. So as we said previously there
are 2 phase one is the prepare phase and the other commit phase. In prepare
phase computer ‘A’ sends messages to all the WCF services saying, are they
ready to commit?. Once all WCF services respond saying that they are ready for
commit it starts the second phase i.e. In the second phase the WCF client issues
a commit command. All the WCF services start execution and once they are done
they revert back saying they have committed. When all the WCF services revert
saying they have committed the transaction is marked as successful.
Two
different kinds of phases in WCF transactions :-
WCF
transactions follow 2 phase commit. So there are 2 phases one is the prepare
phase and the other is the commit phase. All co-ordination of transactions is
done by the transaction manager.
In prepare phase the transaction
manager checks whether all entities are prepared to commit. In commit phase the
actual commit starts. You can think about prepare phase as a check saying that
all entities are ready to commit and in the commit phase we do the actual work.
Which
protocol is used to handle transactions in WCF :-
WCF follows
WS-* specifications. So it uses WS-Atomic protocol to managed transaction
across WCF services. So you can have different WCF services hosted on different
computers and they all can run under one transaction unit. The best part of
WS-Atomic protocol is that in one transaction you can have heterogeneous WCF
services developed in different platform. In other words you can have JAVA and
.NET web services running under one transaction. WS-* specifications are
globally approved standards to create services.
Dead
letter queues :-
The main use
of queue is that you do not need the client and the server running at one time.
Therefore, it is possible that a message will lie in queue for long time until
the server or client picks it up. But there are scenarios where a message is of
no use after a certain time. Therefore, these kinds of messages if not
delivered within that time span it should not be sent to the user.
Below is the config snippet, which defines for how much time the message should
be in queue.
<bindings>
<netMsmqBinding>
<binding name="MyBindings"
deadLetterQueue="Custom"
customDeadLetterQueue="net.msmq://localhost/private/ServiceModelSamples"
timeToLive="00:00:02"/>
</netMsmqBinding>
Volatile
queues :-
There are
scenarios in the project when you want the message to deliver in proper time.
The timely delivery of message is more important than losing message. In these
scenarios, Volatile queues are used.
Below is the code snippet, which shows how to configure Volatile queues. You
can see the binding Configuration property set to Volatile Binding. This code
will assure that message will deliver on time but there is a possibility that
you can lose data.
<appSettings>
<!-- use appSetting to configure MSMQ queue name -->
<add key="queueName" value=".\private$\ServiceModelSamplesVolatile" />
</appSettings>
<system.serviceModel>
<services>
<service name="Samples.StockTickerServ"
behaviorConfiguration="CalculatorServiceBehavior">
...
<!-- Define NetMsmqEndpoint -->
<endpoint address="net.msmq://localhost/private/ServiceModelSamplesVolatile"
binding="netMsmqBinding"
bindingConfiguration="volatileBinding"
contract="Samples.InterfaceStockTicker" />
...
</service>
</services>
<bindings>
<netMsmqBinding>
<binding name="volatileBinding"
durable="false"
exactlyOnce="false"/>
</netMsmqBinding>
</bindings>
...
</system.serviceModel>