.NET Core 3.1使用SignalR做登录、推送

2021-03-20 10:25

阅读:671

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 List OnlineUser { 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 = ‘
  • 在线用户:
  • ; 61 for (var i = 0; i ) { 62 _lis += `
  • ${res.onlineUser[i].userName}
  • `; 63 } 64 document.getElementById("usersList").innerHTML = _lis; 65 } 66 }); 67 }

     

    3. signalrjs库,你可以自行下载;或者“项目右键 -> 添加 -> 客户端库”;

        提供程序改为“unpkg”,输入“@microsoft/signalr”按回车搜索,勾选自己需要的,最后注意存放的位置

     技术图片   技术图片

     

    4. 创建页面:新建一个HomeController,添加视图,去掉布局页勾选

    技术图片

     

    Index.cshtml代码如下:

     1 @{
     2     Layout = null;
     3 }
     4 
     5 
     6 
     7 
     8 9     10     Index11 
    12 
    13     
    14
    15
    16 17 18
    19
      20
    21
      22
    23 24 25 26

     

    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


    评论


    亲,登录后才可以留言!