Implementing Waiting Pages in ASP.NET

The users of your application will be more likely to tolerate pauses in your application whilst processing goes on, if you provide a 'waiting' page.

One thing users do not like about Web-applications is waiting for some long-running process to finish without knowing if it is really working or not. There are few greater frustrations than looking at the screen and think “What’s going on?”, while the application performs some undercover operation. That is why application should provide user with feedback, showing that something is happening and, telling the user that he will have to wait just a little bit longer.

If the process is running synchronously you have no options – the user will have to wait while page is reloading anyway. But then an asynchronous process comes to play, you may like to work out various solutions for a better user experience. In this article we will discover a few ways to create a waiting page.

Architecture of the waiting page solution

Before we start to build a waiting pages, we have to decide on architecture of the solution. The easiest to implement solution is shown at Fig. 1.

411-Figure1.gif

Fig. 1.Waiting page architecture

The main page starts a new thread and assigns a unique ID to it, then redirects user to the waiting page, passing ID to the waiting page to enable waiting page to track progress of the process running in a thread which was started by the main page. The process submits results to a special controller object that contains collection of key-value pairs to identify results submitted by threads with different IDs. The waiting page queries the controller to check if the process is still running or has already finished.

Solutions

Now we are set with the architectural decision and are ready to start building waiting page. Let’s go from the easiest solution to the more complex ones.

The simplest solution

The simplest solution to implement is which does not require tracking real progress of asynchronous process, thus showing only two states of the process – still running or already finished.

At first, we should create a controller object that can simply provide the waiting page with the state of the request.

The controller:

The main page should assign the asynchronous process with an unique ID and pass this ID to the waiting page, then waiting page will query SimpleProcessCollection for the result with the given ID. The process, in turn, should add the result to the SimpleProcessCollection to notify waiting page that the process ended.

The main page

The waiting page

You can see that the solution is very simple and required just a dozen lines of code. As we are free to use an animated gif on the waiting page, the user will have fun while waiting for the process to complete. The waiting page discussed is presented at Fig. 2.

411-Figure2.gif 

Fig. 2. The simplest waiting page.

Waiting for more than one process

If there is more than one process running in the background waiting page should wait for, then it is necessary to implement some kind of progress bar control and extend the sample shown above to handle more than one process. To do that, we can implement a simple counter of processes that are still running as shown in the following code snippet.

The controller

This time controller increments the counter then a process is registered and decrements the counter as a process notifies the controller that it is finished. Thus, code for the main page and for the waiting page will be a little bit more complex.

The main page

The waiting page

This time we can make the user experience a little bit better by showing the progress bar indicating the real progress. To do this we implement a simple progress bar control and use it on a modified waiting page.

The progress bar control

The more advanced waiting page

This page looks like the shown one on fig. 3.

411-Figure3.gif

Fig. 3. More advanced waiting page.

Returning custom data objects from the asynchronous processes

The next step on the way to building more advanced waiting page is to modify the controller object to work with custom data objects thus enable asynchronous process to return these custom data objects and provide the waiting page with more data about the state of the process.

For instance, if the process can be split into a few different steps it may notify the waiting page about the percentage of its completeness – this value can be stored in a field of custom data object used.

The custom data object

The controller

To use this features we have to modify the waiting page and the main page.

The main page

The waiting page

Now we are able to get any data as a result from an asynchronous process as well as percentage of the process completeness.

Adding Ajax features

Eventually, to make user experience even greater we can use Ajax features to our waiting page. Thanks to Microsoft Ajax Extensions (http://ajax.asp.net/) we do not need to do much work. We will add ScriptManager control and UpdatePanel controls and modify only the waiting page. (Please note, to use Microsoft Ajax Extensoins for ASP.NET you should add a reference to System.Web.Extenstions assembly and configure web.config file for your application. You may look through the sample application configuration file to get familiar with the configuration.)

The waiting page

As this is all we have to change to use Ajax features at our waiting page. Now only the small part of the page will be updated during the progress control refreshes.

Conclusion

In this paper we saw how to quickly create a waiting page to use in our applications. If you need only to show to user that a process is still running or already finished, the simplest solution will do for you (note that you also can add Ajax features for better user experience!). If your process should return complex data or may be split in discrete parts you may like to use the waiting page with feedback, or if you have to run a few processes you may use the multi-process version of the waiting page.

To understand this stuff better look through the attached source code.