61
WCF Service FAQs - Part 1 The article is a collection of most frequently asked questions about Windows Communication Foundation covering the beginner level. What is WCF? Microsoft refers WCF as a programming platform that is used to build Service- oriented applications. Windows Communication Foundation is basically a unified programming model for developing, configuring and deploying distributed services. Microsoft has unified all its existing distributed application technologies (e.g. MS Enterprise Services, ASMX web services, MSMQ, .NET Remoting etc) at one platform i.e. WCF. Code name for WCF was Indigo. Why to use WCF? or What are the advantages for using WCF? Service Orientation is one of the key advantages of WCF. We can easily build service-oriented applications using WCF. If compared with ASMX web services, WCF service provides reliability and security with simplicity. As oppose to .NET Remoting, WCF services are interoperable. Different clients can interact with same service using different communication mechanism. This is achieved by using service endpoints. A single WCF service can have multiple endpoints. So, developer will write code for service once and just by changing configuration (defining another service endpoint), it will be available for other clients as well. Extensibility is another key advantage of WCF. We can easily customize a service behavior if required. What are the core components of WCF Service? A WCF service has at least following core components. Service Class: A ervice class implementing in any CLR-based language and expose at least one method. Hosting Environment: a managed process for running service. Endpoint: a client uses it to communicate with service. What is the difference between WCF and ASMX Web services? The basic difference is that ASMX web service is designed to send and receive messages using SOAP over HTTP only. While WCF service can exchange messages using any format (SOAP is default) over any transport protocol (HTTP, TCP/IP, MSMQ, Named Pipes etc). You can find detailed discussion on WCF Vs ASMX Web services here. What are the Endpoints in WCF? or Explain ABCs of endpoint? For WCF services to be consumed, it’s necessary that it must be exposed; Clients need information about service to communicate with it. This is where service endpoints play their role.

Wcf

Embed Size (px)

DESCRIPTION

WCF Overview

Citation preview

Page 1: Wcf

WCF Service FAQs - Part 1The article is a collection of most frequently asked questions about Windows Communication Foundation covering the beginner level.

What is WCF?Microsoft refers WCF as a programming platform that is used to build Service-oriented applications. Windows Communication Foundation is basically a unified programming model for developing, configuring and deploying distributed services.  Microsoft has unified all its existing distributed application technologies (e.g. MS Enterprise Services, ASMX web services, MSMQ, .NET Remoting etc) at one platform i.e. WCF. Code name for WCF was Indigo.

Why to use WCF? or What are the advantages for using WCF?

Service Orientation is one of the key advantages of WCF. We can easily build service-oriented applications using WCF.

If compared with ASMX web services, WCF service provides reliability and security with simplicity.

As oppose to .NET Remoting, WCF services are interoperable.

Different clients can interact with same service using different communication mechanism. This is achieved by using service endpoints. A single WCF service can have multiple endpoints. So, developer will write code for service once and just by changing configuration (defining another service endpoint), it will be available for other clients as well.

Extensibility is another key advantage of WCF.  We can easily customize a service behavior if required.

What are the core components of WCF Service?A WCF service has at least following core components.

Service Class:  A ervice class implementing in any CLR-based language and expose at least one method.

Hosting Environment: a managed process for running service.

Endpoint: a client uses it to communicate with service.

What is the difference between WCF and ASMX Web services?The basic difference is that ASMX web service is designed to send and receive messages using SOAP over HTTP only. While WCF service can exchange messages using any format (SOAP is default) over any transport protocol (HTTP, TCP/IP, MSMQ, Named Pipes etc).

You can find detailed discussion on WCF Vs ASMX Web services here.

What are the Endpoints in WCF? or Explain ABCs of endpoint?For WCF services to be consumed, it’s necessary that it must be exposed; Clients need information about service to communicate with it. This is where service endpoints play their role.A service endpoint has three basic elements or also called ABCs of an endpoint i.e. Address, Binding and Contract.Address: It defines “WHERE”. Address is the URL that identifies the location of the service.Binding: It defines “HOW”. Binding defines how the service can be accessed.Contract: It defines “WHAT”. Contract identifies what is exposed by the service.

What is a WCF Binding? How many different types of bindings available in WCF?Bindings in WCF actually defines that how to communicate with the service. Binding specifies that what

Page 2: Wcf

communication protocol as well as encoding method will be used. Optionally, binding can specify other important factors like transactions, reliable sessions and security.Another WCF Tutorial gives more detailed understanding of Binding concept in WCF.

There are different built-in bindings available in WCF, each designed to fulfill some specific need. 

basicHttpBinding

wsHttpBinding

netNamedPipeBinding

netTcpBinding

netPeerTcpBinding

netmsmqBinding

For details on different binding types, please follow the link to WCF bindings.

Can we have multiple endpoints for different binding types in order to serve different types of clients?

Yes, we can have multiple endpoints for different binding types. For example, an endpoint with wsHttpBinding and another one with netTcpBinging.

What are the hosting options for WCF Services? Explain.

For a service to host, we need at least a managed process, a ServiceHost instance and an Endpoint configured. Possible approaches for hosting a service are:      1.    Hosting in a Managed Application/ Self Hosting             a.    Console Application             b.    Windows Application             c.    Windows Service        2.    Hosting on Web Server             a.    IIS 6.0 (ASP.NET Application supports only HTTP)             b.    Windows Process Activation Service (WAS) i.e. IIS 7.0 supports HTTP, TCP,                    NamedPipes, MSMQ.

What are Contracts in WCF?

A Contract is basically an agreement between the two parties i.e. Service and Client. In WCF, Contracts can be categorized as behavioral or structural.

1. Behavioral Contracts  define that what operations client can perform on a service.

ServiceContract attribute is used to mark a type as Service contract that contains operations.

OperationContract attributes is used to mark the operations that will be exposed.

Fault Contract defines what errors are raised by the service being exposed.

2. Structural Contracts

DataContract  attribute define types that will be moved between the parties.

MessageContract attribute define the structure of SOAP message.

What Message Exchange Patterns supported by WCF?   Request/Response

Page 3: Wcf

  One Way

  Duplex

Request/ResponseIt’s the default pattern. In this pattern, a response message will always be generated to consumer when the operation is called, even with the void return type. In this scenario, response will have empty SOAP body.One WayIn some cases, we are interested to send a message to service in order to execute certain business functionality but not interested in receiving anything back. OneWay MEP will work in such scenarios.If we want queued message delivery, OneWay is the only available option.

DuplexThe Duplex MEP is basically a two-way message channel. In some cases, we want to send a message to service to initiate some longer-running processing and require a notification back from service in order to confirm that the requested process has been completed.

WCF Service FAQs - Part 2This WCF service tutorial is part-2 in series of WCF Service FAQs. Previous part in this series is already published at WCF Service FAQs – Part 1.

What are the different ways to expose WCF Metadata?By default, WCF doesn’t expose metadata. We can expose it by choosing one of the following ways:1.    In configuration file, by enabling metadata exchange as follows:       <system.serviceModel>           <services>                  <service name="MyService.Service1"                              behaviorConfiguration="MyService.Service1">

                 <endpoint address="" binding="wsHttpBinding"                              contract="MyService.IService1">                   <identity>                       <dns value="localhost"/>                    </identity>                 </endpoint>                 <endpoint address="mex" binding="mexHttpBinding"                             contract="IMetadataExchange"/>                 </service>         </services>         <behaviors>                 <serviceBehaviors>                           <behavior name="MyService.Service1">                               <serviceMetadata httpGetEnabled="true"/>                              <serviceDebug includeExceptionDetailInFaults="false"/>                                               </behavior>                 </serviceBehaviors>           </behaviors>

Page 4: Wcf

      </system.serviceModel>

2.  ServiceHost can expose a metadata exchange endpoint to access metadata at runtime.

     using (ServiceHost host = new ServiceHost(typeof(MyService)))    {         ServiceMetadataBehavior behavior = new ServiceMetadataBehavior();         behavior.HttpGetEnabled = true;         host.Description.Behaviors.Add(behavior);         host.Open();         Console.WriteLine("My Service here..........");

         Console.ReadLine();         host.Close();    }

What is mexHttpBinding in WCF?   In order to generate proxy, we need service metadata and mexHttpBinding returns service metadata.

If we look into our configuration file, service will have an endpoint with mexHttpBinding as follows:          <endpoint address="mex" binding="mexHttpBinding"   contract="IMetadataExchange"/>

and service metadata behavior will be configured as follows:        <serviceMetadata httpGetEnabled="true"/>

Before deployment of application to production machine, it should be disabled.In order to support other protocols, related bindings are mexHttpBinding, mexHttpsBinding, mexTcpBinding.

