Base solution for your next web application
Open Closed

Custom Domain Events on EventBus not not triggering mapped handlers #10348


User avatar
0
jtallon created

Prerequisites

Please answer the following questions before submitting an issue. YOU MAY DELETE THE PREREQUISITES SECTION.

  • What is your product version? 9.2
  • What is your product type (Angular or MVC)? Angular
  • What is product framework type (.net framework or .net core)? .net core

If issue related with ABP Framework

  • What is ABP Framework version? 5.10.1

Im trying to leverage Event Bus to fire Custom Domain Events but looks there is some problem and the subscribed handlers are not receiving the event data. Below is a s sample of code of what I am doing.

https://aspnetboilerplate.com/Pages/Documents/EventBus-Domain-Events

` /* SAMPLE CODE */

public class InspectionFailedEventData : EventData
{
    // Few Properties which will be part of Event Data
}

public interface IInspectionFailedEventManager : IEventHandler<InspectionFailedEventData>, ITransientDependency
{
    // Interface for Handlers
}

public class SendEmailOnInspectionStatusChange : IInspectionFailedEventManager
{
    // First handler (Subscription) for the event data
    private readonly IEmailTemplateProvider _emailTemplateProvider;
    private readonly ISiteRepository _siteRepository;
    private readonly IEmailSender _emailSender;
    private readonly IRepository<Capture, Guid> _captureRepository;
    private const string TemplateName = "InspectionCompleteEmailTemplate";

    public SendEmailOnInspectionStatusChange(IEmailTemplateProvider emailTemplateProvider,
        ISiteRepository siteRepository,
        IEmailSender emailSender,
        IRepository<Capture, Guid> captureRepository)
    {
        _emailTemplateProvider = emailTemplateProvider;
        _siteRepository = siteRepository;
        _emailSender = emailSender;
        _captureRepository = captureRepository;
    }

    public void HandleEvent(InspectionFailedEventData eventData)
    {
        var captureDetails = _captureRepository.GetAllIncluding(s => s.CaptureTemplate)
            .Include(s => s.CaptureTemplate)
            .FirstOrDefault(s => s.Id == eventData.InspectionId);
        if (captureDetails != null)
        {
            var templateForStatusChange = _emailTemplateProvider.GetTemplate(eventData.TenantId, TemplateName);
            templateForStatusChange = templateForStatusChange.Replace("{Material}", captureDetails.CaptureTemplate.ItemName);
            templateForStatusChange = templateForStatusChange.Replace("{ItemNumber}", captureDetails.SMPItemNumber);
            templateForStatusChange = templateForStatusChange.Replace("{SMPLotNumber}", captureDetails.SMPLotNumber);
            templateForStatusChange = templateForStatusChange.Replace("{CompletedUser}", eventData.UserName);
            templateForStatusChange = templateForStatusChange.Replace("{StatusColour}", eventData.InspectionPassed ? "green" : "red");
            templateForStatusChange = templateForStatusChange.Replace("{MaterialStatus}", ((CaptureStatusEnum)captureDetails.CaptureStatusId).ToString());

            var wareHouseEmail = _siteRepository.Get(eventData.TenantId).WarehouseDistributionEmail;

            if (string.IsNullOrEmpty(wareHouseEmail))
            {
                throw new EntityNotFoundException("No email sent. Warehouse email was not set for this site");
            }

            _emailSender.SendAsync(new MailMessage
            {
                To = { wareHouseEmail },
                Subject = "Inspection Complete",
                Body = templateForStatusChange,
                IsBodyHtml = true

            });
        }
    }
}

public class SendStatusToQadOnInspectionStatusChange : IInspectionFailedEventManager
{
    // Second handler (Subscription) for the event data
    private readonly IQadIntegrationAction _qadIntegrationAction;

    public SendStatusToQadOnInspectionStatusChange(IQadIntegrationAction qadIntegrationAction)
    {
        _qadIntegrationAction = qadIntegrationAction;
    }

    public void HandleEvent(InspectionFailedEventData eventData)
    {
        var stockInboundMessage = new QadStockInboundMessage()
        {
            Id = eventData.Id,
            ExpiryDate = eventData.ExpiryDate,
            Status = eventData.InspectionPassed ? QadStatus.Available : QadStatus.Quality
        };

        _qadIntegrationAction.SendStockUpdateToServiceBusAsync(stockInboundMessage);
    }
}

// AppService
public async Task<string> SetInspectionStatus(SetInspectionStatusDto input)
    {
        var user = await GetCurrentUserAsync();
        var tenant = await GetCurrentTenantAsync();
        var userName = user.FullName;
        var hasInspectionPassed = CheckIfCaptureHasPassed(input.CaptureId);
        capture.CaptureTypeLockId = null;
        capture.ReleasedTime = DateTime.UtcNow;
        capture.ReleasedById = (await GetCurrentUserAsync()).Id;
        if (!hasInspectionPassed)
        {
            capture.CaptureStatusId = (int)CaptureStatusEnum.ReleaseFailed;
        }

        // Event Data Creation
        var eventData = new InspectionFailedEventData
        {
            Id = capture.GRN,
            InspectionId = capture.Id,
            InspectionPassed = hasInspectionPassed,
            ExpiryDate = capture.ExpiryDate,
            UserName = userName,
            TenantId = tenant.Id
        };

        // EventData passed to a Domain Service with some extra info
        await _inspectionEventManager.TakeActionOnInspectionFailAsync(eventData, user, tenant);
        return CaptureStatusEnum.Release.ToString();
    }

    // DomainService
    class InspectionEventManager : PortalDomainServiceBase, IInspectionEventManager
    {
        public IEventBus EventBus { get; set; }

        public InspectionEventManager()
        {
            EventBus = NullEventBus.Instance;
        }

        public async Task TakeActionOnInspectionFailAsync(InspectionFailedEventData eventData, User user1, Tenant tenant)
        {
            await EventBus.TriggerAsync(this, eventData);
        }
    }
 `

