業務型網站使用過程中,消息通知是一個不可或缺的功能,采用站內通知、短信通知、郵件通知、微信通知等等各種方式都有,ABP框架對這部分工作已經封裝的很好了,站在巨人的肩膀上,一覽全貌,帶來的就是心情舒暢。
ABP官網地址:https://aspnetboilerplate.com/
一、明確概念及設計
一次完整的消息發送/接收過程中,會存在幾個必要的點,也正如同現實生活中的場景,有人發送,有人接收,發送的消息本身也有類型。
1、消息類型定義
在ABP中已經提供了消息類型定義的相關類,但是需要我們去實現,在領域層新建一個Notifications文件夾並添加一個定義常用消息類型名稱的靜態類如AppNotificationNames(名稱可隨意),在其中開始定義消息類型名稱。
/// <summary> /// 設置應用程序中常用通知唯一的名稱常量 /// </summary> public static class AppNotificationNames { #region 新的任務 public const string NewTask = "App.NewTask"; #endregion #region 簡單消息 public const string SimpleMessage = "App.SimpleMessage"; #endregion }
其次,開始消息類型定義,新建一個NotificationProvider的類,完成消息類型定義,管理消息類型時,可以針對消息設置權限,這樣方便不同的角色擁有不同的消息通知。
/// <summary> /// 消息類型定義 /// </summary> public class AppNotificationProvider : NotificationProvider { /// <summary> /// 設置消息類型 /// </summary> /// <param name="context"></param> public override void SetNotifications(INotificationDefinitionContext context) { #region 任務提醒 context.Manager.Add( new NotificationDefinition( AppNotificationNames.NewTask, displayName: L("NewTask"), permissionDependency: new SimplePermissionDependency(PermissionNames.Pages_TaskManage) ) ); #endregion } private static ILocalizableString L(string name) { return new LocalizableString(name, SurroundConsts.LocalizationSourceName); } }
最后在領域層的Module.PreInitialize()中完成加入。
//通知定義 Configuration.Notifications.Providers.Add<AppNotificationProvider>();
2、消息訂閱方式
對於消息訂閱環節,是存在兩種情形的,第一種,發送方發出的消息,可以指定所有訂閱了的人員接收,比如,只有擁有任務管理權限的人才會接收到新的任務下發的通知;第二種就是指定到具體人員接收,比如文件上傳完畢的消息通知是通知到負責文件上傳的人。
消息訂閱的管理,在ABP框架中已經封裝好了,我們可以通過構造函數注入直接使用,通過獲取系統內的提前定義的所有消息類型,我們可以在界面上完成訂閱工作,為當前用戶訂閱在他角色權限內的消息通知及無權限限制的消息通知等。
private readonly INotificationDefinitionManager _notificationDefinitionManager; private readonly INotificationSubscriptionManager _notificationSubscriptionManager; public NotificationAppService( INotificationDefinitionManager notificationDefinitionManager, INotificationSubscriptionManager notificationSubscriptionManager) { _notificationDefinitionManager = notificationDefinitionManager; _notificationSubscriptionManager = notificationSubscriptionManager; }
3、消息發布方式
消息發布時,可以是嵌入在其它操作中,比如制定完成一個新的任務后,發送消息給相關人員,或是在文件上傳完畢后,發送給文件上傳人員,也可以是定時任務中,指定時間點發送消息,對於這部分來講,在領域層建立一個消息通知的類,來負責處理消息通知,而具體實現消息通知的過程ABP框架中已經實現了,如同消息訂閱一樣,只需要在構造函數中注入即可,其次定義具體的消息發送方法,使得具體操作結束后調用具體的消息發送來發送消息。
/// <summary> /// 消息通知發布實例 /// </summary> public class AppNotifier : DomainService, IAppNotifier { #region 初始化 private readonly INotificationPublisher _notificationPublisher; public AppNotifier(INotificationPublisher notificationPublisher) { _notificationPublisher = notificationPublisher; } #endregion #region 消息發送 public async Task SendMessageAsync(UserIdentifier user, string message, NotificationSeverity severity = NotificationSeverity.Info) { await _notificationPublisher.PublishAsync( AppNotificationNames.SimpleMessage, new MessageNotificationData(message), severity: severity, userIds: new[] { user } ); } #endregion #region 任務提醒 public async Task NewTaskAsync(string message, NotificationSeverity severity = NotificationSeverity.Info) { await PublishMessage(AppNotificationNames.NewTask, message); } #endregion #region 輔助方法 private async Task PublishMessage(string appNotificationName, string message) { await _notificationPublisher.PublishAsync(appNotificationName, new MessageNotificationData(message)); } #endregion }
二、完成用戶訂閱消息
在MVC層,在用戶控制器中完成對消息通知設置,消息本身是獨立的,只應有了用戶才活躍起來,因此把消息的設定掛鈎在用戶身上,應該算是合理的,並同時完成頁面的設計。
/// <summary> /// 通知設置 /// </summary> /// <returns></returns> public async Task<ActionResult> NotificationSetting() { var notificationSettings = await _notificationAppService.GetNotificationSettings(); return View(notificationSettings); } /// <summary> /// 更新通知訂閱 /// </summary> /// <returns></returns> [HttpPost] public async Task<JsonResult> UpdateNotificationSetting([FromBody]UpdateNotificationSettingsInput input) { await _notificationAppService.UpdateNotificationSettings(input); return Json(new ResponseParamViewModel("通知設置已更新")); }
頁面設計只需要對提前在領域層中定義好的消息類型展示出來即可,用戶自主勾選哪些想要接收的消息提示。
三、發布消息通知用戶
在指定操作完畢,可以調用消息服務來推送消息到目標接收人員,此處,更改了原先數據字典創建處的代碼,當創建數據字典成功后,給與一個消息提示來模擬發布消息通知用戶的過程。
var existedDataDictionary = await _dataDictionaryRepository.GetAll().Where(d => d.TypeName == input.DataDictionary.TypeName).FirstOrDefaultAsync(); if (existedDataDictionary != null) { throw new UserFriendlyException(L("該字典類型已存在,無法添加")); } var dataDictionary = ObjectMapper.Map<DataDictionary>(input.DataDictionary); await _dataDictionaryRepository.InsertAsync(dataDictionary); //模擬測試消息通知 await _appNotifier.NewTaskAsync("字典類型已完成添加,可以開始使用了");
該消息觸發的前提是,需要訂閱該消息,不然有人發,無人收,總是很難為情。因此提前在通知設置中開啟類型為“新的任務”的開關。
對於消息發送到了瀏覽器中呈現,這個過程采用了SignalR,ABP框架也完成了前后端的消息通知,因此可以直接使用即可。
至此,站內消息通知的設計完畢,對於業務需求中可能面對的更為豐富的功能就得花更多時間來完成了。
代碼地址:https://gitee.com/530521314/Partner.Surround.git
2019-07-27,望技術有成后能回來看見自己的腳步