Callback Contract :
Callback
operations are part of the service contract
and service contract can have at
most one callback contract
Once callback
contract defined, the clients are required to support the callback and provide
the callback endpoint to the service in every call.
To define a
callback contract, the ServiceContract attribute offers the CallbackContract property
[AttributeUsage(AttributeTargets.Interface | AttributeTargets.Class)]
public sealed class ServiceContractAttribute
: Attribute
{
public Type
CallbackContract
{
get; set; }
//More members
}
Example :
interface IMyFirstContractCallback
{
[OperationContract]
void
OnCallback();
}
[ServiceContract(CallbackContract = typeof(IMyFirstContractCallback))]
interface IMyFirstInterface
{
[OperationContract]
void AnyMethod();
}
Note :
Callback
contract need not be defined with a ServiceContract
attribute and it will be included
in the service metadata.
All methods in callback interface defined with
with the OperationContract attribute.
Once the client imports the metadata
of the callback contract, the imported callback interface will not have the
same name as in the original service-side definition. It will become interface suffixed with the word Callback.
Example :
Interface :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
namespace CallBackOperation
{
//Interface IDuplexServiceContract which is our service
contract
//In service Contract need to make sure WCF maintains
session information for the duration of a client's connection.
//Secondly, we need to specify that which interface will be
handling the callback contract eg :IDuplexCallback.
[ServiceContract(SessionMode = SessionMode.Required, CallbackContract = typeof(IDuplexCallback))]
public interface IDuplexServiceContract
{
[OperationContract(IsOneWay = true)]
void Stringmanagement(string
value);
[OperationContract]
List<string>
GetData();
}
//Callback contract which client will call, creating a new
interface IDuplexCallback
//This interface has two Call Back methods ,In order that
it should be asynchronous,
//we have defined the one-way attribute on the doHugeTask
method.
public interface IDuplexCallback
{
[OperationContract(IsOneWay = true)]
void CallBacktestingFunction(string
requestString);
[OperationContract(IsOneWay = true)]
void LodingDataStatus(string[]
data);
}
}
Service :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using System.Text;
using System.Threading;
using System.Data.SqlClient;
using System.Data;
namespace CallBackOperation
{
//InstanceContextMode is PerSession because the use of
callback contracts requires a session
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
public class DuplexCallBack : IDuplexServiceContract
{
SqlConnection Conn;
IDuplexCallback _callback;
string _requestString = String.Empty;
public DuplexCallBack()
{
//The OperationContext.Current.GetCallBackChannel will be
used to make callback to the client.
//When the service receives a call,
OperationContext.Current.GetCallbackChannel returns a channel to just that
caller.
//It does not return a channel that broadcasts to all of
the clients.
_callback = OperationContext.Current.GetCallbackChannel<IDuplexCallback>();
Conn = new SqlConnection("Connection String");
}
public void
Stringmanagement(string value)
{
_requestString = string.Format("Hey, Welcome {0} , So finally you did it.",
value);
// CallBack Function
_callback.CallBacktestingFunction(_requestString);
}
List<string>
IDuplexServiceContract.GetData()
{
List<string>
lstFunds = new List<string>();
Conn.Open();
SqlCommand Cmd = new
SqlCommand("Select
top 10 FundName from tblfund order by FundID", Conn);
SqlDataReader Reader = Cmd.ExecuteReader();
while (Reader.Read())
{
lstFunds.Add(Reader["FundName"].ToString());
}
Reader.Close();
Conn.Close();
string[] returndataArray = lstFunds.ToArray();
// CallBack Function
_callback.LodingDataStatus(returndataArray);
return lstFunds;
}
}
}
WebConfig :
<system.webServer>
<validation validateIntegratedModeConfiguration="false" />
<modules>
<add name="ScriptModule" preCondition="integratedMode" type="System.Web.Handlers.ScriptModule,
System.Web.Extensions, Version=3.5.0.0, Culture=neutral,
PublicKeyToken=31BF3856AD364E35" />
</modules>
<handlers>
<remove name="WebServiceHandlerFactory-Integrated" />
<add name="ScriptHandlerFactory" verb="*" path="*.asmx" preCondition="integratedMode" type="System.Web.Script.Services.ScriptHandlerFactory,
System.Web.Extensions, Version=3.5.0.0, Culture=neutral,
PublicKeyToken=31BF3856AD364E35" />
<add name="ScriptHandlerFactoryAppServices" verb="*" path="*_AppService.axd" preCondition="integratedMode" type="System.Web.Script.Services.ScriptHandlerFactory,
System.Web.Extensions, Version=3.5.0.0, Culture=neutral,
PublicKeyToken=31BF3856AD364E35" />
<add name="ScriptResource" preCondition="integratedMode" verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler,
System.Web.Extensions, Version=3.5.0.0, Culture=neutral,
PublicKeyToken=31BF3856AD364E35" />
</handlers>
<directoryBrowse enabled="true" />
</system.webServer>
<system.serviceModel>
<services>
<service behaviorConfiguration="DuplexWcfService.Service1Behavior" name="CallBackOperation.DuplexCallBack">
<endpoint address="http://localhost:62345/DuplexCallBack.svc" binding="wsDualHttpBinding" contract="CallBackOperation.IDuplexServiceContract">
</endpoint>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="DuplexWcfService.Service1Behavior">
<!-- To avoid disclosing metadata information, set the value below to
false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="true" />
<!-- To receive exception details in faults for debugging purposes,
set the value below to true. Set to
false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
Add Service reference :
Client WebConfig :
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<bindings>
<wsDualHttpBinding>
<binding name="WSDualHttpBinding_IDuplexServiceContract" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard"
maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<reliableSession ordered="true" inactivityTimeout="00:10:00" />
<security mode="Message">
<message clientCredentialType="Windows" negotiateServiceCredential="true"
algorithmSuite="Default" />
</security>
</binding>
</wsDualHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost:62345/DuplexCallBack.svc"
binding="wsDualHttpBinding" bindingConfiguration="WSDualHttpBinding_IDuplexServiceContract"
contract="ServiceReference1.IDuplexServiceContract" name="WSDualHttpBinding_IDuplexServiceContract">
<identity>
<userPrincipalName value="vikas.kumar@Vam.Local" />
</identity>
</endpoint>
</client>
</system.serviceModel>
</configuration>
Client Code :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using Console_CallBack_Client.ServiceReference1;
namespace Console_CallBack_Client
{
//Following methods are callback methods, which the server
will call after service methods completed eg :
Stringmanagement() and GetData.
class DuplexCallbackHandler
: IDuplexServiceContractCallback
{
public void
CallBacktestingFunction(string value)
{
Console.WriteLine("\n");
Console.WriteLine("\t
Callback returned from the server");
Console.WriteLine("\n");
Console.WriteLine(value);
Console.WriteLine("\n");
}
public void
LodingDataStatus(string[] data)
{
Console.WriteLine("\n");
Console.WriteLine(string.Format("Total Length of array : {0}", data.Length.ToString()));
Console.WriteLine("\n");
}
}
class Program
{
static void Main(string[] args)
{
//here I create object of the Instance Context
class.Instance Context represents context information of a service.
//The main use of Instance Context is to handle incoming
messages.
//In short, service reference or proxy is used to send
messages to server and Instance Context is used to accept incoming messages.
InstanceContext instanceContext = new InstanceContext(new DuplexCallbackHandler());
//In this step we pass the Instance Context object to the
constructor of service reference or proxy.
//server will use the same channel to communicate to the
client.
DuplexServiceContractClient
client = new DuplexServiceContractClient(instanceContext);
client.Stringmanagement("Guugeeaa");
string[] listvalues;
listvalues = client.GetData();
for (int
i = 0; i <= listvalues.Length - 1; i++)
{
Console.WriteLine(listvalues[i].ToString());
}
Console.WriteLine("\n");
Console.ReadLine();
}
}
}
OutPut :
No comments :
Post a Comment