Nothing happens when TriggerAsync method is called, and I cant figure out a way to debug or resolve it.

6 Answer(s)
  • User Avatar
    0
    musa.demir created

    Hi @jtallon I could not reproduce the problem. Can you please check if your EventBus is NullEventBus.Instance. Here is my test case:

    public class InspectionFailedEventData : EventData
    {
        // Few Properties which will be part of Event Data
    }
    
    public interface IInspectionFailedEventManager : IEventHandler<InspectionFailedEventData>, ITransientDependency
    {
        // Interface for Handlers
    }
    
    public class SendEmailOnInspectionStatusChange : IInspectionFailedEventManager
    {
        // First handler (Subscription) for the event data
        public ILogger Logger { get; set; }
    
        public SendEmailOnInspectionStatusChange()
        {
            Logger = NullLogger.Instance;
        }
    
        public void HandleEvent(InspectionFailedEventData eventData)
        {
            Logger.Info("SendEmailOnInspectionStatusChange Handled");
        }
    }
    
    public class SendStatusToQadOnInspectionStatusChange : IInspectionFailedEventManager
    {
        // First handler (Subscription) for the event data
        public ILogger Logger { get; set; }
    
        public SendStatusToQadOnInspectionStatusChange()
        {
            Logger = NullLogger.Instance;
        }
    
        public void HandleEvent(InspectionFailedEventData eventData)
        {
            Logger.Info("SendStatusToQadOnInspectionStatusChange  Handled");
        }
    }
    

    And trigger event somewhere you want

    public async Task TestEvent()
    {
        Logger.Info("TestEvent Started");
        await EventBus.TriggerAsync(this, new InspectionFailedEventData());
    }
    

    And the log file :

    Can you also please try that test case on your project?

  • User Avatar
    0
    jtallon created

    Hi Team,

    I figured out the work around by bringing my handlers back into Application project.

    It was not working when I had handlers in a new class library, as you can see I did made them ITransientDependency as well which should Ideally register the handlers in dependency container for the event.

    My assumption, somehow handlers in different projects dont get recognised/ mapped although after implementing ITransientDependency, thats why even if trigger the event from application project, they dont get picked by handlers.

    Please look into it, is there anything extra I need to do to keep the handlers in a separate prooject, its very important as we are planning to divide the whole project into smaller libraries instead of one FAT application or core etc project, which will also help us in upgrading version of aspnetzero as eventually the shipped projects will be untouched.

    Regards

  • User Avatar
    0
    musa.demir created

    Does your console app's AbpModule contains following code? https://github.com/aspnetzero/aspnet-zero-core/blob/d36630adeb04ac12c2ad768530f3c8889375a743/aspnet-core/src/MyCompanyName.AbpZeroTemplate.Application/AbpZeroTemplateApplicationModule.cs#L26-L29

  • User Avatar
    0
    jtallon created

    That link is not reachable.

  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi,

    Please add your GitHub user on https://aspnetzero.com/LicenseManagement. You can reach the link after accepting the invitation from GitHub.

  • User Avatar
    0
    musa.demir created

    See https://support.aspnetzero.com/QA/Questions/9580/How-to-access-the-ASPNET-Zero-private-GitHub-repository