Introduction
This article addresses the dreaded "Page Cannot be Displayed" message, and explains how to use HTML frames and JavaScript to catch web server failures and automatically reconnect when the server comes back on line. It's best suited for intranet applications that auto-refresh themselves and don't necessarily have users working at them all the time (like a manufacturing facility).
Background
I write intranet applications that run on screens throughout the company and display up-to-date statistics. Most of the time, there is not a user standing at the screen clicking a "refresh" button; the pages automatically refresh themselves using JavaScript. This works great until the web server goes down either for scheduled downtime or for a failure. This results in a "Page Cannot be Displayed" message and the page no longer tries to refresh itself. In the past, this meant going to each computer and reloading the web page--a simple task, but not when you have hundreds of them!
Using the code
This technique requires two HTML files that handle the error trapping and recovery. The demo VB.NET project includes these files along with Home.aspx as an example auto-refreshing application. The architecture of the setup uses an HTML FRAMESET
as diagrammed below:
The client uses the URL http://MyServer/MainFrame.html, which contains the FRAMESET
, which contains two FRAME
s: Monitor.html and Home.aspx. The frames are setup so that Monitor.html is initially hidden and Home.aspx takes up the entire client area:
<FRAMESET id="FrameSet"
rows="0,*"
frameborder="0"
border="0">
<FRAME SRC="Monitor.html">
<FRAME SRC="Home.aspx">
</FRAMESET>
The main application takes care of refreshing itself. The magic is in the Monitor.html page, which checks the innerHTML
of the other frame (Home.aspx) looking for tale-tell signs of an error. It does simple string matching to look for things like "HTTP 404" or "The page might be temporarily unavailable". It is up to the developer to come up with the necessary criteria.
function frameHasError() {
try {
var frameDoc= window.parent.frames(1).document;
HTML= frameDoc.body.innerHTML;
if (findText(HTML,"HTTP 404")) return true;
if (findText(HTML,"The page might be temporarily unavailable."))
return true;
if (findText(HTML,"Cannot find server or DNS Error"))
return true;
lastURL= window.parent.frames(1).location.href;
}
catch(e) {
return true;
}
return false;
}
Once this function detects an error, it takes over by resizing the FRAMESET
so that it now takes up the entire screen with a user-friendly message explaining that the server is not available. It then goes into a refresh loop (in this case, every 5 seconds) refreshing the application page (Home.aspx) and checking for errors. If none are found, the server must be back up. It resets the parent FRAMESET
back to its original state (with Monitor.html hidden).
function checkStatus() {
try {
if (frameHasError()) {
setFrameSize("100%");
reloadFrame();
}
else {
setFrameSize("0");
}
}
catch(e) {
setFrameSize("0");
}
window.setTimeout("checkStatus()",5000);
}
function setFrameSize(size) {
var frameset=window.parent.document.getElementById("FrameSet");
if (frameset) {
frameset.rows=size + ",*";
}
}
An additional recovery method (not covered here) is to have a .NET <customErrors>
redirect page setup in the web.config that points to an HTML page that contains similar logic. This way, you not only catch server failures but unhandled exceptions as well.
Points of Interest
You can alter the refresh times and monitor times by editing the JavaScript in Monitor.html. This technique can be heavy on the network, that's why I only suggest it for intranet applications that need to auto-refresh and recover from server failures.