Asp.net 当ajax仍在vb.net中加载时,是否可以更新标签对象的文本?

Asp.net 当ajax仍在vb.net中加载时,是否可以更新标签对象的文本?,asp.net,ajax,vb.net,Asp.net,Ajax,Vb.net,基本上,我知道如何跟踪正在循环的函数的进度。该函数由Ajax调用 例如,我有一个更新面板: <form runat="server"> <asp:ScriptManager ID="ScriptManager1" runat="server"> </asp:ScriptManager> <asp:UpdatePanel ID="UpdatePanel1" runat="server" ChildrenAsTriggers="True" UpdateM

基本上,我知道如何跟踪正在循环的函数的进度。该函数由Ajax调用

例如,我有一个更新面板:

<form runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager> 

<asp:UpdatePanel ID="UpdatePanel1" runat="server" ChildrenAsTriggers="True" UpdateMode="Always">

<ContentTemplate> 

<div>
<asp:Label ID="testing" runat="server"></asp:Label>
</div>          

</ContentTemplate> 
<Triggers>

<asp:AsyncPostBackTrigger ControlID="myButton" EventName="Click"/>
</Triggers>
</asp:UpdatePanel>

<div style="display:none;">
<asp:Button ID="myButton" Text="SomeFunction" OnClick="myFunc" runat="server">
/asp:Button>
</div>

...
</form>
理解Response.write不会与ajax混合使用,因此我希望使用label对象更新文本并跟踪函数循环的进度

然而,在ajax调用完全完成之前,文本似乎不会被更新,它只会更改为循环的最后一个数字

我的问题是,当循环函数仍在服务器端运行时,是否有任何方法可以让文本对象保持实时更改


谢谢

是的,这是可能的。但这不是一个简单的解决方案。迪诺·埃斯波西托(Dino Esposito)有很多关于这个话题的好文章:

正在使用ASP.NET AJAX取消服务器任务- 使用信号器构建进度条-


至于我,我在我的一个项目中使用了第一篇文章中描述的方法。

为了其他访问者,我将从另一页复制我的答案:

你不能用.net UpdatePanel来实现这一点,至少我不认为这很容易。尽管您可以通过两个单独的AJAX调用来实现

本例使用JQuery实现AJAX,代码在vb.net中

基本上,您需要做的是第一次调用以开始长流程,然后重复进行第二次调用,使用第二种方法获取长流程的状态

阿贾克斯

这是你对漫长过程的主要呼吁。如果需要,您需要将数据传递给方法。请注意,有一个processName。这应该是一个排序的随机字符串,以确保您只获得此进程的状态。其他用户将使用不同的随机进程名,这样您就不会混淆状态

    var processName = function GenerateProcessName() {

        var str = "";
        var alhpabet = "abcdefghijklmnopqrstuvwxyz";
        for (i = 1; i < 20; i++) {
            str += alhpabet.charAt(Math.floor(Math.random() * alhpabet.length + 1));
        }
        return str;
    }


    function StartMainProcess(){
    $j.ajax({
            type: "POST",
            url: "/MyWebservice.asmx/MyMainWorker",
            data: "{'processName' : '" + processName + "','someOtherData':'fooBar'}",
            contentType: "application/json; charset=utf-8",
            dataType: "json",
            success: function (msg) {
                if (msg.d) {                        
                    // do a final timerPoll - process checker will clear everything else
                    TimerPoll();
                }
            }
        });
        TimerPoll();
     }
最后,GetProgress()函数用于获取进度。我们必须传入与上面使用的相同的processName,以便仅获取此用户调用的进程