What is a Service Proxy in Windows Communication Foundation?A service proxy or simply proxy in WCF enables application(s) to interact with WCF Service by sending and receiving messages. It’s basically a class that encapsulates service details i.e. service path, service implementation technology, platform and communication protocol etc. It contains all the methods of service contract (signature only, not the implementation). So, when the application interact the service through proxy, it gives the impression that it’s communicating a local object.We can create proxy for a service by using Visual Studio or SvcUtil.exe.

What are the different ways to generate proxy in WCF?Generating proxy using Visual Studio is simple and straight forward.       i) Right click References and choose “Add Service Reference”.      ii) Provide base address of the service on “Add Service Reference” dialog box and click “Go”             button. Service will be listed below.       iii) Provide namespace and click OK.Visual studio will generate a proxy automatically.We can generate proxy using svcutil.exe utility using command line. This utility requires few parameters like HTTP-GET address or the metadata exchange endpoint address and a proxy filename i.e. optional.        svcutil http://localhost/MyService/Service1.svc /out:MyServiceProxy.cs 

If we are hosting the service at a different port(other than default for IIS which is 80), we need to provide port number in base address. 

Page 5: Wcf

       svcutil http://localhost:8080/MyService/Service1.svc /out:MyServiceProxy.csFor parameter details regarding svcutil, please follow the MSDN linkhttp://msdn.microsoft.com/en-us/library/aa347733.aspx

Difference between using ChannelFactory and Proxies in WCF?A ChannelFactory creates a kind of Channel used by clients to communicate with service endpoints.

If we have control over Server and Client, then ChannelFactory is a good option because it relies on having local interfaces that actually describes the service i.e. service contract.On the other hand, If we don’t have control over server and only have WSDL/URL, then it’s better to generate proxy using Visual Studio or SvcUtil.  SvcUtil is better option as compared to Visual Studio because we have more control in case of SvcUtil.

How to create proxy for Non-WCF Services?In case of Non-WCF Services, we can create proxy by either using Visual Studio or svcUtil.exe tool by pointing to WSDL of the non-WCF service. In this scenario, we can’t create proxy through ChannelFactory or manually developing proxy class because we don’t have local interfaces i.e. service contract.

Breifly explain Automatic Activation in WCF?Automatic activation means service starts and serves the request when a message request is received, but service doesn’t need to be running in advance. There are few scenarios in which service needs to be running in advance, For example, in case of Self-Hosting.

What are the different WCF Instance Activation Methods available?WCF supports three different types of Instance Activation methods:a)    Per Callb)    Per Sessionc)    SingletonFor details on WCF Instance Management, please refer other article “3 techniques for Instance Management in WCF”.

What are the different ways to handle concurrency in WCF?There are three different ways to handle concurrency in WCF that are:           a)    Single           b)    Multiple           c)    ReentrantSingle: means at a given time, only a single request can be processed by WCF service instance. Other requests will be waiting until the first one is fully served.Multiple: means multiple requests can be served by multiple threads of a single WCF service instance. Reentrant: means a single WCF service instance can process one request at a given time but the thread can exit the service to call another service.We can apply these concurrency settings by putting ConcurrencyMode property in ServiceBehavior as follows:

[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple] Public class MyService : IMyService{}

What is WCF throttling?WCF throttling enables us to regulate the maximum number of WCF instances, concurrent calls and concurrent

Page 6: Wcf

sessions. Basic purpose is to control our WCF service performance by using Service throttling behavior.

In configuration file we can set this behavior as follows:<serviceBehavior>       <behavior name=”MyServiceBehavior”>              <serviceThrottling                               maxConcurrentInstances=”2147483647”                              maxConcurrentCalls="16"                              maxConcurrentSessions="10"       </behavior></serviceBehavior>

Above given values are the default ones, but we can update it after looking into the requirements of our application.

1. What is the difference between WCF and ASMX Web Services?

Simple and basic difference is that ASMX or ASP.NET web service is designed to send and receive messages using SOAP over HTTP only. While WCF can exchange messages using any format (SOAP is default) over any transport protocol (HTTP, TCP/IP, MSMQ, NamedPipes etc).

Another tutorial WCF Vs ASMX has detailed discussion on it.

2. What are WCF Service Endpoints? Explain.

For Windows Communication Foundation services to be consumed, it’s necessary that it must be exposed; Clients need information about service to communicate with it. This is where service endpoints play their role.

A WCF service endpoint has three basic elements i.e. Address, Binding and Contract.

Address: It defines "WHERE". Address is the URL that identifies the location of the service. Binding: It defines "HOW". Binding defines how the service can be accessed. Contract: It defines "WHAT". Contract identifies what is exposed by the service.

3. What are the possible ways of hosting a WCF service? Explain.

For a Windows Communication Foundation service to host, we need at least a managed process, a ServiceHost instance and an Endpoint configured. Possible approaches for hosting a service are:

1. Hosting in a Managed Application/ Self Hostinga. Console Application

Page 7: Wcf

b. Windows Applicationc. Windows Service2. Hosting on Web Servera. IIS 6.0 (ASP.NET Application supports only HTTP)b. Windows Process Activation Service (WAS) i.e. IIS 7.0 supports HTTP, TCP, NamedPipes,

MSMQ.

4. How we can achieve Operation Overloading while exposing WCF Services?

By default, WSDL doesn’t support operation overloading. Overloading behavior can be achieved by using "Name" property of OperationContract attribute.

 Collapse | Copy Code

 Collapse | Copy Code

[ServiceContract]interface IMyCalculator{ [OperationContract(Name = "SumInt")] int Sum(int arg1,int arg2);

[OperationContract(Name = "SumDouble")] double Sum(double arg1,double arg2);}

When the proxy will be generated for these operations, it will have 2 methods with different names i.e. SumInt and SumDouble.

5. What Message Exchange Patterns (MEPs) supported by WCF? Explain each of them briefly.

1. Request/Response 2. One Way 3. Duplex

Request/Response

It’s the default pattern. In this pattern, a response message will always be generated to consumer when the operation is called, even with the void return type. In this scenario, response will have empty SOAP body.

One Way

In some cases, we are interested to send a message to service in order to execute certain business functionality but not interested in receiving anything back. OneWay MEP will work in such scenarios. If we want queued message delivery, OneWay is the only available option.

Duplex

The Duplex MEP is basically a two-way message channel. In some cases, we want to send a message to service to initiate some longer-running processing and require a notification back from service in order to confirm that the requested process has been completed.

Page 8: Wcf

6. What is DataContractSerializer and How its different from XmlSerializer?

Serialization is the process of converting an object instance to a portable and transferable format. So, whenever we are talking about web services, serialization is very important.

Windows Communication Foundation has DataContractSerializer that is new in .NET 3.0 and uses opt-in approach as compared to XmlSerializer that uses opt-out. Opt-in means specify whatever we want to serialize while Opt-out means you don’t have to specify each and every property to serialize, specify only those you don’t want to serialize. DataContractSerializer is about 10% faster than XmlSerializer but it has almost no control over how the object will be serialized. If we wanted to have more control over how object should be serialized that XmlSerializer is a better choice.

7. How we can use MessageContract partially with DataContract for a service operation in WCF?

MessageContract must be used all or none. If we are using MessageContract into an operation signature, then we must use MessageContract as the only parameter type and as the return type of the operation.

8. Which standard binding could be used for a service that was designed to replace an existing ASMX web service?

The basicHttpBinding standard binding is designed to expose a service as if it is an ASMX/ASP.NET web service. This will enable us to support existing clients as applications are upgrade to WCF.

9. Please explain briefly different Instance Modes in WCF?

WCF will bind an incoming message request to a particular service instance, so the available modes are:

Per Call: instance created for each call, most efficient in term of memory but need to maintain session.

Per Session: Instance created for a complete session of a user. Session is maintained. Single: Only one instance created for all clients/users and shared among all.Least efficient

in terms of memory.

10. Please explain different modes of security in WCF? Or Explain the difference between Transport and Message Level Security.

In Windows Communication Foundation, we can configure to use security at different levels

a. Transport Level security means providing security at the transport layer itself. When dealing with security at Transport level, we are concerned about integrity, privacy and authentication of message as it travels along the physical wire. It depends on the binding being used that how WCF makes it secure because most of the bindings have built-in security.

Page 9: Wcf

 Collapse | Copy Code

 Collapse | Copy Code

<netTcpBinding> <binding name="netTcpTransportBinding"> <security mode="Transport"> <Transport clientCredentialType="Windows" /> </security> </binding> </netTcpBinding>

b. Message Level Security For Tranport level security, we actually ensure the transport that is being used should be secured but in message level security, we actually secure the message. We encrypt the message before transporting it.

 Collapse | Copy Code

 Collapse | Copy Code

<wsHttpBinding> <binding name="wsHttpMessageBinding"> <security mode="Message"> <Message clientCredentialType="UserName" /> </security> </binding> </wsHttpBinding>

