Can*_*man 2 asp.net-mvc-3 signalr asp.net-core
我想用Mssql数据库实现私人聊天系统。当我发送消息时,此代码作为公共代码工作,消息会出现在所有客户端。但我想要一对一的聊天系统。用户输入数据库中存储的接收者ID和消息文本,然后将消息发送给接收者。然后该消息将出现在具有该接收者 ID 的接收者消息区域中。
这是我的js代码
"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, "&").replace(/</g, "<").replace(/>/g, ">");
var encodedMsg = user + ":" + msg;
var li = document.createElement("li");
li.textContent = encodedMsg;
document.getElementById("messagesList").appendChild(li);
});
Run Code Online (Sandbox Code Playgroud)
这是我的中心课程
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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
这是我的 html 代码
<div class="container">
<div class="row"> </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"> </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>
Run Code Online (Sandbox Code Playgroud)
要将消息发送给特定用户,您可以使用以下方法:
使用单用户组。
您可以为每个用户创建一个组,然后当您只想联系该用户时向该组发送消息。每个组的名称就是用户的名称。如果一名用户有多个连接,则每个连接 ID 都会添加到该用户的组中。
例如,根据入门文档,我创建了一个 SignalR 应用程序,它将向所有用户发送消息。然后,在 ChatHub 类中,添加 Authorize 属性并重写 OnConnectedAsync() 方法,在 OnConnectedAsync 方法中,我们可以基于身份用户创建一个组。然后,添加 SendMessageToGroup 方法以将消息发送到组。
[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);
}
}
Run Code Online (Sandbox Code Playgroud)
在 Index.cshtml 页面中,添加 Receiver 输入元素以输入接收者名称(与组名称相同)。
<div class="container">
<div class="row"> </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"> </div>
<div class="row">
<div class="col-6">
<input type="button" id="sendButton" value="Send Message" />
</div>
</div>
</div>
Run Code Online (Sandbox Code Playgroud)
然后,更新 chat.js 文件中的 sendButton 单击事件:
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();
});
Run Code Online (Sandbox Code Playgroud)
之后,我们就可以向特定用户发送消息,截图如下(如果接收者为空,则向所有用户发送消息,否则,向特定用户发送消息):
通过 ConnectionID 发送消息。
从上面的示例代码中,在OnConnectedAsyc方法中,我们可以获得ConnectId和User Name,然后,您可以将它们存储到数据库中。然后,您可以在 ChatHub.cs 中添加 SendMessageToUser 方法。在此方法中,您可以查询数据库并根据接收者名称找到connectionId,然后使用Clients.Client("connectionId").SendAsync()方法将消息发送给特定用户。
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);
}
Run Code Online (Sandbox Code Playgroud)
这里有一些相关的文章,你可以参考一下:
在 SignalR 中使用 ASP.NET Core 的集线器
更新:
详细步骤:
打开Visual Studio 2019(最新版本),创建一个Asp.net Core Web应用程序(名为SignalRApp,使用.net core 3.1版本):
选择 MVC 模板并将身份验证更改为“个人用户帐户”。
在包管理器控制台工具中使用以下命令。更多详细信息,请查看EF Core 迁移。
add-migration InitialCreate
update-database
之后,我们可以运行应用程序并注册用户。登录截图如下:
添加 SignalR 客户端库
创建 SignalR 集线器。
在Project文件夹中,创建一个Hubs文件夹并添加一个ChatHub.cs文件,其中包含以下代码:
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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
在 Startup.cs 文件中配置 SignalR。你可以看看这篇文章。
startup.cs文件如下:
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");
});
}
}
Run Code Online (Sandbox Code Playgroud)
添加SignalR客户端代码:
【注意】这一步请注意js文件路径。如果js文件没有成功加载,客户端代码将无法工作。
在Home控制器索引页面(Index.cshtml)中,替换内容如下:
@{
ViewData["Title"] = "Index";
}
<h1>Index</h1>
<div class="container">
<div class="row"> </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"> </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>
Run Code Online (Sandbox Code Playgroud)
在 wwwroot/js 文件夹中,使用以下代码创建 chat.js 文件:
"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, "&").replace(/</g, "<").replace(/>/g, ">");
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();
});
Run Code Online (Sandbox Code Playgroud)
之后我们可以通过组向用户发送消息。像这样:
| 归档时间: |
|
| 查看次数: |
10070 次 |
| 最近记录: |