简介

在ABP中,提供了通知服务。它是一个基于实时通知的基础设施。分为订阅模式和发布模式。

本次会在项目中使用发布模式来演示一个用户注册后,收到的欢迎信息。

发布模式

首先我们在领域层建立“INotificationManager”接口和“NotificationManager”实现类,如下:

  1. /// <summary>
  2. /// 通知管理领域服务
  3. /// </summary>
  4. public interface INotificationManager
  5. {
  6. Task WelcomeToCmsAsync(User user);
  7. }
  1. public class NotificationManager : CmsDomainServiceBase, INotificationManager
  2. {
  3. private readonly INotificationPublisher _notificationPublisher;
  4. public NotificationManager(INotificationPublisher notificationPublisher)
  5. {
  6. _notificationPublisher = notificationPublisher;
  7. }
  8. public async Task WelcomeToCmsAsync(User user)
  9. {
  10. await _notificationPublisher.PublishAsync(
  11. CmsConsts.NotificationConstNames.WelcomeToCms,
  12. new MessageNotificationData(L("WelcomeToCms")),severity:NotificationSeverity.Success,userIds:new []{user.ToUserIdentifier()}
  13. }
  14. }

以上就是一个简单的欢迎信息。

以上我们来分析下,调用的"INotificationManager"中的PublishAsync方法。

在源代码的定义中,我们看到了他有8个参数,我们来说说他具体去干嘛了,首先在ABP源代码中调用了这个方法之后,他会到实体NotificationInfo和UserNotification两个实体中进行处理,源代码中的结构很清晰。关联关系很明确是一个一对多的关系。

这个也就是我们在调用PublishAsync方法的时候需要我们键入一个键名,他是全局唯一的,在ABP的代码中的限制也是说明了,禁止使用空格和空字符串。

实时通知

我们刚刚说到了在PublishAsync中,涉及到了UserNotification实体,他的作用是通知用户消息,具体的代码实现中涉及到了后台作业和实时通知SignalR,而我们在客户端获取信息的时候,ABP是触发了一个全局事件。

···

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

console.log(userNotification);

});

···

此处涉及的知识点为领域事件中的事件总线。

打印userNotification的Json格式如下:

  1. {
  2. id: "9c0aaf34-c620-4d05-89df-1f4ae11f3686",
  3. notification: {
  4. creationTime: "2017-05-05T01:27:25.7639034Z"
  5. data: {
  6. message: "This is a test notification, created at 2017/5/5 1:27:25"
  7. type: "Abp.Notifications.MessageNotificationData"
  8. }
  9. entityId: null
  10. entityType: null
  11. entityTypeName: null
  12. id: "724d670e-2cfa-4656-a9b6-ff76ceba5ce3"
  13. notificationName: "App.SimpleMessage"
  14. severity: 0
  15. tenantId: 1
  16. }
  17. state: 0
  18. tenantId: 1
  19. userId: 2
  20. }

在这个对象中:

  • userId:当前用户Id。通常你不需要知道这个,因为你知道那个是当前用户。

  • state:枚举类型 UserNotificationState 的值。 0:Unread,1:Read。

  • notification:通知详细信息:

  • notificationName: 通知的唯一名字(发布通知时使用相同的值)。

  • data:通知数据。在上面例子中,我们使用了 LocalizableMessageNotificationData (在之前的例子中我们使用它来发布的)。

    • message: 本地化信息。在UI端,我们可以使用 sourceName 和 name 来本地化信息。

    • type:通知数据类型。类型的全名称,包含名称空间。当处理这个通知数据的时候,我们可以检查这个类型。

    • properties:自定义属的基于字典类型的属性。

  • entityType,entityTypeName 和 entityId:实体信息,如果这是一个与实体相关的通知。

  • severity:枚举类型 NotificationSeverity 的值。0: Info, 1: Success, 2: Warn, 3: Error, 4: Fatal。

  • creationTime:表示通知被创建的时间。

  • id:通知的id。

  • id:用户通知id。

以上就是消息通知功能的一个介绍,我们来实现这么个功能吧。

YoYoCms中消息通知的应用

我们继续在NotificationManager中添加方法SendMessageAsync


  1. public async Task SendMessageAsync(UserIdentifier user, string messager, NotificationSeverity severity = NotificationSeverity.Info)
  2. {
  3. await _notificationPublisher.PublishAsync(
  4. CmsConsts.NotificationConstNames.SendMessageAsync,
  5. new MessageNotificationData(messager),severity:severity,userIds:new []{user});
  6. }

