SignalR《二》接着前篇的继续

SignalR身份验证

在ChatRoomHub加上[Authorize] 这样登录了才能发送消息
 using Microsoft.AspNetCore.Authorization;
 using Microsoft.AspNetCore.Identity;
 using Microsoft.AspNetCore.SignalR;
 using SignalRStudy.Entity;
 using System.Security.Claims;
 ​
 namespace SignalRStudy.Hubs
 {
    [Authorize]
     public class ChatRoomHub : Hub
    {
 ​
         private readonly UserManager<MyUser> _userManager;
 ​
         public ChatRoomHub(UserManager<MyUser> userManager)
        {
             _userManager = userManager;
        }
 ​
         //SignalR的基本使用
 ​
         public Task SendPublicMessage(string messgae)
        {
             //获取当前连接id
             var connid = this.Context.ConnectionId;
             var msg = $"{connid}:{DateTime.Now}发送了{messgae}";
             //SendAsync 是对SendCoreAsync的封装
             //对所有人发送消息 只有一个异步方法可以 不屑async 和 await
             //ReceivePublicMessage 为前端接受消息方法
             var res = Clients.All.SendAsync("ReceivePublicMessage", msg);
             return res;
        }
 ​
         public async Task<string> SendPrivateMessage(string destUserName, string message)
        {
             var destUser = await _userManager.FindByNameAsync(destUserName);
             if (destUser == null)
            {
                 return "DestUserNotFound";
            }
             string destUserId = destUser.Id.ToString();
             string srcUserName = this.Context.User!.FindFirst(ClaimTypes.Name)!.Value;
             string time = DateTime.Now.ToShortTimeString();
             await this.Clients.User(destUserId).SendAsync("ReceivePrivateMessage",
                 srcUserName, time, message);
             return "ok";
        }
 ​
    }
 }
如下图

前端代码(前端 Vue3 我不是很熟,不多讲了)
 <template>
     <fieldset>
         <legend>登录</legend>
         <div>
            用户名:<input type="text" v-model="state.loginData.userName"/>
         </div>
         <div>
            密码:<input type="password"  v-model="state.loginData.password">
         </div>
         <div>
             <input type="button" value="登录" v-on:click="loginClick"/>
         </div>
     </fieldset>
    公屏:<input type="text" v-model="state.userMessage" v-on:keypress="txtMsgOnkeypress" />
     <div>
        私聊给<input type="text" v-model="state.privateMsg.destUserName"/>
        说<input type="text" v-model="state.privateMsg.message"
                 v-on:keypress="txtPrivateMsgOnkeypress"/>
     </div>
     <div>
         <ul>
             <li v-for="(msg,index) in state.messages" :key="index">{{msg}}</li>
         </ul>
     </div>
 </template>
 <script>
     import { reactive, onMounted } from 'vue';
     import * as signalR from '@microsoft/signalr';
     import axios from 'axios';
     let connection;
     export default {name: 'Login',
         setup() {
             const state = reactive({accessToken:"",userMessage: "", messages: [],
                 loginData: { userName: "", password: "" },
                 privateMsg: { destUserName:"",message:""},
            });
             const startConn = async function () {
                 const transport = signalR.HttpTransportType.WebSockets;
                 const options = { skipNegotiation: true, transport: transport };
                 options.accessTokenFactory = () => state.accessToken;
                 connection = new signalR.HubConnectionBuilder()
                    .withUrl('https://localhost:7298/Hubs/ChatRoomHub', options)
                    .withAutomaticReconnect().build();
                 try {
                     await connection.start();
                } catch (err) {
                     alert(err);
                     return;
                }
                 connection.on('ReceivePublicMessage', msg => {
                     state.messages.push(msg);
                });
                 connection.on('ReceivePrivateMessage', (srcUser,time,msg) => {
                     state.messages.push(srcUser+"在"+time+"发来私信:"+msg);
                });
                 connection.on('UserAdded', userName => {
                     state.messages.push("系统消息:欢迎" + userName+"加入我们!");
                });
                 alert("登陆成功可以聊天了");
            };
             const loginClick = async function () {
                 const resp = await axios.post('https://localhost:7298/api/Test/Login',
                     state.loginData);
                 state.accessToken = resp.data;
                 startConn();
            };
             const txtMsgOnkeypress = async function (e) {
                 if (e.keyCode != 13) return;
                 try {
                     await connection.invoke("SendPublicMessage", state.userMessage);
                }catch (err) {
                     alert(err);
                     return;
                }
                 state.userMessage = "";
            };
             const txtPrivateMsgOnkeypress = async function (e) {
                 if (e.keyCode != 13) return;
                 const destUserName = state.privateMsg.destUserName;
                 const msg = state.privateMsg.message;
                 try {
                     const ret = await connection.invoke("SendPrivateMessage", destUserName, msg);
                     if (ret != "ok") { alert(ret);};
                } catch (err) {
                     alert(err);
                     return;
                }
                 state.privateMsg.message = "";
            };
             return { state, loginClick, txtMsgOnkeypress, txtPrivateMsgOnkeypress };
        },
    }
 </script>
 <style scoped>
 </style>
