Responsive WCF service With ICallbackEventHandler InterfaceHere I designed WCF service which is place order for client and reply back to client that order placed successfully or not. ICallbackEventHandler interface implemented on page display response to client. Before I discuss more here is the screen that shows output
Place Order
WCF service placing order
Order placed successful or not
To accomplish this whole program get divide in two part
1) Design of callback WCF service
2) Design of WEB page with ICallbackEventHandler interface to provide response on screen
Design of callback WCF service
Config file
You need to config WCF service as below to make service reliable(duplex) i.e send response back to client once task done.
<configuration>
<system.servicemodel>
<bindings>
<wsdualhttpbinding>
<binding bypassproxyonlocal="true" name="sampleBinding" usedefaultwebproxy="true">
</binding></wsdualhttpbinding>
</bindings>
<services>
<service behaviorconfiguration="returnFaults" name="Service.DemoService">
<endpoint binding="wsDualHttpBinding" bindingconfiguration="sampleBinding" contract="Service.IDemoService">
</endpoint></service>
</services>
<behaviors>
<servicebehaviors>
<behavior name="returnFaults">
<servicedebug includeexceptiondetailinfaults="true">
<servicemetadata httpgetenabled="true">
</servicemetadata></servicedebug></behavior>
</servicebehaviors>
</behaviors>
</system.servicemodel>
<system.web>
<compilation debug="true">
</compilation></system.web>
</configuration>
Thing to note in config file is used protocol called "wsDualHttpBinding" that allows to create reliable session that means it allows to send response back to client who made call to service once task get completed.
WSDualHttpBinding - A secure and interoperable binding that is designed for use with duplex service contracts that allows both services and clients to send and receive messages.
WCF Service file
After creating or modifying you can code service file as below .
using System;
using System.ServiceModel;
using System.Collections.Generic;
using System.Threading;
using System.Runtime.Serialization;
namespace Service
{
IDemoService- interface that is implemented in WCF service. whose method get called by application consuming wcf service.
[ServiceContract(CallbackContract = typeof(IClientCallBack))]
public interface IDemoService
{
[OperationContract(IsOneWay = true)]
void PlaceOrder(OrderItem item);
}
ServiceContractAttribute.CallbackContract - This attribute allows to set callback contract when the contract is a duplex contract i.e callback interface that get called by service to inform client.
So this allows client applications to listen for inbound operation calls that the server-side service application can send to client application which is independent from client activity. Callback contracts that have one-way operations represent calls from the service that the client can handle.
IClientCallBack- interface that is get implemented on the client side i.e by the application which is consuming the wcf service. Method of this interface get called from wcf service methods which is discussed below.
public interface IClientCallBack
{
[OperationContract(IsOneWay = true)]
void ISOrerPlaceSuccessfully(bool issuccess, float total);
}
OrderItem - is datacontract class of wcf service.
[DataContract]
public class OrderItem
{
float price;
string name;
int qty;
[DataMember]
public float Price
{
get { return price; }
set { price = value;}
}
[DataMember]
public string Name
{
get { return name; }
set { name = value; }
}
[DataMember]
public int Quantity
{
get { return qty; }
set { qty = value; }
}
}
DemoService - Implement service contract interface.
public class DemoService : IDemoService
{
public void PlaceOrder(OrderItem item)
{
IClientCallBack callback = OperationContext.Current.GetCallbackChannel<IClientCallBack>();
bool success = true;
//process order
float total = item.Price * item.Quantity;
callback.ISOrerPlaceSuccessfully(success, total);
}
}
}
PlaceOrder - method call the callback contract method ISOrerPlaceSuccessfully.
OperationContext.Current -Gets the execution context for the current thread.
code uses the Current property and GetCallbackChannel method to create a channel back to the caller i.e to client from service method. one-way method allows service and client to communicate in both directions independently.
Design of WEB page with ICallbackEventHandler interface to provide response on screen
.ASPX file
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="WebClient.Default" EnableSessionState="True"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body id="formBody" runat="server" >
<form id="form1" runat="server">
<div style="text-align:center">
<h1>Place Order</h1>
</div>
<div>
<table>
<tr>
<td><asp:Label ID="lblItemName" runat="server" Text="Label">Item Number :</asp:Label></td>
<td><asp:Label ID="lblItemValue" runat="server" Text="Label">Test</asp:Label></td>
</tr>
<tr>
<td><asp:Label ID="Label1" runat="server" Text="Label">Price :</asp:Label></td>
<td><asp:Label ID="Label2" runat="server" Text="Label">500</asp:Label></td>
</tr>
<tr>
<td><asp:Label ID="Label3" runat="server" Text="Label">Qunatity :</asp:Label></td>
<td><asp:TextBox ID="txtQunatity" runat="server" ></asp:TextBox></td>
</tr>
</table>
<asp:Button ID="Button1" runat="server" Text="Place Order" OnClick="Button1_Click" />
<asp:Label ID="lblMsg" runat="server"></asp:Label></div>
</form>
</body>
</html>
.Cs file
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using WebClient.DemoService;
using System.ServiceModel;
using System.Threading;
namespace WebClient
{
Implementation of Client callback interface - here all method declare in service as part of callback contract get implemented. This method is get called by the service method once task done on service side.
public class CallBack : WebClient.DemoService.IDemoServiceCallback
{
public string Message
{
get;set;
}
public void ISOrerPlaceSuccessfully(bool issuccess, float total)
{
Thread.Sleep(5000);
if (issuccess)
this.Message = "Order with total of : " + total + " placed successfully";
else
this.Message = "Order with total of : " + total + " failed to place";
}
}
ISOrerPlaceSuccessfully - is callback method which is get called back from the placeorder method of service. Once response is arrived Message property value get updated which is used to show the order stats on user screen.
Note - Thread.Sleep is used in code just for the delay/demo purpose i.e to show the how it actually works when longer process get called on service. Remove it when make use in project.
ICallbackEventHandler Interface - Used to indicate that a control can be the target of a callback event on the server.
The ICallbackEventHandler is a wrapper on XMLHTTP. So that it allow to call the serverside method without any postback and there is no need to wirte any javascript/jquery for making ajax call all things get handle this interface in .net framework.
public partial class Default : System.Web.UI.Page, ICallbackEventHandler
{
static CallBack callback;
DemoServiceClient client;
protected void Page_Load(object sender, EventArgs e)
{
}
protected void Button1_Click(object sender, EventArgs e)
{
setupClientSideCallback();
callback = new CallBack();
InstanceContext ic = new InstanceContext(callback);
client = new DemoServiceClient(ic);
OrderItem item = new OrderItem();
item.Name = "Test";
item.Price = 12;
item.Quantity = Convert.ToInt32(txtQunatity.Text);
lblMsg.Text = "Placing Order...";
client.PlaceOrder(item);
}
Here in above code callback is variable of type Callback clas which is static because on the order pace button get clicked value of callback is remain as it is i.e its not get created again for later on use in GetCallbackResult method which is discussed below.
OnCallback is method defined at client side which is used to call back once the clientscript register by serverside code and eventArg is a variable defined at the client side which holds the parameter value.
protected void setupClientSideCallback()
{
string ScriptRef = this.ClientScript.GetCallbackEventReference(this, "'" + 0 + "'", "OnCallback", "'" + lblMsg.ClientID + "'");
formBody.Attributes.Add("onload", ScriptRef);
string script = "<script language="javascript" type="text/javascript">
" +
" function getResponse() " +
" { " + ScriptRef + " } " +
" function OnCallback(Result,Context) " +
" { " +
" var lbl=document.getElementById(Context); " +
" lbl.innerText=Result ; " +
" setTimeout(getResponse, 1000); " +
" } " +
"
</script> ";
this.ClientScript.RegisterClientScriptBlock(this.GetType(), "ClientCallback", script);
}
Javascript code - get register when placeorder button get clicked. After that to check the response arrived from the wcf service or not it makes call at regular interval by using setTimeout function. So it works like timer which execute set of code at regular interval.
The ICallbackEventHandler interface has two methods which required to be implemented in the page.
RaiseCallbackEvent - This event is called when the call from client side (Javascript)i.e from browser to server. This is the event to handle the call back handler. Here eventArgs is a parameter which is passed from client side.
GetCallbackResult - This methos returns the result of the callback event to client side i.e from serverside to browser.
string ICallbackEventHandler.GetCallbackResult()
{
if (callback!=null && callback.Message != null)
{
return callback.Message;
}
return "Placing Order..." ;
}
string eventArgument;
void ICallbackEventHandler.RaiseCallbackEvent(string eventArgument)
{
this.eventArgument = eventArgument;
}
}
}
Summary
WCF reliable(duplex) service useful to inform the cosumer of service i.e client of service that task completed or not by calling the consumer i.e client from service. This kind of suff useful when we are creating modules where payment of order take place as I did in my implementation.
Note
I cannot upload code over here but if you want code of the same mail me at pranayamr@gmail.com or just follow the post step and paste code in your project.
Javascript code is currenly working on IE only which will be modified soon.