Introduction
Push notification is a term that has been around a lot. Almost every SmartPhone manufactured has an option for enabling push notification. The word 'PUSH' is a contrast to 'PULL'. It means rather than pulling the content from the server or requesting from the server, the server pushes the content or sends the response as soon as an update is available. On mobiles, this technology is a great battery saver. In web technologies, it saves a lot of server request traffic. There are tons of articles available on the internet about implementing this technique, but I found MSDN the best. Therefore, I went ahead and made the MSDN tutorial even easier for beginners. Remember, this is beginners article, but the idea of implementing a real life application stays around this. You can recode it as best as you can.
Over here, we are going to see a Silverlight application requesting for stock prices of Yahoo! The server will start pushing the latest stock prices. The stock prices are random numbers. The application is based on some assumptions.
Background
As a newbie, you must be aware of WCF, basic Silverlight, and terms like Push notification. Please refer to Wikipedia for the definitions.
Using the code
I have used .NET Framework 4.0 to develop the example. You might have to change some code if you are using an earlier version.
- Go to the new project and create a WCF Service Application. The first thing to add is the reference to the Polling Duplex DLL. You need to browse in your Add References window to %Program Files%\Microsoft SDKs\Silverlight\v3.0\Libraries\Server\System.ServiceModel.PollingDuplex.dll. Please look carefully, we are referencing the polling duplex DLL from the libraries\server folder.
- Right click the project and add a new item 'Interface'. You can name it IService1.cs.
- You must include these in the header area-->
using System.ServiceModel;
and using System.ServiceModel.Web;
. - Copy-paste the following code. Basically, we have defined two interfaces within this interface.
IsOneWay=true
is a messaging pattern which means 'call and forget' in contrast to 'request-response'.
namespace DuplexService
{
[ServiceContract(Namespace="Silverlight",
CallbackContract = typeof(IDuplexClient))]
public interface IDuplexService
{
[OperationContract(IsOneWay = true)]
void RequestPrice(string stocksyb);
}
[ServiceContract]
public interface IDuplexClient
{
[OperationContract(IsOneWay = true)]
void PushPrices(string p);
}
}
- Go to service1.svc.cs. Include these in the header if they do not exist:
using System.ServiceModel;
and using System.ServiceModel.Web;
. You must also include: using System.Threading;
. - Copy-paste the following code in your service1.svc.cs. The
RequestPrice(string stocksyb)
method is going to be called from Silverlight with the stockname
parameter. At this point, we have three stocks in the list which will be searched and responded with a random price. The searching is done via LINQ, therefore you need to have System.Linq
as a reference. PushData
is being called by the timercallback
delegate every second. client.PushPrices(_i);
is the method that is going to push the content on the client.
namespace DuplexService
{
public class StockService: IDuplexService
{
IDuplexClient client;
Random num = new Random();
public void RequestPrice(string stocksyb)
{
client = OperationContext.Current.GetCallbackChannel<IDuplexClient>();
List<string> stocklist = new List<string>();
stocklist.Add("Yahoo");
stocklist.Add("Microsoft");
stocklist.Add("Google");
var query = from s in stocklist where s == stocksyb select s;
var result = query.SingleOrDefault();
if (result != null)
{
using (Timer timer =
new Timer(new TimerCallback(PushData), stocksyb, 1000, 1000))
{
Thread.Sleep(System.Threading.Timeout.Infinite);
}
}
else
{
client.PushPrices("Invalid Stock Request");
}
}
private void PushData(object o)
{
string _i = num.Next(201,205).ToString();
client.PushPrices(_i);
}
}
}
- The next step is to create a class file. Therefore, add a new class and name it PollingDuplexServiceHostFactory.cs. Add the following content:
using System;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using DuplexService;
namespace DuplexService
{
public class PollingDuplexServiceHostFactory : ServiceHostFactoryBase
{
public override ServiceHostBase CreateServiceHost(string constructorString,
Uri[] baseAddresses)
{
return new PollingDuplexSimplexServiceHost(baseAddresses);
}
}
class PollingDuplexSimplexServiceHost : ServiceHost
{
public PollingDuplexSimplexServiceHost(params System.Uri[] addresses)
{
base.InitializeDescription(typeof(StockService),
new UriSchemeKeyedCollection(addresses));
}
protected override void InitializeRuntime()
{
this.AddServiceEndpoint(
typeof(IDuplexService),
new CustomBinding(
new PollingDuplexBindingElement(),
new BinaryMessageEncodingBindingElement(),
new HttpTransportBindingElement()),
"");
this.AddServiceEndpoint(
typeof(IMetadataExchange),
MetadataExchangeBindings.CreateMexHttpBinding(),
"mex");
base.InitializeRuntime();
}
}
}
- Go to the markup code of your Service.svc file. Right click File->View markup. Replace it with the following code:
<%@ServiceHost language="c#" Debug="true"
Factory="DuplexService.PollingDuplexServiceHostFactory"%>
- Build the service and see if it displays correctly. If you are working on the development server, then make sure that your dynamic port stays the same till we complete our client application. This is it; we are done with the WCF side coding. Now let's make the client application.
- We are going to develop the client application in Silverlight. You must have the SDL installed. Add a new project to the same solution. Select Silverlight Application.
- The first step is to add the reference to the client side Polling Duplex DLL. Add a reference and browse to it from %Program Files%Microsoft SDKs\Silverlight\v3.0\Libraries\Client\System.ServiceModel.PollingDuplex.dll.
Watch carefully, it's not the same as the previous one. This DLL is being referenced from the Libraries\Client folder.
- Now you need to add the service reference. Right click on the service reference->Add Service Reference. Click Discover. You should see Service.svc. Enter the namespace as StockService and press OK.
- Go to your default XAML page "MainPage.xaml". Add two
TextBlock
s. Name them 'info
' and 'reply
'.
- Add references in the header of your MainPage.xaml.cs:
using System.ServiceModel;
, using System.ServiceModel.Channels;
, using SilverlightApplication2.StockService;
. - Copy paste the following code:
- The
EndpointAddress
should contain the URI to your service. Don't forget to check your current port while you are working on your development server. - The proxy object is the object of our service reference namespace "
StockService
". - The event handler will handle the incoming values from the service. The handler handles the
proxy_PushPricesReceived
method. - The
e
object is the (_i
) returned value from the service.
You can see we are requesting for Yahoo!'s price as it exists in our list. If we enter something else, then the server will respond with an "invalid stock request".
namespace SilverlightApplication2
{
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
EndpointAddress address =
new EndpointAddress("http://localhost:1582/Service1.svc");
PollingDuplexHttpBinding binding = new PollingDuplexHttpBinding();
DuplexServiceClient proxy = new DuplexServiceClient(binding, address);
proxy.PushPricesReceived +=
new EventHandler<PushPricesReceivedEventArgs>(
proxy_PushPricesReceived);
string stocksymb = "Yahoo";
proxy.RequestPriceAsync(stocksymb);
info.Text = "Fetch price for " + stocksymb +
Environment.NewLine + Environment.NewLine;
}
void proxy_PushPricesReceived(object sender, PushPricesReceivedEventArgs e)
{
reply.Text = "Current Market Price : ";
reply.Text += e.p;
}
}
}
- Build the project and navigate to the Silverlight application folder, \SilverlightApplication2\Bin\Debug. Copy the SilverlightApplication2.xap file and paste it in your WcfService1\ClientBin folder. You will need to create the ClientBin folder. You will need to do this every time you make changes in your .xaml and xaml.cs file.
- In your WCF project, add a new HTML file. Copy paste the following code in the body tag:
<div id="silverlightControlHost">
<object data="data:application/x-silverlight-2,"
type="application/x-silverlight-2" width="100%" height="100%">
<param name="source" value="ClientBin/SilverlightApplication2.xap"/>
<param name="onError" value="onSilverlightError" />
<param name="background" value="white" />
<param name="minRuntimeVersion" value="3.0.40818.0" />
<param name="autoUpgrade" value="true" />
<a href="http://go.microsoft.com/fwlink/?LinkID=149156&v=3.0.40818.0"
style="text-decoration:none">
<img src="http://go.microsoft.com/fwlink/?LinkId=161376"
alt="Get Microsoft Silverlight" style="border-style:none"/>
</a>
</object><iframe id="_sl_historyFrame"
style="visibility:hidden;height:0px;width:0px;border:0px">
</iframe>
</div>
- Build everything. Set your HTML page as your start up file and run the project. The application will request for Yahoo!'s price and the server will push the content every second.
- Use Fiddler to see the responses from the server.