Tuesday, May 22, 2012

WCF- ONE Way Operation

Operations  in WCF
·         One-Way Operations
·         Request-Reply Operations
·         Callback Operations

One Way Operation : In One-Way operation mode, client will send a request to the server and does not care whether it is success or failure of service execution. There is no return from the server side.Client will be blocked only for a moment till it dispatches its call to service. If any exception thrown by service will not reach the server.Client can continue to execute its statement, after making one-way call to server.

One-way property could only be set true to the operations that are not returning Void.

 ********Right*********
       [OperationContract(IsOneWay = true)]
        void operation2Successfull();


********Wrong*********
        [OperationContract(IsOneWay = true)]          
        string operation1returnError();

        ERROR                           


Example :  
 [ServiceContract]
    public interface IOneWay
    {
        [OperationContract]
        double Addition(int i, int j);

        [OperationContract(IsOneWay = true)]
        void Multiply(int i, int j);

        [OperationContract]
        double Subtraction(int i, int j);
    }

Service
namespace Operations
{
    public class OneWay : IOneWay
    {
       

        public double Addition(int i, int j)
        {
           return    i + j;

        }

        public void Multiply(int i, int j)    In This Method We are Dividing Numbers
        {
            double val = i / j;
        }

        public double Subtraction(int i, int j)
        {
          return    i - j;
        }
    }
}

Client Side :
// Service Reference
 OneWayServicereference.OneWayClient client = new  OneWayServicereference.OneWayClient();

Response.Write("Addition : " +  client.Addition(10, 10).ToString() + "</BR>");

client.Multiply(5,0);   so In service It will generate ERROR 5/0

Response.Write("Subtraction : " + client.Subtraction(10, 5).ToString() + "</BR>");

OUTPUT :
If any exception thrown by service will not reach the server.Client can continue to execute its statement, after making one-way call to server.

Nne-way operations shouldn't be used in a sessionful contract if using SessionMode.PerSession instantiation, but it is not a bad design to use one-way operations with sessionful contract when SessionMode is either per-call or per-singleton.

One-Way operation you don't know if it caused exception on the service. Unhandled exception on the service always faults the channel. If InstanceContextMode is set to PerSession it faults sessionful channel and it disposes service instance. Because of the one way nature client will not know about it and next call to the service from the same client proxy will end with exception (channel is faulted )

Example 2 :
[ServiceContract]
    public interface IOneWay
    {
        [OperationContract]
        double Addition(int i, int j);

       [OperationContract(IsOneWay = true)]
        void Multiply(int i, int j);

        [OperationContract]
        double Subtraction(int i, int j);

        [OperationContract]
        double result();
    }

Service

namespace Operations
{
    public class OneWay : IOneWay
    {
        double result = 0.10;

        public double Addition(int i, int j)
        {
             result= i + j;
             return i + j;

        }
        public void Multiply(int i, int j)
        {
            result = result + 10;
            double val = i / j;
            result = result + 10000;
        }
        public double Subtraction(int i, int j)
        {
            result = result + (i - j);
          return    i - j;
        }

        double IOneWay.result()
        {
            return result;
        }
    }
}

WebConfig File :
<?xml version="1.0"?>
<configuration>

  <system.web>
    <compilation debug="true" targetFramework="4.0" />
  </system.web>
  <system.serviceModel
    <bindings>   
    </bindings>
    <behaviors>
      <serviceBehaviors>
        <behavior>
           <serviceMetadata httpGetEnabled="true"/>
           <serviceDebug includeExceptionDetailInFaults="false"/>
        </behavior>
      </serviceBehaviors>
    </behaviors
      <services>
      <service name="Operations.OneWay">       
        <endpoint name="" address="http://localhost:51417/OneWay.svc" binding="basicHttpBinding" contract="Operations.IOneWay"/>
       </service>
    </services>
       
  </system.serviceModel>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
      </system.webServer>
</configuration>


Client Side :  
 ServiceContractWebWsBinding.ServiceReference1.OneWayClient client = new ServiceContractWebWsBinding.ServiceReference1.OneWayClient();
         
             Response.Write("Addition : " +  client.Addition(10, 10).ToString() + "</BR>");
             client.Multiply(5,0);
             Response.Write("Subtraction : " + client.Subtraction(10, 5).ToString() + "</BR>");
             Response.Write("Result : " + client.result().ToString() + "</BR>");

OutPut :
Result Method returning 0.1 value as declared in service at TOP.Wae are using basichttpBinding which does not support session so value remain as initialize at TOP.

If we User   wsHttpBinding binding instead of basicHttpBinding

      <endpoint name="" address="http://localhost:51417/OneWay.svc" binding="wsHttpBinding"
contract="Operations.IOneWay"/>
A  service-side exception, including those thrown by one-way operations, will fault the channel, and the client will not be able to issue any new calls using the same proxy instance

Note  if We comment Exception code  double val = i / j;  in Multipy Method then service works fine

     
     public void Multiply(int i, int j)
        {
            result = result + 10;
           // double val = i / j;
            result = result + 10000;
        }



Error: client is using same proxy instance to call Subtraction method After Multipy Method which cause exception and result into Error occer



Next : One Way operation and Session full Services
Change Interface
[ServiceContract(SessionMode = SessionMode.Required)]
    public interface IOneWay
    {
        [OperationContract]
        double Addition(int i, int j);

        [OperationContract(IsOneWay = true, IsInitiating = false, IsTerminating = true)]
        void Multiply(int i, int j);

        [OperationContract]
        double Subtraction(int i, int j);

        [OperationContract]
        double result();
    }
Use the IsTerminating property to indicate that calling a service operation terminates the communication session.
The IsInitiating property controls whether an operation can be the first operation called when a session is created.

The default is true, which means that an operation can be the first one called on a channel. Subsequent calls to the initiating method have no effect, other than to call the method. No other sessions are created. If the contract does not make use of a session, setting IsInitiating to false is ignored.

Theoretically it is possible to design a one way service as session full service but it is considered as a bad design.
One way Service should be applied either on Per Call or single service. Even if we want to make a one way operation as session full service then we should design our contact such that only the last operation is terminating the session.
One more thing to make sure the last operation is adhering the one way operation rules that is returning void.

Client Side :
ServiceContractWebWsBinding.ServiceReference1.OneWayClient client = new ServiceContractWebWsBinding.ServiceReference1.OneWayClient();
         
             Response.Write("Addition : " +  client.Addition(10, 10).ToString() + "</BR>");
         
             Response.Write("Subtraction : " + client.Subtraction(10, 5).ToString() + "</BR>");
             Response.Write("Result : " + client.result().ToString() + "</BR>");
             client.Multiply(5, 0);


In Interface SessionMode = SessionMode.Required and   Multiply() is IsOneWay = true, IsInitiating = false, IsTerminating = true 

Note Client need to call Multiply method at end as last operation other wise following xxecption will occer
Code :

 Response.Write("Addition : " +  client.Addition(10, 10).ToString() + "</BR>");
 client.Multiply(5, 0);
 Response.Write("Subtraction : " + client.Subtraction(10, 5).ToString() + "</BR>");
 Response.Write("Result : " + client.result().ToString() + "</BR>");



2 comments :