系列
源碼地址:https://github.com/QQ2287991080/SignalRServerAndVueClientDemo
上一篇博客實現是了消息的實時通信,這一篇博客主要講如何從中心服務內部向客戶端發送消息。
先看下最終效果:
在core應用程序里加一個控制器TestController
注入控制器中的IHubContext實例,並且添加方法
[Route("api/[controller]/[action]")] [ApiController] public class TestController : ControllerBase { private readonly IHubContext<ChatHub> _hubContext; public TestController(IHubContext<ChatHub> hubContext) { _hubContext = hubContext; } [HttpGet] public async Task<int> Get() { await _hubContext.Clients.All.SendAsync("ReceiveMessage", "系統通知", $"北京時間{DateTime.Now}"); return 0; } }
然后啟用路由和控制器
//啟用控制器 services.AddControllers();
app.UseEndpoints(endpoints => { //終結點設置路由默認 endpoints.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); endpoints.MapRazorPages(); endpoints.MapHub<ChatHub>("/chathub"); });
哎呀忘記配置跨域了
//配置跨域 services.AddCors(c => c.AddPolicy("AllowAll", p => { p.AllowAnyOrigin(); p.AllowAnyMethod(); p.AllowAnyHeader(); }) );
//配置跨域別把中間件的位置放錯了哦 app.UseCors("AllowAll");
這里為啥要配置跨域呢,因為之前signalr的連接時連接客戶端的,它們基於底層的通信協議(這太高深了 ,俺也不懂),而現在我們通過瀏覽器發送請求獲取系統通知的話,就會存在跨域的情況,所以需要配置
因為現在需要發送請求,所以我安裝個axios
npm install axios
然后在mian.js配置下。
import axios from 'axios' Vue.prototype.$http = axios
更新一下上次寫的home.vue里的代碼
<template> <div class="home"> <h1>前端演示SignalR</h1> <input v-model="user" type="text" /> <input v-model="message" type="text" /> <button @click="sendAll">發送全部</button> <button @click="sendOwn">對自己發送</button> <button @click="sendClient">系統發送消息</button> <div> <ul v-for="(item ,index) in messages" v-bind:key="index +'itemMessage'"> <li>{{item.user}} says {{item.message}}</li> </ul> </div> </div> </template> <script> // @ is an alias to /src import HelloWorld from "@/components/HelloWorld.vue"; import * as signalR from "@aspnet/signalr"; export default { name: "Home", components: { HelloWorld }, data() { return { user: "", //用戶 message: "", //消息 connection: "", //signalr連接 messages: [] //返回消息 }; }, methods: { //給全部發送消息 sendAll: function() { this.connection .invoke("SendMessage", this.user, this.message) .catch(function(err) { return console.error(err); }); }, //只給自己發送消息 sendOwn: function() { this.connection .invoke("SendMessageCaller", this.message) .catch(function(err) { return console.error(err); }); }, //系統發送消息 sendClient: function() { this.$http.get("http://localhost:13989/api/test/get").then(resp => { console.log(resp); }); } }, created: function() { let thisVue = this; this.connection = new signalR.HubConnectionBuilder() .withUrl("http://localhost:13989/chathub", { skipNegotiation: true, transport: signalR.HttpTransportType.WebSockets }) .configureLogging(signalR.LogLevel.Information) .build(); this.connection.on("ReceiveMessage", function(user, message) { thisVue.messages.push({ user, message }); console.log({ user, message }); }); this.connection.on("ReceiveCaller", function(message) { let user = "自己"; //這里為了push不報錯,我就弄了一個默認值。 thisVue.messages.push({ user, message }); console.log({ user, message }); }); this.connection.start(); } }; </script>
這樣的話,就能開篇那個效果了。
這里說幾個注意的點,添加控制器之后一定要啟用他,還有路由也要配置,否則你用postman的也是請求不到的,然后就是跨域配置,這些都是實現這個功能不能缺少的配置。
源碼地址:https://github.com/QQ2287991080/SignalRServerAndVueClientDemo