.NET Core 3.1使用SignalR做登录、推送
2021-03-20 10:25
YPE html>
标签:浏览器 sig 添加 技术 configure control exist tin file
过多介绍我就不叙述了,奉上官方文档
创建SignalR的服务端和客户端,结构如下:
一、创建服务端
用VS2019创建一个空的Web应用程序,命名为SignalRServer
1. 添加ResultModel类:
public class ResultModel { public int Status { get; set; } public string Message { get; set; } public ListOnlineUser { get; set; } }
2. 添加UserModel类:
public class UserModel { public string ID { get; set; } public string UserName { get; set; } public string Password { get; set; } public string GroupName { get; set; } }
3. 添加ChatHub类:
1 public class ChatHub : Hub 2 { 3 ///4 /// 已登录的用户信息 5 /// 6 public static List OnlineUser { get; set; } = new List (); 7 8 /// 9 /// 模拟存放在数据库里的用户信息 10 /// 11 private static readonly List _dbuser = new List { 12 new UserModel{ 13 UserName = "test1", Password = "111", GroupName = "Group1" 14 }, 15 new UserModel{ 16 UserName = "test2", Password = "111", GroupName = "Group2" 17 }, 18 new UserModel{ 19 UserName = "test3", Password = "111", GroupName = "Group2" 20 }, 21 new UserModel{ 22 UserName = "test4", Password = "111", GroupName = "Group1" 23 }, 24 new UserModel{ 25 UserName = "test5", Password = "111", GroupName = "Group3" 26 }, 27 }; 28 29 /// 30 /// 登录验证 31 /// 32 public async Task Login(string username, string password) 33 { 34 string connid = Context.ConnectionId; 35 ResultModel result = new ResultModel 36 { 37 Status = 0, 38 Message = "登录成功!" 39 }; 40 if (!OnlineUser.Exists(u => u.ID == connid)) 41 { 42 var model = _dbuser.Find(u => u.UserName == username && u.Password == password); 43 if (model != null) 44 { 45 model.ID = connid; 46 OnlineUser.Add(model); 47 //给当前的连接分组 48 await Groups.AddToGroupAsync(connid, model.GroupName); 49 } 50 else 51 { 52 result.Status = 1; 53 result.Message = "账号或密码错误!"; 54 } 55 } 56 //给当前连接返回消息 57 await Clients.Client(connid).SendAsync("LoginResponse", result); 58 } 59 60 /// 61 /// 获取所在组的在线用户 62 /// 63 public async Task GetUsers() 64 { 65 var model = OnlineUser.Find(u => u.ID == Context.ConnectionId); 66 ResultModel result = new ResultModel(); 67 if (model == null) 68 { 69 result.Status = 1; 70 result.Message = "请先登录!"; 71 } 72 else 73 { 74 result.OnlineUser = OnlineUser.FindAll(u => u.GroupName == model.GroupName); 75 } 76 //给所在组返回消息 77 await Clients.Group(model.GroupName).SendAsync("GetUsersResponse", result); 78 } 79 80 public async Task SendMessage(string user, string message) 81 { 82 ResultModel result = new ResultModel(); 83 var model = OnlineUser.Find(u => u.ID == Context.ConnectionId); 84 if (model == null) 85 { 86 result.Status = 1; 87 result.Message = "请先登录!"; 88 } 89 else 90 { 91 result.Status = 0; 92 result.Message = $"“{user}”发送的消息:{message}"; 93 } 94 await Clients.Group(model.GroupName).SendAsync("SendMessageResponse", result); 95 } 96 97 public override Task OnConnectedAsync() 98 { 99 return base.OnConnectedAsync(); 100 } 101 102 /// 103 /// 当连接断开时的处理 104 /// 105 public override Task OnDisconnectedAsync(Exception exception) 106 { 107 string connid = Context.ConnectionId; 108 var model = OnlineUser.Find(u => u.ID == connid); 109 int count = OnlineUser.RemoveAll(u => u.ID == connid); 110 if (model != null) 111 { 112 ResultModel result = new ResultModel() 113 { 114 Status = 0, 115 OnlineUser = OnlineUser.FindAll(u => u.GroupName == model.GroupName) 116 }; 117 Clients.Group(model.GroupName).SendAsync("GetUsersResponse", result); 118 } 119 return base.OnDisconnectedAsync(exception); 120 } 121 }
可以重写基类的两个方法:
OnConnectedAsync 当连接成功时执行
OnDisconnectedAsync 当连接断开时执行,关闭浏览器或关闭浏览标签页都会执行
服务端发送给客户端的信息,我是通过分组推送,就是在同一个组里的用户才会收到(类似群聊):
Clients.Group(groupName).SendAsync();
也可以所有在线用户都收到:
Clients.All.SendAsync();
4. Startup类的配置如下:
1 public class Startup 2 { 3 // This method gets called by the runtime. Use this method to add services to the container. 4 // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 5 public void ConfigureServices(IServiceCollection services) 6 { 7 services.AddCors(options => options.AddPolicy("CorsPolicy", 8 builder => 9 { 10 builder.AllowAnyMethod().AllowAnyHeader() 11 .WithOrigins("https://localhost:44395") 12 .AllowCredentials(); 13 })); 14 15 services.AddSignalR(); 16 } 17 18 // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 19 public void Configure(IApplicationBuilder app, IWebHostEnvironment env) 20 { 21 if (env.IsDevelopment()) 22 { 23 app.UseDeveloperExceptionPage(); 24 } 25 26 app.UseRouting(); 27 28 app.UseCors("CorsPolicy"); 29 30 app.UseEndpoints(endpoints => 31 { 32 endpoints.MapGet("/", async context => 33 { 34 await context.Response.WriteAsync("Hello World!"); 35 }); 36 endpoints.MapHub("/chatHub"); 37 }); 38 } 39 }
注意:跨域是要指定地址的,不能是全部,否则客户端无法连接;当前你先留空,等客户端建立好了记得回来修改。
二、创建客户端
用VS2019创建一个空的Web应用程序,命名为SignalRClient
1. 新建文件夹,命名为wwwroot(如果不是这个名字,需要在中间件中指定了)
2. chat.js代码如下,注意withUrl中的地址,改为你的SignalRServer实际运行成功后的地址
1 "use strict"; 2 3 var connection = new signalR.HubConnectionBuilder().withUrl("https://localhost:44317/chatHub").build(); 4 5 connection.start(); 6 7 8 //---消息--- 9 document.getElementById("sendButton").addEventListener("click", function (event) { 10 var user = document.getElementById("userInput").value; 11 var message = document.getElementById("messageInput").value; 12 connection.invoke("SendMessage", user, message).catch(function (err) { 13 return console.error(err.toString()); 14 }); 15 event.preventDefault(); 16 }); 17 18 connection.on("SendMessageResponse", function (res) { 19 if (res && res.status == 0) { 20 var li = document.createElement("li"); 21 li.textContent = res.message; 22 document.getElementById("messagesList").appendChild(li); 23 } else { 24 alert(res.message); 25 } 26 }); 27 //---消息--- 28 29 30 //---登录--- 31 document.getElementById("btnLogin").addEventListener("click", function (event) { 32 var user = document.getElementById("userInput").value; 33 var message = document.getElementById("messageInput").value; 34 connection.invoke("Login", user, message).catch(function (err) { 35 return console.error(err.toString()); 36 }); 37 event.preventDefault(); 38 }); 39 40 connection.on("LoginResponse", function (res) { 41 if (res && res.status == 0) { 42 sessionStorage.setItem(‘curuser‘, res.data); 43 alert(res.message); 44 getUsers(); 45 } 46 else { 47 alert(‘登录失败!‘); 48 } 49 }); 50 //---登录--- 51 52 53 //获取在线用户 54 function getUsers() { 55 connection.invoke("GetUsers").catch(function (err) { 56 return console.error(err.toString()); 57 }); 58 connection.on("GetUsersResponse", function (res) { 59 if (res && res.status == 0) { 60 var _lis = ‘
3. signalr的js库,你可以自行下载;或者“项目右键 -> 添加 -> 客户端库”;
提供程序改为“unpkg”,输入“@microsoft/signalr”按回车搜索,勾选自己需要的,最后注意存放的位置
4. 创建页面:新建一个HomeController,添加视图,去掉布局页勾选
Index.cshtml代码如下:
1 @{ 2 Layout = null; 3 } 4 5 6 7 8 9 10Index 11 12 131419
15
16 17 18
-
20
-
22
5. Startup类的配置如下:
1 public class Startup 2 { 3 // This method gets called by the runtime. Use this method to add services to the container. 4 // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 5 public void ConfigureServices(IServiceCollection services) 6 { 7 services.AddControllersWithViews(); 8 } 9 10 // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 11 public void Configure(IApplicationBuilder app, IWebHostEnvironment env) 12 { 13 if (env.IsDevelopment()) 14 { 15 app.UseDeveloperExceptionPage(); 16 } 17 app.UseStaticFiles(); 18 19 app.UseRouting(); 20 21 app.UseEndpoints(endpoints => 22 { 23 endpoints.MapControllerRoute( 24 name: "default", 25 pattern: "{controller=Home}/{action=Index}/{id?}"); 26 }); 27 } 28 }
服务端跑起来,客户端跑起来,最后来看下效果:
(test1和test4是一组的,注意它们的变化,test5的组只有它一个,所以它收不到其它用户的消息)
本文代码:https://files.cnblogs.com/files/shousiji/SignalRDemo.rar
.NET Core 3.1使用SignalR做登录、推送
标签:浏览器 sig 添加 技术 configure control exist tin file
原文地址:https://www.cnblogs.com/shousiji/p/12737925.html
文章标题:.NET Core 3.1使用SignalR做登录、推送
文章链接:http://soscw.com/index.php/essay/66658.html