asp.net mvc signalR 实现一对一聊天

本文详细介绍了如何使用ASP.NET MVC和SignalR实现一对一聊天的应用。首先创建一个简单的HomeController和View,然后建立SignalR Hub,处理用户连接、断开以及广播和私聊的方法。接着在前端HTML页面中添加JavaScript代码,监听和调用Hub的方法,完成用户列表显示和消息传递。最后,展示了完成的页面和关键代码片段,提供了一个实时聊天功能的基础实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

之前做了一篇关于asp.net mvc signalR聊天室的简单入门例子, 其中用的是 Clients.All.xxx_js   ,这个All代表了全体广播,今天写了   一对一聊天的例子 。 

//前一篇文章
https://blog.youkuaiyun.com/MFCdestoryer/article/details/116304333

按照之前的例子,先用NuGet工具下载好signalr的包 , 然后进行开发。

首先建立一个简单的controller 和 view , 比方说 HomeController.SL  , 备注:我平时页面布局都是用bootstrap 这套样式,所以除了 jquery 之外,html页面还引入了bootstrap样式。

   public class HomeController : Controller
    {
         

        //私聊
        public ActionResult SL()
        {
            return View();
        }

    }

@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>SL</title>

    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" integrity="sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu" crossorigin="anonymous">
 
    <script src="https://cdn.jsdelivr.net/npm/jquery@1.12.4/dist/jquery.min.js" integrity="sha384-nvAa0+6Qg9clwYCGGPpDQLVpLNn0fRaROjHqs13t4Ggj3Ez50XnGQqc/r8MhnRDZ" crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js" integrity="sha384-aJ21OjlMXNL5UyIl/XNwTMqvzeRMZH2w8c5cRVpzpU8Y5bApTppSuUkhZXN0VxHd" crossorigin="anonymous"></script>

    <!--Reference the SignalR library. -->
    <script src="~/Scripts/jquery.signalR-2.4.1.min.js"></script>
    <!--Reference the autoGenerated SignalR hub script. -->
    <script src="~/signalr/hubs"></script>

    

</head>
<body>
    <div class="container"> 
        <div class="row">
            <div class="col-md-12 col-sm-12">
                <div class="well well-sm">
                    <div class="text-center">
                        当前用户: 
                        <span id="curUserName"></span>
                    </div>
                </div>
            </div>
        </div>

        <div class="row">
            <div class="col-md-2 col-sm-4">
                <div id="user-list-group" class="list-group">
                    <button type="button" class="list-group-item" title="aaa" onclick="listGroupItemClick(this);" >小黄</button>
                    <button type="button" class="list-group-item" title="bbb" >李小龙</button>
                    <button type="button" class="list-group-item">乔丹</button>
                    <button type="button" class="list-group-item">李荣浩</button>
                    <button type="button" class="list-group-item">大哥</button>
                </div>
                <!--hiden value-->
                <div style="display:none;">
                    <input type="text" id="userName" name="userName" />
                </div>
            </div>  <!--end left-->

            <div class="col-md-10 col-sm-8">
                <div class="row">
                    <!--CHART text-->
                    <div class="panel panel-primary">
                        <div class="panel-heading">
                            对话框:
                            <span id="sname"></span> 
                            【<span id="sid"></span>】
                        </div>

                        <div class="panel-body">
                            <div id="contextDIV" style="height:500px;overflow:auto;">
                                @*<p><span class="label label-success">Myself</span> Example heading </p>
                                  <p><span class="label label-info">Info</span> heellelee222 </p>*@
                            </div>
                        </div> <!--end panel body-->

                        <div class="panel-footer">
                            <div class="row">
                                <div class="col-md-12 col-sm-12">
                                    <div class="input-group">
                                        <input type="text" id="message" name="message" class="form-control" />
                                        <span class="input-group-btn">
                                            <input type="button" class="btn btn-default" id="sendmessage" name="sendmessage" value="发送" />
                                        </span>
                                    </div>
                                </div>
                            </div>
                        </div><!--end pannel foot-->

                    </div> <!--end pannel-->
                </div>
            </div>  <!--end right-->
        </div>
        
    </div>
</body>
</html>

运行可以看到一个简单的例子页面:

然后,我们 新建一个 signalr hub class ,在  new item 里面选择 signalr hub class ,这个步骤可以看以前写的文章 , 这里不截图了 , 建好之后,改下代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Web;
using Microsoft.AspNet.SignalR;
using Microsoft.AspNet.SignalR.Hubs;
using signalrTest7.Models;

namespace signalrTest7.Controllers
{
     