然后在Account控制器中进行调用:


  1. [AbpMvcAuthorize]
  2. public async Task<ActionResult> TestNotification( string message = "" , NotificationSeverity severity = NotificationSeverity.Info)
  3. {
  4. if (message.IsNullOrEmpty())
  5. {
  6. message = "这是一条测试消息 " + Clock.Now;
  7. }
  8. await _notificationManager.SendMessageAsync(AbpSession.ToUserIdentifier(), message, severity: severity);
  9. return Content("发送提示信息: " + message);
  10. }



然后我们可以在TenantNotifications和UserNotifications可以看到发布的信息和关联关系。

登陆到管理中心可以看到:

当前的用户信息,通知。

  1. vm.unReadUserNotificationCount = 0;
  2. vm.userNotifications = [];
  3. //格式化消息
  4. var formattedMessage = function (item) {
  5. var message = {
  6. id: item.id,
  7. text: abp.notifications.getFormattedMessageFromUserNotification(item),
  8. time: item.notification.creationTime,
  9. image: getNotificationImgBySeverity(item.notification.severity),
  10. state: abp.notifications.getUserNotificationStateAsString(item.state),
  11. }
  12. return message;
  13. }
  14. //获取图片路径
  15. function getNotificationImgBySeverity(severity) {
  16. switch (severity) {
  17. case abp.notifications.severity.SUCCESS:
  18. return '/App/assets/yoyocms/notification/1.png';
  19. case abp.notifications.severity.WARN:
  20. return '/App/assets/yoyocms/notification/2.png';
  21. case abp.notifications.severity.ERROR:
  22. return '/App/assets/yoyocms/notification/3.png';
  23. case abp.notifications.severity.FATAL:
  24. return '/App/assets/yoyocms/notification/4.png';
  25. case abp.notifications.severity.INFO:
  26. default:
  27. return '/App/assets/yoyocms/notification/0.png';
  28. }
  29. }
  30. //获取所有的消息信息
  31. vm.getUserNotificationsAsync= function() {
  32. notificationService.getPagedUserNotificationsAsync({
  33. maxResultCount: 5
  34. }).then(function(result) {
  35. vm.unReadUserNotificationCount = result.data.unreadCount;
  36. vm.userNotifications = [];
  37. $.each(result.data.items,
  38. function (index, item) {
  39. vm.userNotifications.push(formattedMessage(item));
  40. });
  41. console.log(vm.userNotifications);
  42. });
  43. }
  44. //标记所有为已读
  45. vm.makeAllAsRead= function() {
  46. notificationService.makeAllUserNotificationsAsRead().then(function() {
  47. vm.getUserNotificationsAsync();
  48. });
  49. }
  50. //设置消息为已读
  51. vm.makeNotificationAsRead = function (userNotification) {
  52. notificationService.makeNotificationAsRead({ id: userNotification.id }).
  53. then(function () {
  54. for (var i = 0; i < vm.userNotifications.length; i++) {
  55. if (vm.userNotifications[i].id == userNotification.id) {
  56. vm.userNotifications[i].state = 'READ';
  57. }
  58. }
  59. vm.unReadUserNotificationCount -= 1;
  60. });
  61. }
  62. //初始化方法
  63. function init() {
  64. vm.getUserNotificationsAsync();
  65. }
  66. init();
  67. //测试为领域事件的一个例子
  68. abp.event.on('abp.notifications.received', function (userNotification) {
  69. abp.notifications.showUiNotifyForUserNotification(userNotification);
  70. vm.getUserNotificationsAsync();
  71. });
  72. }

其中有'abp.notifications.received'是一个领域事件的简单实现,大家有兴趣可以继续研究。以上整个功能已经发布到GitHub上,欢迎大家下载使用。

THE END

本开源项目的地址为:https://github.com/ltm0203/YoYoCms

预览网址为:http://www.yoyocms.com/

涉及的技术选型:https://github.com/ltm0203/YoYoCms/tree/dev/doc

