ASP.NET MVC, ASP.NET Tips: Provide immediate feedback to the browser on Long Running Tasks – using IFrame and web handlers

Download to download the source code please click here


The <iframe> tag defines an inline frame that contains another document and is supported in all major browsers.
Internet Explorer Firefox Opera Google Chrome Safari

The <iframe> can be placed anywhere in the document flow. The iframe properties such as  height and width can be easily modified by CSS and JavaScript. Data can be passed back and forth between the parent container and iframe using Javasrcipt. The document that is displayed inside an iframe can access the main window by the parent keyword. Iframe can have their own source URL that is distinct from the parent page and we are interested on this feature. We first declare an Iframe in the page and keep it hidden. We then point the Iframe to our preferred web handler, during page load iframe initiate a request to the server and the server start the lengthy task, and flushes state change information. The server flushes the response wrapped inside <script> tag to perform DOM manipulation on the parent container – similar technique that we have seen in one of my post earlier. Here are the steps to follow.

  1. Declare Iframe in the page.
  2. Hide the Iframe.
  3. Point the src of the Iframe to the web handler.
  4. Get Iframe to initiate request from the the browser client to the web server when the page loads.
  5. Get the web handler to flush response on task state changes.
  6. Perform DOM manipulation on the parent container.


 Iframe

Here I have declared two javascript functions in the parent page – “updateContent” and “hide”. “UpdateContent” replaces the data on “ReportDiv” element. “Hide” hides the loader image when lengthy task ends. Then down below on the same page I have declared the iframe tag, pointed the src of the iframe to a regular web handler “JsWrappedDataHandler.ashx”, and used the style elements to hide the iframe. Lets look at the web handler and what is cooking there.

jswrappedhandler

This is a regular web handler and you may be wondering why am I sending 256 dummy bytes. This is a workaround to make IE work properly because IE accepts a message from the server after the first 256 bytes.

This technique is handy when we do not know about the message size and we can avoid any unexpected event by sending 256 dummy bytes before sending the - message.

Next thing to look at is the script block - where it invokes the javascript functions that we have defined in the parent container. Example "window.parent.updateContent", "window.parent.hide".

Finally the server flushes the response directly to the browser. The Iframe receives the progressive flushed response chunk/script block and executes the javascript code - which invokes the javascript functions from the parent container and updates the content of of “ReportDiv” element until the task completes.

The end user gets immediate feedback on task state changes and do not need to wait until the entire response download. When the task is complete it invokes the "hide" function to hide the loader image. This is what it looks like.


 iframefeedback

 

Asynchronous web handlers

I discussed a little bit about asynchronous web handlers  in earlier post and I promised that I will talk about it later – so I do so. It is recommended to use asynchronous web handlers for long/ lengthy tasks. An asyncchronous web handler implements IHttpAsyncHanddler – this means it implements two additional methods BeginProcessRequest and EndProcessRequest. The idea here is to spawn custom threads by hand to run the lengthy portion of the task and not block important ASP.NET work threads from the threadpool. I have discussed about why we should spawn an additional thread in great length in this post, and I am not going to go through that again here, I am jumping straight in to the implentation of Asynchronous web handler.

IframeAsyncPage

This page is exactly same as the first one in this post where I declared 2 javascript function in the parent container such as “undateContent” and “hide”. The only difference is the iframe is now pointing to a different web handler and this time an asynchronous handler.

jswrappedAsynchandler

Here this asynchronous web handler implements the IHttpAsyncHandler. The BeginProcessRequest performs all the lengthy bits inside request.BeginProcessRequest method asynchronously and signals when the task is completed. This executes the EndProcessRequest method. The AsycWebHandlerRequest class is a custom hand written class and I paste the code below.

AsyncwebhandlerRequest

Here I spawn custom Threads by hand to invoke the LongTask method. Long task has exact same code as we have seen in the regular web handler ProcessRequest method above, except the last line where it signals that the task is complete by invoking "requestState.CompleteRequest" method. Here the Response.Flush method does all the hard work to notify the connected browser about the task state changes and end user can enjoy immediate feedback from the server. You may be wondering about the AsyncRequestState class. I have used the exact same class during implementation of the Asynchrounous Page and can be found here.

I have indicated earlier that a web handlers is recommended for performance critical web pages. I have done some load tests to compare the result of regular web handler, asynchronous web handler and the asynchronous page that pretty much does the exact same operation. The test result of load tests that I have performed in exact same environment can be found below.

IframeAsync

Fig: Load test of Iframe and asychronous web handler that uses custom thread

IframeRegular

Fig: Load test of Iframe and regular web handler

WebPageAsync

Fig: Load test of asynchronous web page that implements custom thread

You can see that the asynchronous web handler that spawns custom thread is the clear winner. And when you compare Asynchronous page with web handler – we see web handler is superior.

Please note that the different techniques that I have been discussing  in last several posts  is also known as Comet that describe the web application model in which a long-held HTTP request allows a web server to push data to a browser, without the browser expicitly requesting it. However holding a connection open for infinite period has negative impact on browser usability. The problem is the javascript will keep accumulating and the page will have to preserve them in the page itself, resulting in a unbound page size and memory implications – at worst the page becomes totally unresponsive and will crash the browser. These is ok to choose for long task that has a definite end, however we need to be a bit careful when it comes to a “real-time” applications that keeps running for indefinite period. For example an airlines time table,

For a “real-time” application ( i.e. chat application, airline timetable ) a polling / long polling mechanism is more suitable where the server keeps looping for infinite period - produces the latest content and store it in a persistent layer – example a database/file, or in the application memory. The browser polls the latest response periodically, performs DOM manipulation to updates the page – and the user gets to see the latest record. Lets look at the polling techniques in my next post.

Published Tue, Oct 27 2009 5:19 by shahed

Comments

# ASP.NET MVC, ASP.NET Tips: Provide immediate feedback to the browser on Long Running Tasks – using XMLHttpRequest call

Monday, October 26, 2009 1:21 PM by Shahed Khan (MVP C#)

XMLHttpRequest (XHR) is a DOM API that can be used inside a web browser scripting language, such as JavaScript

# ASP.NET MVC, ASP.NET Tips: Provide immediate feedback to the browser on Long Running Tasks – using XMLHttpRequest call

Tuesday, October 27, 2009 12:24 PM by Shahed

XMLHttpRequest (XHR) is a DOM API that can be used inside a web browser scripting language, such as JavaScript

# ASP.NET MVC, ASP.NET Tips: Provide immediate feedback to the browser on Long Running Tasks – using regular web handler

Sunday, November 15, 2009 8:24 AM by Shahed Khan (MVP C#)

As an ASP.NET developer we frequently deal with long running tasks for example: Making long-lasting...

Powered by Community Server (Commercial Edition), by Telligent Systems