之前做了一篇关于asp.net mvc signalR聊天室的简单入门例子, 其中用的是 Clients.All.xxx_js ,这个All代表了全体广播,今天写了 一对一聊天的例子 。
//前一篇文章
https://blog.csdn.net/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>
到这里就写好了一对一聊天的功能了 ,试一试。