版本.Net6+Vue3+Element-Plus
问题
- Swagger加锁后不能访问接口 (看第三步)
- 跳过WebSocket验证 (看第四步里面)
- 添加自定义接受方法 (看第四步)
- 不能使用
第一步、下载包
后端:
前端:命令
npm install @microsoft/signalr
第二步、加后端触发方法
后端:
public class ServerHub : Hub
{
/// <summary>
/// 已连接的用户信息
/// </summary>
public static List<UserModel> OnlineUser { get; set; } = new List<UserModel>();
private readonly ILogger<ServerHub> _logger;
private readonly IHttpContextAccessor _accessor;
public ServerHub(ILogger<ServerHub> logger, IHttpContextAccessor accessor)
{
_logger = logger;
_accessor = accessor;
}
/// <summary>
/// 当连接成功时执行
/// </summary>
public override Task OnConnectedAsync()
{
string connId = Context.ConnectionId;
_logger.LogWarning("SignalR已连接");
//验证Token "access_token"这个值是默认的不要改
var token= _accessor.HttpContext.Request.Query["access_token"];
var user = JwtHelper.SerializeJwt(token);
_logger.LogWarning("SignalR已连接,用户名:" + user.UserName);
//连接用户 这里可以存在Redis
var model= new UserModel
{
ConnectionId = connId,
Token = token,
UserName = user.UserName
};
OnlineUser.Add(model);
//给当前连接返回消息 .Clients可以发多个连接ID
// "ConnectResponse"这个是前端接收的方法名字
Clients.Client(connId).SendAsync("ConnectResponse",
new ApiResult<UserModel>()
{
state=200,
data = model,
msg= user.UserName+"连接成功"
});
return base.OnConnectedAsync();
}
/// <summary>
/// 当连接断开时的处理
/// </summary>
public override Task OnDisconnectedAsync(Exception exception)
{
string connId = Context.ConnectionId;
var model = OnlineUser.Find(u => u.ConnectionId == connId);
int count = OnlineUser.RemoveAll(u => u.ConnectionId == connId);
if (model != null)
{
//给当前连接返回消息 .Clients可以发多个连接ID
// "DisconnectResponse"这个是前端接收的方法名字
Clients.Client(connId).SendAsync("DisconnectResponse",
new ApiResult<bool>()
{
state = 1000,
data = true,
msg = "断开连接"
});
}
return base.OnDisconnectedAsync(exception);
}
/// <summary>
/// 自定义方法:接受用户的数进行推送
/// </summary>
/// <returns></returns>
public async Task SendMessage(string user,string msg)
{
ApiResult<UserModel> result = new ApiResult<UserModel>();
result.data = new UserModel
{
ConnectionId = Context.ConnectionId,
Token = "",
UserName = user
};
result.state = 200;
result.msg = msg;
//推送给所有连接ID的第一条数据
await Clients.Clients(OnlineUser.Select(q=>q.ConnectionId).ToList()).SendAsync("SendMessage", result);
}
}
第三步、在Program.cs中添加配置
builder.Services.AddSignalR();
再向中间管道添加终结点
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapHub<ServerHub>("/ServerHub");
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
Swagger加锁后不能访问接口
加锁后的配置方式稍微有点差别(我当时找了半天问题)
等于说把他拆出来了
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
app.UseAuthentication();
app.UseAuthorization();
app.MapHub<ServerHub>("/ServerHub");
第四步、加前端接收方法
前端: 重点注意没有
<template>
<div>
<input type="text" placeholder="请输入用户名" v-model="user" />
<input type="text" placeholder="请输入内容" v-model="msg">
<button @click="Submit">发送消息</button><br/>
<textarea type="text" v-model="txt" ></textarea>
</div>
</template>
<script>
import store from '@/store/index' //这个可以不加,这个是我localStorage缓存的东西
import * as signalR from "@microsoft/signalr";
let hubUrl ="http://localhost:5193/serverHub";
//实例化
const connection = new signalR.HubConnectionBuilder()
.withAutomaticReconnect()
.withUrl(hubUrl,
{accessTokenFactory:()=>store.state.user.refreshToken,//添加Token验证
skipNegotiation:true, //是否跳过协议 true
transport:signalR.HttpTransportType.WebSockets //跳过Websocket协议
})
.build();
//启动
connection.start().catch(err=>{connsole.log(err)});
export default({
data(){return {
txt:"",
user: "",
msg: ""
}},
methods: {
Submit: function() {
if(this.msg.trim()==""){
alert("不能发送空白消息");
return;
}
//访问自定义后端方法"SendMessage"
connection.invoke("SendMessage", this.user, this.msg);
this.msg = "";
}
},
created(){
var _this = this;
//"ConnectResponse" 与后端里面的名字对应,根据名字返回到这个方法里面
connection.on("ConnectResponse", function(data) {
if(data.code==1)
_this.txt = data.message;
})
//接收
connection.on("SendMessage", function(data) {
if(data.code==1)
_this.txt = data.message;
})
}
})
</script>
结果: