今天來點輕鬆的吧!來寫寫強型別的Hub和把HubContext注入Controller
SignalR的Hub
介面只規定我們要實作OnConnectedAsync
和OnDisconnectedAsync
兩個事件而已,其他的事件名稱全都是自定義的magic string
,
這樣會可能會照成大小寫拼錯,或是拼錯了不知道,所以強行別Hub就能幫助我們在開發偵錯時就先找到錯誤。
其實就是也就是定義一個介面Interface
而已,我們來簡單設計一個介面,大概像下面這樣
public interface IChatClient
{
Task AddGroup(string groupName, string user);
Task ReceiveMsgGroup(string groupName, string user, string message);
}
再來套用到自己寫的Hub
上,使用繼承的方式加入,因為是它是一個泛型Hub<T>
public class ChatHub : Hub<IChatClient>
{
public async Task AddGroup(string user, string message)
{
await Groups.AddToGroupAsync(Context.ConnectionId, groupName);
await Clients.Group(groupName).SendAsync("RecGroupMsg", $"{user} 已加入 群組:{groupName}。");
}
public Task ReceiveMsgGroup(tring groupName, string user, string message)
{
return Clients.Group(groupName).SendAsync("ReceiveMessageGroup", groupName , username, message);
}
}
這樣的好處是能把方法寫到Controller裡面,缺點則是我們呼叫不到Context
物件,這樣就沒辦法知道是哪個ClientID
傳過來的
接下來就來看看怎麼把HubContext注入Controller
注入Controller吧!
我們用Day3同一個專案,建立一個Controller資料夾,在裡面建立一個ChatController.cs
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.SignalR;
using CoreWeb.Hubs;
namespace CoreWeb.Controllers
{
public class ChatController : Controller
{
}
}
建立一個變數,在建構子注入HubContext<T>
,<T>
為自己建立的任意Hub
private readonly IHubContext<ChatHub> _hubContext;
public ChatController(IHubContext<ChatHub> hubContext)
{
_hubContext = hubContext;
}
傳送訊息改成從Controller進入,所以我們要在Controller建立傳送訊息的方法,方法基本上跟在Hub裡面時一模一樣
public async Task SendMessage(string user, string message)
{
await _hubContext.Clients.All.SendAsync("ReceiveMessage",user, message);
}
在Starup.cs
註冊MVC
方法
public void ConfigureServices(IServiceCollection services)
{
services.AddSignalR().AddMessagePackProtocol();
services.AddMvc();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseSignalR(routes =>
{
routes.MapHub<ChatHub>("/chatHub");
});
app.UseDefaultFiles();
app.UseStaticFiles();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Chat}/{action=Index}/{id?}");
});
}
前端的呼叫方法有點不一樣,得換用ajax
的方式,這邊我們用HTML5內建的fetch()
document.getElementById("submitBtn").addEventListener("click", function (event) {
var user = document.getElementById("name").value;
var message = document.getElementById("msg").value;
fetch(`Chat/SendMessage?user=${user}&message=${message}`,{
method:"GET"
})
event.preventDefault();
});
前端接收則還是保持原本的狀況,大概這樣就完成了,下一篇我們在來看看前端的方用法。
本篇同步於個人BLOG
有些地方字都沒貼好,連結也放錯...感覺不是很用心
但還是謝謝分享。
謝謝
當時寫的太敢都沒什麼時間校稿
寫完又覺得快虛脫了!XD