4

I'm trying to set up a simple html progress bar for a long-running async task. The problem is that I'm trying to fire off a postback to run some server code and do a client click event at the same time to start the ajax polling, which is causing an error return in the ajax call. Here's my jQuery and html code:

<%@ Page Language="C#" AsyncTimeout="230" CodeFile="test.aspx.cs" Inherits="test" %>

<head>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
    <script>
        "use strict";
        var PROGRESS;
        $(document).ready(function () {
            $.ajaxSetup({
                type: "POST",
                contentType: "application/json",
                data: '{}',
                timeout: 10000,
                converters: {
                    "text json": function (data) {
                        var msg;
                        msg = $.parseJSON(data);
                        return msg.hasOwnProperty('d') ? msg.d : msg;
                    }
                }
            });
            PROGRESS = {
                done: false,
                startProgress: function () {
                    var _progress = this;
                    $.ajax({
                        url: 'test.aspx/getProgress',
                        timeout: 20000,
                        data: '{}',
                        dataType: "json",
                        success: function (data) {
                            var currProgress = data * 100;
                            $("#prog").value = currProgress;
                            if (currProgress > 99)
                                _progress.done = true;
                            else
                                setTimeout("PROGRESS.startProgress()", 5000);
                        },
                        error: function (jqXHR, textStatus, errorThrown) {
                            var s = textStatus == null ? "" : textStatus;
                            s += errorThrown == null ? "" : ", " + errorThrown;
                            alert(s);
                        }
                    });
                }
            };
            $("#body_DoUploadButton").on("click", function (event) {
                //event.preventDefault();
                PROGRESS.startProgress();
            });
        });
    </script>
</head>
<body>
    <asp:Button ID="DoUploadButton" Text="Import file" OnClick="UploadButton_Click" runat="server"></asp:Button>
    <progress id="prog" value="0" max="100"></progress>
</body>

Here is my codebehind:

public partial class test : System.Web.UI.Page
{
    delegate void AsyncTaskDelegate();
    AsyncTaskDelegate _dlgt;

    IAsyncResult OnBegin(object sender, EventArgs e, AsyncCallback cb, object extraData)
    {
        _dlgt = new AsyncTaskDelegate(DoImport);
        IAsyncResult result = _dlgt.BeginInvoke(cb, extraData);
        return result;
    }

    void OnEnd(IAsyncResult ar)
    {
        _dlgt.EndInvoke(ar);
    }

    void OnTimeout(IAsyncResult ar)
    {
        //do something
    }

    [WebMethod(EnableSession = true)]
    public static double getProgress()
    {
        if (HttpContext.Current.Session["pctDone"] == null)
            return 0.0;
        return (double)HttpContext.Current.Session["pctDone"];
    }

    protected void DoImport()
    {
        int i = 10;
        while (i-- > 0)
        {
            System.Threading.Thread.Sleep(5000); //fake some work
            Session["pctDone"] = i / 10.0;
        }
        Session["pctDone"] = 1.0;
    }

    protected void UploadButton_Click(object sender, EventArgs e)
    {
        Session["pctDone"] = 0.0;
        PageAsyncTask task = new PageAsyncTask(new BeginEventHandler(OnBegin), new EndEventHandler(OnEnd),
            new EndEventHandler(OnTimeout), null);
        RegisterAsyncTask(task);
        ExecuteRegisteredAsyncTasks();
    }

    protected void Page_Init(object sender, EventArgs e)
    {
        Server.ScriptTimeout = 240;
    }
}

Apparnetly the postback when clicking the button is interfering with the ajax call. If I add a preventDefault in the javascript clickhandler, the postback never fires (duh) but all the ajax calls work, so at least all the ajax code is working ok. Is there a way to have a button both postback, so my server code can run, and do a client click event so I can start the ajax calls? I think I'm screwed here, I need to do this all with no asp postbacks, since then the page is destroyed and reloaded, right?

I'm sure I'm going about this all wrong. I tried moving all this to a service thinking I'll avoid all postbacks and just make ajax calls to a service to do the async work and also poll the service for percent done, but services don't implement page async so there's no "RegisterAsyncTask()" to call like you can on an .aspx page.

I'm also trying to use the session state to communicate the value of the percent done between the async task and the ajax call, which I have no idea if it will work, but I thought I'd experiment. If it fails I need some way to communicate the percent between the background task and the ajax call.

I've read a lot on how to do make async webservices and using the Beginxxx calls etc. in the proxy generated by the webservice, but I also found a lot of posts of people trying to do something similar to me, making simple ajax calls via jQuery, and having no luck and no real answers given that I can find.

So from an .aspx page how do I start a long-running task either with page async or a service, and update a simple html5 progress bar as the task runs? Seems like that would be simple, but no :\

2 Answers 2

2

You are missing just one basic point. Your ajax calls will not survive a postback.

You cannot call PROGRESS.startProgress() on button click, cause you want the page to post back immediately after that. A postback would cause your ajax call to be terminated.

If you want to show a progress bar, you must upload the file too using ajax and not by using a postback. There are plugins like uploadify that can help.

Sign up to request clarification or add additional context in comments.

1 Comment

I got it working. Here's the basic sequence of events. I stuck with the asp.net upload control to get the file. In the upload button handler, I fire off the async import task and then set a hidden field to signal to my javascript to start polling. The async task sucks the entire file into a MemoryStream (I'm not uploading big files) then starts processing. While it works it gets, updates, and stores the percent done in the Session data. In my javascript, if that hidden field is set, it starts polling via ajax to a WebMethod in my .aspx file to get the current percent done from the Session.
0

After much pain and suffering I have completely rewritten my solution to use SignalR, which vastly simplifies all the code required. For more details on the easy way to do a simple HTML5 progress bar for a long running task using SignalR in a Web Forms web site, see my blog post on the subject, which includes a downloadable minimalist sample and working online demo. I hope someone finds that helpful.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.