Saturday, July 12, 2008

IIS hosted Duplex WCF Service

Today, I'm showing you how to create a Duplex Contract WCF service which will be hosted in the IIS and called from various console App clients. We will be understanding the WCF Duplex Services and Contracts concept from the classic Stock Exchange example. In this example we are having a WCF Duplex service named DuplexStock1. This service will receive subscription requests from various clients for a stock tickers like MSFT, YAHOO, etc.

The WCF Service will create separate threads for each client connecting to it (Though its not quite optimized approach,but simple to explain here). The service will push the stock values to the cilents through Duplex channe periodically (after 5 seconds). Stock values are randomly updated from 0 to 100 and pushed to the client.

The clients will show the updated stock values for the subscribed ticker in their Console Window. The main of this blog post is not explain each and every concept of Duplex Binding but to show a working example.

Lets commence by creating the Server..




namespace StockMarketServer
{
[ServiceContract(CallbackContract=typeof(IClientCallback1))]
public interface IDuplexStock1
{
[OperationContract(IsOneWay = true)]
void SubscribeForStockUpdate(string strTicker);
}

public interface IClientCallback1
{
[OperationContract(IsOneWay=true)]
void UpdatePrice(string ticker, double price);
}

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
public class DuplexStock1 : IDuplexStock1
{
public void SubscribeForStockUpdate(string strTicker)
{
Update objUpdate = new Update();
objUpdate._ticker = strTicker;
objUpdate.callback = OperationContext.Current.GetCallbackChannel();
Thread t = new Thread(new ThreadStart(objUpdate.SendUpdateToClient));
t.IsBackground = true;
t.Start();
}
}
public class Update
{
public IClientCallback1 callback=null;
public string _ticker;
public void SendUpdateToClient()
{
Random rnd= new Random();
for (int i = 0; i < 10; i++)
{
Thread.Sleep(5000);
try
{
callback.UpdatePrice(_ticker, rnd.NextDouble() * 100.0);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
}
}


As you can see in the above code we have two interfaces one for WCF Service Contract [IDuplexStock1]other for the client [IClientCallback1]. The SubscribeForStockUpdate method is invoked by every client when it wants to subscribe for a particular stock ticker update. The service gets the client channel in which to push the updates using the GetCallbackChannel method can spawns a new thread with Update class. This class starts pushing data to client randomly.



Now lets see the WCF service configuration which will help it to be hosted in IIS
































Put the above code in Web.config of your WCF project and make the project folder as the virtual directory. If you have done everything alright, then you should be able to see service metadata when you browse the baseAddress Url in the browser.



Now lets start building the Console Application Clients. Start by adding a console application project to your solution. Then use "Add Service reference" and give the above baseAddress Url. This will create WSDL proxies and put client configuration into the app.config your ConsoleApp. Here's what your console App's app.config should look like







...blah..blah..>
maxBytesPerRead="4096" maxNameTableCharCount="16384" />


algorithmSuite="Default" />





binding="wsDualHttpBinding" bindingConfiguration="WSDualHttpBinding_IDuplexStock1"
contract="StockMarketServerProxy.IDuplexStock1" name="WSDualHttpBinding_IDuplexStock1">










Ensure that the bolded tags shown above are present in your app.config. They are the key pillars to support Duplex Communication. Now finally lets start coding the client console app




namespace StockMarketConsoleClient
{
class Program
{
static InstanceContext site = new InstanceContext(new CallbackHandler());
static DuplexStock1Client objDupCl = new DuplexStock1Client(site);
public Program()
{
try
{
Console.Write("Input Stock ticker::");
string strInputTicker=Console.ReadLine();
objDupCl.SubscribeForStockUpdate(strInputTicker);
Console.WriteLine("Server connection established, wait for updates to be pushed by the server...");
Console.Read();
}
catch (Exception ex)
{
Console.WriteLine("Exception ::" + ex.Message);
Console.Read();
}
}
static void Main(string[] args)
{
Program objPr = new Program();
}
}

public class CallbackHandler : IDuplexStock1Callback
{

public void UpdatePrice(string ticker, double price)
{
Console.WriteLine("Recieved push for ticker :: " + ticker + " value is " + price.ToString() + " on " + DateTime.Now.ToString());
}
}
}







No comments: