Base solution for your next web application
Open Closed

I want to call a AppService from Web.Host project #7355


User avatar
0
SASIMEXICO created

I want to call a AppService from a static Class. This Static Class is defined in a Web.Host project.

  • AppService:

    public interface ISignalRExtensionAppService : IApplicationService { Task<bool> Create(CreateMachineDto input); }


      public class SignalRExtensionAppService : ISignalRExtensionAppService
    

    { public ILogger log { get; set; } private IDbContextProvider<GenTimeDbContext> _sampleDbContextProvider;

      public SignalRExtensionAppService(IDbContextProvider&lt;myDbContext&gt; sampleDbContextProvider)
      {
          _sampleDbContextProvider = sampleDbContextProvider;
          log = NullLogger.Instance;
      }
    
      public async Task&lt;bool&gt; Create(CreateMachineDto input)
      {
          try
          {
              log.Debug(string.Format("Machine: {0} with TenantId is {1} send: {2} - {3}", input.Name, input.TenantId, input.LastLogin, input.LastLogin));
              using (var context = _sampleDbContextProvider.GetDbContext())
              {
                  var machine = context.Machines.Where(x => x.Name == input.Name && x.TenantId == input.TenantId).FirstOrDefault();
                  machine.LastLogin = input.LastLogin;
                  machine.LastLogout = input.LastLogout;
    
                  context.SaveChanges();
              }
              return true;
          }
          catch (Exception ex)
          {
              log.Error(ex.Message, ex);
              return false;
          }
      }
    
      public async Task&lt;string&gt; GetMachineName(int input)
      {
          string result = string.Empty;
          try
          {
              log.Debug(string.Format("MachineId: {0}.", input));
              using (var context = _sampleDbContextProvider.GetDbContext())
              {
                  var machine = context.Machines.Where(x => x.Id == input).FirstOrDefault();
                  result = machine.Name;
              }
          }
          catch (Exception ex)
          {
              log.Error(ex.Message, ex);
          }
    
          return result;
      }
    

- Static Class:

    private static SignalRExtensionAppService _signalRExtensionAppService;
            
     public static void AddSignalR(this IServiceCollection services, IConfiguration configuration)
    {
        var url = configuration["SignalR:Url"];

        _signalRExtensionAppService = signalRExtensionAppService();   **&lt;-- Error How to pass IDbContextProvider&lt;myDbContext&gt; sampleDbContextProvider** 
        
        
*************************************
  • Startup

// Call to staic class services.AddSignalR(_appConfiguration);


how to pass IDbContextProvider<myDbContext> sampleDbContextProvider or IRepository<Application> _applicationRepository when make a new?

Thanks for all

Regards


17 Answer(s)
  • User Avatar
    0
    maliming created
    Support Team

    You need dependency injection, but it is not recommended to use global dependency injection containers in static methods.

    Why do you want to use application services in static methods? Maybe you can do it in another way.

  • User Avatar
    0
    SASIMEXICO created

    Because i need to update machines date (last login and last logout) when the machine disconnected to SignalR. In this static class (add in sistem with singleton) I define the client to connected to SignalR and your events subscrived. This signalR client pass to MachineAppService for send message to machines.

    Could you tell me what the injection of dependencies from the static class should be like or give me a new idea?

    Thanks for all.

    Regards

  • User Avatar
    0
    maliming created
    Support Team

    Where is your static method called?

    If the application is called once after it is started, you can call it in the module and use dependency injection.

    Please share more code.

  • User Avatar
    0
    SASIMEXICO created

    How can I call AppService from the beginning? How can I do it from the Web.Host?

    • Startup

        services.AddSignalR(_appConfiguration);
      
    • Static Class

       public static class SignalRExtension
        {
            private const string WEBAPI = "!GSSYSTEM_WAPI";
            private static SignalRExtensionAppService _signalRExtensionAppService;
            private static IRepository&lt;Machine&gt; _machineRepository;
      
            public static void AddSignalR(this IServiceCollection services, IConfiguration configuration)
            {
                var url = configuration["SignalR:Url"];
      
                //_signalRExtensionAppService = signalRExtensionAppService;
                //_machineRepository = machineRepository;
      
                HubConnection connection = null;
                connection = new HubConnectionBuilder()
                    .WithUrl(url)
                    .Build();
      
                connection.On&lt;string, string, string, int&gt;("GetMessage", (from, to, message, type) =>
                {
                    Task.Run(async () =>
                    {
                        var newMessage = $"{"SIG"}: {message}";
                        //log.Info(newMessage);
                        //Console.WriteLine(newMessage);
                        Recieve_SendMessageToUser(from, to, message, type);
                    });
                });
      
                connection.Closed += async (error) =>
                {
                    await Task.Delay(new Random().Next(0, 5) * 1000);
                    await connection.StartAsync();
                    connection.InvokeAsync&lt;string&gt;("JoinGroup", "monitor", WEBAPI, "1");
                };
      
                connection.StartAsync();
                connection.InvokeAsync&lt;string&gt;("JoinGroup", "monitor", WEBAPI, "1");
                services.AddSingleton(connection);
            }
      
            public static void Recieve_SendMessageToUser(string from, string to, string message, int type)
            {
                string action = message.Split('@')[0];
                switch (action)
                {
                    case "ActualizeRegisterDB":
                        ActualizeRegisterDB(message.Split('@')[1], message.Split('@')[2], message);
                        break;
                    default:
                        break;
                }
            }
      
            private static async Task ActualizeRegisterDB(string machineName, string tenant, string message)
            {
                int tenantId = 0;
                try
                {
                    var lastLogin = DateTime.ParseExact(message.Split('@')[3], "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture);
                    var lastLogout = DateTime.ParseExact(message.Split('@')[4], "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture);
      
                    int.TryParse(message.Split('@')[2], out tenantId);
      
                    CreateMachineDto createMachine = new CreateMachineDto()
                    {
                        Name = message.Split('@')[1],
                        LastLogin = lastLogin,
                        LastLogout = lastLogout,
                        TenantId = tenantId
                    };
      
                    //Call to SignalRExtensionAppService
      
                }
                catch (Exception ex)
                {
                    throw;
                }
            }
        }
      
    • AppService

       [AbpAuthorize(AppPermissions.Pages_Administration_Users)]
        public class MachineAppService : AsyncCrudAppService&lt;Machine, MachineDto, int, ControllerInputDto, CreateMachineDto, UpdateMachineDto&gt;, IMachineAppService
        {
            #region "Members"
      
            public ILogger log { get; set; }
      
            private readonly IRepository&lt;Application&gt; _applicationRepository;
            private readonly IRepository&lt;Machine&gt; _machineRepository;
            private readonly IRepository&lt;AppVersion&gt; _appVersionRepository;
            private readonly IRepository&lt;Tag&gt; _tagRepository;
            private readonly IRepository&lt;License&gt; _licenseRepository;
            private readonly IRepository&lt;Tenant&gt; _tenantRepository;
            private readonly IRepository&lt;AppVendor&gt; _appVendorRepository;
            private readonly IRepository&lt;Active&gt; _activeRepository;
            private readonly IRepository&lt;SamAudit&gt; _samAuditRepository;
            private readonly IRepository&lt;ProductGroup&gt; _productGroupRepository;
            private readonly IObjectMapper _objectMapper;
            private readonly HubConnection _connection;
            private readonly IFileProvider _fileProvider;
      
            #endregion
      
            #region "Constructor"
      
            public MachineAppService(
                IRepository&lt;Machine&gt; machineRepository,
                IRepository&lt;Application&gt; applicationRepository,
                IRepository&lt;AppVersion&gt; appVersionRepository,
                IRepository&lt;Tag&gt; tagRepository,
                IRepository&lt;License&gt; licenseRepository,
                IRepository&lt;Tenant&gt; tenantRepository,
                IRepository&lt;AppVendor&gt; appVendorRepository,
                IRepository&lt;Active&gt; activeRepository,
                IRepository&lt;SamAudit&gt; samAuditRepository,
                IRepository&lt;ProductGroup&gt; productGroupRepository,
                IObjectMapper objectMapper,
                HubConnection connection,
                IFileProvider fileProvider
                ) : base(machineRepository)
            {
                _applicationRepository = applicationRepository;
                _machineRepository = machineRepository;
                _appVersionRepository = appVersionRepository;
                _tagRepository = tagRepository;
                _licenseRepository = licenseRepository;
                _tenantRepository = tenantRepository;
                _appVendorRepository = appVendorRepository;
                _activeRepository = activeRepository;
                _samAuditRepository = samAuditRepository;
                _productGroupRepository = productGroupRepository;
                _objectMapper = objectMapper;
                _connection = connection;
                _fileProvider = fileProvider;
      
                log = NullLogger.Instance;
            }
      
            #endregion
      
            #region "Calls to SignalR"
            public async Task UpdateSigToMachine(List&lt;UpdateMachineDto&gt; input)
            {
                // signal => SIG_SHUTDOWN / SIG_STARTUP
                var tenantId = AbpSession.TenantId;
      
                try
                {
                    var machines = (from a in input
                                         select a);
      
                    foreach (var item in machines)
                    {
                        var signal = item.Active == true ? "SIG_STARTUP" : "SIG_SHUTDOWN";
                        await Update(item);
                        await _connection.InvokeAsync("SendSIGToMachine", item.Name, signal, tenantId.ToString());
                    }
      
                    return;
                }
                catch (Exception ex)
                {
                    log.Error(ex.Message, ex);
                    return;
                }
            }
      
            public async Task UpdateSigToAll(string signal)
            {
                var tenantId = AbpSession.TenantId;
                //int tenantId = 0;
                //int.TryParse(TenantId, out tenantId);
                // signal => SIG_SHUTDOWN / SIG_STARTUP
                bool recibeSignal = signal == "SIG_SHUTDOWN" ? false : true;
                await _connection.InvokeAsync("SendSIGToEverybody", tenantId, signal);
      
                try
                {
                    //var allMachines = _machineRepository.GetAll()
                    //        .Where(x => x.TenantId == tenantId);
      
                    var allMachines = _machineRepository.Query(a => a.Where(x => x.TenantId == tenantId));
      
                    foreach (var machine in allMachines)
                    {
                        if (recibeSignal)
                            machine.LastLogin = DateTime.Now;
                        else
                            machine.LastLogout = DateTime.Now;
      
                        machine.Active = recibeSignal;
                        _machineRepository.InsertOrUpdate(machine);
                    }
                }
                catch (Exception ex)
                {
                    log.Error(ex.Message, ex);
                }
            }
      
            //[AbpAllowAnonymousAttribute]
            [AbpAuthorize(AppPermissions.Pages_Administration_Users)]
            public async Task&lt;List&lt;string&gt;> GetSignalRConnections()
            {
                return await _connection.InvokeAsync&lt;List&lt;string&gt;>("GetConnectedUsers");
            }
      
            //[AbpAllowAnonymousAttribute]
            [AbpAuthorize(AppPermissions.Pages_Administration_Users)]
            public async Task&lt;List&lt;string&gt;> GetSignalRMachineConnections()
            {
                var tenantId = AbpSession.TenantId;
                return await _connection.InvokeAsync&lt;List&lt;string&gt;>("GetConnectedMachines", tenantId);
            }
      
            //[AbpAllowAnonymousAttribute]
            [AbpAuthorize(AppPermissions.Pages_Administration_Users)]
            public async Task&lt;List&lt;string&gt;> GetAvailableApplicationsLogs(string machineName)
            {
                var tenantId = AbpSession.TenantId;
                return await _connection.InvokeAsync&lt;List&lt;string&gt;>("GetAvailableApplicationsLogs", machineName, tenantId);
            }
      
            //[AbpAllowAnonymousAttribute]
            [AbpAuthorize(AppPermissions.Pages_Administration_Users)]
            public async Task&lt;IActionResult&gt; GetServiceLog(string machineName, string serviceName)
            {
                var tenantId = AbpSession.TenantId;
                var pathlog = await _connection.InvokeAsync&lt;string&gt;("GetServiceLog", machineName, tenantId, serviceName);
                FileStreamingAppService fileStreamingAppService = new FileStreamingAppService(_fileProvider);
                return await fileStreamingAppService.DownloadFile(pathlog.Split("@")[1]);
            }
      
            //[AbpAllowAnonymousAttribute]
            [AbpAuthorize(AppPermissions.Pages_Administration_Users)]
            public async Task UpdateApplicationsLogLevel(string machineName, string logLevel)
            {
                var tenantId = AbpSession.TenantId;
                await _connection.InvokeAsync&lt;List&lt;string&gt;>("SendUpdateApplicationsLogLevel", machineName, logLevel, tenantId);
            }
      
            #endregion
      
  • User Avatar
    0
    maliming created
    Support Team

    You can move the contents of the AddSignalR method to the PostInitialize method of the WebHostModule class.

    And use IocManager to get the relevant services you need.

    https://github.com/aspnetzero/aspnet-zero-core/blob/dev/aspnet-core/src/MyCompanyName.AbpZeroTemplate.Web.Host/Startup/AbpZeroTemplateWebHostModule.cs#L58

  • User Avatar
    0
    SASIMEXICO created

    Ok thanks... I try it

  • User Avatar
    0
    SASIMEXICO created

    I've tried to do it, but I don't know what I'm doing wrong.

    • WebHostModule

                IocManager.Resolve&lt;AppService.ISignalRExtensionAppService&gt;();
      
    • ISignalRExtensionAppService

        public interface ISignalRExtensionAppService : IApplicationService
        {
            Task Create(CreateMachineDto input);
        }
      
    • SignalRExtensionAppService

        public class SignalRExtensionAppService : ISignalRExtensionAppService
        {
            #region "Members"
      
        public ILogger log { get; set; }
      
        private readonly IDbContextProvider&lt;GenTimeDbContext&gt; _sampleDbContextProvider;
        private readonly IRepository&lt;Machine&gt; _machineRepository;
        private readonly HubConnection _connection;
      
        #endregion
      
        #region "Constructor"
      
        public SignalRExtensionAppService(
            IRepository&lt;Machine&gt; machineRepository,
            IDbContextProvider&lt;GenTimeDbContext&gt; sampleDbContextProvider,
            HubConnection connection
            )
        {
            _machineRepository = machineRepository;
            _connection = connection;
            _sampleDbContextProvider = sampleDbContextProvider;
      
            log = NullLogger.Instance;
      
            InvokedOn();
        }
      
        #endregion
      
        #region "Private Method"
      
        #region "SignalR"
      
        private async Task InvokedOn()
        {
            _connection.On&lt;string, string, string, int&gt;("GetMessage", (from, to, message, type) =>
            {
                Task.Run(async () =>
                {
                    var newMessage = $"{"SIG"}: {message}";
                    log.Info(newMessage);
                    Recieve_SendMessageToUser(from, to, message, type);
                });
            });
        }
      
        private async Task Recieve_SendMessageToUser(string from, string to, string message, int type)
        {
            string action = message.Split('@')[0];
            switch (action)
            {
                case "ActualizeRegisterDB":
                    ActualizeRegisterDB(message.Split('@')[1], message.Split('@')[2], message);
                    break;
                default:
                    break;
            }
        }
      
        private async Task ActualizeRegisterDB(string machineName, string tenant, string message)
        {
            int tenantId = 0;
            try
            {
                var lastLogin = DateTime.ParseExact(message.Split('@')[3], "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture);
                var lastLogout = DateTime.ParseExact(message.Split('@')[4], "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture);
      
                int.TryParse(message.Split('@')[2], out tenantId);
      
                CreateMachineDto createMachine = new CreateMachineDto()
                {
                    Name = message.Split('@')[1],
                    LastLogin = lastLogin,
                    LastLogout = lastLogout,
                    TenantId = tenantId
                };
      
                await Create(createMachine);
            }
            catch (Exception ex)
            {
                log.Error(ex.Message, ex);
            }
        }
      
        #endregion
      
        #endregion
      
        #region "Interface Implementation Method"
      
        public async Task Create(CreateMachineDto input)
        {
            try
            {
                log.Debug(string.Format("Machine: {0} with TenantId is {1} send: {2} - {3}", input.Name, input.TenantId, input.LastLogin, input.LastLogin));
      
                var machine = _machineRepository.GetAll().Where(x => x.Name == input.Name && x.TenantId == input.TenantId).FirstOrDefault();
                machine.LastLogin = input.LastLogin;
                machine.LastLogout = input.LastLogout;
      
                await _machineRepository.InsertOrUpdateAsync(machine);
            }
            catch (Exception ex)
            {
                log.Error(ex.Message, ex);
            }
        }
      
        #endregion
      

      }

    SignalR events arrive without problem. But when the "Create" is done, I have the following error:

    Cannot access a disposed object. A common cause of this error is disposing a context that was resolved from dependency injection and then later trying to use the same context instance elsewhere in your application. This may occur if you are calling Dispose() on the context, or wrapping the context in a using statement. If you are using dependency injection, you should let the dependency injection container take care of disposing context instances. Object name: 'GenTimeDbContext'.

    Thanks for all

    Regards

  • User Avatar
    0
    maliming created
    Support Team

    Try

    [UnitOfWork]
    public virutal async Task Create(CreateMachineDto input)
    {
    }
    
  • User Avatar
    0
    SASIMEXICO created

    The error has disappeared ... but the IRepository<Machine> is empty.

    What am I doing wrong?

  • User Avatar
    0
    maliming created
    Support Team

    but the IRepository is empty.

    Do you mean that the database has data but _machineRepository does not find any data?

  • User Avatar
    0
    SASIMEXICO created

    Exactly

  • User Avatar
    0
    maliming created
    Support Team

    Does the TenantId and UserId of the AbpSession in the Create(CreateMachineDto input) method have a value?

    Can you share the code for the Machine entity?

  • User Avatar
    0
    SASIMEXICO created
    • Dto

        [AutoMapTo(typeof(Machine))]
                public class CreateMachineDto
                {
                    public int? Id { get; set; }
                    [Required]
                    [StringLength(AbpTenantBase.MaxNameLength)]
                    public string Name { get; set; }
                    public string Description { get; set; }
                    public bool? Active { get; set; }
      
                public int? TenantId { get; set; }
      
                public DateTime InstallDate { get; set; }
                public DateTime LastLogin { get; set; }
                public DateTime? LastLogout { get; set; }
                public bool? IsBlocked { get; set; }
                public string ReasonIsBlocked { get; set; }
      
                // OperatingSystem
                public string OperationSystem { get; set; }
                public string OSVersion { get; set; }
                public string OSArchitecture { get; set; }
                public string OSSerialNumber { get; set; }
                public string OSLanguage { get; set; }
                public string OSTotalVisibleMemorySize { get; set; }
                public string OSSystemDrive { get; set; }
                //ComputerSystem
                public string CSNumberOfLogicalProcessors { get; set; }
                public string CSManufacturer { get; set; }
                public string CSModel { get; set; }
                //LogicalDisk
                public string LDDiskSize { get; set; }
                public string LDFreeSpaceDisk { get; set; }
      
                public DateTime? DateWasBlocked { get; set; }
                public int? LicenseId { get; set; }
      
                public CreateApplicationDto Application { get; set; }
                public ICollection&lt;TagDto&gt; Tags { get; set; }
            }
      
    • Model:

       public partial class Machine : FullAuditedEntity, IMayHaveTenant
           {
               public Machine()
               {
                   Events = new HashSet&lt;Event&gt;();
                   MachineAppVersions = new HashSet&lt;MachineAppVersion&gt;();
                   TagMachines = new HashSet&lt;TagMachine&gt;();
               }
      
           public string Name { get; set; }
           public string Description { get; set; }
           public bool? Active { get; set; }
           public DateTime? InstallDate { get; set; }
           public DateTime? LastLogin { get; set; }
           public DateTime? LastLogout { get; set; }
           public bool? IsBlocked { get; set; }
           public string ReasonIsBlocked { get; set; }
           public DateTime? DateWasBlocked { get; set; }
      
           // OperatingSystem
           public string OperationSystem { get; set; }
           public string OSVersion { get; set; }
           public string OSArchitecture { get; set; }
           public string OSSerialNumber { get; set; }
           public string OSLanguage { get; set; }
           public string OSTotalVisibleMemorySize { get; set; }
           public string OSSystemDrive { get; set; }
           //ComputerSystem
           public string CSNumberOfLogicalProcessors { get; set; }
           public string CSManufacturer { get; set; }
           public string CSModel { get; set; }
           //LogicalDisk
           public string LDDiskSize { get; set; }
           public string LDFreeSpaceDisk { get; set; }
      
           public int? TenantId { get; set; }
           public int? LicenseId { get; set; }
      
           public License License { get; set; }
           public ICollection&lt;Event&gt; Events { get; set; }
           public ICollection&lt;MachineAppVersion&gt; MachineAppVersions { get; set; }
           public ICollection&lt;TagMachine&gt; TagMachines { get; set; }
       }
      
  • User Avatar
    0
    maliming created
    Support Team

    Does the TenantId and UserId of the AbpSession in the Create(CreateMachineDto input) method have a value?

    You can inject the IAbpSession interface to see it.

  • User Avatar
    0
    SASIMEXICO created

    The TenantId and UserId of the AbpSession is null.

    How do I inject the AbpSession?

    I do the following:

        private readonly IRepository&lt;Machine&gt; _machineRepository;
        private readonly IAbpSession _session;
        private readonly HubConnection _connection;
        
        #endregion
    
        #region "Constructor"
    
        public SignalRExtensionAppService(
            IRepository&lt;Machine&gt; machineRepository,
            IAbpSession session,
            HubConnection connection
            )
        {
            _machineRepository = machineRepository;
            _connection = connection;
            _session = session;
            //_sampleDbContextProvider = sampleDbContextProvider;
    
            log = NullLogger.Instance;
    
            InvokedOn();
        }
    
  • User Avatar
    0
    maliming created
    Support Team

    Try

    using (_unitOfWorkManager.Current.DisableFilter(AbpDataFilters.MayHaveTenant))
    {
        var machine = _machineRepository.GetAll().Where(x => x.Name == input.Name && x.TenantId == input.TenantId).FirstOrDefault();
    }
    
  • User Avatar
    0
    SASIMEXICO created

    Great It's working fine!!

    Very, very thanks.

    Regards