2010-03-21 5 views
2

J'ai construit un ajax discuter dans un de mon site Web de mvc. tout fonctionne bien. J'utilise le sondage. À un certain intervalle, j'utilise $ .post pour obtenir les messages de la base de données. Mais il y a un problème. Le message récupéré à l'aide de $ .post ne cesse de se répéter. Voici mon code javascript et la méthode du contrôleur.ASP.NET MVC ajax chat

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

et voici ma méthode du contrôleur pour obtenir les données:

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

Tout fonctionne absloutely parfait. Mais j'ai des messages qui se répètent. La première fois que la page est chargée, je récupère les données et appelle la fonction GetMessages(). Je charge la valeur du champ hdnLastMsgRec la première fois que la page se charge et après que la valeur de ce champ est définie par le javascript.

Je pense que le message ne cesse de se répéter en raison d'appels asynchrones. Je ne sais pas, peut-être que vous pouvez m'aider à résoudre ça.

ou vous pouvez suggérer une meilleure façon de l'implémenter.

+0

J'étais curieux de savoir quel type d'interrogation vous utilisez. – Ciel

Répondre

0

Par défaut .post de $() met en cache les résultats

Vous pouvez appeler .ajaxSetup $ ({cache: false}); avant l'appel de la fonction JS GetMessages pour vous assurer que la mise en cache est désactivée ou modifiez $ .post en $ .ajax et définissez l'attribut de cache sur false. En fin de .post() de $ est une coupe courte à ceci:

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

Kaivalya est correct au sujet de la mise en cache, mais je vous suggère aussi que votre conception pourrait et devrait être changée juste un peu.

J'ai fait une application très similaire récemment, et ce que j'ai trouvé, c'est que mon design a été grandement amélioré en laissant les contrôleurs fonctionner avec le modèle PRG assez standard (post-redirect-get). Pourquoi amélioré? Eh bien, parce que les méthodes POST sont construites pour ajouter des choses à une application, les méthodes GET sont censées être utilisées pour obtenir des informations sans effets secondaires. Votre sondage devrait être juste obtenir de nouveaux messages sans effets secondaires. Donc, plutôt que votre appel $ .post attend des données et le traitement du rappel, ce que je recommande est d'avoir votre contrôleur exposer une méthode pour créer de nouveaux messages de chat via POST, puis une autre méthode qui obtient les derniers messages de chat X, ou les messages depuis un certain horodatage ou quoi que ce soit. Le rappel javascript de l'action de publication, puis peut mettre à jour certaines variables (par exemple le dernier message ID, l'horodatage du dernier message, ou même toute l'URL du prochain message basé sur l'information contenue dans une redirection, peu importe) . Le $ .post ne se déclencherait qu'en réponse à une entrée de l'utilisateur (par exemple, tapez dans une boîte, appuyez sur 'envoyer') Ensuite, vous avez (séparément) un appel $ .get de jquery qui est configuré pour interroger comme vous l'avez dit, et tous il est chercher les derniers messages de chat et son rappel met à jour l'interface utilisateur de chat avec eux.

1

J'ai eu ma réponse ici: ASP.NET AJAX CHAT

Les noms ci-dessous je fais référence sont de lien ci-dessus. Je pense que le vrai problème était avec l'horodatage et le comportement asynchrone de $ .post.après l'appel de la méthode "GetMessages()", même si la requête précédente pour récupérer le message de chat n'était pas terminée, l'appel anathor à la même méthode était déclenché en raison du délai d'attente de la méthode "GetMessages()" en dehors de la méthode $. Dans ma question, vous pouvez voir que le délai d'expiration de la méthode "GetMessages()" est défini en dehors de la méthode $ .post. Maintenant, je définis le délai d'expiration de la méthode "GetMessages()" dans la méthode $ .post. de sorte que le prochain appel à "GetMessages()" ne se produise que 3 secondes après l'achèvement de la méthode $ .post en cours. J'ai posté le code ci-dessous.

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

     } 

En plus de cela j'ai aussi changé quelques choses. Comme suggéré par ignatandrei j'ai placé $ ("# hdnLastMsgRec"). Val (Data.LastMsgRec); immédiatement après la fonction (Data) {.

et aussi

comme dit par MikeSW i modifié le processus de récupération des données. Auparavant, j'extrayais des données sur la base de timespan (récupérer toutes les données associées à cet ID de pièce qui a plus de temps que le dernier délai de message de données récupérées) mais maintenant je garde la trace de l'ID de message. Maintenant, je récupère seulement les données qui ont un identifiant de message supérieur au dernier identifiant de message récupéré.

et devinez quoi aucune application de conversation de repeataion et fonctionnant parfaitement jusqu'ici sur mon intranet.

Je continue de voir ses performances lors d'un déploiement sur Internet.

Je pense qu'il a résolu mon problème.

Je vais quand même tester le système et vous laisser savoir s'il y a un problème.