It totally depends upon the requirements but we can use a mixed security mode also as follows:

 Collapse | Copy Code

 Collapse | Copy Code

<basicHttpBinding> <binding name="basicHttp"> <security mode="TransportWithMessageCredential"> <Transport /> <Message clientCredentialType="UserName" /> </security> </binding> </basicHttpBinding>

Implementing 5 important principles of REST using WCF ServicesWhat is REST?

REST is nothing but using the current features of the “Web” in a simple and effective way. If you see, some of the amazing features of the Web are:

40 years old matured and widely accepted HTTP protocol. Standard and Unified methods like POST, GET, PUT and DELETE. Stateless nature of HTTP protocol.

Page 10: Wcf

Easy to use URI (Uniform resource identifier) format to locate any web resource.

REST leverages these amazing features of the web with some constraints.

Let’s define REST in official words, REST is an architectural style built on certain principles using the current “Web” fundamentals.

There are 5 basic fundamentals of web which are leveraged to create REST services.

Principle 1: Everything is a Resource

Internet is all about getting data. This data can be in a format of web page, image, video, file, etc. It can also be a dynamic output like get customers who are newly subscribed. The first important point in REST is start thinking in terms of resources rather than physical files.

Below are some examples of resources with URI:

www.questpond.com/image/logo.gif (Image resource) www.questpond.com/Customer/1001 (Dynamically pulled resource) www.questpond.com/videos/v001 (Video resource) www.questpond.com/home.html (Static resource)

So the first thing is, visualize everything as resource.

Principle 2: Every Resource is Identified by a Unique Identifier

Page 11: Wcf

The old web identifies all resources by a URI. For instance, if you want to display customer with their orders, you can use www.questpond.com/DisplayCustomerandOrder.aspx. In REST, we add one more constraint to the current URI, every URI should uniquely represent every RESOURCE data.

For instance, you can see the below unique URI format for customer and orders fetched.

Customer data URI

Get Customer details with name “Shiv” http://www.questpond.com/Customer/Shiv

Get Customer details with name “Raju” http://www.questpond.com/Customer/Raju

Get orders placed by customer "Shiv" http://www.questpond.com/Customer/Shiv/Orders

Get orders placed by customer “Raju” http://www.questpond.com/Customer/Raju/Orders

Principle 3: Use Simple and Uniform Interfaces

Simplification is the way to success and that’s what exactly the goal of uniform interfaces is. When external clients are interacting with web resources, they expect simplified interfaces.

For instance, let’s say you have exposed customer and orders data / resource on the web. Let’s assume below are the methods / function names by which external clients can communicate to your application.

AddCustomer InsertOrders SelectCustomer getOrders DeleteCustomer RemoveOrders UpdateCustomers

Do the above method names look inconsistent and difficult to remember? Yes they do. Now what REST says is keep your interfaces uniform and simple. This can be achieved by using the uniform methods of HTTP protocol and combining the same with your resource operation.

Below is the list of HTTP methods for getting, creating, updating and deleting a resource on the web.

Methods Description

GET Get a resource

PUT Create and Update a resource

Page 12: Wcf

Methods Description

DELETE Deletes a resource

POST Submits data the resource

Now by combining the standard HTTP methods and your resource names, you can have uniform interfaces and thus leading to simplified communication. You can see from the below table how we have created uniform REST URL using standard HTTP methods.

Normal Method names HTTP methods REST Uniform URL

AddCustomer PUT Customer/Shiv

InsertOrders PUT Orders/1001

SelectCustomer GET Customer/Shiv

getOrders GET Customer/Shiv/Orders

DeleteCustomer DELETE Customer/Shiv

RemoveOrders DELETE Customer/Shiv

UpdateCustomers PUT Customer/Shiv

Page 13: Wcf

Principle 4: Communication is Done by Representation

When you send any request or you get any response, you are actually sending representations.

For example, let’s say you want to create a new customer record, you would send some kind of representation as shown below using HTTP PUT.

 Collapse | Copy Code

<Customer> <Name>Questpond.com</Name> <Address>Mulund Mumbai</Address></Customer>

Once the resource is created, you would get a representation as shown below. The below representation says the customer questpond has been successfully created and if you wish, you can use “http://www.questpond.com/Customer/Questpond/Orders” defined in the “Next” tag to create orders for the “questpond” customer.

 Collapse | Copy Code

<Customer> <Name>Questpond.com</Name> <Next>http://www.questpond.com/Customer/Questpond/Orders</Next></Customer>

The above representation was in XML format. If you wish, you can also send and receive other presentations like JSON. For instance, below is a simple JSON snippet for creating a new customer record with name and address.

 Collapse | Copy Code

Page 14: Wcf

{Customer :{ Name:'Questpond.com', Address:'Mulund Mumbai'}}

Principle 5: Be Stateless

Every request should be an independent request so that we can scale up using load balancing techniques. Independent request means with the data also send the state of the request so that the server can carry forward the same from that level to the next level.

For instance, below are two simple representations, the first representation is sent for logging in.

 Collapse | Copy Code

<Login> <Name>Questpond.com</Name> <Password>sdkj#43445</Password></Login>

If you are logged in successfully you receive the below representation.

 Collapse | Copy Code

<Login> <Success>true</Success></Login>

If you want to search for customer, you would send him the below representation stating that you are in a state of successful logging in and would like to search all customers.

 Collapse | Copy Code

<Customer> <Filter>All</Filter> <Success>true</Success></Customer>

In other words, every request is independent and the server does not need to remember your previous request and states.

Summarizing 5 Principles of REST

So summarizing REST leverages the old web HTTP by applying principles 5 important principles:

Everything is a resource. Every resource is identified by a unique identifier. Use simple and uniform interfaces. Communication are done by representation. Be Stateless.

Page 15: Wcf

Implementing REST with WCF Services

Enabling WCF REST services is a three step process:

Enable HTTP bindings Expose methods via common interfaces Define your representation

In order to enable HTTP bindings, the first thing is to create an end point behavior with “webHttp” binding. The “webHttp” binding enables HTTP protocol on your WCF services.

 Collapse | Copy Code

<endpointBehaviors> <behavior name="NewBehavior0"> <webHttp /> </behavior></endpointBehaviors>

Create a new endpoint and bind the behavior with your endpoint. Collapse | Copy Code

<services><service name="WcfRest.Service1">

<endpoint behaviorConfiguration="NewBehavior0" binding="webHttpBinding"bindingConfiguration="" contract="WcfRest.IService1" />

</service></services>

In order to make your interfaces uniform, you can use the “UriTemplate” property as shown in the below figure. You can see from the below code snippet how “getStudents” can now be called by using a http GET request on “/Students/123”, where 123 is the id of the student.

 Collapse | Copy Code

[OperationContract][WebGet(UriTemplate = "/Students/{id}")]string getStudents(string id);

Page 16: Wcf

In the same way, in the below code snippet, we are calling “AddStudent” method using HTTP POST and we have made the interface uniform using the “UriTemplate” property as shown in the below code snippet.

 Collapse | Copy Code

[OperationContract]WebInvoke(Method = "POST", UriTemplate = "/Students/{studentname}")]bool Addstudent(string studentName);

So now, if you want to get a particular student use http://localhost:27683/Students.svc/Students/1 with HTTP GETmethod and if you want to add a new student call http://localhost:27683/Students.svc/Students/Shiv with HTTP POST. Isn’t that much simpler as compared to “getStudents” and “AddStudent” methods.

 Collapse | Copy Code

[ServiceContract]

public interface IStudents{

[OperationContract] [WebGet(UriTemplate = "/Students/{id}")] string getStudents(string id);

[OperationContract] [WebInvoke(Method = "POST", UriTemplate = "/Students/{studentname}")] bool Addstudent(string studentName);

}

Below is the implemented code for the above interface. We have created a collection of student names in a stringcollection. In order to add new students, we can call “AddStudent” and to retrieve students, we can call “getStudents”.

 Collapse | Copy Code

public class Students : IStudents { List<string> ostudents = new List<string>(); public Students() { ostudents.Add("Shivprasad"); ostudents.Add("Raju"); } public string getStudents(string id) {

Page 17: Wcf

return ostudents[0]; } public bool Addstudent(string StudentName) { ostudents.Add(StudentName); return true; } }

Testing the Above WCF REST Services using Simple HTML FormTo get a particular student, we need to invoke “getStudents” by using HTTP GET on the URL http://localhost:27683/Students.svc/Students/1 . The “1” indicates that we want to retrieve the student with ID “1”.To add a particular student, we need to invoke “Addstudent“ by using HTTP POST on the URLhttp://localhost:27683/Students.svc/Students/Shiv. “Shiv” is the student name we wish to add to the collection.In order to make a post and get on the above URLs, we will use simple HTML to do the same. You can also use other methods like “xmlhttprequest”, WCF proxy, etc. In order to keep it simple in this article, we will use simple HTML for now.

 Collapse | Copy Code

