原文:weblogs.asp.net/ricardopere…javascript
做者:Ricardo Pereshtml
转载自:oopsguy.comjava
SignalR 是一个用于实现实时功能的 Microsoft .NET 库。它使用了多种技术来实现服务器与客户端间的双向通讯,服务器能够随时将消息推送到链接的客户端。node
如今你能够在 ASP.NET Core 预发行版本中体验它(译者:根据原文的发布时间)。我已经介绍过几回 SignalR 了。web
你将须要安装 Microsoft.AspNetCore.SignalR.Client 和 Microsoft.AspNetCore.SignalR 这两个 Nuget 预发行包。此外,你还须要 NPM(Node 包管理器)。安装 NPM 后,你须要获取 @aspnet/signalr-client 包,以后再从 node_modules@aspnet\signalr-client\dist\browser 文件夹中获取 signalr-client-1.0.0-alpha1-final.js 文件(版本可能不一样),并将其放置在 wwwroot 文件夹下,以即可以从页面引用到它。npm
在使用前,咱们须要在 ConfigureServices 中注册必须的服务:服务器
services.AddSignalR();
复制代码
咱们将实现一个简单的聊天客户端,所以要在 Configure 方法中注册一个 ChatHub:app
app.UseSignalR(routes =>
{
routes.MapHub<ChatHub>("chat");
});
复制代码
注意:UseSignalR 必须在 UseMvc 以前调用!asp.net
若是你有不一样的端点,能够为每一个 hub 执行此操做。async
在视图或布局文件中,添加对 signalr-client-1.0.0-alpha1-final.js 文件的引用:
<script src="libs/signalr-client/signalr-client-1.0.0-alpha1-final.js"></script>
复制代码
该 hub 是一个继承了 Hub 的类。你可在其中添加 JavaScript 可能用到的方法。咱们将实现一个 chat hub:
public class ChatHub : Hub
{
public async Task Send(string message) {
await this.Clients.All.InvokeAsync("Send", message);
}
}
复制代码
如上所述,咱们有一个方法(Send),在本例中,它采用了单参数(message)。你不须要在广播调用(InvokeAsync)上传递相同的参数,能够发送任何你想要传递的参数。
回到客户端部分,在引用 SignalR JavaScript 文件后添加以下代码:
<script> var transportType = signalR.TransportType.WebSockets; //can also be ServerSentEvents or LongPolling var logger = new signalR.ConsoleLogger(signalR.LogLevel.Information); var chatHub = new signalR.HttpConnection(`http://${document.location.host}/chat`, { transport: transportType, logger: logger }); var chatConnection = new signalR.HubConnection(chatHub, logger); chatConnection.onClosed = e => { console.log('connection closed'); }; chatConnection.on('Send', (message) => { console.log('received message'); }); chatConnection.start().catch(err => { console.log('connection error'); }); function send(message) { chatConnection.invoke('Send', message); } </script>
复制代码
请注意:
因此,每当有人访问此页面并调用 JavaScript send函数时,它将调用 ChatHub 类上的 Send 方法。该类基本上会向全部链接的客户端(Clients.All)广播此消息。也能够将消息发送到特定的组:
await this.Clients.Group("groupName").InvokeAsync("Send", message);
复制代码
或特定客户端:
await this.Clients.Client("id").InvokeAsync("Send", message);
复制代码
你若是想启用身份验证,能够添加一个由链接 ID 和 ClaimPrincipal 标识的用户,以下所示:
public override Task OnConnectedAsync() {
this.Groups.AddAsync(this.Context.ConnectionId, "groupName");
return base.OnConnectedAsync();
}
复制代码
OnConnectedAsync 在新用户链接时将被调用。当有人断开链接时,OnDisconnectedAsync 将被调用:
public override Task OnDisconnectedAsync(Exception exception) {
return base.OnDisconnectedAsync(exception);
}
复制代码
若是在断开链接时发生了异常,则 exception 参数将为非空值。
只有当前用户进行身份验证时, Context 属性才会提供 ConnectionId 和 User 两个属性。ConnectionId 始终被设置为同一个用户,不会改变。 另外,假设你想经过定时器 hub 将定时器 tick 发送到全部链接的客户端,则能够在 Configure 方法中执行此操做:
TimerCallback callback = (x) => {
var hub = serviceProvider.GetService<IHubContext<TimerHub>>();
hub.Clients.All.InvokeAsync("Notify", DateTime.Now);
};
var timer = new Timer(callback);
timer.Change(TimeSpan.FromSeconds(0), TimeSpan.FromSeconds(10));
复制代码
咱们启动了一个 Timer,从那里咱们获得了一个定时器 hub 的引用,并使用当前时间戳调用其 Notify 方法。TimerHub 类只是这样:
public class TimerHub : Hub
{
}
复制代码
请注意,此类没有公共方法,由于它不是由 JavaScript 调用,它仅用于从外部广播消息(Timer 回调)。
最后,咱们还能够将消息从外部发送到 hub。当使用控制器时,你须要注入一个 IHubContext 实例,你能够在里面发送消息到 hub,而后将其广播:
private readonly IHubContext<ChatHub> _context;
[HttpGet("Send/{message}")]
public IActionResult Send(string message) {
//for everyone
this._context.Clients.All.InvokeAsync("Send", message);
//for a single group
this._context.Clients.Group("groupName").InvokeAsync("Send", message);
//for a single client
this._context.Clients.Client("id").InvokeAsync("Send", message);
return this.Ok();
}
复制代码
须要注意的是,这与访问 ChatHub 类不一样,实现起来并不简单,你须要使用 chat hub 的链接才行。
SignalR 还没有发布,仍可能会有一些变化。在之后的文章中,我将更详细地介绍 SignalR,包括其可扩展性机制和一些更高级的使用场景。敬请期待!