[ABP实战开源项目]---ABP实时服务-通知系统.发布模式的更多相关文章

  1. [ABP实战开源项目]--YoYoCms目录

    ABP是"ASP.NET Boilerplate Project (ASP.NET样板项目)"的简称. ASP.NET Boilerplate是一个用最佳实践和流行技术开发现代WE ...

  2. 推荐一款稳定快速免费的前端开源项目 CDN 加速服务

    前面学习到什么是CDN,全称是Content Delivery Network,即内容分发网络.CDN的通俗理解就是网站加速,CPU均衡负载. CDN的基本思路是尽可能避开互联网上有可能影响数据传输速 ...

  3. 开源项目 AllJoyn 基础服务

    AllJoyn 基础服务主要包含 Onboarding,Notification 和 Control Panel三个大项. 这三个也是编写App的最基础的,最经常使用的部分. Onboarding 提 ...

  4. .NET ORM 开源项目 FreeSql 1.0 正式版发布

    一.简介 FreeSql 是 .NET 平台下的对象关系映射技术(O/RM),支持 .NetCore 2.1+ 或 .NetFramework 4.0+ 或 Xamarin. 从 0.0.1 发布,历 ...

  5. 开源项目收集:博客系统solo

    前言 一个好的项目,我不会吝啬于推荐之语.找了好久,想要一个最简单的个人博客.由于个人不怎么会写前端页面,怎么也看不到漂亮的设计.没有漂亮的前台都不知道后台需要写一些什么! 这个项目至少目前满足了我的 ...

  6. DIOCP开源项目-DIOCP3的重生和稳定版本发布

    DIOCP3的重生 从开始写DIOCP到现在已经有一年多的时间了,最近两个月以来一直有个想法做个 30 * 24 稳定的企业服务端架构,让程序员专注于逻辑实现就好.虽然DIOCP到现在通讯层已经很稳定 ...

  7. 优秀开源项目之一:视频监控系统iSpy

    iSpy是一个开源的视频监控软件,目前已经支持中文.自己用了一下,感觉还是很好用的.翻译了一下它的介绍. iSpy将PC变成一个完整的安全和监控系统 iSpy使用您的摄像头和麦克风来检测和记录声音或运 ...

  8. Halo 开源项目学习(四):发布文章与页面

    基本介绍 博客最基本的功能就是让作者能够自由发布自己的文章,分享自己观点,记录学习的过程.Halo 为用户提供了发布文章和展示自定义页面的功能,下面我们分析一下这些功能的实现过程. 管理员发布文章 H ...

  9. 实战小项目之RTMP流媒体演示系统

    项目简介 windows下使用基于Qt对之前的RtmpApp进行封装与应用,单独功能使用线程执行,主要包括以下几个功能: 视频下载 推送文件 推送摄像头数据或者桌面 基于libvlc的播放器 视频下载 ...

随机推荐

  1. angularjs fileUpload

    文件上传一直是我不熟悉的地方,<a href='https://github.com/nervgh/angular-file-upload/wiki/Module-API'>官网解释的例子 ...

  2. 【翻译】CSS水平和垂直居中的12种方法

    英语原文链接 在CSS中有许多不同的方法能够做到水平和垂直居中,但很难去选择合适的那个.我会向你展示我所看到的所有的方法,帮助你在所面对的情境下选择最棒的那一个. 方法1 此方法将只能垂直居中单行文本 ...

  3. 浅谈隐语义模型和非负矩阵分解NMF

    本文从基础介绍隐语义模型和NMF. 隐语义模型 ”隐语义模型“常常在推荐系统和文本分类中遇到,最初来源于IR领域的LSA(Latent Semantic Analysis),举两个case加快理解. ...

  4. Unity 3D Framework Designing(4)——设计可复用的SubView和SubViewModel(Part 1)

    『可复用』这个词相信大家都熟悉,通过『可复用』的组件,可以大大提高软件开发效率. 值得注意的事,当我们设计一个可复用的面向对象组件时,需要保证其独立性,也就是我们熟知的『高内聚,低耦合』原则. 组件化 ...

  5. 将ROS中的/sensor_msgs/NavSatFix数据导入google earth显示轨迹

    将ros中的gps_msg数据导入google earth显示轨迹 [TOC] 1. 获取GPS数据 将ros中发布的gps topic输出到文本中 rostopic echo -p /gpsData ...

  6. Java中利用BigInteger类进行大数开方

    在Java中有时会用到大数据,基本数据类型的存储范围已经不能满足要求了,如要对10的1000次方的这样一个数据规模的数进行开方运算,很明显不能直接用Math.sqrt()来进行计算,因为已经溢出了. ...

  7. windows环境搭建jira 详解

    一.事前准备 1:JDK下载并安装:http://www.oracle.com/technetwork/java/javase/downloads/index.html2:MySQL JDBC连接驱动 ...

  8. Intellij Idea 用Maven 创建Hibernate 项目

    第一步:创建maven项目 2. 3. 4.第三步保存之后进行下一步 到此点击finish maven项目创建成功,点击完成后会进行一系列jar包的下载 maven 仓库的默认存储位置 第二步:连接数 ...

  9. children 和childNodes 的区别

    1:childNodes /children相同点:它返回指定元素的子元素集合. 2:区别:children :  它是非标准的,仅返回HTML节点.甚至不返回文本节点.所有浏览器表现一 致. chi ...

  10. kindeditor修改图片上传路径-使用webapi上传图片到图片服务器

    kindeditor是一个非常好用的富文本编辑器,它的简单使用我就不再介绍了. 在这里我着重介绍一些使用kindeditor修改图片上传路径并通过webapi上传图片到图片服务器的方案. 因为我使用的 ...