1

I am developing an application, and I have built a real time chat using SignalR with MVC5. I am using First Code EF. this chat is working fine if I just use send, receive, and save chat to database (chat table), but if I add onconnect method to retrieve the chat from db, it stops working even the send and retrieve will stop either. Whenever I comment onconnect method, the other methods work fine. (the onconnect method was working, but suddenly stopped working). I tried many solution searched a lot and keep trying for a week but still having this issue.

When debug this issue the error is:

XML Parsing Error: no root element found Location: http://localhost:49430/signalr/abort?transport=serverSentEvents&clientProtocol=1.5&

when I click on this error for more details it gives this:

Self referencing loop detected for property 'AspNetUsers' with type 'System.Data.Entity.DynamicProxies.ApplicationUser_23AA294498688966C3E26561B78E32FEA355D79546483C6C3DD66A96A9AF5D33'. Path 'A[1][0].Posts[0]

I believe the issue is in here:

return Clients.Caller.connected(userName, allUsers, messages);

I changed it to

return Clients.All.connected(userName, allUsers, messages);

but still not working, any help would be appreciated.

this is my hub class:

namespace myWall
{
    public class ChatHub : Hub
    {
        public override System.Threading.Tasks.Task OnConnected()
        {
            ApplicationDbContext db = new ApplicationDbContext();
            string userName = Context.User.Identity.Name;

            var allUsers = db.Users.ToList();
            var messages = db.Chats.ToList();

            return Clients.Caller.connected(userName, allUsers, messages);
        }

        public void SendMessageToAll(string UserName, string message)
        {
            ApplicationDbContext dc = new ApplicationDbContext();
            UserName = Context.User.Identity.Name;

            AddAllMessageinCache(UserName, message);

            // Broad cast message
            Clients.All.NewMessage(UserName, message);
        }

        private void AddAllMessageinCache(string UserName, string message)
        {    
            var userId = Context.User.Identity.GetUserId();
            using (ApplicationDbContext dc = new ApplicationDbContext())
            {
                var messageDetail = new Chat
                {
                    UserId = userId,
                    userName = UserName,
                    Message = message
                };
                dc.Chats.Add(messageDetail);
                dc.SaveChanges();
            }
        }
    }

In my HomeController I am using a plain ActionResult method with name chat, and I added a view to this method to connect to hub class. this is my chat view:(this is just the script code not including the html form because it just plain form)

@section scripts {

    <script src="~/Scripts/jquery.signalR-2.2.1.js"></script>
    <script src="~/signalr/Hubs"></script>

    <script>
                $(function () {

                    var chat = $.connection.chatHub;



                    chat.client.connected = function (userName, allUsers, messages) {
                        for (i = 0; i < allUsers.length; i++) {
                            $("#results").append(allUsers[i].UserName + "</br>");

                        }

                        for (i = 0; i < 20; i++) {
                            $("#oldmsg").append(messages[i].userName + ": " + messages[i].Message + "</br>");
                        }
                        $("#oldmsg").append( "<font color= 'red' >" + "Welcome " + "<strong>" + userName + "</strong>" + " to the most fantastic real time chat" + "</font>" + "</br>");
                        $('#chat').scrollTop($('#chat')[0].scrollHeight);
                    };



                    chat.client.NewMessage = function (userName, msg) {
                        $('#Chats').append('<li><strong>' + htmlEncode(userName)
                            + '</strong>: ' + htmlEncode(msg) + '</li>');
                    };

                    registerClientMethods(chat)

                    $.connection.hub.start().done(function () {
                        registerEvents(chat)
                    });
                });




                function registerEvents(chat) {




                    $('#BtnSend').click(function () {
                        chat.server.sendMessageToAll($('#UserName').val(), $('#TxtMessage').val());
                        $('#TxtMessage').val('').focus();
                    });
                }

                function htmlEncode(value) {
                    var encodedValue = $('<div />').text(value).html();
                    return encodedValue;
                }


    </script>

and this my chat table:

[Table("Chat")]
public partial class Chat
{
    public int Id { get; set; }

    [StringLength(128)]
    public string UserId { get; set; }

    public int? WallId { get; set; }

    public DateTime? Time { get; set; }

    [Required]
    [StringLength(500)]
    public string Message { get; set; }

    [MaxLength(1)]
    public byte[] File { get; set; }

    public int? Code { get; set; }

    [Required]
    [StringLength(50)]
    public string userName { get; set; }

    [StringLength(256)]
    public string ConnectionId { get; set; }
}
CodeNotFound
  • 22,153
  • 10
  • 68
  • 69

1 Answers1

1

Your override should return base.OnConnected. So call your Client.Caller.connected then return base.OnConnected

Like this

public override System.Threading.Tasks.Task OnConnected()
    {
        ApplicationDbContext db = new ApplicationDbContext();
        string userName = Context.User.Identity.Name;

        var allUsers = db.Users.ToList();
        var messages = db.Chats.ToList();

        Clients.Caller.connected(userName, allUsers, messages);
        return base.OnConnected();
     }
Mike M
  • 488
  • 5
  • 19