Download Demo Projects
This is one of the projects I have been planning to work on for some time. I was looking into building an event notifier in one of
my ASP.Net application. I wanted it to be more like Outlook Web Access (OWA) new email notifier pop-up. It is the one
that slides up from bottom right corner of your browser when there is a new email in your inbox. I had built it in the past
using all javascript solution. Yes, this Microsoft is one of the earliest implementation of so called AJAX applications.
I did not want to deal with all the javascript code related to setting up HTTP calls and then dealing with response and
rendering the results.
I wanted to leverage Silverlight to do all the heavy lifting. And use light weight javascript implementation on client
to do animated sliding and positioning of the popup notifier box. At the end it turned out be quite an elegant solution
that worked on major browsers like Internet Explorer, FireFox and Chrome. This article is an attempt to describe
How to implement OWA style new email notifier popup using Silverlight and Javascript.
The implementation involved the following technologies and I will describe how each component was implemented
- ASP.Net web application
- ASP.Net web service
- Silverlight application
ASP.Net Web Service
Let's start with discussion of the component that is responsible for communication of data between client and server application.
The client requests data from server at certain frequency to check if there are any new messages. So I implemented as simple
ASP.Net web service application with few web methods. For this demo I had a simple method with following signature.
[WebMethod]
public string GetGlobalMessages()
{
List msgs = MockData.GetGlobalMessages();
return msgs.ToJson();
}
For demo application, I implemented a MockData class that creates a random list of messages and then
serializes that collection as JSON and sends it in response. I implemented ToJson as an
extension method on List<StatusMessage> object. You will find it in Extension.cs
file in ActivityData project.
public static string ToJson(this List<StatusMessage> msgs)
{
var ser = new DataContractJsonSerializer(msgs.GetType());
var ms = new MemoryStream();
ser.WriteObject(ms, msgs);
var serializedData = System.Text.UTF8Encoding.UTF8.GetString(ms.ToArray());
return serializedData;
}
You can see there is nothing fancy about this whole implementation to make it work with a Silverlight client. A very
simple ASP.Net web service.
Silverlight Application
This is where all the action happens. There are few components of this application, rendering and data access. Lets us first
discuss data access. The client application is to talk to server at certain frequency. That means I need some kind of
timer going in the application. When this timer ticks at specified interval of time, it send asynchronous request to server
to get new messages. I have implemented this whole mechanism in MessageMonitor application. When
this class is constructed, it creates an instance of DispatchTimer. You may be asking why DispatchTimer and
why not simple Timer application. The problem is that when you are dealing with user interface application, you
can only update the controls on the thread on which they were dispatched. Regular timer does not executes on that dispatcher
thread. So if you will try to update your user interface on that thread you will get exception complaining about
cross threaded access. Here is the code that created DispatcherTimer for my application.
private void CreateMessagePollTimer()
{
_messagePollTimer = new DispatcherTimer();
_messagePollTimer.Tick += new EventHandler(MessagePollTimer_Tick);
_messagePollTimer.Interval = new TimeSpan(0, 0, MessagePollInterval);
}
When the timer ticks it calls MessagePollTimer_Tick method. And that method makes async request to server
to get new messages.
void MessagePollTimer_Tick(object sender, EventArgs e)
{
if (Stopping || MessagePollInProgress) return;
GetMessages();
}
When async request to server completes, the following method gets called. You can see that now it uses the
same JsonSerializer class to de-serialize the response into list of StatusMessage objects. And
then it raises event for objects that have subscribed to the event.
void GetGlobalMessagesCompleted(object sender,
SiteMessagePanel.ActivityDataServices.GetGlobalMessagesCompletedEventArgs e)
{
if (e.Error != null)
{
return;
}
var msgsData = e.Result as String;
var msgs = msgsData.FromJson();
System.Diagnostics.Debug.WriteLine(msgs);
StatusMessageEventArgs args = new StatusMessageEventArgs(msgs);
OnStatusMessageReceieved(args);
}
Page class that implements user interface for popup, handles this event and renders all the
messages.
void Monitor_StatusMessageReceieved(object sender,
ByteBlocks.ActivityData.StatusMessageEventArgs arg)
{
if (arg.Messages.Count == 0)
{
msgTextBlock.Text = "No messages received";
ShowClientPanel(false);
return;
}
msgTextBlock.Text = string.Empty;
messagesPanel.Children.Clear();
foreach (var msg in arg.Messages)
{
StackPanel sp = new StackPanel();
TextBlock tb = new TextBlock();
tb.Text = msg.Title;
tb.TextWrapping = TextWrapping.Wrap;
sp.Children.Add(tb);
messagesPanel.Children.Add(sp);
}
ShowClientPanel(true);
}
ASP.Net application and javascript
ASP.Net application acts as a host for the silverlight control that I created to render messages. I have
implemented a simple Server Control that hosts it. Then I added that control inside a simple
div on the master page. And I have very simple vanilla implementation of the server control. It does
not have very complicated implementation. I simply copied the code generated by silverlight wizard for test page
into that control
<div id="statusslideup">
<ByteBlocks:StatusPanel runat="server" id="statusPanel" />
</div>
Calling Javascript Method From Silverlight
So far we have implemented two pieces of the application that drive the data and render it. Now comes the
fun part. How are we going to trigger the client to show the popup and animate it to come up from bottom.
First, it is Silverlight application that is running the timer. So it is the one that has to trigger the
client. I implemented some java script code that shows the DIV that hosts silverlight client
component. And then small piece of code that implements animation. Silverlight framework
provides a very simple mechanism to invoke any Javascript method that is implemented on client side.
I implemented a very simple method in silvelight application to call my JS method whenever
there are new messages for the user.
private void ShowClientPanel(bool show)
{
HtmlPage.Window.Invoke("_showStatusPanel", show);
}
It could not be any simpler. And the following Javascript function implements
small piece of code that calculates position of popup notifier window based on browser height and
height of element containing silverlight control.
setStatusPanelPosition = function() {
if (_statusdiv) {
_maxPanelPos = document.body.scrollTop + ($(document).height() - _statusdiv.clientHeight);
_curPanelPos = $(document).height();
if (!_isStatusVisible) {
_sliderInterval = setInterval("_slidePanel()", 5);
}
else {
_statusdiv.style.top = _maxPanelPos + "px";
}
_isStatusVisible = true;
}
}
Demo Project
Attached demo project is a collection of Visual Studio 2010 projects and solution. If you do not have VS2010, you
can simply create a new solution and projects in VS2008 and copy the source files in there. You are also
going to need to download Silverlight 3 Toolkit because I use theming controls from that toolkit to give
some zing to the UI.
I hope this demo project helps you in building cooler implementations of OWA like message and event notifier windows.