This is the scenario : we have a Silverlight application (SL app) which run is running unattended on a big screen in an office. It displays the actual positions of objects on a map. Once every 10 minutes the app queries the hosting web server for position information. The information is not public, it is using asp.net forms authentication to guard it against unauthorized eyes.
To get this to work as intended required some special attention. In this post I will give an overview. The site is using ajax. Also Silverlight is doing a lot of async communication. The combination of async (partial) postback and forms authentication has some quircks on itself, I wrote a little post on that short ago. But as said, there are more quircks.
The user sessions are running a long long time. The risk is that within a session IIS will recycle the underlying web application. When that happens the session state will be lost because, by default, session state is stored inproc. The first step is to store the sesssion state in sql server. This will keep the session information alive when the application is recycled. Setting up sql server is no big deal, this is a good overview. The thing to watch is that now everything you store in the session has to be explicitly serializable. Which usually boils down to setting the serializable attribute and adding default constructors.
A Silverlight application gets it’s data from a service. Our basic service queries a repository to get specific data.
This service is published in a WCF service. A SL app can easily communicate over WCF with a service which is hosted in the same web application as the SL-app itself is running in. It should be possible to host the service somewhere else but that will introduce a large amount of security settings you will have to solve.
In VS there is a template for such a service.
The result is pretty straightforward
As the service is embedded in the website it is guarded by forms authentication. That’s as intended, we don’t want unauthorized people or software to consume our service. But that will hit back, as we will see later.
The Silverlight Application
The application itself is built around Deep Earth. This is an open source project which combines the power of Silverlight with that of a geo image servers like virtual Earth, Yahoo maps, Open Street Maps and many others.
The xaml markup wraps up a deepearth map
A SL-app is living in the browser. The code behind does the registration.
The constructor also initializes a basic geometrylayer. That’s an aerial view of the world, to our app it’s just a background. A background you can zoom into in great detail. Check the deepearth site for more on that.
This method needs the WCF service to get the data.
Consuming the WCF service in Silverlight
The first step is to add a service reference. For this to work you have to disable the forms authentication, else VS cannot get to the service to generate a proxy. The generated proxy, KaartServiceClient, can only be invoked asynchronous.
To encapsulate the specific initialization and async coding aspects of the the proxy I have created a helper class
It wraps the proxy svc. In the constructor the proper address of the service is assembled. As the service is hosted by the same application as the Silverlight app I can use Application.Current.Host.Source to get the right uri.
The GetKaarten method is doing the work. It is passed the parameters to the service and also passes kaarten a callback method to catch the result of the service invocation. The service is explicitly opened, also this has to be done async. OpenCompleted will start the real work by firing KaarternAsync. When that completes the callback method will update the map with the fresh data.
The Silverlight app on a web page
A silverlight application can be used in several styles of web apps. A classical asp.net works well, an MVC app works even better. The latter is easier because the views in MVC are really client side views, the same enviroment the SL-app is living in. Classical Asp.net is more focused on server side code.
It will look like this in an MVC view. The SL- app is between the <object> tags and has id Wereld. The button’s onclick event fires the SL method.
This script is living on a classical asp.net page. Notice the ugly long id you need to get to the SL-app. I have moved all var’s out of the method to the page. Over time this code will build quite a call stack, not need for “invocation specific instance data”.
What’s wrong with this code ?
At first sight this code looks alright. But nevertheless it will hit an exception after a certain amount of time. Usually a quite cryptic Silverlight error. It took some puzzling to find out what went wrong.
The application stays on one and the same page. The script on the page hits the embedded service once every 10 minutes. The service is protected by forms authentication. On every roundtrip the authentication cookie is checked. But what does not happen is updating the timeout of forms authentication. When the user hits code behind a web page the session timeout of forms-authentication is reset. When the user’s page hits the embedded service this time-out is not reset. I’m not sure whether this is a bug or a feature but it is by no means the behavior you would expect.
To prevent the service from timing out the script has to hit some server side code behind the page. As a target I add a dummy webmethod to the page
A webmethod, part of ASP.net ajax, can be called directly from script.
In the loop the hartbeat tickles the server to notify the page is still alive. After which the SL-app can start firing its WCF requests.
I am not checking on exceptions here. In case the session has timed out issuing a HartBeat will redirect the user to the login page. As intended.
And now the app works as intended. Looking back it was a great experience combining all these new api’s. Communication between them works pretty good. Once you know how The bad guy was imho forms authentication. Which dates from a time when there was no such thing as partial or async postback. In a previous post I talked about the problems it has with ajax. Silverlight, another async poster, apparently has its own problems.