Dan's Green Shoes

Got my green shoes on!

Calling into your database on Silverlight Application_Exit

2 Comments

My team has developed several Line of Business applications using Silverlight.  Most but not all have at least 3 if not all of the following feature requests:

  • Allow users to be signed into the LOB more than once. Users like having more than 1 browser tab or even more than 1 browser type with the LOB app loaded simultaneously.
  • Ability to differentiate between a user in Tab1 versus Tab2 for purposes of concurrency, etc.
  • Limit the number of simultaneous sessions a specific user can have. 1 is a valid constraint.
  • Automatically log out a user instance after X seconds a.k.a session time out
  • Gather user information such as browser type/version, screen resolution, IP, etc
  • # of concurrent distinct users logged in over time.
  • # of concurrent users logged in over time total.
  • Max or average simultaneous sessions by users.

All of these are good feature requests for any Line of Business Application. Thinking through it, these features share an implementation detail that requires the LOB to track each signed in user instance.

Implementation Plan

Here was the plan.

  1. Create a new database table called AppInstance. This table will contain a list of all the active users in the system.
  2. Create a new database table called ArchivedAppInstance. This table contains all previously logged in users.
  3. Whenever a user logs in, add a row to the AppInstance table that records the UserId, timestamp of when that user logged in and any other information your LOB might want to know.
  4. Whenever a user logs out, archive the #3 AppInstance row to ArchivedAppInstance table noting the logged out timestamp.

The information in these 2 new tables enable the implementation of the features above. Conceptually this is very simple. In fact, 1 through 3 above are easy. #4 it turns out, in Silverlight was not as straight forward as one might think. Why? First, there are multiple ways the application can be exited such as clicking the LOB “Log Out” button, closing the browser directly, navigating away from the LOB web page or, heaven forbid, a browser crash. Except for crashing, the Silverlight application’s Exit event is raised but if you try to perform some backend action like calling a web service it won’t go through since the thread required to make the service call itself is gone.

I worked on a team to solve this. My colleague Tammy McClellan recently documented our approach for other product owners internally and I thought I would share on my blog. In addition, Tammy created an extremely small and simple sample application with our implementation. You can find the code here.

Example App Explanation

Running the sample app will show 2 buttons. “Insert AppInstance, Delete using WebService” and “Insert AppInstance, Delete using WCF”. Think of the buttons as logging into your Silverlight LOB application. Clicking a button adds a row to the AppInstance table that records the UserId, timestamp of when that user logged in, screen resolution, IP, browser type etc.

clip_image002

Insert AppInstance, Delete using WCF Button

The sample app uses Entity Framework and creating the AppInstance is pretty standard code. I won’t go into much detail, please see the code as needed. The key here is setting the App.OnExitUseWCF to true.

clip_image004

Insert AppInstance, Delete using WebService button

The key here is setting the App.OnExitUseWCF to false.

Shutting Down the Application

Shutting down the sample application will trigger the Silverlight Application_Exit event shown below.

clip_image006

Depending on which button you used, will determine the technique used to archive the AppInstance. If you use the “Insert AppInstance, Delete using WebService” button, the AppInstance is correctly archived. If you use the “Insert AppInstance, Delete using WCF” button the AppInstance does NOT get archived AND no error is thrown. The call to the WCF service silently killed.

In the “WebService” AppInstance archive process, the key to it working is to send an XMLHttpRequest to call a web service. The reason we use XMLHttpRequest is that it will execute even after the browser is closed since the JavaScript method attached to the body onunload event in the default.aspx will be called when the browser exits.

clip_image008

Please check out the XmlHttpRequest.cs class in the source code.

Valuable Relevant Resources

· http://danielvaughan.orpius.com/post/Calling-Web-Services-from-Silverlight-after-the-Browser-has-closed.aspx

· http://emantranet.com/silverlight/?p=52

· http://social.msdn.microsoft.com/Forums/en-US/silverlightbugs/thread/80fa9324-06ef-4784-80ba-57e701316877/

· http://stackoverflow.com/questions/3660560/how-to-detect-a-browser-refresh-from-silverlight-4

· http://social.msdn.microsoft.com/Forums/en-US/silverlightweb/thread/39818d02-91fe-4bbc-ba9b-6efa142d08b5/

Advertisements

Author: Dan Hickman

Chief Technology Officer ProModel Corporation

2 thoughts on “Calling into your database on Silverlight Application_Exit

  1. I remember discussing these requirements with you guys, but never heard how you guys solved this problem. Good to know!

  2. yeah, had this on my todo list for awhile…just getting around to it now that soccer/bball coaching is slowing down.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s