如何更新ajax请求中的状态标签 [英] How to update a status label inside ajax request

查看:27
本文介绍了如何更新ajax请求中的状态标签的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这个代码:

<div style="padding: 0px 12px 12px 12px;"><asp:UpdatePanel runat="server" ID="Panel"><内容模板><asp:Button ID="btnGenerate" CssClass="button" Style="float: right" runat="server"Text="Go" OnClick="btnGenerate_Click"/></内容模板></asp:UpdatePanel>

<div><asp:UpdateProgress runat="server" ID="PageUpdateProgress"><进度模板><img src="ajax-loader.gif"/><asp:Label ID="lblStatus" runat="server" Text="Working..." CssClass="label"/></ProgressTemplate></asp:UpdateProgress>

当我单击按钮时,动画 gif 会显示......这很棒,但这个过程需要一分钟多的时间,我想向用户展示(只要代码不复杂)发生了什么.

所以我在图像旁边放了一个标签,当我尝试这样做时,在后面的代码中:

lblStatus.Text = "做 xyz";

它提供了某种命名空间问题.有什么想法可以实现吗?

更新:错误是找不到类型或命名空间‘lblStatus’".

解决方案

你不能用 .net updatepanels 做到这一点,至少我认为这并不容易.尽管您可以通过 2 个单独的 AJAX 调用来实现..

此示例将 JQuery 用于 AJAX,代码隐藏在 vb.net 中.

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

