Search This Blog

Sunday, July 18, 2010

Silverlight: Notification Messages from the Server

Summary: The article shows how to implement receiving of notification messages from the hosting server in the Silverlight application with using Eneter.Messaging.Framework.




Basically there are two approaches, if you need to implement the communication scenario where the Silverlight client needs to be notified about some events on the server:

Polling
The Silverlight client regularly initiates the Http connection and asks the server for messages. The server then responses messages intended for the client or returns an empty response if messages are not available (that can be the majority of requests).
The advantage of the polling is that it does not block resources. (The problem is that browsers typically limit the number of concurrent Http connections per server to 2 - 8. The polling needs this connection only for short time.)
The disadvantage of the polling is that it can cause a lot of useless communication. (In case the majority of requests return empty response.)

Pushing
The Silverlight client initiates the Http connection. The server receives the request but does not answer until messages for the client are not available - the connection stays open (that can be long time). When the server answers, the client processes notifications and initiates the Http connection again.
The advantage of the pushing is that there is not a useless communication.
The disadvantage of the pushing is that it consumes the Http connection. And because browsers typically limit the number of concurrent Http connections per server to 2 - 8, it can happen that connections are occupied and the client application is blocked.


If you prefer to get notification messages based on the pushing, you can choose WCF. The server can implement the service and the Silverlight client can get notification messages via some call-back interface.

If you prefer to get notification messages based on the polling, you do not have many possibilities. Probably you would need to implement the communication in yourself with using .Net functionality for Http. (The client regularly polls and recognizes messages and the server constantly collects messages and responses them to the client on demand.)

Another possibility you can consider is to use Eneter.Messaging.Framework. The framework provides a great support to implement the notification scenario based on polling.

The example bellow shows how the Silverlight application can get notification messages with using Eneter.Messaging.Framework. The client subscribes to be notified from the server and server notifies the client when the event occurs. (In the example, the server generates numbers based on the timer.)


1. Server Site - ASP.NET Web Application
To use the messaging framework functionality you must add Eneter.Messaging.Framework.dll into references. (Full, not limited and for non-commercial usage free version of the framework can be downloaded from www.eneter.net.)

One of major responsibilities of the server in this communication scenario is to allow Silverlight clients to subscribe for messages. To support publish-subscribe scenario the framework provides the Broker component. The broker receives messages and sends them to subscribers.

We also must ensure that Silverlight eneter messaging is properly connected with Asp.Net Server eneter messaging. To do so the server uses the Bridge component. (The bridge ensures the messages received as Http requests via 'Generic Handler' (ashx file) are correctly forwarded to the eneter messaging on the server site.)

using System;
using System.Timers;
using Eneter.Messaging.DataProcessing.Serializing;
using Eneter.Messaging.MessagingSystems.MessagingSystemBase;
using Eneter.Messaging.MessagingSystems.SynchronousMessagingSystem;
using Eneter.Messaging.Nodes.Bridge;
using Eneter.Messaging.Nodes.Broker;


namespace SilverlightNotifiedFromAsp.Web
{
    public class Global : System.Web.HttpApplication
    {

        protected void Application_Start(object sender, EventArgs e)
        {
            // MessagingSystem that will be used by the Silverlight-ASP messaging "bridge".
            //myServerMessagingSystem = new ThreadMessagingSystemFactory();
            myServerMessagingSystem = new SynchronousMessagingSystemFactory();

            // Create the duplex input channel for the broker.
            // Note: The broker will listen to this channel.
            IDuplexInputChannel aBrokerDuplexInputChannel = myServerMessagingSystem.CreateDuplexInputChannel("BrokerChannel");

            // Create broker.
            // Because we communicate with Silverlight it must be XmlSerialization.
            IDuplexBrokerFactory aBrokerFactory = new DuplexBrokerFactory(new XmlStringSerializer());
            myBroker = aBrokerFactory.CreateBroker();
            myBroker.AttachDuplexInputChannel(aBrokerDuplexInputChannel);

            // Create the duplex output channel for the client that will send notifications.
            IDuplexOutputChannel aClientDuplexOutputChannel = myServerMessagingSystem.CreateDuplexOutputChannel("BrokerChannel");

            // Create sender of notification messages.
            myBrokerClient = aBrokerFactory.CreateBrokerClient();
            myBrokerClient.AttachDuplexOutputChannel(aClientDuplexOutputChannel);

            // Create bridge to connect Silverligh with Asp
            IBridgeFactory aBridgeFactory = new BridgeFactory();
            myBridge = aBridgeFactory.CreateDuplexBridge(myServerMessagingSystem, "BrokerChannel");

            // Store the bridge to be used from MessagingHandler.ashx.cs
            Application["Bridge"] = myBridge;

            // Start timer generating notification messages.
            myTimer = new Timer(1000);
            myTimer.AutoReset = false;
            myTimer.Elapsed += OnTimerElapsed;
            myTimer.Start();
        }

