如何在Asp.Net.Core Mvc Signalr中建立一对一的聊天系统? [英] How can I make one to one chat system in Asp.Net.Core Mvc Signalr?

查看:59
本文介绍了如何在Asp.Net.Core Mvc Signalr中建立一对一的聊天系统?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想用Mssql数据库实现私人聊天系统.当我发送消息时,此代码作为公共代码工作,消息出现在所有客户端上.但是我要一对一的聊天系统.一个用户输入存储在数据库和消息文本中的接收者ID,然后将消息发送给Receiver.然后,该消息将显示在具有该接收者ID的接收者消息区域中.

这是我的js代码

 严格使用";var connection = new signalR.HubConnectionBuilder().withUrl("/chathub").build();//禁用发送按钮,直到建立连接document.getElementById("sendButton").disabled = true;connection.start().then(function(){document.getElementById("sendButton").disabled = false;}).catch(function(err){返回console.error(err.toString());});document.getElementById("sendButton").addEventListener("click",函数(事件){var user = document.getElementById("userInput").value;var message = document.getElementById("messageInput").value;connection.invoke("SendMessage",用户,消息).catch(function(err){返回console.error(err.toString());});event.preventDefault();});connection.on("ReceiveMessage",功能(用户,消息){var msg = message.replace(/&/g,& amp;").replace(////g,& lt").replace(///g,";& gt;");var encodeMsg =用户+:"+味精;var li = document.createElement("li");li.textContent = encodingMsg;document.getElementById("messagesList").appendChild(li);}); 

这是我的中心班

 使用MentorShip.Models;使用Microsoft.AspNetCore.SignalR;使用系统;使用System.Collections.Generic;使用System.Linq;使用System.Threading.Tasks;命名空间MentorShip.Hubs{公共课程SignalRChat:Hub{上下文c = new Context();公共异步任务SendMessage(字符串用户,字符串消息){等待Clients.All.SendAsync("ReceiveMessage",用户,消息);}}} 

这是我的html代码

 < div class ="container">< div class =行"& nbsp;</div>< div class ="row">< div id ="connectionId">//div< div class ="col-2">接收器ID</div>< div class ="col-4"><输入类型=文本"id ="userInput"/></div></div>< div class ="row">< div class ="col-2">消息</div>< div class ="col-4"><输入类型=文本"id ="messageInput"/></div></div>< div class =行"& nbsp;</div>< div class ="row">< div class ="col-6"><输入类型=按钮";id ="sendButton";value =发送消息"/></div></div></div>< div class ="row">< div class ="col-12">< hr/></div></div>< div class ="row">< div class ="col-6">< ul id ="messagesList">/ul</div></div></div> 

解决方案

要将消息发送给特定用户,可以使用以下方法:

  1. 使用单用户组.

    您可以为每个用户创建一个组,然后在只想覆盖该用户时向该组发送消息.每个组的名称是用户的名称.如果用户有多个连接,则每个连接ID都会添加到该用户的组中.

    例如,基于

  2. 通过ConnectionID发送消息.

    从上面的示例代码中,我们可以在OnConnectedAsyc方法中获取ConnectId和用户名,然后将它们存储在数据库中.然后,您可以在ChatHub.cs中添加SendMessageToUser方法.在这种方法中,您可以查询数据库并根据接收方名称找到connectionId,然后使用 Clients.Client("connectionId").SendAsync()方法将消息发送到特定的用户.

     公共任务SendMessageToUser(字符串发送者,字符串接收者,字符串消息){//根据接收方名称查询数据库并获取连接ID返回Clients.Client("connectionId").SendAsync("ReceiveMessage",发送者,消息);} 

以下是一些相关文章,您可以参考它们:

  • 在程序包管理器控制台"工具中使用以下命令.有关更多详细信息,请检查

  • 添加SignalR客户端库

    • 在解决方案资源管理器中,右键单击该项目,然后选择添加>客户端库.
    • 添加客户端库对话框中,为提供者选择取消.
    • 对于库,输入 @ microsoft/signalr @ latest .
    • 选择选择特定文件",展开dist/browser文件夹,然后选择signalr.js和signalr.min.js.
    • 将目标位置"设置为wwwroot/js/signalr/,然后选择安装".LibMan创建一个wwwroot/js/signalr文件夹并将所选文件复制到其中.
  • 创建SignalR集线器.

    在Project文件夹中,创建一个Hubs文件夹并添加带有以下代码的ChatHub.cs文件:

     名称空间SignalRApp.Hubs{//要求使用Microsoft.AspNetCore.SignalR;//要求使用Microsoft.AspNetCore.Authorization;[授权]公共课程ChatHub:集线器{公共重写任务OnConnectedAsync(){Groups.AddToGroupAsync(Context.ConnectionId,Context.User.Identity.Name);返回base.OnConnectedAsync();}公共异步任务SendMessage(字符串用户,字符串消息){等待Clients.All.SendAsync("ReceiveMessage",用户,消息);}公共任务SendMessageToGroup(字符串发送者,字符串接收者,字符串消息){返回Clients.Group(接收者).SendAsync("ReceiveMessage",发送者,消息);}}} 

  • 在Startup.cs文件中配置SignalR.您可以检查

    I want to implement private chat system with Mssql Database. This codes works as public when I send the message, message is appears all clients. But I want to one to one chat system. One user enter the receiver id which stored in database and message text, then send the message to Receiver . Then the message appears in receiver message area which has that receiver id.

    Here is my js code

    "use strict";
    
    var connection = new signalR.HubConnectionBuilder().withUrl("/chathub").build();
    
    //Disable send button until connection is established
    document.getElementById("sendButton").disabled = true;
    
    connection.start().then(function () {
        document.getElementById("sendButton").disabled = false;
    }).catch(function (err) {
        return console.error(err.toString());
    });
    
    document.getElementById("sendButton").addEventListener("click", function (event) {
        var user = document.getElementById("userInput").value;
        var message = document.getElementById("messageInput").value;
        connection.invoke("SendMessage", user, message).catch(function (err) {
            return console.error(err.toString());
        });
        event.preventDefault();
    });
    connection.on("ReceiveMessage", function (user, message) {
        var msg = message.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
        var encodedMsg = user + ":" + msg;
        var li = document.createElement("li");
        li.textContent = encodedMsg;
        document.getElementById("messagesList").appendChild(li);
    });
    

    Here is my hub class

    using MentorShip.Models;
    using Microsoft.AspNetCore.SignalR;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    
    using System.Threading.Tasks;
    
    namespace MentorShip.Hubs
    {
        public class SignalRChat:Hub
        {
            Context c = new Context();
            
            public async Task SendMessage(string user, string message)
            {
               
                await  Clients.All.SendAsync("ReceiveMessage",user,message);
            }
    
        }
    }
    

    Here is my html code

                <div class="container">
                <div class="row">&nbsp;</div>
                <div class="row">
                    <div id="connectionId"></div>
                    <div class="col-2">Receiver Id</div>
                    <div class="col-4"><input type="text" id="userInput" /></div>
                </div>
                <div class="row">
                    <div class="col-2">Message</div>
                    <div class="col-4"><input type="text" id="messageInput" /></div>
                </div>
                <div class="row">&nbsp;</div>
                <div class="row">
                    <div class="col-6">
                        <input type="button" id="sendButton" value="Send Message" />
                    </div>
                </div>
            </div>
            <div class="row">
                <div class="col-12">
                    <hr />
                </div>
            </div>
            <div class="row">
                <div class="col-6">
                    <ul id="messagesList"></ul>
                </div>
            </div>
        </div>
    

    解决方案

    To send the message to specific user, you could use the following methods:

    1. Use Single-user groups.

      You can create a group for each user, and then send a message to that group when you want to reach only that user. The name of each group is the name of the user. If a user has more than one connection, each connection id is added to the user's group.

      For example, base on the getting start document, I have create a SignalR application, it will send message to all users. Then, in the ChatHub class, add the Authorize attribute and override the OnConnectedAsync() method, in the OnConnectedAsync method, we could create a group based on the Identity User. Then, add a SendMessageToGroup method to send message to group.

       [Authorize]
       public class ChatHub : Hub
       {  
           public override Task OnConnectedAsync()
           { 
               Groups.AddToGroupAsync(Context.ConnectionId, Context.User.Identity.Name);
               return base.OnConnectedAsync();
           }
           public async Task SendMessage(string user, string message)
           {
               await Clients.All.SendAsync("ReceiveMessage", user, message);
           }
      
           public Task SendMessageToGroup(string sender, string receiver, string message)
           {
               return Clients.Group(receiver).SendAsync("ReceiveMessage", sender, message);
           }  
       }
      

      In the Index.cshtml page, add a Receiver input element to enter the receiver name (the same as the group name).

       <div class="container">
           <div class="row">&nbsp;</div>
           <div class="row">
               <div class="col-2">Sender</div>
               <div class="col-4"><input type="text" id="senderInput" /></div>
           </div>
           <div class="row">
               <div class="col-2">Receiver</div>
               <div class="col-4"><input type="text" id="receiverInput" /></div>
           </div>
           <div class="row">
               <div class="col-2">Message</div>
               <div class="col-4"><input type="text" id="messageInput" /></div>
           </div>
           <div class="row">&nbsp;</div>
           <div class="row">
               <div class="col-6">
                   <input type="button" id="sendButton" value="Send Message" />
               </div>
           </div>
       </div>
      

      Then, update the sendButton click event in the chat.js file:

       document.getElementById("sendButton").addEventListener("click", function (event) {
           var sender = document.getElementById("senderInput").value;
           var receiver = document.getElementById("receiverInput").value;
           var message = document.getElementById("messageInput").value;
      
           if (receiver !="") {
      
               connection.invoke("SendMessageToGroup", sender, receiver, message).catch(function (err) {
                   return console.error(err.toString());
               });
           }
           else { 
               connection.invoke("SendMessage", sender, message).catch(function (err) {
                   return console.error(err.toString());
               });
           }
           event.preventDefault();
       });
      

      After that, we could send message to specific user, screenshot as below (if the receiver is null, it will send message to all user, else, will send message to specific user):

    2. Send message via the ConnectionID.

      From the above sample code, in the OnConnectedAsyc method, we could get the ConnectId and the User Name, then, you could store them in the database. Then, you can add the SendMessageToUser method in the ChatHub.cs. In this method, you could query the database and find the connectionId based on the receiver name, after that using Clients.Client("connectionId").SendAsync() method to send the message to a specific user.

       public Task SendMessageToUser(string sender, string receiver, string message)
       {
           //based on the receiver name to query the database and get the connection id
      
           return Clients.Client("connectionId").SendAsync("ReceiveMessage", sender, message);
       }
      

    Here are some related articles, you can refer to them:

    Use hubs in SignalR for ASP.NET Core

    Mapping SignalR Users to Connections

    Update:

    Detail Steps:

    1. Open the Visual Studio 2019 (the latest version), and create an Asp.net Core Web Application (named SignalRApp, using .net core 3.1 version):

      Choose the MVC template and change the Authentication to "Individual User Accounts".

    2. Using the following command in the Package Manager Console tools. More detail information, check EF Core Migrations.

      add-migration InitialCreate
      update-database

    3. After that, we could run the application and register users. The login screenshot as below:

    4. Add the SignalR client library

      • In Solution Explorer, right-click the project, and select Add > Client-Side Library.
      • In the Add Client-Side Library dialog, for Provider select unpkg.
      • For Library, enter @microsoft/signalr@latest.
      • Select Choose specific files, expand the dist/browser folder, and select signalr.js and signalr.min.js.
      • Set Target Location to wwwroot/js/signalr/, and select Install. LibMan creates a wwwroot/js/signalr folder and copies the selected files to it.
    5. Create a SignalR hub.

      In the Project folder, create a Hubs folder and add a ChatHub.cs file with the following code:

       namespace SignalRApp.Hubs
       {
           //require using Microsoft.AspNetCore.SignalR;
           //require using Microsoft.AspNetCore.Authorization;
           [Authorize]
           public class ChatHub : Hub
           {
               public override Task OnConnectedAsync()
               {
                   Groups.AddToGroupAsync(Context.ConnectionId, Context.User.Identity.Name);
                   return base.OnConnectedAsync();
               }
               public async Task SendMessage(string user, string message)
               {
                   await Clients.All.SendAsync("ReceiveMessage", user, message);
               }
      
               public Task SendMessageToGroup(string sender, string receiver, string message)
               {
                   return Clients.Group(receiver).SendAsync("ReceiveMessage", sender, message);
               }
           }
       }
      

    6. Configure SignalR in the Startup.cs file. You could check this article.

      The startup.cs file as below:

       public class Startup
       {
           public Startup(IConfiguration configuration)
           {
               Configuration = configuration;
           }
      
           public IConfiguration Configuration { get; }
      
           // This method gets called by the runtime. Use this method to add services to the container.
           public void ConfigureServices(IServiceCollection services)
           {
               services.AddDbContext<ApplicationDbContext>(options =>
                   options.UseSqlServer(
                       Configuration.GetConnectionString("DefaultConnection")));
               services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
                   .AddEntityFrameworkStores<ApplicationDbContext>();
               services.AddControllersWithViews();
               services.AddRazorPages();
      
               services.AddSignalR(); 
           }
      
           // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
           public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
           {
               if (env.IsDevelopment())
               {
                   app.UseDeveloperExceptionPage();
                   app.UseDatabaseErrorPage();
               }
               else
               {
                   app.UseExceptionHandler("/Home/Error");
                   // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                   app.UseHsts();
               }
               app.UseHttpsRedirection();
               app.UseStaticFiles();
      
               app.UseRouting();
      
               app.UseAuthentication();
               app.UseAuthorization();
      
               app.UseEndpoints(endpoints =>
               {
                   endpoints.MapControllerRoute(
                       name: "default",
                       pattern: "{controller=Home}/{action=Index}/{id?}");
                   endpoints.MapRazorPages();
                   endpoints.MapHub<ChatHub>("/chathub");
               });
           }
       }
      

    7. Add SignalR client code:

      [Note] In this step, please pay attention to the js file path. If the js file doesn't load successfully, the client code will not work.

      In the Home controller Index page(Index.cshtml), replace the content as below:

       @{
           ViewData["Title"] = "Index";
       }
      
       <h1>Index</h1>
      
       <div class="container">
           <div class="row">&nbsp;</div>
           <div class="row">
               <div class="col-2">Sender</div>
               <div class="col-4"><input type="text" id="senderInput" /></div>
           </div>
           <div class="row">
               <div class="col-2">Receiver</div>
               <div class="col-4"><input type="text" id="receiverInput" /></div>
           </div>
           <div class="row">
               <div class="col-2">Message</div>
               <div class="col-4"><input type="text" id="messageInput" /></div>
           </div>
           <div class="row">&nbsp;</div>
           <div class="row">
               <div class="col-6">
                   <input type="button" id="sendButton" value="Send Message" />
               </div>
           </div>
       </div>
       <div class="row">
           <div class="col-12">
               <hr />
           </div>
       </div>
       <div class="row">
           <div class="col-6">
               <ul id="messagesList"></ul>
           </div>
       </div>
       <script src="~/js/signalr/dist/browser/signalr.js"></script>
       <script src="~/js/chat.js"></script>
      

      In the wwwroot/js folder, create a chat.js file with the following code:

       "use strict";
      
       var connection = new signalR.HubConnectionBuilder().withUrl("/chatHub").build();
      
       //Disable send button until connection is established
       document.getElementById("sendButton").disabled = true;
      
       connection.on("ReceiveMessage", function (user, message) {
           var msg = message.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
           var encodedMsg = user + " says " + msg;
           var li = document.createElement("li");
           li.textContent = encodedMsg;
           document.getElementById("messagesList").appendChild(li);
       });
      
       connection.start().then(function () {
           document.getElementById("sendButton").disabled = false;
       }).catch(function (err) {
           return console.error(err.toString());
       });
      
       document.getElementById("sendButton").addEventListener("click", function (event) {
           var sender = document.getElementById("senderInput").value;
           var receiver = document.getElementById("receiverInput").value;
           var message = document.getElementById("messageInput").value;
      
           if (receiver != "") {
      
               connection.invoke("SendMessageToGroup", sender, receiver, message).catch(function (err) {
                   return console.error(err.toString());
               });
           }
           else {
               connection.invoke("SendMessage", sender, message).catch(function (err) {
                   return console.error(err.toString());
               });
           }
      
      
           event.preventDefault();
       });
      

    After that we could send messages to user via groups. Like this:

    这篇关于如何在Asp.Net.Core Mvc Signalr中建立一对一的聊天系统?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