Base solution for your next web application
Open Closed

Notifications via HangFire #3922


User avatar
0
cmthomps created

I'm having a similar issue as the one presented at: [https://forum.aspnetboilerplate.com/viewtopic.php?f=5&t=9887&p=22368&hilit=notification#p22368])

I've gone through the post and am not having any luck. The users never receive the notifications. I can see that the service is getting called because I can set a breakpoint and I can also see the jobs in the Hangfire tables.

Here is my domain service code. Happy to send the project along if it would be easier.

Thanks, Craig

using Abp;
using Abp.Domain.Repositories;
using Abp.Domain.Uow;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TestCode.TestCode.Authorization.Users;

namespace TestCode.TestCode.Notifications
{
    public class NotificationDomainService : TestCodeDomainServiceBase, INotificationDomainService
    {
        //private readonly INotificationDomainService _notificationDomainService;

        private readonly IAppNotifier _appNotifier;
        private readonly UserManager _userManager;
        private IRepository<User, long> _userRepository;
        private readonly IUnitOfWorkManager _unitOfWorkManager;

        public NotificationDomainService(IAppNotifier appNotifier, IRepository<User, long> userRepository, IUnitOfWorkManager unitOfWorkManager)//, UserManager userManager)
        {
            _appNotifier = appNotifier;
            //_userManager = userManager;
            _userRepository = userRepository;
            _unitOfWorkManager = unitOfWorkManager;
        }

        
        public virtual void NotifyAllForTenantById(int? tenantId, string message = "Domain Service", string severity = "info")
        {
            using (_unitOfWorkManager.Begin())
            {
                using (CurrentUnitOfWork.DisableFilter(AbpDataFilters.MayHaveTenant))
                {
                    var users = _userRepository.GetAllList(u => u.TenantId == tenantId);
                    
                    UserIdentifier[] userIds = new UserIdentifier[users.Count()];
                    int i = 0;
                    foreach (User u in users)
                    {
                        UserIdentifier userId = new UserIdentifier(tenantId, u.Id);
                        _appNotifier.SendMessageAsync(userId, "Hello to All Tenant Users From The Domain Service");
                  }
                  
                    CurrentUnitOfWork.SaveChanges();
                    
                }
            }
        }


    }
}

11 Answer(s)
  • User Avatar
    0
    aaron created
    Support Team

    Can you check if [http://localhost:62114/Account/TestNotification]) works?

  • User Avatar
    0
    cmthomps created

    It does. I've also created a button in my application that fires off a notification (as a test). Those get to the user without an issue.

  • User Avatar
    0
    aaron created
    Support Team

    Can you try calling unitOfWork.Complete?

    using (var unitOfWork = _unitOfWorkManager.Begin())
    {
        // ...
    
        // CurrentUnitOfWork.SaveChanges();
        unitOfWork.Complete();
    }
    
  • User Avatar
    0
    cmthomps created

    Thanks Aaron - Still no luck. Any other ideas?

  • User Avatar
    0
    cmthomps created

    The odd thing is that sometimes the notification goes through the first time the service is hit. After that, the notifications do not go through.

  • User Avatar
    0
    aaron created
    Support Team

    No error log?

  • User Avatar
    0
    cmthomps created

    No errors. Consistently, the first time the service runs, the notification gets sent and received. After that, none of the other notifications go through. The hangfire jobs show success. Screenshot attached,

  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi @cmthomps,

    I think @aaron's suggestion about using unitOfWork.Complete(); is a must in your case. Can you also try to use <a class="postlink" href="https://aspnetboilerplate.com/Pages/Documents/Abp-Session#user-identifier">https://aspnetboilerplate.com/Pages/Doc ... identifier</a> instead of

    using (CurrentUnitOfWork.DisableFilter(AbpDataFilters.MayHaveTenant))
    

    ?

    Thanks.

  • User Avatar
    0
    cmthomps created

    Thanks. Still no luck. I'm still seeing that the notification goes through the first time the service is hit but not on subsequent passes. Here is what my code looks like now. Happy to send in the project if it helps. It's a test project.

    using Abp;
    using Abp.Domain.Repositories;
    using Abp.Domain.Uow;
    using Abp.Runtime.Session;
    using System.Linq;
    using TestCode.TestCode.Authorization.Users;
    
    namespace TestCode.TestCode.Notifications
    {
        public class NotificationDomainService : TestCodeDomainServiceBase, INotificationDomainService
        {
            //private readonly INotificationDomainService _notificationDomainService;
    
            private readonly IAppNotifier _appNotifier;
            private readonly UserManager _userManager;
            private IRepository<User, long> _userRepository;
            private readonly IUnitOfWorkManager _unitOfWorkManager;
            private readonly IAbpSession _session;
    
            public NotificationDomainService(IAppNotifier appNotifier, IRepository<User, long> userRepository, IUnitOfWorkManager unitOfWorkManager, IAbpSession abpSession)//, UserManager userManager)
            {
                _appNotifier = appNotifier;
                //_userManager = userManager;
                _userRepository = userRepository;
                _unitOfWorkManager = unitOfWorkManager;
                _session = abpSession;
            }
    
    
            public virtual void NotifyAllForTenantById(int? tenantId, string message = "Domain Service", string severity = "info")
            {
                using (_session.Use(tenantId, null))
                {
                    using (var unitOfWork = _unitOfWorkManager.Begin())
                    {
    
                        using (CurrentUnitOfWork.DisableFilter(AbpDataFilters.MayHaveTenant))
                        {
    
                            var users = _userRepository.GetAllList(u => u.TenantId == tenantId);
                            //UserIdentifier[] userIds = new UserIdentifier[users.Count()];
                            int i = 0;
                            foreach (User u in users)
                            {
                                UserIdentifier userId = new UserIdentifier(tenantId, u.Id);
                                //userIds[i] = userId;
                                _appNotifier.SendMessageAsync(userId, "Hello to All Tenant Users From The Domain Service " + System.DateTime.Now.ToLongTimeString());
                            }
                            //_appNotifier.SendAlertToAllTenantUsersAsync("Hello to All Tenant Users From The Domain Service", userIds);
    
                            CurrentUnitOfWork.SaveChanges();
                        }
    
                        unitOfWork.Complete();
                    }
                }
            }
    
    
        }
    }
    
  • User Avatar
    0
    cmthomps created

    I finally figured it out. I was trying to use an async method in the AppNotifier class. When I changed the method to be non-async, the notifications started going through. (Not just on the first pass through the service).

  • User Avatar
    0
    ismcagdas created
    Support Team

    Thanks for the feedback @cmthomps.