简体   繁体   English

在异步操作期间通过jQuery ajax更新ASP.net进度栏

[英]ASP.net progress bar updated via jQuery ajax during async operation

I'm trying to set up a simple html progress bar for a long-running async task. 我正在尝试为长时间运行的异步任务设置一个简单的html进度栏。 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. 问题是我试图触发回发以运行一些服务器代码并同时执行客户端单击事件以启动ajax轮询,这导致ajax调用中返回错误。 Here's my jQuery and html code: 这是我的jQuery和html代码:

<%@ 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. 当单击按钮时,回发明显干扰了ajax调用。 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. 如果我在javascript clickhandler中添加了preventDefault,则回发将永远不会触发(duh),但所有ajax调用都可以正常工作,因此至少所有ajax代码都可以正常工作。 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? 有没有一种方法既可以使按钮回发,也可以使服务器代码运行,又可以进行客户端单击事件,从而可以启动ajax调用? 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? 我想我搞砸了,我需要做所有这些而没有asp回发,因为那之后页面被销毁并重新加载了,对吗?

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. 我试着将所有这些都转移到服务上,以为我会避免所有回发,而只是对服务进行ajax调用以完成异步工作,并轮询服务是否已完成百分比,但是服务没有实现页面异步,因此没有“ RegisterAsyncTask” ()”来调用,就像在.aspx页上一样。

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. 我还尝试使用会话状态在异步任务和ajax调用之间传达完成百分比的值,我不知道它是否会起作用,但我认为我应该进行试验。 If it fails I need some way to communicate the percent between the background task and the ajax call. 如果失败,我需要某种方式在后台任务和ajax调用之间进行通信。

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. 我已经阅读了很多有关如何进行异步Web服务以及如何在Web服务生成的代理中使用Beginxxx调用等内容的文章,但我也发现很多人在尝试做与我类似的事情,进行简单的Ajax调用。通过jQuery,并且没有运气,也没有给出我能找到的真实答案。

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? 因此,如何从.aspx页面开始使用页面异步或服务来启动长时间运行的任务,并在任务运行时更新简单的html5进度栏? Seems like that would be simple, but no :\\ 似乎很简单,但没有:\\

You are missing just one basic point. 您仅缺少一个基本要点。 Your ajax calls will not survive a postback. 您的ajax调用将不会在回发后继续存在。

You cannot call PROGRESS.startProgress() on button click, cause you want the page to post back immediately after that. 您不能在单击按钮时调用PROGRESS.startProgress() ,因为您希望页面在此之后立即回发。 A postback would cause your ajax call to be terminated. 回发将导致您的ajax调用被终止。

If you want to show a progress bar, you must upload the file too using ajax and not by using a postback. 如果要显示进度条,则必须也使用ajax而不是回发来上载文件。 There are plugins like uploadify that can help. 有类似uploadify的插件可以提供帮助。

After much pain and suffering I have completely rewritten my solution to use SignalR, which vastly simplifies all the code required. 经过千辛万苦,我完全重写了使用SignalR的解决方案,从而极大地简化了所需的所有代码。 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. 有关使用Web Forms网站中的SignalR轻松完成长时间运行任务的简单HTML5进度栏的简便方法的详细信息, 请参阅我关于该主题的博客文章 ,其中包括可下载的极简示例和在线工作演示。 I hope someone finds that helpful. 我希望有人觉得有帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM