8.3 ABP实时服务 - 集成Abp.AspNetCore.SignalR

8.3.1 简介

在基于ABP开发的应用中,为了更简单的使用ASP.NET Core SignalR,您可以 使用Abp.AspNetCore.SignalR 包。

注意:该软件包目前是 preview。如果您遇到问题,请提交issues给Github:https://github.com/aspnetboilerplate/aspnetboilerplate/issues/new

8.3.2 安装

1. 服务器端

使用Nuget安装 Abp.AspNetCore.SignalR 到你的项目中(通常是你的Web项目),并且添加依赖模块:

[DependsOn(typeof(AbpAspNetCoreSignalRModule))]
public class YourProjectWebModule : AbpModule
{
    //...
}

然后在启动类中使用 AddSignalR 以及 UseSignalR 方法。

using Abp.Web.SignalR.Hubs;

namespace MyProject.Web.Startup
{
    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddSignalR();
        }

        public void Configure(IApplicationBuilder app)
        {
            app.UseSignalR(routes =>
            {
                routes.MapHub<AbpCommonHub>("/signalr");
            });
        }
    }
}

2. 客户端

请添加脚本: abp.signalr-client.js 到web页面中。它位于 Abp.Web.Resources 包中(它已经被安装到启动模板中)。 我们应该在 signalr hubs 后引用它:


<script src="~/lib/signalr-client/signalr-client.min.js"></script>
<script src="~/lib/abp-web-resources/Abp/Framework/scripts/libs/abp.signalr-client.js"></script>

这么做了后,SignalR就已配置且集成到你的项目中了。

3. 建立连接

abp.signalr-client.js 被引用到页面后,ABP会自动的连接到你的服务器(从客户端)。一般我们都会这么做,但是在某些情况下你不想这样做。你可以像下面代码所示禁用自动连接:

<script>
    abp.signalr = abp.signalr || {};
    abp.signalr.autoConnect = false;
</script>

在这种情况下,你可以手动调用 abp.signalr.connect() 函数来连接服务器。

如果abp.signalr.autoConnect为true ,则在客户端断开连接时,ABP也会自动重新连接到服务器(从客户端)。

当客户端连接到服务器时,全局事件 "abp.signalr.connected" 会被触发。当连接建立成功的时候,你可以注册这个事件来采取相应的行动。详情请参考Javascript函数库

8.3.3 内置功能

你可以在应用程序中使用所有的SignalR的功能。还有,在 Abp.AspNetCore.SignalR 中实现了一些内置功能。

1. 通知

Abp.AspNetCore.SignalR 实现了 IRealTimeNotifier 接口来发送实时时间到客户端(请参阅通知系统)。因此,你的用户可以获得实时的推送通知。

2. 在线客户端

ABP提供了 IOnlineClientManager 来取得在线用户的信息(如:注入IOnlineClientManager以及使用GetByUserIdOrNull, GetAllClients, IsOnline 方法)。为了能够正常工作,IOnlineClientManager需要一个通信基础设施。Abp.AspNetCore.SignalR 提供了这个基础设施。如果安装了SignalR,则可以在应用程序的任何层中注入并使用IOnlineClientManager。

8.3.4 你的SignaR代码

使用 Abp.Web.SignalR 包也会简化你的 SignalR代码。假设我们想要添加一个Hub到你的应用程序中:

public class MyChatHub : Hub, ITransientDependency
{
    public IAbpSession AbpSession { get; set; }

    public ILogger Logger { get; set; }

    public MyChatHub()
    {
        AbpSession = NullAbpSession.Instance;
        Logger = NullLogger.Instance;
    }

    public async Task SendMessage(string message)
    {
        await Clients.All.InvokeAsync("getMessage", string.Format("User {0}: {1}", AbpSession.UserId, message));
    }

    public override async Task OnConnectedAsync()
    {
        await base.OnConnectedAsync();
        Logger.Debug("A client connected to MyChatHub: " + Context.ConnectionId);
    }

    public override async Task OnDisconnectedAsync(Exception exception)
    {
        await base.OnDisconnectedAsync(exception);
        Logger.Debug("A client disconnected from MyChatHub: " + Context.ConnectionId);
    }
}
routes.MapHub<MyChatHub>("/myChatHub");

为了使我们的Hub可以简单的注册到依赖注入系统中,我们可以实现 ITransientDependency 接口。当然你可以根据你的需求,注册它为单例模式。我们也使用属性注入了SessionLogger

SendMessage是hub的一个方法,它可以被客户端使用。在这个方法中,我们可以调用所有客户端的 getMessage函数。正如你看到的那样,我们可以使用AbpSession来获得当前的用户id(如果用户已经登录)。如上所述,我们还重写了OnConnectedAsync和 OnDisconnectedAsync,这仅仅是为了演示而实际上并不需要。。

下面是用在Hub中,用来发送/接受信息的客户端脚本:

var chatHub = null;

abp.signalr.startConnection('/myChatHub', function (connection) {
    chatHub = connection; // 保存引用到hub

    connection.on('getMessage', function (message) { // 注册接收消息
        console.log('received message: ' + message);
    });
});

abp.event.on('abp.signalr.connected', function() { // 注册连接事件
    chatHub.invoke('sendMessage', "Hi everybody, I'm connected to the chat!"); // 发送消息到服务器
});

然后我们可以随时使用chatHub来发送消息给服务器。