<form action="http://localhost:27683/Students.svc/Students/1" method="get"><input type="submit" /></form>

So if you run the above HTML with the action pointing to the URL http://localhost:27683/Students.svc/Students/1 and using the “get” method, you should get the below output.

This XML file does not appear to have any style information associated with it. The document tree is shown below.

 Collapse | Copy Code

<string xmlns="http://schemas.microsoft.com/2003/10/Serialization/">Shivprasad</string>

In the same way, if you run the below HTML with the action pointing to the URL (http://localhost:27683/Students.svc/Students/shiv) and using the “post” method, you should get the below output.

 Collapse | Copy Code

<form action="http://localhost:27683/Students.svc/Students/shiv" method="post"> <input type="submit" /> </form>

This XML file does not appear to have any style information associated with it. The document tree is shown below:

 Collapse | Copy Code

<boolean xmlns="http://schemas.microsoft.com/2003/10/Serialization/">true</boolean>

Page 18: Wcf

In the same way, you can try for other HTTP methods like PUT, DELETE, etc.

What about Representations?When we discussed REST fundamentals, we said one of the most important things is representation and format of representation. The current WCF [WebGet] and [WebInvoke] attributes help you to configure formats in both request and response in XML and JSON format.In the below code snippet, we have created the Responseformat as JSON.

 Collapse | Copy Code

[OperationContract] [WebGet(ResponseFormat=WebMessageFormat.Json, UriTemplate = "/Students/{id}?format=json")]string getStudentsJSON(string id);

If you do a get on the URL you should get the value as shown in the below figure: -

Building SOAP Message Based Web Services with WCF

Introduction

I really like WCF as technical framework, it simplifies creating communication layer, but I don't like WCF's design style. I think creating new method for every data transfer object is poor, so I tried to solve this one.

By nature, WCF is method based web service and has some limitations:

Doesn't support method overloads Doesn't have universal API Service Contract depends on business requirement Versioning should be on DataContract and method levels, operation name should be

universal Other non-.NET clients have to create as many clients as services you have

I think, RPC (Remote Procedure Call) approach isn't a right way, service should be reusable and impact of requirements should be minimal. As for me, remote API have to satisfy following criterias:

Stable and Universal interface

Page 19: Wcf

Transfer data according DTO pattern

Message based service solves major WCF limitations by adding message abstraction.

Spoiler

While reading the article, you'll know how to build reusable message based soap service, soap client and stop creating new WCF services.

Web service design

Let's take a look at Remote Procedure Call and Message based approaches more deeply.

RPC design

The main idea of RPC style is to share methods, so client works with remote service like with local object. WCF'sServiceContract specifies Operations which are available on client side.

For instance:

 Collapse | Copy Code

[ServiceContract]public interface IRpcService{ [OperationContract] void RegisterClient(Client client);

[OperationContract] Client GetClientByName(string clientName);

[OperationContract] List<Client> GetAllClients();}

The service contract is very simple and contains three operations. We have to change the service/client after any changes in the service contract (for example, adding or removing operation, updating operation signature). A real application can have more than 10 operations, so maintaining the service and client is really difficult.

Message based design

The main ideas of Message based design - are Martin Fowler's patterns Data transfer object and Gateway. DTO contains all required data for the communication and Gateway isolate application from communication process. So service based on message design receives a Request message and returns a Response message. Example fromAmazon's API.

Example Request

 Collapse | Copy Code

Page 20: Wcf

https://ec2.amazonaws.com/?Action=AllocateAddressDomain=vpc&AUTHPARAMS

Example Response

 Collapse | Copy Code

<AllocateAddressResponse xmlns="http://ec2.amazonaws.com/doc/2013-02-01/"> <requestId>59dbff89-35bd-4eac-99ed-be587EXAMPLE</requestId> <publicIp>198.51.100.1</publicIp> <domain>vpc</domain> <allocationId>eipalloc-5723d13e</allocationId></AllocateAddressResponse>

So, service contract should look like:

 Collapse | Copy Code

public interface IMessageBasedService{ Response Execute(Request request);}

where Request and Response could be any DTO, i.e., with single method we can replace any RPC service contract, but WCF uses RPC style.

Message Based StyleAs you know, for message based service we could use Request and Response objects for transfer any DTOs. But WCF doesn't support this kind of design. All internal WCF's communication based on Message class, i.e., WCF converts any DTO to Message and sends the Message from client to server. So, we should use Message class as Request andResponse objects.Following service contract describes communication with and without Response object:

 Collapse | Copy Code

[ServiceContract]public interface ISoapService{ [OperationContract(Action = ServiceMetadata.Action.Process)] void Process(Message message);

[OperationContract(Action = ServiceMetadata.Action.ProcessWithResponse, ReplyAction = ServiceMetadata.Action.ProcessResponse)] Message ProcessWithResponse(Message message);}

The ISoapService is flexible and allows transfer of any data, but it's not enough. We want create, delete objects and execute methods on this one. As for me, the best choice is CRUD operations on object (create, read, update, delete), so we could implement any operation. First of all, let's create SoapServiceClient, which is able to send and receive any DTO.

Page 21: Wcf

Soap service client

The SoapServiceClient will illustrate how to create the Message from DTO. The SoapServiceClient is a wrapper which convert any DTO to a Message and sends this one to service. The sending Message should contain following data:

DTO DTO's type, is required for DTO deserialization on the server side Target method, will be invoked on the server side

Our goal is to create reusable soap service client which will be able to send/receive any Request/Response and execute any target operations. As mentioned before, CRUD operations are the best choice, so the client could look like:

 Collapse | Copy Code

var client = new SoapServiceClient("NeliburSoapService");

ClientResponse response = client.Post<CreateClientRequest, ClientResponse>(createRequest);

response = client.Put<UpdateClientRequest, ClientResponse>(updateRequest);

Here is the full SoapServiceClient's Post method, please note on CreateMessage method and how concrete DTO type and target method were added through contentTypeHeader and actionHeader.

 Collapse | Copy Code

public TResponse Post<TRequest, TResponse>(TRequest request) where TRequest : class where TResponse : class{ return ProcessWithResponse<TRequest, TResponse>(request, OperationTypeHeader.Post);}

private TResponse ProcessWithResponse<TRequest, TResponse>(TRequest request, MessageHeader operationType) where TRequest : class where TResponse : class{ using (var factory = new ChannelFactory<ISoapService>(_endpointConfigurationName)) { MessageVersion messageVersion = factory.Endpoint.Binding.MessageVersion; Message message = CreateMessageWithResponse(request, operationType, messageVersion); ISoapService channel = factory.CreateChannel(); Message result = channel.ProcessWithResponse(message); return result.GetBody<TResponse>(); }}

private static Message CreateMessageWithResponse<TRequest>( TRequest request, MessageHeader actionHeader, MessageVersion messageVersion){ Message message = Message.CreateMessage( messageVersion, ServiceMetadata.Operations.ProcessWithResponse, request); var contentTypeHeader = new ContentTypeHeader(typeof(TRequest)); message.Headers.Add(contentTypeHeader); message.Headers.Add(actionHeader);

Page 22: Wcf

return message;}

SoapContentTypeHeader and SoapOperationTypeHeader are almost identical. The SoapContentTypeHeader is used for DTO's type transfer and SoapOperationTypeHeader for transferring target operation. There's not much to speak of all for the MessageHeader, here is full SoapContentTypeHeader's code.

 Collapse | Copy Code

internal sealed class SoapContentTypeHeader : MessageHeader{ private const string NameValue = "nelibur-content-type"; private const string NamespaceValue = "http://nelibur/" + NameValue; private readonly string _contentType;

public SoapContentTypeHeader(Type contentType) { _contentType = contentType.Name; }

public override string Name { get { return NameValue; } }

public override string Namespace { get { return NamespaceValue; } }

public static string ReadHeader(Message request) { int headerPosition = request.Headers.FindHeader(NameValue, NamespaceValue); if (headerPosition == -1) { return null; } var content = request.Headers.GetHeader<string>(headerPosition); return content; }

protected override void OnWriteHeaderContents(XmlDictionaryWriter writer, MessageVersion messageVersion) { writer.WriteString(_contentType); }}

Here're all SoapServiceClient's methods: Collapse | Copy Code

public static TResponse Get<TRequest, TResponse>(TRequest request) where TRequest : class where TResponse : class

public static Task<TResponse> GetAsync<TRequest, TResponse>(TRequest request) where TRequest : class where TResponse : class

Page 23: Wcf

public static void Post<TRequest>(TRequest request) where TRequest : class

public static Task PostAsync<TRequest>(TRequest request) where TRequest : class

public static TResponse Post<TRequest, TResponse>(TRequest request) where TRequest : class where TResponse : class

public static Task<TResponse> PostAsync<TRequest, TResponse>(TRequest request) where TRequest : class where TResponse : class

public static void Put<TRequest>(TRequest request) where TRequest : class

public static Task PutAsync<TRequest>(TRequest request) where TRequest : class public static TResponse Put<TRequest, TResponse>(TRequest request) where TRequest : class where TResponse : class

public static Task<TResponse> PutAsync<TRequest, TResponse>(TRequest request) where TRequest : class where TResponse : class

public static void Delete<TRequest>(TRequest request) where TRequest : class

public static Task DeleteAsync<TRequest>(TRequest request) where TRequest : class

As you note all CRUD operations have async version.

Soap service

SoapService should be able to do the following:

Create concrete Request from Message Invoke target message by Request Create Message from Response and return this one if required

Our goal is to create something that will invoke appropriate CRUD method by concrete Request, this example illustrates how to add and get a client:

 Collapse | Copy Code

public sealed class ClientProcessor : IPutWithResponse<CreateClientRequest>, IGetWithResponse<GetClientRequest>{ private readonly List<Client> _clients = new List<Client>();

public object GetWithResponse(GetClientRequest request) { Client client = _clients.Single(x => x.Id == request.Id); return new ClientResponse {Id = client.Id, Name = client.Name}; }

Page 24: Wcf

public object PutWithResponse(CreateClientRequest request) { var client = new Client { Id = Guid.NewGuid(), Name = request.Name }; _clients.Add(client); return new ClientResponse {Id = client.Id}; }}

The most interesting things: IGetWithResponse and IPostWithResponse interfaces. These interfaces represent CRUD operations, here is a class diagram. Note the difference between I<Operation>WithResponse andI<Operation>. For example, IGetWithResponse and IGet, IGet returns void.

Now, all we need to do is bind a Request with the appropriate CRUD operation, the simplest way is to bind aRequest with the request processor. SoapServiceProcessor is responsible for this functionality. Well, it's as shown below:

 Collapse | Copy Code

private static readonly RequestMetadataMap _requests = new RequestMetadataMap();private static readonly RequestProcessorMap _requestProcessors = new RequestProcessorMap();

public ServiceProcessor Bind<TRequest, TProcessor>() where TRequest : class where TProcessor : IRequestOperation, new(){ _requestProcessors.Add<TRequest, TProcessor>(); _requests.Add<TRequest>(); return this;}

public ServiceProcessor Bind<TRequest, TProcessor>(Func<TProcessor> creator)

Page 25: Wcf

where TRequest : class where TProcessor : IRequestOperation{ if (creator == null) { throw new ArgumentNullException("creator"); } _requestProcessors.Add<TRequest, TProcessor>(creator); _requests.Add<TRequest>(); return this;}

RequestMetadataMap is used for storing Request's type which is required for creating a concrete Request from aMessage.

 Collapse | Copy Code

internal sealed class RequestMetadataMap{ private readonly Dictionary<string, Type> _requestTypes = new Dictionary<string, Type>();

public void Add<TRequest>() where TRequest : class { Type requestType = typeof(TRequest); _requestTypes[requestType.Name] = requestType; }

public RequestMetadata FromMessage(Message message) { string typeName = ContentTypeHeader.ReadHeader(message); Type targetType = _requestTypes[typeName]; return RequestMetadata.FromMessage(message, targetType); }}

RequestProcessorMap binds Request's type with request processor. Collapse | Copy Code

internal sealed class RequestProcessorMap{ private readonly Dictionary<Type, IRequestProcessorContext> _repository = new Dictionary<Type, IRequestProcessorContext>();

public void Add<TRequest, TProcessor>() where TRequest : class where TProcessor : IRequestOperation, new() { Type requestType = typeof(TRequest); IRequestProcessorContext context = new RequestProcessorContext<TRequest, TProcessor>(() => new TProcessor()); _repository[requestType] = context; }

public void Add<TRequest, TProcessor>(Func<TProcessor> creator) where TRequest : class where TProcessor : IRequestOperation { Type requestType = typeof(TRequest);

Page 26: Wcf

IRequestProcessorContext context = new RequestProcessorContext<TRequest, TProcessor>(creator); _repository[requestType] = context; }

public IRequestProcessorContext Get(Type requestType) { return _repository[requestType]; }}

Now we're ready for the last step - invoke target method. Here is our SoapService, the same as usual WCF service.

 Collapse | Copy Code

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]public sealed class SoapService : ISoapService{ public Message Process(Message message) { return SoapServiceProcessor.ProcessWithResponse(message); }

public void ProcessWithoutResonse(Message message) { SoapServiceProcessor.Process(message); }}