function GetProgress() {
        // make the ajax call
        $j.ajax({
            type: "POST",
            url: "/MyWebService.asmx/MyMainWorkerProgress",
            data: "{'processName' : '" + processName + "'}",
            contentType: "application/json; charset=utf-8",
            dataType: "json",
            success: function (msg) {

                // Evaulate result..
                var process = msg.d

                if (process.processComplete) {
                    // destroy the timer to stop polling for progress
                    clearTimeout(timer);

            // Do your final message to the user here.                      

                } else {

                   // show the messages you have to the user.
                   // these will be in msg.d.messages

                    // poll timer for another trip
                    TimerPoll();
                }
        });

    }
现在,在后端,您将有两个与AJAX通信的web方法。您还需要一个共享/静态对象来保存所有进度信息,以及您想要传递回用户的任何内容

在我的例子中,我创建了一个类,该类的属性已填充,并在每次调用MyMainWorkerProcess时传递回来。这看起来有点像这样

    Public Class ProcessData
        Public Property processComplete As Boolean
        Public Property messages As List(Of String) = New List(Of String)
    End Class
我也有一个使用这个类的共享属性,它看起来像。。。(此共享属性能够由多个用户保存多个进程进程-因此是字典。字典的键将是进程名称。所有进程数据都将在ProcessData类中。)

Private Shared processProgress As Dictionary(Of String, ProcessData) = New Dictionary(Of String, ProcessData)
我的主要辅助函数看起来有点像这样。请注意,我们首先要确保没有另一个processProgress使用相同的函数

<WebMethod()> _
<ScriptMethod(ResponseFormat:=ResponseFormat.Json)> _
Public Function MyMainWorker(ByVal processName as string, ByVal SomeOtherData as string) as Boolean

        '' Create progress object - GUI outputs process to user
        '' If the same process name already exists - destroy it
        If (FileMaker.processProgress.ContainsKey(processName)) Then
            FileMaker.processProgress.Remove(processName)
        End If

        '' now create a new process
        dim processD as ProcessData = new ProcessData() with {.processComplete = false}


        '' Start doing your long process.

        '' While it's running and after whatever steps you choose you can add messages into the processData which will be output to the user when they call for the updates
         processD.messages.Add("I just started the process")

         processD.messages.Add("I just did step 1 of 20")

         processD.messages.Add("I just did step 2 of 20 etc etc")

         '' Once done, return true so that the AJAX call to this method knows we're done..
        return true

End Function
_
_
作为布尔值的公共函数MyMainWorker(ByVal processName作为字符串,ByVal SomeOtherData作为字符串)
“”创建进度对象-GUI向用户输出进程
“”如果已存在相同的进程名称-销毁它
如果是(FileMaker.processProgress.ContainsKey(processName)),则
FileMaker.processProgress.Remove(processName)
如果结束
“”现在创建一个新进程
dim processD as ProcessData=new ProcessData(),带{.processComplete=false}
“”开始执行您的长流程。
“”在运行时以及在您选择的任何步骤之后,您都可以将消息添加到processData中,当用户调用更新时,这些消息将输出给用户
processD.messages.Add(“我刚刚启动了流程”)
processD.messages.Add(“我刚刚完成了第1步,共20步”)
processD.messages.Add(“我刚刚做了第2步,共20步等”)
“”完成后,返回true,以便对该方法的AJAX调用知道我们完成了。。
返回真值
端函数
现在只剩下调用progress方法了..所要做的就是返回与我们前面设置的processName相同的dictionary processData

<WebMethod()> _
    <ScriptMethod(ResponseFormat:=ResponseFormat.Json)> _
    Public Function MyMainWorkerProgress(ByVal processName As String) As ProcessData

        Dim serializer As New JavaScriptSerializer()

        If (FileMaker.processProgress.ContainsKey(processName)) Then
            Return processProgress.Item(processName)
        Else
            Return New ProcessData()
        End If

    End Function
_
_
公共函数MyMainWorkerProgress(ByVal processName作为字符串)作为ProcessData
Dim序列化程序作为新的JavaScriptSerializer()
如果是(FileMaker.processProgress.ContainsKey(processName)),则
返回processProgress.Item(processName)
其他的
返回新的ProcessData()
如果结束
端函数

因此,概括地说

  • 创建两个web方法—一个用于执行长过程,另一个用于返回其进度
  • 创建对这些web方法的两个单独调用。第一个是对主辅助进程的调用,第二个是对一个将给出进度的进程的调用,重复xx秒
  • 以您认为合适的方式向用户输出消息
  • 免责声明。。。
    在此之前,我没有提供这么长时间的答案。它可能不符合人们习惯看到的格式。如果这一切看起来有点混乱,很抱歉:)我从正在运行的项目中复制了大部分代码,因此它应该可以工作。。尽管如果有一些拼写错误,请不要向我开枪:)

    我对几乎相同的问题给出了一个冗长的答案,在这里,看一看,看它是否合适:
    <WebMethod()> _
    <ScriptMethod(ResponseFormat:=ResponseFormat.Json)> _
    Public Function MyMainWorker(ByVal processName as string, ByVal SomeOtherData as string) as Boolean
    
            '' Create progress object - GUI outputs process to user
            '' If the same process name already exists - destroy it
            If (FileMaker.processProgress.ContainsKey(processName)) Then
                FileMaker.processProgress.Remove(processName)
            End If
    
            '' now create a new process
            dim processD as ProcessData = new ProcessData() with {.processComplete = false}
    
    
            '' Start doing your long process.
    
            '' While it's running and after whatever steps you choose you can add messages into the processData which will be output to the user when they call for the updates
             processD.messages.Add("I just started the process")
    
             processD.messages.Add("I just did step 1 of 20")
    
             processD.messages.Add("I just did step 2 of 20 etc etc")
    
             '' Once done, return true so that the AJAX call to this method knows we're done..
            return true
    
    End Function
    
    <WebMethod()> _
        <ScriptMethod(ResponseFormat:=ResponseFormat.Json)> _
        Public Function MyMainWorkerProgress(ByVal processName As String) As ProcessData
    
            Dim serializer As New JavaScriptSerializer()
    
            If (FileMaker.processProgress.ContainsKey(processName)) Then
                Return processProgress.Item(processName)
            Else
                Return New ProcessData()
            End If
    
        End Function