    [HubName("chartHubb")]
    public class ChartHubb : Hub
    {
        private static List<UserInfo> USERLIST = new List<UserInfo>();

        //连接
        public override Task OnConnected()
        {
            var currentUser = USERLIST.Where(x => x.ConnectionID == Context.ConnectionId).FirstOrDefault();
            if (currentUser == null) {
                UserInfo newUser = new UserInfo(Context.ConnectionId, "");
                USERLIST.Add(newUser);
            }

            return base.OnConnected();
        }

        //断开
        public override Task OnDisconnected(bool stopCalled)
        {
            var currentUser = USERLIST.Where(x => x.ConnectionID == Context.ConnectionId).FirstOrDefault();
            if (currentUser != null) {
                USERLIST.Remove(currentUser);
            }

            ShowAllUser();
            return base.OnDisconnected(stopCalled);
        }


        /// <summary>
        /// 广播登陆用户列表到全体连接客户端
        /// </summary>
        [HubMethodName("showAllUser")]
        public void ShowAllUser()
        {
            string userJson = Newtonsoft.Json.JsonConvert.SerializeObject(USERLIST);
            Clients.All.broadcastUserList(userJson);
            //前端js定义 function broadcastUserList(userList)
        }

        /// <summary>
        /// 登陆时设置名字
        /// </summary>
        /// <param name="inputName"></param>
        [HubMethodName("setUserName")]
        public void SetUserName(string inputName)
        {
            var currentUser = USERLIST.Where(x => x.ConnectionID == Context.ConnectionId).FirstOrDefault();
            if (currentUser != null) {
                currentUser.UserName = inputName;
            }
            //广播给全体客户端
            this.ShowAllUser();
        }

        /// <summary>
        /// 发送信息给某人
        /// </summary>
        /// <param name="outsideID"></param>
        /// <param name="message"></param>
        [HubMethodName("sendTo")]
        public void SendTo(string outsideID,  string message)
        {
            var myUser = USERLIST.Where(y => y.ConnectionID == Context.ConnectionId).FirstOrDefault();
            var outsideUser = USERLIST.Where(x => x.ConnectionID == outsideID).FirstOrDefault();

            //前端js定义function showMessage(speakerName , message)
            if (outsideUser != null)
            {
                Clients.Client(outsideUser.ConnectionID).showMessage(myUser.UserName, message);
                Clients.Client(myUser.ConnectionID).showMessage(myUser.UserName, message);
                //对方  和  我方 的界面都要显示语录
            }
            else {
                Clients.Client(myUser.ConnectionID).showMessage(outsideUser.UserName + outsideUser.ConnectionID , "离线");
            }
        }


    }


}

这个 hub class 有一些注意的地方,(1)onConnect 和 onDisconnect 都是可以通过 override出来的 , 在visual studio 中,只要输入 override关键字,然后按一下键盘的tab键, 就会有相应的提示弹出来了 , 不用自己手动一个个字母敲。

(2)这里用到一个实体类  UserInfo

 public class UserInfo
    {
        public string ConnectionID { get; set; }
        public string UserName { get; set; }

        //构造函数
        public UserInfo(string cid, string unm) {
            this.ConnectionID = cid;
            this.UserName = unm;
        }
    }

 然后接着是  owin startup 的代码(也可以参考之前写的文章,这里不截图了)

using System;
using System.Threading.Tasks;
using Microsoft.Owin;
using Owin;

[assembly: OwinStartup(typeof(signalrTest7.Startup))]

namespace signalrTest7
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            // Any connection or hub wire up and configuration should go here
            app.MapSignalR();
        }
    }


}

剩下的就是对应编辑注册前端html页面中js function ,慢慢读代码,就能发现:

后台hub 类里面的代码是通过  Clients.All / Client.xxx_js (  )  来触发前端js 方法 ,

前端js 是通过   chat.server.xxx  来触发后台 hub method , 

 

其实微软给开发者提供了这一个比较简单的思路,让我们能写出实时对话的代码。我是菜鸟,写的不对请见谅。

刚刚的SL  view里面 ,js代码改为以下:


