Base solution for your next web application
Open Closed

Notification has been sent to user who has not subscribed (We have only passed excludeuserid in PublishAsync method) #6457


User avatar
0
razkhan78 created

We are implementing Notifications for Create events as well some of update data event.

We have one table called "Document". We have implemented Notifications for following cases with specific tenant:

  1. When user creates new document.
  2. When user changes Document type

In Notification setting, two entries will be displayed with checkboxes:

  1. On New Document creation
  2. On Document type change

Issue:

Case 1(Working): If we subscribe for "On New Document creation" and "On Document type change" everything works fine and both types of notifications will be sent to subscribed users. Case 2(Working): If we subscribe only for "On New Document creation" everything works fine and notification will be sent to subscribed users only for new document creation. Case 3(Not Working): If we subscribe only for "On Document type change" and NOT SUBSCRIBE for "On New Document creation" then notification will not be sent to subscribed users. Case 4(Not Working): If we subscribe only for "On New Document creation" and NOT SUBSCRIBE for "On Document type change" then also notification will be sent for both events. If we remove subscription for "On New Document creation" then only "On Document type change" event notification won't be sent.

For all cases, AbpNotificationSubscription table is populated perfectly as per notification selection from Setting screen. Issue occures only with sending notifications.

We are calling PublishAsync as per following: await _notificationPublisher.PublishAsync("App.NewDocumentCreated", notificationData, null,NotificationSeverity.Info, null, excludedUserIds: new[] { createdByUser.ToUserIdentifier() });

As per our understanding, this method will only send notifications to subscribed users which is not working in our system.

It seems like data update Notification subscription is dependent on data create notification. Please suggest how we can solve these issues.