First of all, let's take a look on the sequence diagram, the diagram describes execution process on the service side.

Page 27: Wcf

Let's dive into code step by step. SoapServiceProcessor just executes another code, take a look.

 Collapse | Copy Code

public sealed class SoapServiceProcessor : ServiceProcessor{ public static void Process(Message message) { RequestMetadata requestMetaData = _requests.FromSoapMessage(message); IRequestProcessor context = _requestProcessors.Get(requestMetaData.Type); context.Process(requestMetaData); }

public static Message ProcessWithResponse(Message message) { RequestMetadata requestMetaData = _requests.FromSoapMessage(message); IRequestProcessor context = _requestProcessors.Get(requestMetaData.Type); return context.ProcessWithResponse(requestMetaData); }}

SoapServiceProcessor just decorate RequestMetadataMap i.e. calls appropriate methods for creatingRequestMetadata for soap message

The most interesting thing happens here:

RequestMetadata requestMetaData = _requests.FromSoapMessage(message) context.Process(requestMetaData).

SoapRequestMetadata is the main object which accumulate: CRUD operation type, Request's data, its type and could a response message.

 Collapse | Copy Code

internal sealed class SoapRequestMetadata : RequestMetadata{ private readonly MessageVersion _messageVersion; private readonly object _request;

internal SoapRequestMetadata(Message message, Type targetType) : base(targetType) { _messageVersion = message.Version; _request = CreateRequest(message, targetType); OperationType = SoapOperationTypeHeader.ReadHeader(message); }

public override string OperationType { get; protected set; }

public override Message CreateResponse(object response) { return Message.CreateMessage (_messageVersion, ServiceMetadata.Operations.ProcessResponse, response); }

public override TRequest GetRequest<TRequest>() { return (TRequest)_request; }

private static object CreateRequest(Message message, Type targetType)

Page 28: Wcf

{ using (XmlDictionaryReader reader = message.GetReaderAtBodyContents()) { var serializer = new DataContractSerializer(targetType); return serializer.ReadObject(reader); } }}

At the end, we just call appropriate CRUD operation thru the RequestProcessor. The RequestProcessor usesRequestMetadata to determine an operation and calls this one then returns result to the SoapServiceClient.

Here's the implementation:

 Collapse | Copy Code

internal sealed class RequestProcessor<TRequest, TProcessor> : IRequestProcessor where TRequest : class where TProcessor : IRequestOperation{ private readonly Func<TProcessor> _creator;

public RequestProcessor(Func<TProcessor> creator) { _creator = creator; }

public void Process(RequestMetadata metadata) { switch (metadata.OperationType) { case OperationType.Get: Get(metadata); break; case OperationType.Post: Post(metadata); break; case OperationType.Put: Put(metadata); break; case OperationType.Delete: Delete(metadata); break; default: string message = string.Format ("Invalid operation type: {0}", metadata.OperationType); throw new InvalidOperationException(message); } }

public Message ProcessWithResponse(RequestMetadata metadata) { switch (metadata.OperationType) { case OperationType.Get: return GetWithResponse(metadata); case OperationType.Post: return PostWithResponse(metadata);

Page 29: Wcf

case OperationType.Put: return PutWithResponse(metadata); case OperationType.Delete: return DeleteWithResponse(metadata); default: string message = string.Format ("Invalid operation type: {0}", metadata.OperationType); throw new InvalidOperationException(message); } }

private void Delete(RequestMetadata metadata) { var service = (IDelete<TRequest>)_creator(); var request = metadata.GetRequest<TRequest>(); service.Delete(request); }

private Message DeleteWithResponse(RequestMetadata metadata) { var service = (IDeleteWithResponse<TRequest>)_creator(); var request = metadata.GetRequest<TRequest>(); object result = service.DeleteWithResponse(request); return metadata.CreateResponse(result); }

private void Get(RequestMetadata metadata) { var service = (IGet<TRequest>)_creator(); var request = metadata.GetRequest<TRequest>(); service.Get(request); }

private Message GetWithResponse(RequestMetadata metadata) { var service = (IGetWithResponse<TRequest>)_creator(); var request = metadata.GetRequest<TRequest>(); object result = service.GetWithResponse(request); return metadata.CreateResponse(result); }

private void Post(RequestMetadata metadata) { var service = (IPost<TRequest>)_creator(); var request = metadata.GetRequest<TRequest>(); service.Post(request); }

private Message PostWithResponse(RequestMetadata metadata) { var service = (IPostWithResponse<TRequest>)_creator(); var request = metadata.GetRequest<TRequest>(); object result = service.PostWithResponse(request); return metadata.CreateResponse(result); }

private void Put(RequestMetadata metadata) { var service = (IPut<TRequest>)_creator(); var request = metadata.GetRequest<TRequest>();

Page 30: Wcf

service.Put(request); }

private Message PutWithResponse(RequestMetadata metadata) { var service = (IPutWithResponse<TRequest>)_creator(); var request = metadata.GetRequest<TRequest>(); object result = service.PutWithResponse(request); return metadata.CreateResponse(result); }}

