ABP文档笔记 - 通知

基础概念

两种通知发送方式

  1. 直接发送给目标用户
  2. 用户订阅某类通知,发送这类通知时直接分发给它们。

两种通知类型

  1. 通常通知:任意的通知类型
    “若是一个用户发送一个好友请求,那么通知我”就是一个此类型的通知
  2. 实体通知:与一个特定的实体关联,
    “若是一个用户给这张(photo)图片发了评论,那么通知我”就是一个基于实体的通知,由于它与一个特定的photo实体关联,用户可能想为某些图片发出通知,而不是全部图片

通知数据

一个通知一般包含一个通知数据,但有些通知也可能不须要数据javascript

例如:“若是一个用户发送一个好友请求,那么通知我”该通知可能有两个数据属性:发送者名字(谁发送了这个好友请求)和备注(发送者写在请求里的信息),很明显,通知数据类型与通知类型是紧密联系的,不一样的通知类型有不一样的数据类型。java

ABP已经提供足以知足大部分状况的预约义通知数据类型,简单的信息能够用MessageNotificationData,本地化和可参数化的通知信息能够使用LocalizableMessageNotificationData。api

通知重要性级别

通知重要性有5个级别,定义在NotificationSeverity枚举里:Info,Success,Warn,Error和Fatal,默认为Info。并发

示例

订阅通知

INotificationSubscriptionManager提供了用来订阅通知的API,例如:异步

public class MyService : ITransientDependency
{
    private readonly INotificationSubscriptionManager _notificationSubscriptionManager;

    public MyService(INotificationSubscriptionManager notificationSubscriptionManager)
    {
        _notificationSubscriptionManager = notificationSubscriptionManager;
    }

    //订阅一个通常通知
    public async Task Subscribe_SentFrendshipRequest(int? tenantId, long userId)
    {
        await _notificationSubscriptionManager.SubscribeAsync(new UserIdentifier(tenantId, userId), "SentFrendshipRequest");    
    }

    //订阅一个实体通知
    public async Task Subscribe_CommentPhoto(int? tenantId, long userId, Guid photoId)
    {
        await _notificationSubscriptionManager.SubscribeAsync(new UserIdentifier(tenantId, userId), "CommentPhoto", new EntityIdentifier(typeof(Photo), photoId));   
    }
}

每个通知类型都应当有一个惟一的名称(如示例中的SentFrendshipRequest 和CommentPhoto)。async

INotificationSubscriptionManager还有UnsubscribeAsync,IsSubscribedAsync,GetSubscriptionsAsyn等方法来管理订阅。ide

发布通知

INotificationPublisher用来发布通知,例如:函数

public class MyService : ITransientDependency
{
    private readonly INotificationPublisher _notiticationPublisher;

    public MyService(INotificationPublisher notiticationPublisher)
    {
        _notiticationPublisher = notiticationPublisher;
    }

    //发送一个通常通知给一个特定用户
    public async Task Publish_SentFrendshipRequest(string senderUserName, string friendshipMessage, UserIdentifier targetUserId)
    {
        await _notiticationPublisher.PublishAsync("SentFrendshipRequest", new SentFrendshipRequestNotificationData(senderUserName, friendshipMessage), userIds: new[] { targetUserId });
    }

    //发送一个实体通知给一个特定用户
    public async Task Publish_CommentPhoto(string commenterUserName, string comment, Guid photoId, UserIdentifier photoOwnerUserId)
    {
        await _notiticationPublisher.PublishAsync("CommentPhoto", new CommentPhotoNotificationData(commenterUserName, comment), new EntityIdentifier(typeof(Photo), photoId), userIds: new[] { photoOwnerUserId });
    }

