ASP.NET MVC ajax 聊天

发布于 2024-08-25 13:26:01 字数 2465 浏览 2 评论 0原文

我在我的一个 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() 函数。我在页面第一次加载时以及由 javascript 设置该字段的值后加载字段 hdnLastMsgRec 的值。

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

或者您可以建议更好的方法来实现这一点。

I built an ajax chat in one of my mvc website. everything is working fine. I am using polling. At certain interval i am using $.post to get the messages from the db. But there is a problem. The message retrieved using $.post keeps on repeating. here is my javascript code and controller method.

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

and here is my controller method to get the data:

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

Everything is working absloutely perfect. But i some messages getting repeated. The first time page loads i am retrieving the data and call GetMessages() function. I am loading the value of field hdnLastMsgRec the first time page loads and after the value for this field are set by the javascript.

I think the message keeps on repeating because of asynchronous calls. I don't know, may be you guys can help me solve this.

or you can suggest better way to implement this.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

榆西 2024-09-01 13:26:01

Kaivalya 关于缓存的说法是正确的,但我还建议您的设计可以而且应该稍微改变一下。

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

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

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

$.post 只会在响应用户输入时触发(例如,在框中键入,点击“发送”)然后,您(单独)从 jquery 进行 $.get 调用,该调用设置为像您所说的那样进行轮询,它所做的就是获取最新的聊天消息,并且它的回调会使用这些消息更新聊天 UI。

Kaivalya is correct about the caching, but I'd also suggest that your design could and should be altered just a tad.

I made a very similar app recently, and what I found was that my design was greatly enhanced by letting the controllers work with the fairly standard PRG pattern (post-redirect-get). Why enhanced? well, because POST methods are built to add stuff to an app, GET methods are supposed to be used to get information without side effects. Your polling should be just getting new messages w/o side effects.

So rather than your $.post call expecting data and handling the callback, what I'd recommend is having your controller expose a method for creating new chat messages via POST and then another method that get the last X chat messages, or the messages since a certain timestamp or whatever.

The javascript callback from the post action, then can update some variables (e.g. the last message id, timestamp of the last message, or even the whole URL of the next message based on the info contained in a redirect, whatever).

The $.post would fire only in response to user input (e..g type in a box, hit 'send') Then, you have (separately) a $.get call from jquery that's set up to poll like you said, and all it does is fetch the latest chat messages and it's callback updates the chat UI with them.

热情消退 2024-09-01 13:26:01

我在这里得到了答案: 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);紧接着函数(数据){。

以及

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

猜猜到目前为止,我的 Intranet 上没有重复且运行良好的聊天应用程序。

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

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

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

I got my answer here: ASP.NET AJAX CHAT

The names below i am referring to are from above link.

i think the actual problem was with the timestamp thing and asynchronous behaviour of $.post. after calling "GetMessages()" method, even if the previous request to retrive chat message was not complete anathor call to same method used to fire due to setting timeout for "GetMessages()" method outside the $.post method. In my question you can see that timeout for "GetMessages()" method is set outside the $.post method. Now i set the timeout for "GetMessages()" method inside the $.post method. so that next call to "GetMessages()" only occur after 3 seconds of completion of current $.post method. I have posted the code below.

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");

        }

I addition to that i also changed few things. As suggested by ignatandrei i placed $("#hdnLastMsgRec").val(Data.LastMsgRec); immediately after function(Data) {.

and also

as said by MikeSW i changed the data retrieval process. Previously i was extracting data on the basis of timespan(retrieve all the data associated with
this room id that has greater timespan than last data retrieved message timespan) but now i keep track of the messageid. Now i retrieve only those data that
has message id greater than last retrieved message id.

and guess what no repeataion and perfectly working chat application so far on my intranet.

I still got to see it's performance when deployed on internet.

i think it solved my problem.

i will still test the system and let u guys know if there is any problem.

栀子花开つ 2024-09-01 13:26:01

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

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

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

By default $.post() caches the results

You can either call $.ajaxSetup ({ cache: false}); before JS GetMessages function call to ensure caching is disabled or change the $.post to $.ajax and set cache attribute to false. In the end $.post() is a short cut to this:

$.ajax({
  type: 'POST',
  url: url,
  data: data,
  success: success
  dataType: dataType
});
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文