Demo Sample

Well, the theoretical part is over. Let's take a look at the practical side. The demo shows how to register client, update some information and get the client.

First of all, we declare data contracts:

CreateClientRequest - request for creating a new client UpdateClientRequest - request for updating client's email GetClientRequest - request for get client by Id ClientResponse - client's info RemoveClientRequest - removal request

Server's side

Config file is the same as usual.  Collapse | Copy Code

<configuration>

<!--WCF--> <system.serviceModel> <services> <service name="Nelibur.ServiceModel.Services.SoapServicePerCall"> <endpoint address="http://localhost:5060/service" binding="basicHttpBinding" bindingConfiguration="ServiceBinding" contract="Nelibur.ServiceModel.Contracts.ISoapService" /> </service> </services> <bindings> <basicHttpBinding> <binding name="ServiceBinding"> <security mode="None"> <transport clientCredentialType="None" /> </security> </binding> </basicHttpBinding> </bindings> </system.serviceModel>

<startup>

Page 31: Wcf

<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" /> </startup></configuration>

WCF's service is as simple as possible:

 Collapse | Copy Code

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]public sealed class SoapServicePerCall : ISoapService{ /// <summary> /// Process message without response. /// </summary> /// <param name="message">Request message.</param> public void Process(Message message) { SoapServiceProcessor.Process(message); }

/// <summary> /// Process message with response. /// </summary> /// <param name="message">Request message.</param> /// <returns>Response message.</returns> public Message ProcessWithResponse(Message message) { return SoapServiceProcessor.ProcessWithResponse(message); }}

Bind all requests with request processor. I've created only one request processor for simplicity. You can create as many request processors as you want. Take a look at Martin Fowler's article about CQRS, it'll help you to make the right choice.

Here's the binding:

 Collapse | Copy Code

private static void BindRequestToProcessors(){ new SoapServiceProcessor() .Bind<CreateClientRequest, ClientProcessor>() .Bind<UpdateClientRequest, ClientProcessor>() .Bind<DeleteClientRequest, ClientProcessor>() .Bind<GetClientRequest, ClientProcessor>();}

and finally the ClientProcessor: Collapse | Copy Code

public sealed class ClientProcessor : IPostWithResponse<CreateClientRequest>, IGetWithResponse<GetClientRequest>, IDelete<DeleteClientRequest>, IPutWithResponse<UpdateClientRequest>{

Page 32: Wcf

private static List<Client> _clients = new List<Client>();

public void Delete(DeleteClientRequest request) { Console.WriteLine("Delete Request: {0}\n", request); _clients = _clients.Where(x => x.Id != request.Id).ToList(); }

public object GetWithResponse(GetClientRequest request) { Console.WriteLine("GetWithResponse Request: {0}", request); Client client = _clients.Single(x => x.Id == request.Id); var response = new ClientResponse { Id = client.Id, Email = client.Email }; Console.WriteLine("GetWithResponse Response: {0}\n", response); return response; }

public object PostWithResponse(CreateClientRequest request) { Console.WriteLine("PostWithResponse Request: {0}", request); var client = new Client { Id = Guid.NewGuid(), Email = request.Email }; _clients.Add(client); var response = new ClientResponse { Id = client.Id, Email = client.Email }; Console.WriteLine("PostWithResponse Response: {0}\n", response); return response; }

public object PutWithResponse(UpdateClientRequest request) { Console.WriteLine("PutWithResponse Request: {0}", request); Client client = _clients.Single(x => x.Id == request.Id); client.Email = request.Email; var response = new ClientResponse { Id = client.Id, Email = client.Email }; Console.WriteLine("PutWithResponse Response: {0}\n", response); return response; }}

Client's side

Client's code is as simple as possible:

 Collapse | Copy Code

private static void Main(){ var client = new SoapServiceClient("NeliburSoapService");

var createRequest = new CreateClientRequest { Email = "[email protected]" }; Console.WriteLine("POST Request: {0}", createRequest); ClientResponse response =

Page 33: Wcf

client.Post<CreateClientRequest, ClientResponse>(createRequest); Console.WriteLine("POST Response: {0}\n", response);

var updateRequest = new UpdateClientRequest { Email = "[email protected]", Id = response.Id };

Console.WriteLine("PUT Request: {0}", updateRequest); response = client.Put<UpdateClientRequest, ClientResponse>(updateRequest); Console.WriteLine("PUT Response: {0}\n", response);

var getClientRequest = new GetClientRequest { Id = response.Id }; Console.WriteLine("GET Request: {0}", getClientRequest); response = client.Get<GetClientRequest, ClientResponse>(getClientRequest); Console.WriteLine("GET Response: {0}\n", response);

var deleteRequest = new DeleteClientRequest { Id = response.Id }; Console.WriteLine("DELETE Request: {0}", deleteRequest); client.Delete(deleteRequest);

Console.ReadKey();}

and execution results:

Here's the Service Client:

Page 34: Wcf

and soap service:

Expose WCF 4.0 Service as SOAP and RESTAbstract: By exposing a WCF service on REST and SOAP, you can make it more accessible to all types of clients. This is especially useful for the clients who can consume the proxy as well as can understand only HTTP communication with XML data processing. This article shows how to do so.

WCF services in enterprises are used for developing distributed enterprise application. There are lots of advantages of using WCF services. WCF service can be exposed on multiple endpoints e.g. HTTP, TCP etc. and the client applications have a choice to select the specific endpoint for the communication. WCF 3.5 had introduced support for Representational State Transfer (REST) using which the response from the service can be directly send using Plain Old Xml form (POX). If the WCF service is using REST/POX, then it is not necessary for the client to consume the WCF service proxy. For REST, WCF introduced a new binding i.e. WebHttpBinding. A client application that can do HTTP communication and can process XML, could now directly make a call to the WCF service and perform operations using XML.

 

And now the million dollar question which motivated me to write this article – If an existing service is already exposing SOAP using bindings like the basicHttpBinding, then can the same service expose REST i.e. using WebHttpBinding too? The answer is YES and in this article, I have explained the same.

Page 35: Wcf

Step 1: Open VS2010 and create a Blank solution, name it as ‘WCF_SOAP_REST’. In this solution, add a new WCF service application and call it ‘WCF_SOAP_REST_Service’. Make sure that .NET 4.0 framework is selected.Step 2: Rename IService1.cs to IService.cs and rename Service1.svc to Service.svc . Add the following ServiceContract, OperationContract and DataContract in IService.cs.

The OperationContract GetEmployees() also applied with WebGet attribute for REST exposure.Step 3: Open the Web.Config file and define two endpoints - one each for SOAP and REST. The binding for SOAP is basicHttpBinding and for REST is webHttpBinding. Also define ServiceBehavior for publishing metadata for SOAP endpoint so that the client application can consume the WCF service. Define EndpointBehavior for the REST endpoint so that the XML response can be send and the help page is displayed to the end user.

Page 36: Wcf

Step 4: Open Service.svc.cs and write the following code:

Page 37: Wcf

The attribute AspNetCompabilityRequirements is used for specifying an ASP.NET compatible environment for WCF service execution.Step 5: Right-Click on the Service.svc and select ‘View in Browser’ and the result will be as shown below:

The above image shows SOAP hosting and you can verify it by clicking on the URL with ?wsdl. You should see the wsdl as below:

Page 38: Wcf

The Endpoint address used by the client application to interact with WCF with SOAP will be:“http://localhost:5460/Service.svc/soapService”

In the Web.Config file, we have created a REST endpoint of the name ‘XMLService’. So to check the REST-POST (XML) response, change the browser’s address bar contents as shown below and hit Enter:“http://localhost:5460/Service.svc/XmlService/Employees”

..and you should see the following XML

Page 39: Wcf

We have successfully exposed the WCF service both on SOAP and REST.Consuming the WCF service in a ProjectStep 6: To consume the WCF service in the same solution, add a new WPF project, name it as ‘WPF4_WCF_SOAP_REST_Client’. In this project, add the service reference of the WCF service using the following address:“http://localhost:5460/Service.svc”

Step 7: Open MainWindow.xaml and write the XAML shown below:

The above xaml declares two buttons and DataGrids, each for the SOAP and REST call.Step 8: Use the following namsepaces in the MainWindow.xaml.cs:using System.Net;

Page 40: Wcf

using System.Runtime.Serialization;  

Step 9: In the MainWindow.Xaml.cs, write code for every button click:SOAP Call Button click:

REST Call Button Click:

The above code creates a WebRequest using the WCF Service Url with REST endpoint name. The response is collected using WebResponse class. Since the response is containing a stream of objects using DataContractSerializer, the response message stream is deserialized and the result is stored in an Employee[].Step 10: Run the client application and click on both buttons. The result will be as shown below:

Page 41: Wcf

Conclusion: By exposing a WCF service on REST and SOAP, you can make it more accessible to all types of clients. This is especially useful for the clients who can consume the proxy as well as can understand only HTTP communication with XML data processing.

WCF Transactions in Five Easy Steps, With Example

Introduction

In this article, I will first explain what is transaction and what are the properties of transaction and then I will try to explain how we can implement transactions in WCF service.

Implementing transactions in WCF is very easy, you use attributes to control the service and operations behaviors, and you are done

So we will create WCF services which do database transactions and then check the transaction. I will first understand the steps how to enable transactions in WCF services. At the end of the article, I will try to force an error and see how the transaction is rolled back after the error.

BackgroundI already posted my article for WCF insert update delete on CodeProject. Please go to that link for basic WCF and for how to host WCF Service please go to this link.

Page 42: Wcf

Using the code

First I will tell you what is Transaction

What are Transactions?

A transaction is a unit of work that is performed against a database. Transactions are units or sequences of work accomplished in a logical order, whether in a manual fashion by a user or automatically by some sort of a database program.

Properties of Transactions

Transactions have the following four standard properties, usually referred to by the acronym ACID:

Atomicity: ensures that all operations within the work unit are completed successfully; otherwise, the transaction is aborted at the point of failure, and previous operations are rolled back to their former state.

Consistency: ensures that the database properly changes states upon a successfully committed transaction.

Isolation: enables transactions to operate independently of and transparent to each other. Durability: ensures that the result or effect of a committed transaction persists in case of a

system failure.There are five easy steps for setting transactions in WCFStep 1: For service operation setting. Create a WCF Service for Account and enable TransactionFlowOption Mandatory. There are three modes for transaction flow option:

Allowed: Transaction may be flowed. Mandatory: Transaction must be flowed. NotAllowed: A transaction should not be flowed. This is the default value.

Note: TransactionFlow can be enabled only at the operation level not at the service level.

TransactionFlowOption

Binding configuration

NotAllowed

transactionFlow="true" 

or

transactionFlow="false"

Client cannot propagate its transaction to service even client has transaction

AllowedtransactionFlow="true"

Service will allow to flow client transaction.

It is not necessary that service to use client transaction.

Page 43: Wcf

AllowedtransactionFlow="false"

If service disallows at binding level, client also should disable at binding level else error will be occurred.

MandatorytransactionFlow="true"

Both Service and client must use transaction aware binding

MandatorytransactionFlow="false"

InvalidOperationException will be throw when service binding disables at binding level. 

FaultException will be thrown when client disable at its binding level.

In the below service I creates one Service contract IAccountService and two Service operations Deposit and Withdraw for particular Account ID a

 Collapse | Copy Code

//Here I Created IAccountService and enabled TransactionFlowOption Mandatory

[ServiceContract]public interface IAccountService{ [OperationContract] [TransactionFlow(TransactionFlowOption.Mandatory)] [FaultContract(typeof(ErrorInfo))] void Deposit(int AccountId, decimal amount);

[OperationContract] [TransactionFlow(TransactionFlowOption.Mandatory)] [FaultContract(typeof(ErrorInfo))] void WithDraw(int AccountId, decimal amount);}

Step 2: In Operational Behavior Setting. In Operation Behavior, we have to enable TransactionScopeRequired = true and TransactionAutoComplete=true.

TransactionScopeRequired: indicates whether the method requires a transaction scope for its execution.

TransactionAutoComplete: indicates whether to automatically complete the current transaction scope if no unhandled exceptions occur.

 Collapse | Copy Code

//Here I crated class AccountService and enabled TransactionScopeRequired

[ServiceBehavior(TransactionIsolationLevel=System.Transactions.IsolationLevel.Serializable)]public class AccountService:IAccountService{ [OperationBehavior(TransactionScopeRequired=true,TransactionAutoComplete=true)] public void Deposit(int AccountId, decimal amount) { //Your Code Here }

[OperationBehavior(TransactionScopeRequired=true,TransactionAutoComplete=true)]

Page 44: Wcf

public void withDraw(int AccountId, decimal amount) { //Your Code Here }}

Step 3: Enable Transaction Flow using WCF Service Config File.Binding - In WCF not all bindings support transactions, only TCP, IPC, and WS bindings support transactions. IPC (NetNamedPipeBinding) and TCP (NetTcpBinding) bindings support transactions because they deal with AppDomains whether on the same machine (IPC) or across machines (TCP).

There are only few bindings in WCF that can support transaction, these are NetTcpBinding, NetNamedPipeBinding, WSHttpBinding, WSDualHttpBinding, and WSFederationHttpBinding. So, in order to configure transaction, one has to make a choice out of such bindings. Though these bindings do have transaction support but by default it is disabled, so one has to make them enabled.

We also need to enable transactions for wsHttpBinding by setting the transactionFlow attribute to true. And give this setting to bindingConfiguration.

 Collapse | Copy Code

<bindings> <wsHttpBinding> <binding name="WsHttpConfig" transactionFlow="true"> <reliableSession enabled="true" /> </binding> </wsHttpBinding></bindings>

<services> <service behaviorConfiguration="MetaBehavior" name="WCFClassLibrary.AccountService"> <endpoint address="BankService" binding="wsHttpBinding" bindingConfiguration="WsHttpConfig" name="BankService_http" contract="WCFClassLibrary.IAccountService" /> <host> <baseAddresses> <add baseAddress="http://localhost:8055" /> </baseAddresses> </host> </service></services>

Step 4: On the Client Side Use TrasactionScope

We need to use TrasactionScope Attribute on to the client side for Transaction. Create the TrasactionScope to execute the commands, guaranteeing that both commands can commit or roll back as a single unit of work.

 Collapse | Copy Code

using (TransactionScope t = new TransactionScope()){

Page 45: Wcf

AccountService.AccountServiceClient proxy = new AccountService.AccountServiceClient(); proxy.Deposit(1, 2000); proxy.WithDraw(2, 200); t.Complete(); proxy.Close();}

This is all we need to do for enabling transactions in WCF.

Step 5: Check the Transactions is Working or not

In the above WCF Service in withdraw method we are checking that if the Account balance is less than 500 then we are throwing the fault exception and Transaction is rollback.

 Collapse | Copy Code

if (accountBalance - amount < 500) throw new FaultException<ErrorInfo>(new ErrorInfo() { ErrorCode = "200", ErrorDescription = "InSufficient Balance found" }, "InSufficient Balance found");

In this way you can test the Transactions is working or not on the client side.

I have attached Code snippet for that. Please download this.

Happy programming!!

Tutorial on Understanding Transactions and Creating Transaction Enabled WCF Services

Page 46: Wcf

Introduction

In this article we will discuss about creating transaction enabled WCF service. We will see what needs to be done on the WCF service end so that it support transactions. We will also see how a client application can work with these transaction enabled services using a sample application. 

Background

When we talk about transactions in database operations, we need to perform some operation(database operations) in such a way that either all the operations are successful or all of them fail. This would result in the amount information being same once the transaction is successful or it fails.

Properties of Transaction

By definition a transaction must be Atomic, Consistent, Isolated and Durable. What does we mean by all these terms

Atomic: Atomic means that all the statements (SQL statement or operations) that are a part of the transaction should work as atomic operation i.e. either all are successful or all should fail.

Consistent: This means that in case the atomic transaction success, the database should be in a state that reflect changes. If the transaction fails then database should be exactly like it was when the transaction started.

Isolated: If more than one transactions are in process then each of these transactions should work independently and should not effect the other transactions.

Durable: Durability means that once the transaction is committed, the changes should be permanent i.e. these changes will get saved in database and should persist no matter what(like power failure or something).Now having transactions from a simple class library's perspective ot from a simple .Net applications, it is just a matter of calling the operations within a transaction, checking whether all the operations are successful or not and deciding whether to commit or rollback the transaction. Refer this article to know about transactions in normal application: A Beginner's Tutorial for Understanding Transactions and TransactionScope in ADO.NET[^]

But from a WCF service perspective, since the service itself may be running on a remote server and all the communication between the service and the client is in form of messages, the service itself need some configuration so that it can be made transaction enabled.

Now in rest of the article we will see how we can configure a WCF service to support transactions and how we can call a WCF operation within transactions.

Using the code

Understanding Two Phase Commit

Page 47: Wcf

The WCF transactions happen using two phase commit protocol. Two phase commit protocol is the protocol that is used to enable transactions in a distributed environment. This protocol mainly consist of two phases:

Prepare phase: In this phase the client application performs the operations of a WCF service. WCF service determines whether the requested operation will be successful or not and notify the client about the same.

Commit Phase: In the commit phase the client checks for the responses it got from the prepare phase and if all the responses are indicating that the operation can be carried out successfully the transaction is committed. If the response from any one of the operations indicates failure then the transaction will be rolled back. The actual operation on the service end will happen in the commit phase.Now from the protocol, it is pretty clear that the WCF service will have to send the notification of whether the operation will succeed or fail to the client application. It would mean that the One way operations can never support transactions. The operations that support transactions have to follow the Request-Response Model(refer this for details on message exchange modes: Tutorial on Message Exchange Patterns and Asynchronous Operations in WCF[^])

A note on binding

Since services communicate in form of messages the underlying message specifications play a very important role in supporting transactions. To have the possibility of transactions, the WS-AT(WS-AtomicTransaction) protocol need to be used. The binding that supports this is wsHttpBinding. So we will be using this binding to create our transaction enabled service.

Description of the Test Application

To illustrate the above process, let say I have two account holders, one person is trying to transfer some money to other person. From the database perspective this operation consist of two sub-operations i.e.

Debiting the first account by specified amount. Secondly, crediting the second account with required amount.

Now from a technical perspective, if the first operation is successful but second one fails the result would be that the first persons account will be debited but second one will not be credited i.e. we loose the amount of information. The other way round will in fact increase the amount ion second account without even debiting the first amount.

So the bottom-line here is that we need either both of them to be successful to both of them should fail. Success of any one operation will result in inconsistent results and thus even if one operation fails we need to rollback what we did in the other operation. This is precisely where transaction are useful.

Let us say that the operations for credit and debit are exposed separately from a service. What we need to do is that, we need to transaction enable this service and then call these two methods within a transaction. The transaction will be committed only when both the operation indicate success. In case any one operation indicates failure or throws an exception, the transaction will not be committed.

Page 48: Wcf

Creating the Service

Let us create a simple service with a ServiceContract that exposes operations to debit an account, credit an account and get the account balance information for any account.

 Collapse | Copy Code

[ServiceContract]public interface IService1{ [OperationContract] bool PerformCreditTransaction(string creditAccountID, double amount);

[OperationContract] bool PerformDebitTransaction(string debitAccountID, double amount);

[OperationContract] decimal GetAccountDetails(int id);}

Now we want the operations PerformCreditTransaction and PerformDebitTransaction to work within a transaction. To do this we need to make some configuration in the service. The very first thing that is required with theOperationContract is to set the TransactionFlow property with the desired TransactionFlowOption. There are 3 possible values for TransactionFlowOption:

Mandatory: This specifies that this function can only be called within a transaction. Allowed: This specifies that this operation can be called within a transaction but its not

mandatory. NotAllowed: This specifies that this operation can not be called within a transaction.

Now for both our operations, we want the operations to be called mandatory within a transaction so we will specify them with this option.

 Collapse | Copy Code

[ServiceContract]public interface IService1{ [OperationContract, TransactionFlow(TransactionFlowOption.Mandatory)] bool PerformCreditTransaction(string creditAccountID, double amount);

[OperationContract, TransactionFlow(TransactionFlowOption.Mandatory)] bool PerformDebitTransaction(string debitAccountID, double amount);

[OperationContract] decimal GetAccountDetails(int id);}

Now to illustrate the implementation part, We will work on a small application that contains a single table database. This table contains the account id and the amount present in the account.

The sample DB table looks like:

Page 49: Wcf

The UI will look like:

And now to perform these operations, we will write simple ADO.NET code in our service implementation. The important thing from the service implementation perspective is that the service implementation also needs to be decorated/adorned with OperationBehavior attribute with TransactionScopeRequired property set to true. So now let us look at the sample implementation of the service operations.

 Collapse | Copy Code

public class Service1 : IService1{ readonly string CONNECTION_STRING = ConfigurationManager.ConnectionStrings["SampleDbConnectionString1"].ConnectionString;

[OperationBehavior(TransactionScopeRequired = true)] public bool PerformCreditTransaction(string creditAccountID, double amount) { bool creditResult = false;

try { using (SqlConnection con = new SqlConnection(CONNECTION_STRING)) { con.Open();

// And now do a credit using (SqlCommand cmd = con.CreateCommand()) { cmd.CommandType = CommandType.Text; cmd.CommandText = string.Format(

Page 50: Wcf

"update Account set Amount = Amount + {0} where ID = {1}", amount, creditAccountID);

// Let us emulate some failure here to see the that transaction will not // get committed // return false;

creditResult = cmd.ExecuteNonQuery() == 1; } } } catch { throw new FaultException("Something went wring during credit"); } return creditResult; }

[OperationBehavior(TransactionScopeRequired = true)] public bool PerformDebitTransaction(string debitAccountID, double amount) { bool debitResult = false;

try { using (SqlConnection con = new SqlConnection(CONNECTION_STRING)) { con.Open();

// Let us do a debit using (SqlCommand cmd = con.CreateCommand()) { cmd.CommandType = CommandType.Text; cmd.CommandText = string.Format( "update Account set Amount = Amount - {0} where ID = {1}", amount, debitAccountID);

debitResult = cmd.ExecuteNonQuery() == 1; } } } catch { throw new FaultException("Something went wring during debit"); } return debitResult; }

public decimal GetAccountDetails(int id) { decimal? result = null;

using (SqlConnection con = new SqlConnection(CONNECTION_STRING)) { using (SqlCommand cmd = con.CreateCommand()) { cmd.CommandType = CommandType.Text; cmd.CommandText = string.Format("select Amount from Account where ID = {0}", id);

Page 51: Wcf

try { con.Open(); result = cmd.ExecuteScalar() as decimal?; } catch (Exception ex) { throw new FaultException(ex.Message); } } }

if (result.HasValue) { return result.Value; } else { throw new FaultException("Unable to retrieve the amount"); } }}

Note: The code is written to elaborate the transaction enabled services only, it is not as per the coding standards i.e it is vulnerable to SQL injection. It should not be taken as code that could go in production. It is just the sample code and has a lot of scope for improvement.Now we have our ServiceContract ready and service implementation ready. Let us now use the appropriate binding i.e. wsHttpBinding to use this service. Also, in the service configuration we need to specify that this service is transaction enabled. This can be done by setting the transactionFlow property of the binding configuration ofwsHttpBiding to trueNote: Please refer the web.config of the sample code to see how this is done.

Test Application

From our test application, we will simply call the functions within a transaction(using TransactionScope). We will check both the operations' return value, if both of the indicates success, we will commit the transaction(by calling Complete method on TransactionScope object). If any operation fails we will rollback the transaction by not calling Complete function and simply letting the TransactionScope object go out of scope).

 Collapse | Copy Code

private void PerformTransaction(string creditAccountID, string debitAccountID, double amount){ // they will be used to decide whether to commit or rollback the transaction bool debitResult = false; bool creditResult = false;

try { using (TransactionScope ts = new TransactionScope()) {

Page 52: Wcf

using (ServiceReference1.Service1Client client = new ServiceReference1.Service1Client()) { debitResult = client.PerformDebitTransaction(debitAccountID, amount); creditResult = client.PerformCreditTransaction(creditAccountID, amount); }

if (debitResult && creditResult) { // To commit the transaction ts.Complete(); } } } catch { // the transaction scope will take care of rolling back }}

The code currently will work fine i.e. both the methods will return true and the transaction will get committed. To check the rollback action, we have a simple return false; statement commented in our service'sPerformCreditTransaction operation, un-comment this statement to check that the transaction will not get committed.Note: The code snippets shows the relevant code in the context. Please look at the sample code to get the full understanding.

So now we have a service that supports transactions. Before wrapping up let is look at the main operations we need in order to make a service transaction enabled. 

1. Decorate the OperationContract with required TransactionFlowOption.2. Decorate the operation implementation with OperationBehavior with

TransactionScopeRequired as true.3. Use wsHttpBinding to utilize the underlying WS-AtomicTransaction protocol.4. Specify the transactionFlow property of the

binding configuration of wsHttpBinding as true.