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技术内幕与项目实战》一书中内容,此文只是做学习记录,如有侵权,联系立马删除。

 

SignalR《二》接着前篇的继续的更多相关文章

  1. 数据库索引<二> 补充前篇 (上一篇抽风了,这个补上)

    在前一个创建索引中已经大概说了三部分的影响,基本应该注意哪一些.写完上一篇后我感觉有很多地方没有写清楚,所以这篇就是更深入一些的理解索引到底是怎么和数据表关联,怎么快速查询的. 先看一下下面的图,图是 ...

  2. 数据库索引<二> 补充前篇

    你要准备的软件有: 最新版 Rsync for windows 服务端:cwRsync_Server_2.1.5_Installer.zip 客户端:cwRsync_2.1.5_Installer.z ...

  3. 前端面试题总结(二)CSS篇

    前端面试题总结(二)CSS篇 一.link和@import的区别? link属于HTML标签,可以引入出css以外的事务,如RSS,而@import是css提供的,只能加载css文件. link会在页 ...

  4. Linux负载均衡软件LVS之二(安装篇)[转]

    Linux负载均衡软件LVS之二(安装篇) 2011-04-26 16:01:47 标签:lvs安装配置 linux lvs 休闲 linux高可用 原创作品,允许转载,转载时请务必以超链接形式标明文 ...

  5. 【原创】构建高性能ASP.NET站点 第六章—性能瓶颈诊断与初步调优(下前篇)—简单的优化措施

    原文:[原创]构建高性能ASP.NET站点 第六章-性能瓶颈诊断与初步调优(下前篇)-简单的优化措施 构建高性能ASP.NET站点 第六章—性能瓶颈诊断与初步调优(下前篇)—简单的优化措施 前言:本篇 ...

  6. [原创].NET 分布式架构开发实战之四 构建从理想和实现之间的桥梁(前篇)

    原文:[原创].NET 分布式架构开发实战之四 构建从理想和实现之间的桥梁(前篇) .NET 分布式架构开发实战之四 构建从理想和实现之间的桥梁(前篇) 前言:上一篇文章讲述了一些实现DAL的理论,本 ...

  7. 隐马尔科夫模型HMM(二)前向后向算法评估观察序列概率

    隐马尔科夫模型HMM(一)HMM模型 隐马尔科夫模型HMM(二)前向后向算法评估观察序列概率 隐马尔科夫模型HMM(三)鲍姆-韦尔奇算法求解HMM参数(TODO) 隐马尔科夫模型HMM(四)维特比算法 ...

  8. jQuery-Selectors(选择器)的使用(二、层次篇)(转载)

    原文:http://www.cnblogs.com/bynet/archive/2009/12/01/1614405.html 本系列文章导航 jQuery-Selectors(选择器)的使用(一.基 ...

  9. [知乎]老狼:深入PCI与PCIe之二:软件篇

    深入PCI与PCIe之二:软件篇 https://zhuanlan.zhihu.com/p/26244141 我们前一篇文章(深入PCI与PCIe之一:硬件篇 - 知乎专栏)介绍了PCI和PCIe的硬 ...

  10. Android深入四大组件(四)Android8.0 根Activity启动过程(前篇)

    前言 在几个月前我写了Android深入四大组件(一)应用程序启动过程(前篇)和Android深入四大组件(一)应用程序启动过程(后篇)这两篇文章,它们都是基于Android 7.0,当我开始阅读An ...

随机推荐

  1. ETCD 实现服务发现讲解

    租约:具有时间有效期,键绑定到租约后,当租约到期失效,绑定到的租约的键也会被删除. 创建租约 etcdctl lease grant 600 lease 694d81f509b7940a grante ...

  2. ubuntu 查看已安装软件命令

    一.查看所有已安装软件包 dpkg -l 二.过滤安装包 yang@ubuntu:~/ansible$ dpkg -l | grep vim ii vim 2:8.1.2269-1ubuntu5.9 ...

  3. LWC-001_Event

    文章来源: Events (lwc.dev) 1. 监控子组件的动作: Child.html <template> <button>Click</button> & ...

  4. Activity 的窗口去头的方式

    1\窗口去头的第一种方式 public class SplashActivity extends Activity { @Override protected void onCreate(Bundle ...

  5. iframe 父子页面调用vue函数,并解决跨域问题,宽度自适应

    第一: 1. 父页面 html <iframe id="external-frame" name="external-frame" ref="i ...

  6. python菜鸟学习: 11. 装饰器的基础用法

    # -*- coding: utf-8 -*-# decorator# 定义:本质是函数,就是为其他函数添加附件功能# 原则:# 1.不能修改被装饰的函数的源代码# 2.不能修改被装饰的函数的调用方式 ...

  7. IBM免费服务器试用

    IBM公司的免费资源,仅需一个邮箱就可以注册申请,注册可以有60天试用期. 1.注册 点击 注册进入IBM教育资源官网进行注册,注册时仅需要一个有效邮箱,QQ,Gmail,outlook均可. 注册邮 ...

  8. 宝塔部署 vue + thinkphp

    部署https://blog.csdn.net/xinxinsky/article/details/105441164?spm=1001.2101.3001.6650.2&utm_medium ...

  9. VS2019使用Qt4.8.7

    取消系统变量中的Qt_INCLUDEPATH_. C:\Users\octob\AppData\Local\QtMsBuild中添加qt4.natvis.xml,qt4.natvis for visu ...

  10. usb 2.0 request