Leon's Weblog

September 28, 2013

Splash Screen for ASP.NET Site

Filed under: Software Dev — Leon @ 10:09 am

Loading ASP.NET can be used to create powerful and efficient web applications; however, there are times when users will experience a lag during the initial connection to the site. Even though subsequent page requests during the user’s session will be much faster, that initial lag will create a perception of sluggishness. This issue is due to ASP.NET dynamically compiling the site and loading it into the cache of the IIS application pool. The actual duration of the lag depends on many factors including the complexity of the site and the IIS configuration. There are many discussions online about ways to address this perceived problem which include 1) Precompilation prior to deployment 2) configuring IIS to hold on to the cache of compiled web applications longer and 3) using site warmup scripts. In this post, I will describe another option: the use of a site splash screen.

Precompilation is probably the most effective way to address this problem (that is if you are willing and able to go through the deployment configuration). Disabling the IIS application pool cache timeout may seem like a quick fix but it can lead to site stability problems (i.e. bad idea). The warmup script idea is actually a fairly simple and effective solution (particularly for sites with low traffic). Just make a simple script that requests a page from the site and use Windows Task Scheduler to run that script periodically during the day. However, there are times when this is still not enough (e.g. large sites with frequent changes to application logic). In this case, instead of increasing the frequency of the warmup script schedule (which would create unnecessary site traffic), I use a splash screen to let users know the site is loading. Using both warmup scripts and a splash screen may seem like a “belt with suspenders” type of solution but I think it actually fits in nicely into most ASP.NET site designs. As long as the splash screen does not appear unnecessarily (i.e. when the site is immediately available), it doesn’t hurt to put one in.

The design of the splash screen relies on the same technique used in the “pre-broadband days” to cache images on a site in order to speed up loading times. That is, we can use JavaScript to create an image object; however, instead of caching it we set it’s source to a dynamically generated image file on the site. When the site is ready (i.e. the image file is generated), the client browser will fire the JavaScript image object’s onload event and the user is redirected to the site’s home page.

Markup for a sample splash screen is provided below. The file is saved as index.html so that the web server loads it by default before any other page (this configuration may vary on different servers so adjust it accordingly). Of course if the user bookmarks another page inside the site this splash screen will be bypassed (I am going to dodge that issue). The logic is self-explanatory but there are a few items to note. In most cases, the user will never see the splash screen because the re-direction will happen instantly. On rare occasions (e.g. a user with a slow PC, network lag, or high server load), the user may see a flicker. To avoid this, a 100ms delay was put in before the user sees the loading message. Using setTimeout also gives us an opportunity to reset the loading animated gif to get around an Internet Explorer bug which stops the animation.

<head>
    <title>System</title>
    <script type="text/javascript">
        //redirect to homepage once it is up
        function imageLoaded() {
            window.location = "Default.aspx";
        }

        function imageError() {
            alert("Site is down. Please try again later.");
        }

        function showLoadingMessage() {
            document.getElementById('LoadingImage').src = "Images/loading.gif";
            document.getElementById('Message').style.display = "block";
        }

        setTimeout(showLoadingMessage, 100);

        var img = new Image();
        img.onload = imageLoaded;
        img.onerror = imageError;
        img.src = 'Pulse.ashx';
    </script>
    <style type="text/css">
        .Background { background-color:Silver; }
        .Message { background-color:#F5F5F5; border-width:3px; border-style:solid; border-color:Gray; 
                   padding:20px 10px 20px 10px; width:420px; height: 130px; text-align:center; vertical-align: bottom; 
                   position: absolute; z-index:15; top: 50%; left: 50%; margin:-210px 0 0 -210px;
                   font-size: 1.7em; color: #191970; font-family: Arial; display:none }
    </style>
</head>
<body class="Background">
    <div id="Message" class="Message">
        Please wait while the site loads...<br />
        <img id="LoadingImage" src="Images/loading.gif" alt="Loading" />
    </div>
</body>
</html>

Now all that is left to do is use ASP.NET to generate a dynamic image (that’s the Pulse.ashx file referenced in the markup above). An HTTP Handler is best suited for this task because it avoids the overhead of a full .aspx page. We don’t want to create anything overly complicated or resource intensive so a 1 pixel image will suffice.

Imports System.Web
Imports System.Drawing

Public Class Pulse
    Implements IHttpHandler

    Public Sub ProcessRequest(ByVal context As System.Web.HttpContext) Implements IHttpHandler.ProcessRequest
	' validate parameters
	If context Is Nothing Then Exit Sub

	' create canvas
	Dim objBmp As New Bitmap(1, 1)
	Dim objGraphics As Graphics = Graphics.FromImage(objBmp)
	objGraphics.Clear(Color.Red)

	' create the picture and output to client
	objGraphics.Flush()
	context.Response.ContentType = "image/jpeg"

	objBmp.Save(context.Response.OutputStream, Imaging.ImageFormat.Jpeg)
	context.Response.Flush()

	' clean up
	objBmp.Dispose()
	objGraphics.Dispose()
    End Sub

    Public ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable
	Get
	    Return False
	End Get
    End Property
End Class

Code
The sample code files are provided below:
Pulse.ashx
Index.html

No Comments »

No comments yet.

RSS feed for comments on this post. TrackBack URI

Leave a comment