7 Answer(s)
  • User Avatar
    0
    ryancyq created
    Support Team

    please share your code for

    1. subscribing the user(s) to new document creation/change notification
    2. notification subscription records (in the database) for the user(s) & notifications in point (1)
  • User Avatar
    0
    razkhan78 created
    ==============================AppNotificationProvider.cs==============================
    
    /* Document create */
    context.Manager.Add(
    	new NotificationDefinition(
            AppNotificationNames.NewDocumentCreated,
            displayName: L("NewDocumentCreatedNotificationDefinition"),
            permissionDependency: new SimplePermissionDependency(AppPermissions.Pages_Documents_Create)
            )
    );
    
    /* Document type update */
    context.Manager.Add(
    	new NotificationDefinition(
            AppNotificationNames.DocumentTypeChanged,
            displayName: L("DocumentTypeChangedNotificationDefinition"),
            permissionDependency: new SimplePermissionDependency(AppPermissions.Pages_Documents_Edit)
            )
    );
    
    
    ==============================NotificationAppService.cs==============================
    
    	public async Task<GetNotificationSettingsOutput> GetNotificationSettings()
            {
                var output = new GetNotificationSettingsOutput();
    
                output.ReceiveNotifications = await SettingManager.GetSettingValueAsync<bool>(NotificationSettingNames.ReceiveNotifications);
    
                /*Get general notifications, not entity related notifications*/
                //var notificationDefinitions = (await _notificationDefinitionManager.GetAllAvailableAsync(AbpSession.ToUserIdentifier())).Where(nd => nd.EntityType == null);
    
                /*Get all notifications (general+entity related)*/
                var notificationDefinitions = (await _notificationDefinitionManager.GetAllAvailableAsync(AbpSession.ToUserIdentifier()));
    
                output.Notifications = ObjectMapper.Map<List<NotificationSubscriptionWithDisplayNameDto>>(notificationDefinitions);
    
                var subscribedNotifications = (await _notificationSubscriptionManager
                    .GetSubscribedNotificationsAsync(AbpSession.ToUserIdentifier()))
                    .Select(ns => ns.NotificationName)
                    .ToList();
    
                output.Notifications.ForEach(n => n.IsSubscribed = subscribedNotifications.Contains(n.Name));
    
                return output;
            }
    
            public async Task UpdateNotificationSettings(UpdateNotificationSettingsInput input)
            {
                await SettingManager.ChangeSettingForUserAsync(AbpSession.ToUserIdentifier(), NotificationSettingNames.ReceiveNotifications, input.ReceiveNotifications.ToString());
    
                foreach (var notification in input.Notifications)
                {
                    if (notification.IsSubscribed)
                    {
                        await _notificationSubscriptionManager.SubscribeAsync(AbpSession.ToUserIdentifier(), notification.Name);                    
                    }
                    else
                    {
                        await _notificationSubscriptionManager.UnsubscribeAsync(AbpSession.ToUserIdentifier(), notification.Name);
                    }
                }
            }
    
    ==============================AppNotifier.cs==============================
    
    /*We have called this function on Document save method:*/
    
    await _notificationPublisher.PublishAsync(AppNotificationNames.NewDocumentCreated, notificationData, null,
                        NotificationSeverity.Info, null, excludedUserIds: new[] { createdByUser.ToUserIdentifier() });
    
    /*We have called this function on change of Document type:*/
    
    await _notificationPublisher.PublishAsync(AppNotificationNames.DocumentTypeChanged, notificationData, null,
                        NotificationSeverity.Info, null, excludedUserIds: new[] { createdByUser.ToUserIdentifier() });
    

    We have passed required dynamic fields values in notification data object.

    In database, subscriptions and tenant notifications are populating fine still it is creating issues in Notifications.

  • User Avatar
    0
    aaron created
    Support Team

    What is "document type change"?

  • User Avatar
    0
    ryancyq created
    Support Team

    /* We have called this function on Document save method:*/

    also, was this done via Entity Change Handler?

  • User Avatar
    0
    razkhan78 created
    1. What is "document type change"? Comment: We have one dropdown for "document type". Whenver any user change document type from its initial value we have to send notification.

    For eg. I have created one document "MyLicenseDoc" with "DocType1". Now in edit mode, I have changed it to "DocType2". So in this case, all subscribed users will get notification.

    1. We have called this function on Document save method: was this done via Entity Change Handler? Comment: No. We have just called PublishAsync method when our update method is called.
  • User Avatar
    0
    aaron created
    Support Team

    Show the complete update method.

  • User Avatar
    0
    razkhan78 created
    /*=======================documentAppService.cs==============================*/
    [AbpAuthorize(AppPermissions.Pages_Documents_Edit)]
    private async Task<CreateOrEditDocumentDto> Update(CreateOrEditDocumentDto input)
    {
        var user = await UserManager.FindByIdAsync(AbpSession.GetUserId().ToString());
        var document = await _documentRepository.FirstOrDefaultAsync((int)input.Id);
        var oldDocumentType = document.DocumentyTypeName;                       
    
        var documentMappedEntity = ObjectMapper.Map(input, document);
        await _documentRepository.UpdateAsync(documentMappedEntity);
        await UnitOfWorkManager.Current.SaveChangesAsync();            
    
       if(oldDocumentType != documentMappedEntity.DocumentTypeName)
       {
    	/*Send notification for Document type update to all subscribed users*/
    	_appNotifier.NotificationForDocumentTypeChangedAsync(user,notificationForDocumentDto);
       }
    		
       return ObjectMapper.Map<CreateOrEditDocumentDto>(documentMappedEntity);
    }
    
    /*=================AppNotifier.cs===================*/
    public async Task NotificationForDocumentTypeChangedAsync(User createdByUser, CreateOrEditDocumentDto notificationForDocumentDto)
    {
    	try
    	{
    		/*Set Notification data for dynamic localization string and set parameters for Notification message text*/
                    var notificationData = new LocalizableMessageNotificationData(
                        new LocalizableString(
                            CommonMethodHelper.GetNotificationTextLocalizationString("DocumentTypeChangedNotificationMessage"),
                            LoadStopConsts.LocalizationSourceName
                            )
                        );
    
                    notificationData["documentName"] = notificationForNewDocumentCreatedDto.CreateOrEditDocumentDto.Name;
                    notificationData["documentType"] = notificationForNewDocumentCreatedDto.DocumentTypeName;
                    notificationData["user"] = createdByUser.FullName;
    
                    //Write logs
                    Logger.Info("document type changed notification Publish Notification Start: " + notificationForNewDocumentCreatedDto.CreateOrEditDocumentDto.Name);
    
                    await _notificationPublisher.PublishAsync(AppNotificationNames.DocumentTypeChanged, notificationData, null,
                        NotificationSeverity.Info, null, excludedUserIds: new[] { createdByUser.ToUserIdentifier() });
    
                    Logger.Info("document type changed notification Publish Notification End: " + notificationForNewDocumentCreatedDto.CreateOrEditDocumentDto.Name);
                    
            }
    	catch(Exception ex)
    	{
    	       var errorMessage = ex.Message;
    	}            
    }
    
    /*=====================.xml file========================*/
    
    <text name="DocumentTypeChangedNotificationMessage" value="Document type changed to {documentType} for Document: {documentName} by {user}"></text>
    
    /*=====================AppNotificationNames.cs========================*/
    public const string DocumentTypeChanged = "App.DocumentTypeChanged";
    
    /*=====================AppNotificationProvider.cs========================*/
    
    /* Document create */
    context.Manager.Add(
    	new NotificationDefinition(
            AppNotificationNames.NewDocumentCreated,
            displayName: L("NewDocumentCreatedNotificationDefinition"),
            permissionDependency: new SimplePermissionDependency(AppPermissions.Pages_Documents_Create)
            )
    );
    
    /* Document type update */
    context.Manager.Add(
    	new NotificationDefinition(
            AppNotificationNames.DocumentTypeChanged,
            displayName: L("DocumentTypeChangedNotificationDefinition"),
            permissionDependency: new SimplePermissionDependency(AppPermissions.Pages_Documents_Edit)
            )
    );