ABP文檔 - 通知系統

文檔目錄javascript

 

本節內容:html

 

簡介java

通知用來告知用戶系統裏特定的事件發生了,ABP提供一個發佈/訂閱,它基於實時通知基礎框架。api

 

發送模式併發

有兩種方式能夠發送通知給用戶:框架

  • 用戶訂閱一個特定的通知類型,而後咱們發佈一個此類型的通知,它會分發給全部訂閱的用戶,這就是發佈/訂閱模式。
  • 咱們能夠直接發送一個通知給目標用戶(users)。

 

通知類型異步

有兩種通知類型:async

  • 通常通知:任意的通知類型,「若是一個用戶發送一個好友請求,那麼通知我」就是一個此類型的通知。
  • 實體通知:與一個特定的實體關聯,「若是一個用戶給這張(photo)圖片發了評論,那麼通知我」就是一個基於實體的通知,由於它與一個特定的photo實體關聯,用戶可能想爲某些圖片發出通知,而不是全部圖片。

通知數據ide

一個通知一般包含一個通知數據,例如:「若是一個用戶發送一個好友請求,那麼通知我」該通知可能有兩個數據屬性:發送者名字(誰發送了這個好友請求)和備註(發送者寫在請求裏的信息),很明顯,通知數據類型與通知類型是緊密聯繫的,不一樣的通知類型有不一樣的數據類型。函數

通知數據是可選的,有些通知可能就不須要數據。ABP已經提供足以知足大部分狀況的預約義通知數據類型,簡單的信息能夠用MessageNotificationData,本地化和可參數化的通知信息可使用LocalizableMessageNotificationData,咱們會在之後章節看到使用示例。

 

通知重要性

通知重要性有5個級別,定義在NotificationSeverity枚舉裏:Info,Success,Warn,ErrorFatal,默認爲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));   
    }
} 

首先,咱們注入INotificationSubscriptionManager,第一方法訂閱一個通常通知,當某人發送一個好友請求時,用戶會收到通知,第二個訂閱一個與特定實體(Photo)相關的通知,當某人給特定照片寫評論後,用戶會收到通知。

每個通知類型都應當有一個惟一的名稱(如示例中的SentFrendshipRequest 和CommentPhoto)。

INotificationSubscriptionManager還有UnsubscribeAsync,IsSubscribedAsyncGetSubscriptionsAsyn等方法來管理訂閱。

 

發佈通知

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,以下所示:

[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序列器),但建議把它標記爲可序列化,由於你可能會在不一樣應用中移動並且你未來也可能想使用二進制可序列化器。固然如前面所述,通知數據是可選的,並非全部的通知都須要它。

注意:若是咱們發佈一個通知給一個特定用戶,那麼這個用戶不須要訂閱這個通知。

第三個例子,咱們沒有定義一個專用的通知數據類,而是直接使用內容的LocalizableMessageNotificationData類,並使用基於字典的數據,併發佈一個「Warn」通知,LocalizableMessageNotificationData能夠存儲基於字典的任意數據(若是自定義的通知數據類繼承於NotificationData類,那麼也能夠這麼用),咱們使用「remainingDiskInMb」做爲本地化參數,本地化信息能夠包含這些參數(如示例中的「Attention!Only{remainingDiskInMb} MBs left on the disk!」),咱們在客戶端小節裏能夠看到若是本地化。

 

用戶通知管理器

IUserNotificationManager用來管理用戶的通知,它get,update或delete一個用戶的通知,你能夠用它爲你的應用準備一個通知列表頁面。

 

實時通知

雖然你能夠用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。

啓動模板包含了當接收到一個推送信息後顯示UI通知的代碼。

 

通知存儲

通知系統使用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")
                )
            );
    }
}

 

「Abp.NewUserRegistered」是這個通知的惟一名稱,咱們定義了一個可本地化的displayName(當在UI上訂閱這個通知時能夠顯示它),最後,咱們聲明這個通知只對擁有「App.Pages.UserManagerment」許可的用戶可用。

這裏還有一些其它參數,你能夠在代碼中檢查它,一個通知的定義只有名稱是必需的。

在定義好這個通知供應器後,咱們應該在模塊的PreInitialize事件裏註冊它,以下所示:

public class AbpZeroTemplateCoreModule : AbpModule
{
    public override void PreInitialize()
    {
        Configuration.Notifications.Providers.Add<MyAppNotificationProvider>();
    }

    //...
}

 

最後,你能夠在你應用中注入並使用INotificationDefinitionManager來獲取通知定義,接着你可能想準備一個容許用戶本身訂閱這些通知的頁面。

 

kid1412附:英文原文:http://www.aspnetboilerplate.com/Pages/Documents/Notification-System

相關文章
相關標籤/搜索