【问题标题】:ASP.NET MVC ajax chatASP.NET MVC ajax 聊天
【发布时间】:2010-03-21 08:19:08
【问题描述】:

我在我的一个 mvc 网站中建立了一个 ajax 聊天。一切正常。我正在使用轮询。在一定的时间间隔内,我使用 $.post 从数据库中获取消息。但有一个问题。使用 $.post 检索到的消息不断重复。这是我的 javascript 代码和控制器方法。

 var t;        
        function GetMessages() {        
            var LastMsgRec = $("#hdnLastMsgRec").val();
            var RoomId = $("#hdnRoomId").val();
            //Get all the messages associated with this roomId
            $.post("/Chat/GetMessages", { roomId: RoomId, lastRecMsg: LastMsgRec }, function(Data) {
                if (Data.Messages.length != 0) {
                    $("#messagesCont").append(Data.Messages);
                    if (Data.newUser.length != 0)
                        $("#usersUl").append(Data.newUser);
                    $("#messagesCont").attr({ scrollTop: $("#messagesCont").attr("scrollHeight") - $('#messagesCont').height() });
                    $("#userListCont").attr({ scrollTop: $("#userListCont").attr("scrollHeight") - $('#userListCont').height() });
                }
                else {
                }
                $("#hdnLastMsgRec").val(Data.LastMsgRec);
            }, "json");


            t = setTimeout("GetMessages()", 3000);
        }

这是我获取数据的控制器方法:

public JsonResult GetMessages(int roomId,DateTime lastRecMsg)
        {
            StringBuilder messagesSb = new StringBuilder();
            StringBuilder newUserSb = new StringBuilder();            
            List<Message> msgs = (dc.Messages).Where(m => m.RoomID == roomId && m.TimeStamp > lastRecMsg).ToList();
            if (msgs.Count == 0)
            {
                return Json(new { Messages = "", LastMsgRec = System.DateTime.Now.ToString() });
            }            
            foreach (Message item in msgs)
            {
                messagesSb.Append(string.Format(messageTemplate,item.User.Username,item.Text));
                if (item.Text == "Just logged in!")
                    newUserSb.Append(string.Format(newUserTemplate,item.User.Username));
            }            

            return Json(new {Messages = messagesSb.ToString(),LastMsgRec = System.DateTime.Now.ToString(),newUser = newUserSb.ToString().Length == 0 ?"":newUserSb.ToString()});
        }

一切都完美无缺。但是我有些消息被重复了。第一次加载页面时,我正在检索数据并调用 GetMessages() 函数。我在第一次加载页面时加载字段 hdnLastMsgRec 的值,并且在该字段的值由 javascript 设置之后。

我认为由于异步调用,消息会不断重复。我不知道,也许你们能帮我解决这个问题。

或者您可以提出更好的实施方法。

【问题讨论】:

  • 我很好奇您使用的是哪种投票方式。

标签: asp.net-mvc ajax chat


【解决方案1】:

Kaivalya 对缓存的看法是正确的,但我也建议您的设计可以而且应该稍作改动。

我最近做了一个非常相似的应用程序,我发现通过让控制器使用相当标准的 PRG 模式(重定向后获取),我的设计得到了极大的改进。为什么要加强?好吧,因为 POST 方法是为向应用程序添加内容而构建的,所以 GET 方法应该用于获取没有副作用的信息。您的投票应该只是收到没有副作用的新消息。

因此,我建议您的控制器公开一个通过 POST 创建新聊天消息的方法,然后是另一个获取最后 X 个聊天消息的方法,而不是您的 $.post 调用期望数据并处理回调,或者自某个时间戳或其他任何时间以来的消息。

来自 post 操作的 javascript 回调,然后可以更新一些变量(例如,最后一条消息 id、最后一条消息的时间戳,甚至是基于重定向中包含的信息的下一条消息的整个 URL,等等)。

$.post 只会在响应用户输入时触发(例如,输入一个框,点击“发送”)然后,你(单独)有一个来自 jquery 的 $.get 调用,它设置为轮询你说过,所有它所做的就是获取最新的聊天消息,它的回调会用它们更新聊天 UI。

【讨论】:

    【解决方案2】:

    我在这里得到了答案:ASP.NET AJAX CHAT

    下面我所指的名字来自上面的链接。

    我认为实际的问题在于 $.post 的时间戳和异步行为。在调用“GetMessages()”方法后,即使先前的检索聊天消息的请求没有完成对相同方法的调用,因为在 $.post 方法之外为“GetMessages()”方法设置了超时。在我的问题中,您可以看到“GetMessages()”方法的超时设置在 $.post 方法之外。现在我在 $.post 方法中为“GetMessages()”方法设置超时。这样下一次调用“GetMessages()”只会在当前 $.post 方法完成 3 秒后发生。我已经发布了下面的代码。

    var t;
            function GetMessages() {
                var LastMsgRec = $("#hdnLastMsgRec").val();
                var RoomId = $("#hdnRoomId").val();
                //Get all the messages associated with this roomId
                $.post("/Chat/GetMessages", { roomId: RoomId, lastRecMsg: LastMsgRec }, function(Data) {
                    if (Data.LastMsgRec.length != 0)
                        $("#hdnLastMsgRec").val(Data.LastMsgRec);
                    if (Data.Messages.length != 0) {
                        $("#messagesCont").append(Data.Messages);
                        if (Data.newUser.length != 0)
                            $("#usersUl").append(Data.newUser);
                        $("#messagesCont").attr({ scrollTop: $("#messagesCont").attr("scrollHeight") - $('#messagesCont').height() });
                        $("#userListCont").attr({ scrollTop: $("#userListCont").attr("scrollHeight") - $('#userListCont').height() });
                    }
                    else {
                    }
                    t = setTimeout("GetMessages()", 3000);
                }, "json");
    
            }
    

    除此之外,我还改变了一些东西。正如 ignatandrei 所建议的,我放置了 $("#hdnLastMsgRec").val(Data.LastMsgRec);紧接在 function(Data) {.

    之后

    还有

    正如 MikeSW 所说,我改变了数据检索过程。以前我是根据时间跨度提取数据(检索与 这个房间 id 的时间跨度大于上次检索到的数据的时间跨度),但现在我跟踪 messageid。现在我只检索那些数据 消息 ID 大于上次检索到的消息 ID。

    猜猜到目前为止我的 Intranet 上没有重复和完美运行的聊天应用程序。

    我仍然需要看到它在互联网上部署时的性能。

    我认为它解决了我的问题。

    我仍然会测试系统并让你们知道是否有任何问题。

    【讨论】:

      【解决方案3】:

      默认情况下 $.post() 会缓存结果

      您可以调用 $.ajaxSetup ({ cache: false});在调用 JS GetMessages 函数以确保禁用缓存或将 $.post 更改为 $.ajax 并将缓存属性设置为 false 之前。最后 $.post() 是一个捷径:

      $.ajax({
        type: 'POST',
        url: url,
        data: data,
        success: success
        dataType: dataType
      });
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-11-01
        • 1970-01-01
        • 2010-11-08
        • 2011-01-12
        • 2011-07-12
        • 2017-09-10
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多