    //发送一个通常通知给全部当前租户(在会话里)里的订阅它的用户
    public async Task Publish_LowDisk(int remainingDiskInMb)
    {
        //Example "LowDiskWarningMessage" content for English -> "Attention! Only {remainingDiskInMb} MBs left on the disk!"
        var data = new LocalizableMessageNotificationData(new LocalizableString("LowDiskWarningMessage", "MyLocalizationSourceName"));
        data["remainingDiskInMb"] = remainingDiskInMb;

        await _notiticationPublisher.PublishAsync("System.LowDisk", data, severity: NotificationSeverity.Warn);   
    }
}

通知类型

在第一个例子里, 咱们发布一个通知给一个单独的用户,SentFrendshipRequestNotificationData应该继承于NotificationData,以下所示:ui

[Serializable]
public class SentFrendshipRequestNotificationData : NotificationData
{
    public string SenderUserName { get; set; }

    public string FriendshipMessage { get; set; }

    public SentFrendshipRequestNotificationData(string senderUserName, string friendshipMessage)
    {
        SenderUserName = senderUserName;
        FriendshipMessage = friendshipMessage;
    }
}

第二个例子,咱们发送一个通知给一个特定用户并传递一个特定实体,通知数据类不须要可序列化(由于默认使用JSON序列器),但建议把它标记为可序列化,由于你可能会在不一样应用中移动并且你未来也可能想使用二进制可序列化器。固然如前面所述,通知数据是可选的,并非全部的通知都须要它。3d

注意:若是咱们发布一个通知给一个特定用户,那么这个用户不须要订阅这个通知。

第三个例子,咱们没有定义一个专用的通知数据类,而是直接使用内容的LocalizableMessageNotificationData类,并使用基于字典的数据,并发布一个“Warn”通知,LocalizableMessageNotificationData能够存储基于字典的任意数据(若是自定义的通知数据类继承于NotificationData类,那么也能够这么用),咱们使用“remainingDiskInMb”做为本地化参数,本地化信息能够包含这些参数(如示例中的“Attention!Only{remainingDiskInMb} MBs left on the disk!”)。

用户通知管理器IUserNotificationManager

IUserNotificationManager用来管理用户的通知,它get,update或delete一个用户的通知,你能够用它为你的应用准备一个通知列表页面。

实时通知IRealTimeNotifier + SignalR

虽然能够用IUserNotificationManager来查询通知,但咱们一般想推送一个实时通知到客户端。

通知系统使用IRealTimeNotifier来发送实时通知给用户,这能够使用任何类型的实时通信系统实现,咱们能够用一个单独实现的SignalR包,启动模板已经安装了SignalR,查看SignalR集成文档获取更多信息。

注意:通知系统用一个后台做业异步调用IRealTimeNotifier,因此,通知可能会有一点点的延迟。

客户端

当接收到一个实时的通知,ABP在客户端触发一个全局事件,你能够用以下的方式注册来获得通知:

abp.event.on('abp.notifications.received', function (userNotification) {
    console.log(userNotification);
});

每接收到一个实时通知,都会触发abp.notifications.received事件事件,你能够像上面那样注册该事件来获取通知,查看javascript事件总线文档获取事件更多信息。一个收到的“System.LowDisk”通知的Json示例:

{
    "userId": 2,
    "state": 0,
    "notification": {
        "notificationName": "System.LowDisk",
        "data": {
            "message": {
                "sourceName": "MyLocalizationSourceName",
                "name": "LowDiskWarningMessage"
            },
            "type": "Abp.Notifications.LocalizableMessageNotificationData",
            "properties": {
                "remainingDiskInMb": "42"
            }
        },
        "entityType": null,
        "entityTypeName": null,
        "entityId": null,
        "severity": 0,
        "creationTime": "2016-02-09T17:03:32.13",
        "id": "0263d581-3d8a-476b-8e16-4f6a6f10a632"
    },
    "id": "4a546baf-bf17-4924-b993-32e420a8d468"
}

