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來獲取通知定義,接着你可能想準備一個容許用戶本身訂閱這些通知的頁面。

相關文章
相關標籤/搜索