I am trying to set up a simple html progress bar for a long-running async task. The problem is that I am trying to disable the postback to run some server code and click and click at the same time to start the ajax polling, which causes an error to be returned in the ajax call. Here is 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) { </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 code:
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; } }
Obviously, postback on button click affects ajax call. If I add preventDefault to the javascript clickhandler, postback never fires (duh), but all ajax calls work, so at least all ajax code works fine. Is there a way for the button to be inverse so that my server code can start and do click-click so that I can make ajax calls? I think I'm screwed here, I need to do all this without asp postbacks, since then the page is destroyed and reloaded, right?
I am sure that all this is wrong. I tried to move all this to the service, thinking that I would avoid all postbacks and just make ajax calls to the service to do asynchronous work, and also poll the service for percentages, but the services do not implement async pages, so there is no "RegisterAsyncTask () "to call as you can on the .aspx page.
I am also trying to use session state to pass the percentage value executed between an asynchronous task and an ajax call, which I have no idea if this will work, but I thought I was experimenting. If this fails, I need to somehow communicate the percentage between the background task and the ajax call.
I read a lot about how to make asynchronous web services and use Beginxxx calls, etc. in the proxy created by the web service, but I also found a lot of messages saying that people are trying to do something similar to me, making simple ajax calls through jQuery and lack of luck and no real answers that I can find.
So, from an .aspx page, how to start a long-term task either with an async page or with a service, and update a simple html5 progress bar as the task starts? It sounds like it would be simple, but no: \