[译] 在 ASP.NET Core 中使用 SignalR

weblogs.asp.net/ricardopere…
作者:Ricardo Peres
译者:oopsguy.com

介绍

SignalR 是一个用于实现实时网站的 Microsoft .NET 库。它使用多种技术来实现服务器与客户端间的双向通信,服务器可以随时将消息推送到连接的客户端。

它现在可在 ASP.NET Core 预发行版本中使用(译者:根据原文的发布时间)。我已经介绍过几次 SignalR 了。

安装

您将需要安装 Microsoft.AspNetCore.SignalR.ClientMicrosoft.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 文件夹下,以便您可以从页面引用到它。

接下来,我们需要在使用之前在 ConfigureServices 中注册所需的服务:

services.AddSignalR();复制代码

我们将实现一个简单的聊天客户端,因此将在 Configure 方法中注册一个 ChatHub:

app.UseSignalR(routes =>
{
    routes.MapHub<ChatHub>("chat");
});复制代码

注意:UseSignalR 必须在 UseMvc 之前调用!

如果你有不同的端点,可以为任意数量的 hub 执行此操作。

在您的视图或布局文件中,添加对 signalr-client-1.0.0-alpha1-final.js 文件的引用:

<script src="libs/signalr-client/signalr-client-1.0.0-alpha1-final.js"></script>复制代码

实现 Hub

该 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>复制代码

请注意:

  1. 创建指向当前 URL 的连接添加了 chat 后缀,这与在 MapHub 中注册的一致
  2. 它使用特定的传输进行初始化(本例中是 WebSockets),但这不是必需的,也就是说,您可以让 SignalR 自己采用合适的方式。对于某些操作系统(如 Windows 7),您可能无法使用 WebSockets,因此您必须选择 LongPollingServerSentEvents
  3. 需要通过调用 start 来初始化连接
  4. 有一个 Send 方法的 handler,它与 ChatHubSend 方法有相同的单个参数(message)

所以,每当有人访问此页面并调用 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 属性才会提供 ConnectionIdUser 两个属性。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

最后,还可以将消息从外部发送到 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,包括其可扩展性机制和一些更高级的使用场景。敬请期待!

关注公众号 oopsguy_com

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值