Base solution for your next web application
Open Closed

Hangfire Job #4115


User avatar
0
pankajmathur created

Hi,

My application services class is decorated with ABPAuthorize attribute. This has been done so as to avoid any unauthenticated user to call any of my service method. Due to this I am trap with a problem. I am using hangfire. Once a user import an excel file, I put the excel data in Hangfire Job. Now when The hangfire start executing, it calls a method of the service to check whether the data imported already available in the database. Now since my service class is decorated with ABPAuthorize attribute, it does not allow the hangfirew to call the service method and it says "The current user did not login to the application". If I decorate the service method with ABPAllowAnonymous, it works fine. But I dont want the method to be called anonymously.

Please help me how can I successfully let the hangfire call the service method.

Regards, Mahendra


5 Answer(s)
  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi @pankajmathur,

    I suggest you to create a domain class and use it both in your App service and hangfire job. In that way, you can add AbpAuthorize attribute to your app service.

  • User Avatar
    0
    pankajmathur created

    Hi,

    I did not understand you fully what do you mean by domain class. Could you please provide me a sample or provide me a link where I can read more about domain class.

    By the way, I saw a strange behavior. Please have a look at the following code.

    Hangfire Code (Please note that this class is not decorated with ABPAuthorize attribute)


    public override void Execute(DataImportJobArgs dataImportJobArgs) {

            Task ImportTask = Task.Run(() => ImportData(dataImportJobArgs));
            ImportTask.Wait();
        }
    

    private async Task ImportData(DataImportJobArgs dataImportJobArgs) { ImportAppService = (IImportAppService)IocManager.Instance.Resolve(typeof(CustomerAppService)); await ImportAppService.ImportData(dataImportJobArgs.DataToImport, false); }

    CustomerAppService Code ((This class is decorated with ABPAuthorize attribute)


    public async Task<DataTable> ImportData(DataTable dataTable, bool ImportInBackground = true) { CustomerDto ExistingCustomer = GetCustomerByEntityId(Row["CustomerId"].ToString());

        }
    

    public CustomerDto GetCustomerByEntityId(string EntityId) { CustomerDto Customer = _CustomerRepository.FirstOrDefault(x => x.EntityId == EntityId).MapTo<CustomerDto>();

            if (Customer != null && Customer.AddressKey != 0)
                Customer.CustomerAddress = AddressAppService.GetAddress(Customer.AddressKey);
    
            return Customer;
        }
    

    Now, the Background job is able to call the ImportData method of CustomerAppService (Though the CustomerAppService is decorated with ABPAuthorize). However GetCustomerByEntityId method of CustomerAppService is not able to call the GetAddress method of AddressAppService (Which is yet another AppService decorated with ABPAuthorize attribute)

    So the flow is:

    1. Hangfire Background Class calls the CustomerAppService (Which gets called successfully) and then
    2. CustomerAppService calls the AddressAppService (Which gets failed).

    Please note that both the above AppService is decorated with ABPAuthorize. The strange behavior that I feel is if customer is not logged in then why even the method CustomerAppService is getting invoked by Background Job class. (In my Case why even the ImportData method of CustomerAppService is getting called.

    Please help me.

  • User Avatar
    0
    aaron created
    Support Team

    That's because you resolve CustomerAppService directly in Resolve(typeof(CustomerAppService)). See restrictions of AbpAuthorize attribute: https://aspnetboilerplate.com/Pages/Documents/Authorization#abpauthorize-attribute-notes

    You need to:

    private async Task ImportData(DataImportJobArgs dataImportJobArgs)
    {
        // var userId = ...
        // var tenantId = ...
    
        using (_session.Use(userId, tenantId))
        {
            ImportAppService = (IImportAppService)IocManager.Instance.Resolve(typeof(ICustomerAppService)); 
            await ImportAppService.ImportData(dataImportJobArgs.DataToImport, false);
        }
    }
    
  • User Avatar
    0
    pankajmathur created

    Thanks aaron....It worked...cheers....

  • User Avatar
    0
    pankajmathur created

    Hi,

    One more small question regarding hangfire....

    In SQL database tables, can I figure out when a task that is scheduled is about to run (I mean date and time)....

    Regards, Mahendra