在这个对象里:

  • userId:当前用户Id,一般你不须要这个由于你知道当前的户。
  • state:UserNotificationState的枚举值,0:Unread(未读),1:Read(已读)。
  • notification:通知明细:
    • notificationName:这个通知的惟一名称(发布时也用这个名称)。
    • data:通知数据,在这个示例里,咱们使用LocalizableMessageNotificationData(和以前发布的示例一致):
      • message:本地化的消息信息,咱们能够用sourceName和name来本地化界面上的消息。
      • type:通知数据类型,全类型名,包含命名空间,当在处理通知数据时,咱们能够检查这个类型。
      • properties:基于字典的自定义属性。
    • entityType、entityTypeName和entityId:实体信息(若是这是一个实体实时通知)
    • severity:一个NotificationSeverity枚举值,0:Info,1:Success,2:Warn,3:Error,4:Fatal。
    • id:通知Id。
  • id:用户通知Id。

把通知信息显示给用户

abp.event.on('abp.notifications.received', function (userNotification) {
    if (userNotification.notification.data.type === 'Abp.Notifications.LocalizableMessageNotificationData') {
        var localizedText = abp.localization.localize(
            userNotification.notification.data.message.name,
            userNotification.notification.data.message.sourceName
        );

        $.each(userNotification.notification.data.properties, function (key, value) {
            localizedText = localizedText.replace('{' + key + '}', value);
        });

        alert('New localized notification: ' + localizedText);
    } else if (userNotification.notification.data.type === 'Abp.Notifications.MessageNotificationData') {
        alert('New simple notification: ' + userNotification.notification.data.message);
    }
});

为了能处理通知数据,咱们应当检查这个数据类型,这个例子简单的从通知数据里获取消息,若是是本地化的消息(LocalizableMessageNotificationData),咱们本地化这个消息并替换参数, 若是是简单消息(MessageNotificationData),咱们直接获取这个消息,固然,在真实的项目里,咱们不会使用alert函数,咱们能够使用abp.notify api来显示良好的UI通知。

若是你想实现上面这样的逻辑,有一个更容易且富有弹性的方式,当接收到一个推送的通知,你只须要一行代码来显示UI通知:

abp.event.on('abp.notifications.received', function (userNotification) {
    abp.notifications.showUiNotifyForUserNotification(userNotification);
});

这显示一个UI通知,以下所示(上面描述的推送的System.LowDisk通知):

它可工做于内容的通知数据类型(LocalizableMessageNotificationData和MessageNotificationData),若是你是自定义的通知数据类型,那么你应该像下面这样注册数据格式:

abp.notifications.messageFormatters['MyProject.MyNotificationDataType'] = function(userNotification) {
    return ...; //此处格式化并返回消息
};

所以,showUiNotifyForUserNotification能够为你的数据类型建立显示的消息,若是你只是须要格式的消息,你能够直接使用abp.notifications.getFormattedMessageFromUserNotification(userNotification), 它内部被showUiNotifyForUserNotification。

通知存储

通知系统使用INotificationStore来持久化通知,该接口实现后才能使通知系统正常工做,你能够本身实现它或使用已经实现它的module-zero。

通知定义

你不须要在用前先定义一个通知,你只管使用任何通知名称而无需定义,可是,定义它可能给你带来额外的好处,例如,定义后你能够在你的应用里检查全部的通知。鉴于这种状况,咱们能够为咱们的模块定义一个通知供应器,以下所示:

public class MyAppNotificationProvider : NotificationProvider
{
    public override void SetNotifications(INotificationDefinitionContext context)
    {
        context.Manager.Add(
            new NotificationDefinition(
                "App.NewUserRegistered",
                displayName: new LocalizableString("NewUserRegisteredNotificationDefinition", "MyLocalizationSourceName"),
                permissionDependency: new SimplePermissionDependency("App.Pages.UserManagement")
                )
            );
    }
}

在模块的PreInitialize事件里注册它

Configuration.Notifications.Providers.Add<MyAppNotificationProvider>();

最后,你能够在你应用中注入并使用INotificationDefinitionManager来获取通知定义,接着你可能想准备一个容许用户本身订阅这些通知的页面。

相关文章
相关标签/搜索