ASP.NET Core SignalR 入门
本章将和大家分享使用 SignalR 生成实时应用的基础知识。通过本文您将学习如何:使用ASP.NET Core SignalR + MVC + Vue 2.x + require 最终创建一个正常运行的简易聊天应用。
废话不多说,我们直接来看一个Demo,Demo的目录结构如下所示:

本Demo的Web项目为ASP.NET Core Web 应用程序(目标框架为.NET 7.0) MVC项目。
1、创建 SignalR 中心
中心是一个类,用作处理客户端 - 服务器通信的高级管道。
可通过已连接客户端调用 SendMessage,以向所有客户端发送消息。
using Microsoft.AspNetCore.SignalR;
namespace SignalRChat.Hubs
{
/// summary>
/// Hub 类管理连接、组和消息
/// /summary>
public class ChatHub : Hub
{
/// summary>
/// 可通过已连接客户端调用 SendMessage,以向所有客户端发送消息
/// /summary>
public async Task SendMessage(string user, string message)
{
//Clients.All 向所有的客户端发送消息(服务端调用客户端)
//ReceiveMessage 是客户端监听的方法
await Clients.All.SendAsync("ReceiveMessage", user, message);
/*
// 常用方法
// 给所有人发送消息
await Clients.All.SendAsync("ReceiveMessage", data);
// 给组里所有人发消息
await Clients.Group("Users").SendAsync("ReceiveMessage", data);
// 给调用方法的那个人发消息
await Clients.Caller.SendAsync("ReceiveMessage", data);
// 给除了调用方法的以外所有人发消息
await Clients.Others.SendAsync("ReceiveMessage", data);
// 给指定connectionId的人发消息
await Clients.User(connectionId).SendAsync("ReceiveMessage", data);
// 给指定connectionId的人发消息
await Clients.Client(connectionId).SendAsync("ReceiveMessage", data);
// 给指定connectionId的人发消息,同时指定多个connectionId
await Clients.Clients(IReadOnlyList>
connectionIds).SendAsync("ReceiveMessage", data);
*/
}
}
}
2、配置 SignalR
必须将 SignalR 服务器配置为将 SignalR 请求传递给 SignalR。将以下代码添加到 Program.cs 文件。
builder.Services.AddSignalR();
app.MapHubChatHub>
("/chatHub");
完整的Program.cs 文件:
using SignalRChat.Hubs;
namespace SignalRChat
{
public class Program
{
public static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
//服务注册(往容器中添加服务)
// Add services to the container.
builder.Services.AddControllersWithViews();
builder.Services.AddSignalR();
//SignalR
var app = builder.Build();
//配置Http请求处理管道
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Home/Error");
}
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
//配置MVC路由
app.MapControllerRoute(
name: "areas",
pattern: "{
area:exists}
/{
controller=Home}
/{
action=Index}
/{
id?}
");
app.MapControllerRoute(
name: "default",
pattern: "{
controller=Home}
/{
action=Index}
/{
id?}
");
app.MapHubChatHub>
("/chatHub");
//SignalR
app.Run();
}
}
}
以上突出显示(标红)的代码将 SignalR 添加到 ASP.NET Core 依赖关系注入和路由系统。
3、添加 SignalR 客户端代码
chat.js 文件,核心 JavaScript 代码如下:
//第一个参数:加载依赖模块,可以是require_config中定义的短模块名,也可以是完整的模块路径(去掉.js后缀名,根目录为require_config中设置的baseUrl)
//第二个参数:执行加载完后的回调函数
require(['../common/base', 'jquery', 'signalr'], function (base, $, signalR) {
let axios = base.axios;
var vm = new base.vue({
el: '#app', //挂载点
mixins: [base.mixin], //混入,类似基类的概念
data: {
connectionSignalR: '', //SignalR连接
user: '',
message: '',
msgList: []
}
,
//created钩子函数
created: function () {
this.initSignalR();
//初始化SignalR
}
,
//mounted钩子函数
mounted: function () {
//console.log('This is index mounted');
}
,
//方法
methods: {
//初始化SignalR
initSignalR: function () {
var _this = this;
//创建连接
_this.connectionSignalR = new signalR.HubConnectionBuilder()
.withUrl("/chatHub")
.configureLogging(signalR.LogLevel.Error)
.build();
/*
日志等级:
signalR.LogLevel.Error:错误消息。Error仅记录消息。
signalR.LogLevel.Warning:有关潜在错误的警告消息。日志 Warning 和 Error 消息。
signalR.LogLevel.Information:无错误的状态消息。日志 Information 、 Warning 和 Error 消息。
signalR.LogLevel.Trace:跟踪消息。记录所有内容,包括中心和客户端之间传输的数据。
*/
//监听中心(服务端)发送的消息(服务端调用客户端)
//ReceiveMessage 是服务端调用客户端的方法名
_this.connectionSignalR.on("ReceiveMessage", function (user, message) {
_this.msgList.push({
user: user,
message: message
}
);
}
);
//启动连接
_this.connectionSignalR.start().then(function () {
//启动连接后需要立即执行的逻辑
//document.getElementById("sendButton").disabled = false;
}
).catch(function (err) {
return console.error(err.toString());
}
);
}
,
//发送消息
sendMsg: function () {
var _this = this;
if (_this.message) {
//向中心(服务端)发送消息(客户端调用服务端)
//SendMessage 是服务端定义的的方法
_this.connectionSignalR.invoke("SendMessage", _this.user, _this.message).catch(function (err) {
return console.error(err.toString());
}
);
_this.message = '';
//发送完清空消息
}
}
,
}
}
);
}
);
公共脚本文件代码如下:
其中 require_config.js 文件代码如下:
//主要用来配置模块的加载位置(设置短模块名)
require.config({
baseUrl: '/js/lib', //设置根目录
paths: {
//如果没有设置根目录则需要填写完整路径
'vue': 'vue',
'axios': 'axios',
'jquery': 'jquery-3.6.3',
'signalr': 'signalr',
//paths还有一个重要的功能,就是可以配置多个路径,如果远程cdn库没有加载成功,可以加载本地的库,如下:
//'jquery': ['http://libs.baidu.com/jquery/2.0.3/jquery', '/js/lib/jquery-3.6.3'],
}
}
);
其中 base.js 文件代码如下:
//define用来自定义模块
//第一个参数:加载依赖模块,可以是require_config中定义的短模块名,也可以是完整的模块路径(去掉.js后缀名)
//第二个参数:执行加载完后的回调函数
define(['vue', 'axios', '../components/buttonCounter'], function (vue, axios, buttonCounter) {
//TODO 此处可以处理一些公共的逻辑
//vue.component('component-a', {
/* ... */ }
);
//全局注册组件
//vue.mixin({
...}
);
//全局混入
/*
定义组件名的方式有两种:
1、使用 kebab-case (短横线分隔命名)
当使用 kebab-case (短横线分隔命名) 定义一个组件时,你也必须在引用这个自定义元素时使用 kebab-case,例如 my-component-name>
2、使用 PascalCase (首字母大写命名)
当使用 PascalCase (首字母大写命名) 定义一个组件时,你在引用这个自定义元素时两种命名法都可以使用。
也就是说 my-component-name>
和 MyComponentName>
都是可接受的。
注意,尽管如此,直接在 DOM (即非字符串的模板) 中使用时只有 kebab-case 是有效的。
*/
//Vue.component(...) 的第一个参数为组件名。
vue.component('button-counter', buttonCounter);
//全局注册
return {
vue: vue,
axios: axios,
//Vue混入
mixin: {
//数据
data: function () {
return {
domain: '', //域名
}
}
,
//组件
components: {
}
,
//created钩子函数
created: function () {
//console.log('This is base created');
var _this = this;
_this.getDomain();
}
,
//mounted钩子函数
mounted: function () {
console.log('This is base mounted');
}
,
//方法
methods: {
//测试
doTest: function () {
console.log('This is base doTest');
}
,
//获取域名
getDomain: function () {
var _this = this;
_this.domain = 'http://localhost:5296';
}
,
}
}
,
}
;
}
);
控制器和视图文件代码如下:
其中 HomeController 控制器代码如下:
using Microsoft.AspNetCore.Mvc;
using SignalRChat.Models;
using System.Diagnostics;
namespace SignalRChat.Controllers
{
public class HomeController : Controller
{
private readonly ILoggerHomeController>
_logger;
public HomeController(ILoggerHomeController>
logger)
{
_logger = logger;
}
public IActionResult Index()
{
return View();
}
}
}
其中布局页 _Layout.cshtml 视图文件代码如下:
!DOCTYPE html>
html lang="en">
head>
meta charset="utf-8" />
meta name="viewport" content="width=device-width, initial-scale=1.0" />
title>
@ViewData["Title"] - SignalRChat/title>
script src="/js/lib/require.js">
/script>
script src="/js/common/require_config.js">
/script>
@await RenderSectionAsync("header", required: false)
/head>
body>
div class="container">
@RenderBody()
/div>
@await RenderSectionAsync("footer", required: false)
/body>
/html>
其中 Index.cshtml 视图文件代码如下:
@{
ViewData["Title"] = "Home Page";
}
div id="app">
template>
p>
User:input v-model="user" type="text" />
/p>
p>
Message: input v-model="message" type="text" />
/p>
p>
button v-on:click="sendMsg">
发送/button>
/p>
hr />
ul>
li v-for="(item, index) in msgList" :key="index">
{
{
item.user }
}
says {
{
item.message }
}
/li>
/ul>
/template>
/div>
@section footer{
script src="/js/pageScript/chat.js">
/script>
}
4、运行应用
此处我使用的是 .NET Core CLI 命令行的方式来运行应用,如下所示:

打开两个浏览器实例,分别访问:http://localhost:5296/ , 运行结果如下:

选择任一浏览器,输入名称和消息,然后点击“发送”按钮:

可以发现,两个页面上会立即显示名称和消息。
Demo源码:
链接:https://pan.baidu.com/s/13ppUjr0h2dse5vnw5uiZ9Q
提取码:qm2a
声明:本文内容由网友自发贡献,本站不承担相应法律责任。对本内容有异议或投诉,请联系2913721942#qq.com核实处理,我们将尽快回复您,谢谢合作!
若转载请注明出处: ASP.NET Core SignalR 入门
本文地址: https://pptw.com/jishu/557845.html