NET SignalR 与 LayIM2.0
ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(五) 之 加好友,加群流程,消息管理和即时消息提示的实现
前言
前前一篇留了个小问题,在上一篇中忘了写了,就是关于LayIM已经封装好的上传文件或者图片的问题。对接好接口之后,如果上传速度慢,界面就会出现假死情况,虽然文件正在上传。于是我就简单做了个图标替代来增强用户体验。
上传中。。。
上传完成后
是不是很简单啊,接下来进入正题。
业务介绍
LayIM中的加好友可以说是不太必要的逻辑,而且其实大部分在模仿QQ,当然业务复杂度肯定没法和QQ比。主线,就是用户A请求添加用户B为好友,用户B收到消息提示之后点击同意或者拒绝或者直接忽略,然后在将消息反馈到用户A。就是这么一个比较简单的流程,不过细节还是比较多的。
实战演示
第一步,发送好友申请。
第二步,接收好友申请(小气球为消息提示)
第三步:消息处理(这里拒绝会输入拒绝理由,忽略不做消息提示)
第四步:同意(拒绝)之后消息回传。
第五步:流程结束
讲解
数据库上的业务逻辑不多赘述,一般的设计只要包含请求表和处理结果表就可以了,然后根据用户id去查询他自己未处理的消息。可能看上面的图看不出哪里即时来,其实我在截图过程中,全程两个浏览器并没有刷新页面,完全是依靠后台的Hub消息推送来实现。在这之前呢,我们要做好准备工作,就是使用自定义用户Id,也就是我们数据库中的userId,而不是Hub中给我们的Guid。我们重写 接口 IUserIdProvider的GetUserId的方法就可以了。
namespace Microsoft.AspNet.SignalR
{
public interface IUserIdProvider
{
string GetUserId(IRequest request);
}
}
添加自定义类继承自接口 IUserIdProvider
public class LayIMUserFactory : IUserIdProvider
{
/// <summary>
/// 自定义获取用户ID方法
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
public string GetUserId(IRequest request)
{
//直接读取Cookie中的userid,然后将userid返回,否则返回空,未登录
if (request.GetHttpContext().Request.Cookies[LayIMConst.LayIM_SignalR_UserId] != null)
{
return request.GetHttpContext().Request.Cookies[LayIMConst.LayIM_SignalR_UserId].Value;
}
return "";
}
}
然后在startup文件中,我们注册一下这个类
public void Configuration(IAppBuilder app)
{
///注册自定义用户ID方法
var userIdProvider = new LayIMUserFactory();
GlobalHost.DependencyResolver.Register(typeof(IUserIdProvider), () => userIdProvider);
//ConfigureAuth(app);
//其他代码
}
同理呢,在ChatServer.LayIMHub 中,我们也是读取cookie中的用户Id
public string CurrentUserId
{
get
{ var cookie = Context.Request.GetHttpContext().Request.Cookies[LayIMConst.LayIM_SignalR_UserId];
if (cookie != null) { return cookie.Value; }
return "";
}
}
然后针对某一个用户发送消息的时候调用
Clients.User(CurrentUserId).receiveMessage("你好,我给你发送了一个消息,用Client.User发给你的");
这样做有什么好处呢,因为如果用户连接Hub服务器后,刷新页面的话,用户的ConnectionId是会变的,但是如果用我们自定义的userId来发送消息,只要是同一个用户,都能够使用UserId来进行发送消息的操作,省去了对ConnectionId的处理。所以这个场景很适合用在添加好友过程中的消息提醒上。比如,我们申请已经提交,那么后台就需要给被申请人发送一个提示消息:
public static void SendMessage(object message, string userId, ChatToClientType type, bool moreUser = false)
{
//构造消息体
ToClientMessageResult result = new ToClientMessageResult
{
msg = message,
msgtype = type,
other = null
};
//获取当前的Hub对象
IHubContext hub = GlobalHost.ConnectionManager.GetHubContext<LayIMHub>();
// 给多个用户发送消息
if (moreUser)
{
hub.Clients.Users(userId.Split(',').ToList()).receiveMessage(result);
}
else
{
//给单个用户发送消息
hub.Clients.User(userId).receiveMessage(result);
}
}
只要实现了以上这个方法,不管我们是发送申请信息,消息处理信息还是其他信息,都可以在后台调用。只要该用户在线,就能够实现实时推送,如果不在线,即使推送了,也是收不到的。那就是历史消息的功能了。这里不再赘述。
所以,当请求发送出去的时候,另外一个客户端就会看到这么一条消息:
对应界面上呢,就是那个右下角的小气球闪烁,因为是截图,所以闪烁效果看不出,虽然很low。。实现方法 是用setInterval 然后控制文字实现的。
var i = 0;
var blings = function () {
//html交替变换,一会是图标一会是空,就会有图标闪动的效果,不过如果有一个漂亮的gif就更好了。
$('.layim-tool-apply').attr('title', msg).html(i % 2 ? '' : '');
i++;
}
other.msgTipInterval = setInterval(blings, 500);
至于用户打开消息界面,因为是另外一个界面,所以直接读取该用户需要处理的消息即可,当用户同意或者拒绝该请求时,后台同样调用:
public static void SendMessage(ApplyHandledMessgae message)
{
short agreeFlag = 1;
short refuseFlag = 2;
//只有有消息,并且同意
if (message.id > 0)
{
var userid = message.applyuid.ToString();
if (message.result == refuseFlag)
{
//如果是被拒绝,只需要发送一条提示消息即可 var msg = new ApplySendedMessage
{
msg = "您的" + (message.applytype == 0 ? "好友" : "加群") + "请求已经被处理,请点击查看详情"
};
SendMessage(msg, userid, ChatToClientType.ApplyHandledToClient); }
else if (message.result == agreeFlag)
{
//如果同意了,判断如果是加群,需要给群发送消息:某某某已经加入群,如果是加好友,发送一条消息,我们已经成为好友了,开始聊天吧。
var msg = "您的" + (message.applytype == 0 ? "好友" : "加群") + "请求已经被处理,请点击查看详情";
if (message.applytype == ApplyType.Friend.GetHashCode())
{
//这里的friend是为了配合 LayIM的 addList接口
SendMessage(new { friend = message.friend, msg =msg }, userid, ChatToClientType.ApplyHandledToClient);
}
else {
//发送群信息 group也是为了配合Layim的addList接口
SendMessage(new { group = message.group, msg = msg }, userid, ChatToClientType.ApplyHandledToClient);
} }
}
}
所以,当处理完申请消息时候,申请方用户就会收到如下的消息:
客户端消息处理:
console.log("收到申请被处理的消息");
//开始闪烁右下角消息图标
global.other.startTips(result.msg.msg);
if (result.msg.friend) {
result.msg.friend.remark = result.msg.friend.sign;
//调用layim接口,将好友直接添加到相应的好友组里面
global.layim.addList(result.msg.friend);
}
if (result.msg.group) {
//调用layim接口,将群组直接添加到相应的好友组里面
global.layim.addList(result.msg.group);
}
到这里,基本上加好友流程就完成了,加群同理,不过加群不同的是,群主和管理员都可以审批,所以会出现给多个用户发送即时消息的情况。处理的时候也得注意重复操作的问题。
所以,本篇的核心内容就是Hub在后台的调用,以及自定义UserId的使用方法。不过好像我们还少些东西,比如说,提示群里的其他成员:xxx已经加入群。或者自动给申请成功的好友发送一条:“我们已经是好友了,开始聊天吧。”的消息。
总结
万变不离其宗,其实只要掌握了,消息推送机制,能够实现客户端与服务器端的联通。消息推送做任何业务都可以游刃有余。今天的加好友流程就到这里了。你会了吗?
下篇预告:【中级】ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(六) 之 Layim源码改造右键菜单--好友、组管理功能的实现。
NET SignalR 与 LayIM2.0的更多相关文章
- ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室 实战系列
ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(零) 前言 http://www.cnblogs.com/panzi/p/5742089.html ASP.NET S ...
- ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(十二) 代码重构使用反射工厂解耦(一)缓存切换
前言 上一篇中,我们用了反射工厂来解除BLL和UI层耦合的问题.当然那是最简单的解决方法,再复杂一点的程序可能思路相同,但是在编程细节中需要考虑的就更多了,比如今天我在重构过程中遇到的问题.也是接下来 ...
- ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(零) 前言
前端时间听一个技术朋友说 LayIM 2.0 发布了,听到这个消息抓紧去官网看了一下.(http://layim.layui.com/)哎呀呀,还要购买授权[大家支持一下哦],果断买了企业版,喜欢钻研 ...
- ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(一) 之 基层数据搭建,让数据活起来(数据获取)
大家好,本篇是接上一篇 ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(零) 前言 ASP.NET SignalR WebIM系列第二篇.本篇会带领大家将 LayIM ...
- ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(二) 之 ChatServer搭建,连接服务器,以及注意事项。
上篇:ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(一) 之 基层数据搭建,让数据活起来(数据获取) 上一篇我们已经完成了初步界面的搭建工作,本篇将介绍IM的核心内容 ...
- ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(三) 之 实现单聊,群聊,发送图片,文件。
上篇讲解了如何搭建聊天服务器,以及客户端js怎么和layui的语法配合.服务器已经连接上了,那么聊天还会远吗? 进入正题,正如上一篇提到的我们用 Client.Group(groupId)的方法向客户 ...
- ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(四) 之 用户搜索(Elasticsearch),加好友流程(1)。
前面几篇基本已经实现了大部分即时通讯功能:聊天,群聊,发送文件,图片,消息.不过这些业务都是比较粗犷的.下面我们就把业务细化,之前用的是死数据,那我们就从加好友开始吧.加好友,首先你得知道你要加谁.L ...
- ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(五) 之 加好友,加群流程,消息管理和即时消息提示的实现
前言 前前一篇留了个小问题,在上一篇中忘了写了,就是关于LayIM已经封装好的上传文件或者图片的问题.对接好接口之后,如果上传速度慢,界面就会出现假死情况,虽然文件正在上传.于是我就简单做了个图标替代 ...
- ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(六) 之 Layim源码改造右键菜单--好友、组管理功能的实现。
前言 上一篇中讲解了加好友的流程,本篇将介绍好友管理,群组管理的右键菜单功能.当然由于菜单项目太多,都实现也得花费时间.只讲解一下我是如何从不知道怎么实现右键菜单到会自定义菜单的一个过程.另外呢,针对 ...
- ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(七) 之 历史记录查询(时间,关键字,图片,文件),关键字高亮显示。
前言 上一篇讲解了如何自定义右键菜单,都是前端的内容,本篇内容就一个:查询.聊天历史纪录查询,在之前介绍查找好友的那篇博客里已经提到过 Elasticsearch,今天它又要上场了.对于Elastic ...
随机推荐
- Entity Framework with MySQL 学习笔记一(查看EF和SQL请求日志)
做数据库的一向来都会很注意请求的次数还有语句.这关系到很多性能的问题. 因此在使用EF的时候如果不了解原理很可能会搞出很糟糕的请求. 所以呢,在还没有搞懂EF前最基本的是你得"看得见&quo ...
- Backward_chaining
http://en.wikipedia.org/wiki/Backward_chaining
- poj 3130 How I Mathematician Wonder What You Are!
http://poj.org/problem?id=3130 #include <cstdio> #include <cstring> #include <algorit ...
- HDOJ(HDU) 1555 How many days?(水题)
Problem Description 8600的手机每天消费1元,每消费K元就可以获赠1元,一开始8600有M元,问最多可以用多少天? Input 输入包括多个测试实例.每个测试实例包括2个整数M, ...
- RSA算法python实现
RSA算法是一种非对称加密算法,是现在广泛使用的公钥加密算法,主要应用是加密信息和数字签名.详情请看维基:http://zh.wikipedia.org/wiki/RSA%E5%8A%A0%E5%AF ...
- mybatis dao无实现类的配置
spring的配置文件 添加: <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> ...
- lesson3:java的锁机制原理和分析
jdk1.5之前,我们对代码加锁(实际是对象加锁),都是采用Synchronized关键字来处理,jdk1.5及以后的版本中,并发编程大师Doug Lea在concurrrent包中提供了Lock机制 ...
- @property属性关键字
关于@property属性关键字使用注意:* weak(assign) : 代理\UI控件* strong(retain) : 其他对象(除代理\UI控件\字符串以外的对象)* copy : 字符串 ...
- @IBDesignable和@IBInspectable
近期一直在看苹果公司提供的两本swift官方教程电子书,一部是<The Swift Programming Language>,还有一部是<Using Swift With Coco ...
- 关于使用Jsonp做跨域请求
今天在使用Jsonp做跨域请求的练习时碰上这样一个问题 代码如下 <!DOCTYPE html> <html> <head> <meta charset=&q ...