        protected void Session_Start(object sender, EventArgs e){}

        protected void Application_BeginRequest(object sender, EventArgs e){}

        protected void Application_AuthenticateRequest(object sender, EventArgs e){}

        protected void Application_Error(object sender, EventArgs e){}

        protected void Session_End(object sender, EventArgs e){}

        protected void Application_End(object sender, EventArgs e){}


        // Generate the number and send the message to the broker.
        private void OnTimerElapsed(object sender, ElapsedEventArgs e)
        {
            ++myNumber;

            myBrokerClient.SendMessage("MyMessageType", myNumber);

            myTimer.Start();
        }



        private Timer myTimer;
        private int myNumber = -1;

        private IMessagingSystemFactory myServerMessagingSystem;

        private IDuplexBroker myBroker;
        private IDuplexBrokerClient myBrokerClient;

        private IDuplexBridge myBridge;

    }
}

The following code shows how to implement the generic handler (ashx) to receive messages from Silverlight eneter messaging system. It uses the bridge to forward incoming messages to the messaging system in the server.

using System.Web;
using Eneter.Messaging.Nodes.Bridge;

namespace SilverlightNotifiedFromAsp.Web
{
    // Handles messaging communication with Silverlight clients.
    public class MessagingHandler : IHttpHandler
    {
        public void ProcessRequest(HttpContext context)
        {
            context.Application.Lock();
            
            // Get the bridge to the broker and forward the message to the messaging system
            // connected with the bridge.
            IDuplexBridge aBridge = context.Application["Bridge"] as IDuplexBridge;
            aBridge.ProcessRequestResponse(context.Request.InputStream, context.Response.OutputStream);
            
            context.Application.UnLock();
        }

        public bool IsReusable { get { return false; } }
    }
}



2. Client Site - Silverlight Application
To use the messaging framework functionality you must add Eneter.Messaging.Framework.Silverlight.dll into references. (Full, not limited and for non-commercial usage free version of the framework can be downloaded from www.eneter.net.)

The client subscribes to be notified about generated numbers. The received messages are displayed in UI.

using System.Windows;
using System.Windows.Controls;
using Eneter.Messaging.DataProcessing.Serializing;
using Eneter.Messaging.MessagingSystems.HttpMessagingSystem;
using Eneter.Messaging.MessagingSystems.MessagingSystemBase;
using Eneter.Messaging.Nodes.Broker;

namespace SilverlightNotifiedFromAsp
{
    public partial class MainPage : UserControl
    {
        public MainPage()
        {
            InitializeComponent();

            // Create Http messaging for the specified message handler on the server side.
            myHttpMessagingFactory = new HttpMessagingSystemFactory(1000);
            string aChannelId = ServerUri.GetServerUri("/MessagingHandler.ashx");
            IDuplexOutputChannel aDuplexOutputChannel = myHttpMessagingFactory.CreateDuplexOutputChannel(aChannelId);


            // Create broker client to receive notifications from the server.
            IDuplexBrokerFactory aBrokerFactory = new DuplexBrokerFactory(new XmlStringSerializer());
            myBrokerClient = aBrokerFactory.CreateBrokerClient();
            myBrokerClient.BrokerMessageReceived += OnBrokerMessageReceived;
            myBrokerClient.AttachDuplexOutputChannel(aDuplexOutputChannel);
        }

        // Subscribes the broker receiver to get notifications from the server.
        private void SubscribeBtn_Click(object sender, RoutedEventArgs e)
        {
            string[] aMessageTypes = {"MyMessageType"};
            myBrokerClient.Subscribe(aMessageTypes);
        }


        // Unsubscribes the broker message receiver.
        private void UnsubscribeBtn_Click(object sender, RoutedEventArgs e)
        {
            myBrokerClient.Unsubscribe();
        }


        // Is called when the notification message from the broker is received.
        private void OnBrokerMessageReceived(object sender, BrokerMessageReceivedEventArgs e)
        {
            // Display the message in the listbox.
            MessagesList.Items.Insert(0, e.Message);
        }


        private IMessagingSystemFactory myHttpMessagingFactory;
        private IDuplexBrokerClient myBrokerClient;
    }
}


For the completeness here is the simple UI in Silverlight displaying generated numbers notified from the server.

I hope you found the article useful and you enjoyed the reading. If you would like to get more technical information you can visit http://www.eneter.net/OnlineHelp/EneterMessagingFramework/Index.html.

Your feedback is always welcome.

2 comments:

  1. Gr8 this notification mechanism worked on Windows Phone 7 Native app. :)

    I have a question can we create some client libraries that will work regardless of platform?

    ReplyDelete
  2. Hi Access Denied,
    I am glad, you found the framework useful.

    Yes, you are welcome to develop the libraries.

    If you need a technical support for your development, do not hesitate to ask me.

    ReplyDelete