总结:

对应的方法名和后端对应,参数都对应即可

外部向SignalR的Hub发送消息

TestController代码

     [HttpPost]
         public async Task<IActionResult> SendMsgToUser(AddNewUserRequest req)
        {
             //查询用户
             var user = await _userManager.FindByNameAsync(req.UserName);
             if (user == null)
            {
                 return BadRequest($"查无此人{req.UserName}");
            }
 ​
             var pm = await _userManager.FindByNameAsync("PM");
 ​
             string time = DateTime.Now.ToShortTimeString();
             string msg = @"PM,我来了";
             //这是给PM发送消息
             await _hubContext.Clients.User(pm.Id.ToString()).SendAsync("ReceivePrivateMessage", req.UserName,time, msg);
             return Ok(req.UserName+"存在");
        }

本来应该是添加一个用户,然后给PM(领导)自动发个消息,手下来新人了。 复制的AddUser方法,不想再添加用户了,所以虽然是Post请求 ,我只是查询了数据库是否有此人,然后给PM发了消息。只是单纯学习演示下功能。

测试结果如下

SignalR向部分客户端发消息

上述代码其实已经包含了向部分客户端发消息,不过是以调用接口然后发送,下面的是加上前端实现的类似于私聊的功能。

ChatRoomHub里面的SendPrivateMessage方法已经上面的写了,前端只写了一个方法接受ReceivePrivateMessage,在上述前端代码中,不影响渲染。

测试结果如下

SignalR综合案例

我就不贴代码了:使用场景是

英汉词典ECDICT中导入单词到数据库。

下载地址:https://github.com/skywind3000/ECDICT/blob/master/stardict.7z

是一个csv文件,目的就是把这个文件读取出来然后存到数据库里面,数据量比较大,通过SignalR通知前端,完成一个进度条的功能。

核心就是 list< entity >存到数据库里面

当前插入条数/总条数

不要一下全部插入,分批量 100或者1000、10000都可以看自己

前端progress就可以通过百分比来形成进度条。

提示:EF Core 目前还不支持批量处理(里面还是一条一条的 ,学习的话 这样也可以)

如果要批量 可以使用sqlbulk或者使用这个https://github.com/yangzhongke/Zack.EFCore.Batch

本文内容大部分都为杨中科老师《ASP.NET Core技术内幕与项目实战》一书中内容,此文只是做学习记录,如有侵权,联系立马删除。

 

最新文章

  1. iOS的nil,Null,NSNull的使用
  2. Knockout.js是什么?
  3. centOS6.4 extundelete工具恢复rm -rf 删除的目录
  4. $.noop()和$.map()函数
  5. 2014多校第五场1001 || HDU 4911 Inversion (归并求逆序数)
  6. cocos2d-x3.2 使用开关控制按钮 ControlSwitch
  7. Daily Scrum 11.9
  8. SparkGraphXTest.scala
  9. 【Electron】Electron开发入门(五):项目打包
  10. 通过ArcMap发布服务
  11. 较复杂makefile跟lds脚本程序的编写
  12. Beta 第五天
  13. 自己的mongodb的CRUD封装
  14. mongo 数据库
  15. PHP生成器细说
  16. Python课程目录
  17. PHP使用Apache中的ab测试网站的压力性能及mpm介绍
  18. 第一章 FFmpeg简介
  19. 终端命令行开启和关闭mac隐藏文件
  20. myeclipse2017 安装包及破解插件的下载

热门文章

  1. 那些年我们用过的xshell小彩蛋
  2. ubuntu18.04 安装cython_bbox
  3. vue将地区以对象、数组的格式传给后端
  4. Kubernetes--管理资源标签(标签)
  5. Usage of Seven Zip in C#
  6. openGL 学习笔记 (二) 使用GL API 绘制出属于自己的矩形
  7. 如何进行多平台部署Client和Server详细讲解
  8. 25 String 对象中的属性
  9. 22_webpack_优化
  10. [转]如何将本地项目上传至Gitee仓库(详细教程)