Callback Reentrancy or returning values in callback or duplex service in WCF

No.of Views2724
Bookmarked0 times
Downloads 
Votes0
By  Dhananjay Kumar   On  09 Sep 2010 08:09:36
Tag : WCF , REST Services
This article will explain how to return values in call back or duplex operation.
emailbookmarkadd commentsprint

Images in this article missing? We recently lost them in a site migration. We're working to restore these as you read this. Should you need an image in an emergency, please contact us at info@codegain.com

 

Introduction

Before read this article, please read part of this article here

This article will explain how to return values in call back or duplex operation.If you read above article, you will notice below points

1.    The entire operation contract is configured for one way operation.
2.    Return type of the entire operation contract is void.

Now assume there is a requirement

1.    To have request and reply on operation contract.
2.    To return some value from functions rather than void.

I mean we want signature of call back operation contract and operation of service contract as below , 

Image Loading
Image Loading

Now if we modify contract as below,

IService1.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
namespace WcfService3
{   
    [ServiceContract(CallbackContract=typeof(IMyContractCallBack))]public interface IService1
    {
        [OperationContract]string  NormalFunction();
    }public interface IMyContractCallBack
    {
        [OperationContract]string  CallBackFunction(string str); 

    }    
}

And modify the Service implementation as below,

Service1.svc.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;

namespace WcfService3
{   
    [ServiceBehavior(InstanceContextMode=InstanceContextMode.PerCall)]public class Service1 : IService1
    {public string  NormalFunction()
        {
            IMyContractCallBack callback = OperationContext.Current.GetCallbackChannel<IMyContractCallBack>();return  callback.CallBackFunction("Calling from Call Back");
            
        }

    }
}

 And service is configured as below,

Web.Config

<?xml version="1.0"?>
<configuration>
  <system.web>
    <compilation debug="true" targetFramework="4.0" />
  </system.web>
  <system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior name ="svcbh">         
          <serviceMetadata httpGetEnabled="False"/>         
          <serviceDebug includeExceptionDetailInFaults="False"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <!--<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />-->
    <services>
      <service name ="WcfService3.Service1" behaviorConfiguration ="svcbh" >
        <host>
          <baseAddresses>
            <add baseAddress = "http//localhost:9000/Service1/" />
          </baseAddresses>
        </host>
        <endpoint name ="duplexendpoint" 
                  address ="" 
                  binding ="wsDualHttpBinding" 
                  contract ="WcfService3.IService1"/>
        <endpoint name ="MetaDataTcpEndpoint"
                  address="mex" 
                  binding="mexHttpBinding" 
                  contract="IMetadataExchange"/>
      </service>
    </services>
  </system.serviceModel>
 <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
  </system.webServer>  
</configuration>

Once we consume the above service in a console application and modify the duplex proxy class as below,
MyCallBack.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ConsoleApplication1.ServiceReference1;
using System.ServiceModel;

namespace ConsoleApplication1
{class MyCallBack :IService1Callback ,IDisposable 

    {
        Service1Client proxy;public string   CallBackFunction(string str)
        {return str; 
        }public void callService()
        {
           InstanceContext context = new InstanceContext(this);
           proxy = new Service1Client(context);
          Console.WriteLine(proxy.NormalFunction());

        }public void Dispose()
        {
            proxy.Close();
        }
    }
}

 And at the client side,

Programs.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ConsoleApplication1.ServiceReference1;
using System.ServiceModel; 

namespace ConsoleApplication1
{class Program
    {static void Main(string[] args)
        {

            MyCallBack obj = new MyCallBack();
            obj.callService();
            Console.Read();
            obj.Dispose();

        }
    }
}

 And after consumption of service try to run the client, you will get an exception while trying to call the operation contract from call back function. 

Image Loading

The error message is operation would deadlock because the reply cannot be received until the current message completes processing. 

Image Loading

how to solve the above exception?

We will have to configure the service behavior for reentrancy. 

Image Loading

By setting the concurrency mode as Reentrant

1.    Service will access the operation context and call back reference and then invokes it.
2.    After the call back returns control will go to service and the lock will get reallocated to thread.

So now modified Service implementation will be as below,

Service1.svc.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;

namespace WcfService3
{   
    [ServiceBehavior(ConcurrencyMode =ConcurrencyMode.Reentrant)]public class Service1 : IService1
    {public string  NormalFunction()
        {
            IMyContractCallBack callback = OperationContext.Current.GetCallbackChannel<IMyContractCallBack>();return  callback.CallBackFunction("Calling from Call Back");
            
        }

    }
}

 Now on running the client after service consumption, we will get output as below, 

Image Loading

That's all enjoy happy coding.

 
Sign Up to vote for this article
 
About Author
 
Dhananjay Kumar
Occupation-Software Engineer
Company-Infosys Technolgies,Pune
Member Type-Gold
Location-India
Joined date-20 Jul 2009
Home Page-http://dhananjaykumar.net/
Blog Page-http://dhananjaykumar.net/
Dhananjay Kumar is Microsoft MVP on connected system. He blogs at http://dhananjaykumar.net/ . You can follow him http://twitter.com/debugmode_/ and reach him at dhananjay.25july@gmail.com
 
 
Other popularSectionarticles
Comments
There is no comments for this articles.
Leave a Reply
Title:
Display Name:
Email:
(not display in page for the security purphase)
Website:
Message:
Please refresh your screen using Ctrl+F5
If you can't read this number refresh your screen
Please input the anti-spam code that you can read in the image.
^ Scroll to Top
</