ExtJS and ASP.NET part 4 -Generic Progress Bar Control

Very often that server is asked to do a long running procedure, it poses a challenge to both scenarios as ASP.Net post back and even ajax call . It is possible that the synchronous call to server timed out the postback, to an ajax request, the call back is also possible timedout if it is not made in a short period of time.

The solution will be to run this long run process in a separate thread, this is only half of a decent solution, the other half will be to keep user updated namely with a progress bar like this.

Progress Bar

Progress Bar


I developed a generic progress bar control that can be used with any long running process either it be a time consuming calculation or file downloading, this control will make wcf calls to your ASP.Net server to get the progress of a task. When you use this control, you just need to implement that progress notifying server method, normally you create a table in database or in session, store all the long running progress in there.

Not long ago I also blogged about javascript object programming, this can also be treated as a javascript class example made in ExtJS, you can find some examples from internet about how to extend ExtJS controls, but hardly can you find an example of how to build an extensible ExtJS control from scratch.

1. Create a javascript file : extjs-sms-cometservice.js

2. Add these two files to this file to enable the extjs javascript intellisense in vs :

///<reference path="../ext-3.1.1/adapter/ext/ext-base-debug.js">
/// <reference path="../ext-3.1.1/ext-all-debug.js">

There is a trick here, some time it is vary hard to figure out the path part of ‘path’ attribute, the simplest way to do this is just drag your js file and drop it at the top of this file

3. Create a name space:
Ext.namespace(‘Ext.SMS’);

4. Constructor of the our class

Ext.SMS.Comet = function(config) {

    // create properties, and set default values
    this.taskName = "";
  
    // to accept values when constructed
    Ext.apply(this, config);

    // private
    task = null;
    runner = new Ext.util.TaskRunner();
    // display the message box
    // create the progress bar
    progressbar = Ext.MessageBox.show({
        title: 'Please wait',
        msg: 'Loading target file.',
        progressText: 'Initializing...',
        width: 300,
        progress: true,
        closable: false,
        animEl: 'Button1'
    });
        
};

A couple of points:

4.1. This will accept ‘taskname’ as the parameter to differentiate from other tasks, as you will see I am using asp.net compatible wcf service, so no need to pass in the session id, with taskname as a parameter, practically same user can ask progress on different long running tasks

4.2. Do we need to make superclass.constructor.call(this) ?
If this is class that is not inheriting from any other classes, do not make superclass call, there will be an exception, because it does not have a super class, if it has a super class, this call will trigger the constructor of superclass, is it necessary? it is, because Ext.extend does not call super class constructor as a default, it is a programming decision left up to you.

4.3. Protected members : task, runner, and progress bar
Please be aware of how to make members protected.
The runner will be used to run progress fetching call every 1 second, and progress bar is just using Ext.MessageBox which has a progress mode, there is also a control of progressbar in Ext, I guess the only difference between these two is MessageBox is a modal window.

5. The only public method for this class run()

Ext.SMS.Comet.prototype.run = function () {
    // Start a simple clock task that updates a div once per second
    task = {
        started: false,
        run: function () {
            Ext.Ajax.request({
                url: "Service2.svc/Update",
                method: 'GET',
                success: function (response, options) {
                    var currentprogress = (Ext.decode(response.responseText)).d;

                    if (currentprogress.percentage >= 100) {
                        if (task.started) {
                            // finished
                            runner.stop(task);
                            progressbar.hide();
                            // to tell responses of calls that are made after reading 100% : stop, ignore,
                            task.started = false;
                            // display error message
                            Ext.MessageBox.alert("OK", "Finished");
                        }
                        else {
                        // ignore the ajax response 
                        }
                    }
                    else {
                        progressbar.updateProgress(currentprogress.percentage / 100, currentprogress.message);
                        if (!task.started) {
                            task.started = true;
                        }
                    }

                },
                failure: function (response, options) {
                    // some thing wrong, kill the task
                    runner.stop(task);
                    // kill the progress bar
                    progressbar.hide();

                    task.started = false;

                    // display error message
                    Ext.MessageBox.alert("Error", "Unable to get");

                },
                params: { taskname: arguments[0] }

            });

        },
        interval: 1000 //1 second
    }


    //set parameter
    task.args = [this.taskName];
    runner.start(task);

}


So you can see the progress update comes from a wcf call to ‘Service2.svc/Update’

6. The server update implementation as an example only.

[OperationContract]
    [WebInvoke(Method = "GET", BodyStyle = WebMessageBodyStyle.WrappedRequest, ResponseFormat = WebMessageFormat.Json)]
    public ProgressOb Update(string taskname)
    {
        ProgressOb defaultp = new ProgressOb();

        int currentposition; 
       
        if (HttpContext.Current.Session[taskname] == null)
        {
            HttpContext.Current.Session[taskname] = 0; 
            
        }

        currentposition = (int)HttpContext.Current.Session[taskname];

      //  if (currentposition < 100)
      //  {
            currentposition = currentposition + 10;
            Thread.Sleep(2000);
      //  }
        
 
        HttpContext.Current.Session[taskname] = currentposition;

        defaultp.message = "Processing the request:"+currentposition.ToString()+"% finished"  ;
        defaultp.percentage = currentposition;


        return defaultp;
    }

Have fun.

Tags: ,

This entry was posted on Monday, August 9th, 2010 at 1:38 am and is filed under ASP.NET, Javascript. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.

One Response to “ExtJS and ASP.NET part 4 -Generic Progress Bar Control”

  1. ExtJS and ASP.NET part 4 -Generic Progress Bar Control…

    Very often that server is asked to do a long running procedure, it poses a challenge to both scenarios as ASP.Net post back and even ajax call . It is possible that the synchronous call to server timed out the postback, to an ajax request, the call bac…

Leave a Reply

*