@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>SL</title>

    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" integrity="sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu" crossorigin="anonymous">
 
    <script src="https://cdn.jsdelivr.net/npm/jquery@1.12.4/dist/jquery.min.js" integrity="sha384-nvAa0+6Qg9clwYCGGPpDQLVpLNn0fRaROjHqs13t4Ggj3Ez50XnGQqc/r8MhnRDZ" crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js" integrity="sha384-aJ21OjlMXNL5UyIl/XNwTMqvzeRMZH2w8c5cRVpzpU8Y5bApTppSuUkhZXN0VxHd" crossorigin="anonymous"></script>

    <!--Reference the SignalR library. -->
    <script src="~/Scripts/jquery.signalR-2.4.1.min.js"></script>
    <!--Reference the autoGenerated SignalR hub script. -->
    <script src="~/signalr/hubs"></script>

    <script type="text/javascript">

        $(function () {

            //存储当前用户名称
            $('#userName').val(prompt('请输入您的名称', ''));
             
            //连接后端hub
            chat = $.connection.chartHubb;
            console.info(chat);

            //注册后台
            chat.client.broadcastUserList = function (data) {
                if (data) {
                    var json = $.parseJSON(data);
                    console.info(json); 

                    $('#user-list-group').html('');
                    for (var i = 0; i < json.length; i++) {
                        
                        var mhtml = '<button type="button" class="list-group-item" title="' + json[i].ConnectionID + '" onclick="listGroupItemClick(this);" >' + json[i].UserName + '</button>';
                         
                        $('#user-list-group').append(mhtml);
                    }
                }
            }  //end broadcastUserList

            //注册后台
            chat.client.showMessage = function (speakerName, message) {
                var msg = ''; 

                if (speakerName == $('#curUserName').text()) {
                    msg = '<p><span class="label label-success"> ' + speakerName + '</span>' + message + '</p>';
                }
                else {
                    msg = '<p><span class="label label-info"> ' + speakerName + '</span>' + message + '</p>';
                }
                
                $('#contextDIV').append(msg);
                $('#message').val('');
                $('#message').val('').focus();
            }   //end showMessage

            //发送按钮
            $('#sendmessage').click(function () {
                var outid = $('#sid').text();
                var outmessage = $('#message').val();

                if (outid != '' && outmessage != '' ) {
                    chat.server.sendTo(outid, outmessage);
                } 
                else {
                    alert('请选择接收消息的用户(或者没有输入任何内容)');
                }
                
            });  //end click

            
            //连接成功后获取自己的信息
            $.connection.hub.start().done(function () {
                $('#curUserName').text($('#userName').val());
                chat.server.setUserName($('#userName').val());
            }); 

        });   //end page ready


        //左侧名字列表 点击事件
        function listGroupItemClick(that) {
            var tname = $(that).text();
            var tid = $(that).attr('title');

            $('#sname').text(tname);
            $('#sid').text(tid);
        }//end listGroupItemClick


        //回车键
        $(document).keydown(function () {
            if (event.keyCode == 13) {
                $('#sendmessage').click();
            }
        });  //end keydown



    </script>

</head>
<body>
    <div class="container"> 
        <div class="row">
            <div class="col-md-12 col-sm-12">
                <div class="well well-sm">
                    <div class="text-center">
                        当前用户: 
                        <span id="curUserName"></span>
                    </div>
                </div>
            </div>
        </div>

        <div class="row">
            <div class="col-md-2 col-sm-4">
                <div id="user-list-group" class="list-group">
                    <button type="button" class="list-group-item" title="aaa" onclick="listGroupItemClick(this);" >小黄</button>
                    <button type="button" class="list-group-item" title="bbb" >小龙</button>
                    <button type="button" class="list-group-item">乔</button>
                    <button type="button" class="list-group-item">李</button>
                    <button type="button" class="list-group-item">大哥</button>
                </div>
                <!--hiden value-->
                <div style="display:none;">
                    <input type="text" id="userName" name="userName" />
                </div>
            </div>  <!--end left-->

            <div class="col-md-10 col-sm-8">
                <div class="row">
                    <!--CHART text-->
                    <div class="panel panel-primary">
                        <div class="panel-heading">
                            对话框:
                            <span id="sname"></span> 
                            【<span id="sid"></span>】
                        </div>

                        <div class="panel-body">
                            <div id="contextDIV" style="height:500px;overflow:auto;">
                                @*<p><span class="label label-success">Myself</span> Example heading </p>
                                  <p><span class="label label-info">Info</span> heellelee222 </p>*@
                            </div>
                        </div> <!--end panel body-->

                        <div class="panel-footer">
                            <div class="row">
                                <div class="col-md-12 col-sm-12">
                                    <div class="input-group">
                                        <input type="text" id="message" name="message" class="form-control" />
                                        <span class="input-group-btn">
                                            <input type="button" class="btn btn-default" id="sendmessage" name="sendmessage" value="发送" />
                                        </span>
                                    </div>
                                </div>
                            </div>
                        </div><!--end pannel foot-->

                    </div> <!--end pannel-->
                </div>
            </div>  <!--end right-->
        </div>
        
    </div>
</body>
</html>

到这里就写好了一对一聊天的功能了 ,试一试。

 

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值