【问题标题】:ASP.net progress bar updated via jQuery ajax during async operation在异步操作期间通过 jQuery ajax 更新 ASP.net 进度条
【发布时间】:2012-10-14 20:29:11
【问题描述】:

我正在尝试为长时间运行的异步任务设置一个简单的 html 进度条。问题是我试图触发回发以运行一些服务器代码并同时执行客户端单击事件以启动 ajax 轮询,这导致 ajax 调用中返回错误。这是我的 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>

这是我的代码隐藏:

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;
    }
}

显然,单击按钮时的回发会干扰 ajax 调用。如果我在 javascript clickhandler 中添加了 preventDefault,则回发永远不会触发(duh),但所有 ajax 调用都可以正常工作,因此至少所有 ajax 代码都可以正常工作。有没有办法让一个按钮既回发,所以我的服务器代码可以运行,并执行客户端点击事件,以便我可以启动 ajax 调用?我想我在这里搞砸了,我需要在没有asp回发的情况下完成这一切,因为那时页面被破坏并重新加载,对吧?

我确定我做错了。我尝试将所有这些转移到服务中,我认为我会避免所有回发,只需对服务进行 ajax 调用以完成异步工作并轮询服务以获取完成百分比,但服务没有实现页面异步,因此没有“RegisterAsyncTask ()" 像在 .aspx 页面上一样调用。

我还尝试使用会话状态来传达异步任务和 ajax 调用之间完成的百分比值,我不知道它是否会起作用,但我想我会尝试一下。如果失败,我需要某种方式来传达后台任务和 ajax 调用之间的百分比。

我已经阅读了很多关于如何在 web 服务生成的代理中进行异步 web 服务和使用 Beginxxx 调用等的文章,但我也发现很多人试图做与我类似的事情,使通过 jQuery 进行简单的 ajax 调用,没有运气,也没有我能找到的真正答案。

那么,如何从 .aspx 页面开始使用页面异步或服务启动长时间运行的任务,并在任务运行时更新简单的 html5 进度条?看起来这很简单,但没有:\

【问题讨论】:

    标签: jquery asp.net ajax asynchronous progress-bar


    【解决方案1】:

    你只漏掉了一个基本点。您的 ajax 调用将无法在回发后继续存在。

    您不能在单击按钮时调用PROGRESS.startProgress(),因为您希望页面在此之后立即回发。回发会导致您的 ajax 调用被终止。

    如果您想显示进度条,您也必须使用 ajax 上传文件,而不是使用回发。有像uploadify 这样的插件可以提供帮助。

    【讨论】:

    • 我搞定了。这是事件的基本顺序。我坚持使用 asp.net 上传控件来获取文件。在上传按钮处理程序中,我启动异步导入任务,然后设置一个隐藏字段以向我的 javascript 发出信号以开始轮询。异步任务将整个文件吸入 MemoryStream(我没有上传大文件)然后开始处理。当它工作时,它会在会话数据中获取、更新和存储完成的百分比。在我的 javascript 中,如果设置了该隐藏字段,它会开始通过 ajax 轮询我的 .aspx 文件中的 WebMethod,以从 Session 中获取当前完成的百分比。
    【解决方案2】:

    在经历了许多痛苦和磨难之后,我完全重写了使用 SignalR 的解决方案,这极大地简化了所需的所有代码。有关在 Web 表单网站中使用 SignalR 为长时间运行的任务执行简单的 HTML5 进度条的简单方法的更多详细信息,see my blog post 主题,其中包括可下载的极简主义示例和工作在线演示。我希望有人觉得这很有帮助。

    【讨论】:

      猜你喜欢
      • 2012-12-08
      • 2023-02-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多