ABP官方文档翻译 8.1 通知系统
通知系统
- 介绍
- 发送模型
- 通知类型
- 通知数据
- 通知严重性
- 关于通知持久化
- 订阅通知
- 发布通知
- 用户通知管理
- 实时通知
- 客户端
- 通知存储
- 通知定义
介绍
在系统中通知用来基于特定的事件告知用户。ABP提供了pub/sub基础实时通知基础设施。
发送模型
有两种给用户发送通知的方式:
- 用户订阅一个特定的通知类型。然后我们发布此类型的一个通知,此类型会被发送给所有订阅的用户。这就是pub/sub模型。
- 我们可以直接给目标用户发送一个通知。
通知类型
通知有两种类型:
- 普通通知可以是任意类型。“如果一个用户发送给我一个友好的请求,通知我”就是这种通知类型的一个例子。
- 实体通知关联到一个特定的实体。“如果一个用户评论了这张照片,通知我”就是一种实体基础类型,因为它和一个特定的photo实体关联。用户可能想得到一些照片的通知,而不是全部。
通知数据
一个通知一般包含通知数据。例如:“如果一个用户发送给我一个友好的请求,通知我”通知会有两个数据属性:sender user name(哪个用户发送了这个友好请求)和request note(发送用户在请求中的笔记)。很显然通知数据的类型和通知类型紧密相连。不同的通知类型有不同的数据类型。
通知数据是可选的。一些通知可能不请求数据。这有预定义的通知数据类型,这些可以满足大多数场景。MessageNotificationData可以用于简单的信息,LocalizableMessageNotificationData可以用于本地化和参数化的通知信息。在之后的部分我们将会看到示例用法。
通知严重性
通知严重性有5种等级,定义在NotificationSeverity枚举中:Info,Success,Warn,Error和Fatal。默认值是Info。
关于通知持久化
参见通知存储部分了解更多关于通知持久化的信息。
订阅通知
INotificationSubscriptionManaer提供了API类来订阅通知。示例:
public class MyService : ITransientDependency {private readonly INotificationSubscriptionManager _notificationSubscriptionManager;public MyService(INotificationSubscriptionManager notificationSubscriptionManager){_notificationSubscriptionManager = notificationSubscriptionManager;}//Subscribe to a general notificationpublic async Task Subscribe_SentFrendshipRequest(int? tenantId, long userId){await _notificationSubscriptionManager.SubscribeAsync(new UserIdentifier(tenantId, userId), "SentFrendshipRequest"); }//Subscribe to an entity notificationpublic 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,IsSubscribedAsync,GetSubscriptionsAsync...方法来管理订阅。
发布通知
INotificationPublisher用来发布通知。示例:
public class MyService : ITransientDependency {private readonly INotificationPublisher _notiticationPublisher;public MyService(INotificationPublisher notiticationPublisher){_notiticationPublisher = notiticationPublisher;}//Send a general notification to a specific userpublic async Task Publish_SentFrendshipRequest(string senderUserName, string friendshipMessage, UserIdentifier targetUserId){await _notiticationPublisher.PublishAsync("SentFrendshipRequest", new SentFrendshipRequestNotificationData(senderUserName, friendshipMessage), userIds: new[] { targetUserId });}//Send an entity notification to a specific userpublic 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 });}//Send a general notification to all subscribed users in current tenant (tenant in the session)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); } }
在第一个例子中,我们发布了一个通知给一个单独的用户。SetFrendshipRequestNotificationData需要继承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 event bus文档来获取关于事件的更多信息。一个通知"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在UI中本地化信息。
- type:通知数据类型。全类型名称,包含命名空间。当处理通知数据时,我们可以检查这个类型。
- properties:基于字典的自定义属性。
- entityType,entityTypeName和entityId:实体信息,如果这是一个实体相关的通知。
- severity:NotificationSeverity枚举的值。0:Info,1:Success,2:Warn,3:Error,4:Fatal。
- creationTime:通知创建的时间。
- 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通知:
p.event.on('abp.notifications.received', function (userNotification) {abp.notifications.showUiNotifyForUserNotification(userNotification); });
这会显示一个UI通知(如收到上面发布的System.LowDisk通知):
这适用于內建通知数据类型(LocalizableMessageNotificationData和MessageNotificationData)。如果你有自定义数据类型,那么你应该如下所示注册数据格式化器:
abp.notifications.messageFormatters['MyProject.MyNotificationDataType'] = function(userNotification) {return ...; //format and return message here };
因此,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")));} }
"App.NewUserRegistered"是通知的唯一名称。我们定义了一个本地化displayName(然后当在UI中订阅这个通知时,可以显示它)。最后,我们声明只有有"App.Pages.UserManagement"权限的用户这个通知才可用。
还有其他的一些参数,你可以在代码中研究它。对于通知定义,只有通知名称是必须的。
当定义了一个通知提供者之后,我们需要在模块的PreInitialize方法中注册它,如下所示:
public class AbpZeroTemplateCoreModule : AbpModule {public override void PreInitialize(){Configuration.Notifications.Providers.Add<MyAppNotificationProvider>();}//... }
最后,你可以在应用程序中注入并使用INotificationDefinitionManager来获取通知定义。然后你可能想准备一个自动页来允许用户订阅这些通知。
返回主目录
转载于:https://www.cnblogs.com/xajh/p/7128804.html
ABP官方文档翻译 8.1 通知系统相关推荐
- ABP官方文档翻译 1.3 模块系统
ABP模块系统 介绍 模块定义 生命周期方法 PreInitialize Initialize PostInitialize Shutdown 模块依赖 插件系统 ASP.NET Core ASP.N ...
- ABP官方文档翻译 0.0 ABP官方文档翻译目录
一直想学习ABP,但囿于工作比较忙,没有合适的契机,当然最重要的还是自己懒.不知不觉从毕业到参加工作七年了,没留下点儿什么,总感觉很遗憾,所以今天终于卯足劲鼓起勇气开始写博客.有些事能做的很好,但要跟 ...
- ABP官方文档翻译 6.3 本地化
本地化 介绍 应用程序语言 本地化源 XML文件 注册XML本地化源 JSON文件 注册JSON本地化源 资源文件 自定义源 当前语言是如何决定的 ASP.NET Core ASP.NET MVC 5 ...
- ABP官方文档翻译 1.2 N层架构
N层架构 介绍 ABP架构 其他(通用) 领域层 应用层 基础设施层 网络和展现层 其他 总结 介绍 应用程序代码库的分层架构是被广泛认可的可以减少程序复杂度.提高代码复用率的技术.为了实现分层架构, ...
- ABP官方文档翻译 3.7 领域事件(事件总线)
领域事件(事件总线) 事件总线 注入IEventBus 获取默认实例 定义事件 预定义事件 处理异常 实体更改 触发事件 处理事件 处理基础事件 处理者异常 处理多个事件 注册处理者 自动 手动 取消 ...
- ABP官方文档翻译 6.1.3 异常处理
处理异常 介绍 启用错误处理 Non-Ajax请求 显示异常 UserFriendlyException Error模型 AJAX请求 异常事件 介绍 此文档是与ASP.NET MVC和Web API ...
- ABP官方文档翻译 6.1.1 MVC控制器
ASP.NET MVC控制器 介绍 AbpController基类 本地化 其他 过滤器 异常处理和结果包装 审计日志 验证 授权 工作单元 介绍 ABP通过Abp.Web.Mvc nuget包集成到 ...
- ABP官方文档翻译 1.5 多租户
多租户 什么是多租户? 数据库和部署架构 多部署-多数据库 单部署-多数据库 单部署-单数据库 单部署-混合数据库 多部署-单/多/混合数据库 ABP的多租户 启用多租户 租主和租户 会话 决定当前租 ...
- ABP官方文档翻译 4.6 审计日志
审计日志 介绍 关于IAuditingStore 配置 通过特性启用/禁用 注意事项 介绍 维基百科:"审计追踪(也称为审计日志)是与安全相关的按时间先后的记录.记录集合.记录的目的地和源, ...
- ABP官方文档翻译 5.1 Web API控制器
ASP.NET Web API控制器 介绍 AbpApiController基类 本地化 其他 过滤器 审计日志 授权 反伪造过滤器 工作单元 结果包装和异常处理 结果缓存 校验 模型绑定器 介绍 A ...
最新文章
- HDU1201 18岁生日【日期计算】
- 【Tiny4412】Uboot常用命令
- Win7 路由上网DNS服务器ping不通的解决方法
- 机器学习算法优缺点改进总结
- 评论中显示表情,苹果和安卓都一样
- pythonexecquery_python 进程信息
- [转载]网页栅格系统研究(1):960的秘密
- 基于扩展性考虑,不同场景选择的不同方案
- Linux下卸载miniconda3(Anaconda类系)
- GDI与DirectX对比
- 升级Spring Boot 2.x后RelaxedPropertyResolver不可用的解决方案
- 内网网段范围_局域网网段到底是什么意思?怎么划分的啊?为什么要划分网段?...
- RabbitMq Direct exchange路由模型
- 快速查询出中通快运物流信息,将信息导出EXCEL表格
- 苹果手机怎么设置时间24小时制_手机资讯:无法激活 iMessage 等问题及解决办法汇总...
- 计算机二级vb选择题分值,计算机二级VB考试的考试分值和考试题型剖析及解题技巧...
- Field类的概述和使用
- 海外专利紧缺 中国IT企业国际化维艰
- 三国杀神话再临java版,神话再临 雷包10将 各版技能+台词 《三国杀》武将资料收录...
- 分享一套宾馆客房管理系统源码,功能完善,代码完整