AJAX

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

 var processName = function GenerateProcessName() {var str = "";var alhpabet = "abcdefghijklmnopqrstuvwxyz";对于 (i = 1; i <20; i++) {str += alhpabet.charAt(Math.floor(Math.random() * alhpabet.length + 1));}返回字符串;}函数 StartMainProcess(){$j.ajax({类型:POST",url: "/MyWebservice.asmx/MyMainWorker",数据:"{'processName' :'" + processName + "','someOtherData':'fooBar'}",contentType: "application/json; charset=utf-8",数据类型:json",成功:功能(味精){如果(味精.d){//做最后的 timerPoll - 进程检查器将清除其他所有内容定时器轮询();}}});定时器轮询();}

您的第二个 AJAX 调用将使用另一种方法来获取进度.这将通过计时器方法每 XXX 次调用一次.

这是TimerPoll函数;在这种情况下,它将每 3 秒触发一次

function TimerPoll() {timer = setTimeout("GetProgress()", 3000)}

最后,GetProgress() 函数可以获取进度.我们必须传入与上面使用的相同的processName,才能得到这个用户调用的进程

function GetProgress() {//进行ajax调用$j.ajax({类型:POST",url: "/MyWebService.asmx/MyMainWorkerProgress",数据:"{'processName' :'" + processName + "'}",contentType: "application/json; charset=utf-8",数据类型:json",成功:功能(味精){//评估结果..var 进程 = msg.d如果(process.processComplete){//销毁计时器以停止轮询进度清除超时(定时器);//在此处向用户发送最后一条消息.} 别的 {//向用户显示您拥有的消息.//这些将在 msg.d.messages 中//轮询另一次旅行的计时器定时器轮询();}});}

现在,在后端,您将拥有几个与 AJAX 通信的 Web 方法.您还需要一个共享/静态对象来保存所有进度信息,以及您想传回给用户的任何信息.

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

 公共类 ProcessData公共属性 processComplete As Boolean公共属性消息 As List(Of String) = New List(Of String)结束班

我也有一个使用这个类的共享属性,它看起来像......(这个共享属性能够保存多个用户的多个进程进度 - 因此是字典.字典的键将是进程名称.所有进度数据将在类 ProcessData

Private Shared processProgress As Dictionary(Of String, ProcessData) = New Dictionary(Of String, ProcessData)

我的主要工作函数看起来有点像这样.请注意,我们首先确保没有另一个具有相同

的 processProgress

_<ScriptMethod(ResponseFormat:=ResponseFormat.Json)>_Public Function MyMainWorker(ByVal processName as string, ByVal SomeOtherData as string) as Boolean'' 创建进度对象 - GUI 向用户输出进程'' 如果相同的进程名已经存在 - 销毁它如果 (FileMaker.processProgress.ContainsKey(processName)) 然后FileMaker.processProgress.Remove(processName)万一''现在创建一个新进程将 processD 调暗为 ProcessData = new ProcessData() with {.processComplete = false}''开始做你漫长的过程.'' 在它运行时以及在您选择的任何步骤之后,您都可以将消息添加到 processData 中,这些消息将在用户调用更新时输出给用户processD.messages.Add("我刚刚开始这个过程")processD.messages.Add("我只做了 20 步中的第 1 步")processD.messages.Add("我刚刚做了 20 步中的第 2 步等等")'' 完成后,返回 true 以便对此方法的 AJAX 调用知道我们已完成..返回真结束函数

现在剩下的就是调用progress方法..所有这一切要做的就是返回具有我们之前设置的相同processName的字典processData..

_<ScriptMethod(ResponseFormat:=ResponseFormat.Json)>_公共函数 MyMainWorkerProgress(ByVal processName As String) As ProcessDataDim serializer As New JavaScriptSerializer()如果 (FileMaker.processProgress.ContainsKey(processName)) 然后返回 processProgress.Item(processName)别的返回新的 ProcessData()万一结束函数

瞧..

总结一下..

  1. 创建 2 种网络方法 - 一种用于执行漫长的过程,一种用于返回进度
  2. 创建 2 个对这些网络方法的单独调用.第一个是给主要工作人员,第二个是重复 xx 秒,给一个会提供进度的人
  3. 以您认为合适的方式向用户输出您的消息...

免责声明...我之前很久没有在这里提供答案..它可能不遵循人们习惯看到的格式.对不起,如果这一切看起来有点混乱:) 我已经从一个正在运行的项目中复制了大部分代码,所以它应该可以工作..但如果有一些错别字,请不要向我开枪:)

I have this code :

<div style="padding: 0px 12px 12px 12px;">
    <asp:UpdatePanel runat="server" ID="Panel">
        <ContentTemplate>
            <asp:Button ID="btnGenerate" CssClass="button" Style="float: right" runat="server"
                Text="Go" OnClick="btnGenerate_Click" />
        </ContentTemplate>
    </asp:UpdatePanel>
</div>
<div>
    <asp:UpdateProgress runat="server" ID="PageUpdateProgress">
        <ProgressTemplate>
            <img src="ajax-loader.gif" />
            <asp:Label ID="lblStatus" runat="server" Text="Working..." CssClass="label" />
        </ProgressTemplate>
    </asp:UpdateProgress>
</div>

When I click the button the animated gif shows... which is great, but the process takes over a minute and I would like to show the user (as long as the code is not complex) what is going on.

So I put a label next to the image, and in the code behind when I try and do :

lblStatus.Text = "Doing xyz";

It gives some sort of namespace issue. Any ideas how I can acheive this?

UPDATE : The error is "the type or namespace 'lblStatus' cannot be found".

解决方案

You can't do this with the .net updatepanels, least I don't believe it to be easy. Though you can do it with 2 separate AJAX calls..

This example is using JQuery for the AJAX and the code-behind is in vb.net.

Essentially what you need to do is make your first call to begin the long process, then make a second call, repeatedly, using a second method to get the status of the long one.

AJAX

This is your main call to the long process. If needed, you will need to pass in the data to the method. Notice there is a processName. This should be a random string of sorts to ensure that you get the status of this process only. Other users will have a different random processName so you don't get confused status.

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

Your second AJAX call will be to another method to get the progress. This will be called every XXX time by a timer method.

This is the TimerPoll function; which will fire every 3 seconds in this case

function TimerPoll() {
        timer = setTimeout("GetProgress()", 3000)
    }

And finally, the GetProgress() function to, well, get the progress. We have to pass in the same processName used above, to get the process of this users call only

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

    }

Now, in the back-end, you will have a couple of web methods that your AJAX communicates with. You will also need a shared/static object to hold all of the progress information, along with anything you want to pass back to the user.

In my case, i created a class which has its properties filled and passed back with every call to MyMainWorkerProcess. This looks a little like this.

    Public Class ProcessData
        Public Property processComplete As Boolean
        Public Property messages As List(Of String) = New List(Of String)
    End Class

I also have a shared property using this class, which looks like... ( this shared property is capable of holding multiple process progresses by multiple users - hence the dictionary. the key of the dictionary will be the process name. All progress data will be in the class ProcessData

Private Shared processProgress As Dictionary(Of String, ProcessData) = New Dictionary(Of String, ProcessData)

My main worker function looks a little like this. Notice that we first make sure there isn't another processProgress with the same

<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

now all that is left is to call the progress method..All this is going to do is return the dictionary processData that has the same processName we set up earlier..

<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

And voila..

So to recap..

  1. Create 2 web methods - one to do the long process and one to return it's progress
  2. Create 2 separate calls to these web methods. The first is to the main worker, the second, which is repeated xx seconds, to one that will give the progress
  3. Output your messages to the user however you see fit...

Disclaimer... I haven't provided an answer this long on here before.. It might not follow the format people are used to seeing. Sorry if it all seems a little confusing :) I have copied most of the code from a running project so it should work.. though don't shoot me if there are a few typos :)

这篇关于如何更新ajax请求中的状态标签的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
C#/.NET最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