Open Closed

Accessing DomainService, Repositories from outside Web Solution #9031


0
SEB_ADMIN created

Hi- We are creating custom applications ( e.g say a Web API ) that would need to access ZERO Domain services, repositories, Dbcontext etc,..

What are the Project references that I would need to add to our custom application.

How do I inject all dependencies?.. I know in the web solution castle windsor takes care of all dependencies through dependency injection

Basically we would need access to all libraries except the application service layer for the custom application. The appSettings from our custom application need to be fed into all these dependencies ( e.g conn string etc,..).

Do you have any sample projects other than the ZERO web solution that access these libraries ?

Please let me know.

Regards, Sesha K


13 Answer(s)
  • 0
    ismcagdas created
    Support Team

    Hi @SEB_ADMIN,

    We don't have a sample but you can easily do it like this;

    Create a module class for your new project (see https://aspnetboilerplate.com/Pages/Documents/Module-System) and on this module, depend on the related AspNet Zero modules you want to use. Of cours,e you also need to ference to *.Core and *.EntityFramework projects if you want to depend on their modules.

  • 0
    SEB_ADMIN created

    Hi- Thanks for the information. I was able to get it working for a Console Application.

     But I need to hookup a startup module to my   .NET Core Worker service I am creating ( Windows Service ).
     
     How do I hook up a start up module to my worker service using a default host builder. For e.g below
     
    

    ** it seems the extension method "AddAbp" is not available for a default Host Builder.**

     "CalculatorSchedulerModule" is my custom start up module for my custom worker service and I have set the 
     dependency of that module to Core Module and Entity framework module.
     
     I noticed that the extension method is part of namespace "Abp.AspNetCore".  How do I reference that in my custom
     worker service which I am planning to run as a  Windows Service.
     
     The below code is in "Program.cs".
     
        Host.CreateDefaultBuilder(args)
                .UseWindowsService()
             
                .ConfigureServices((hostContext, services) =>
                {
                    services.AddHostedService<CalculatorScheduler>();
                 **   services.AddAbp<CalculatorSchedulerModule>();**
                                      
                });
    
  • 0
    ismcagdas created
    Support Team

    Hi,

    You are right. AddAbp is designed for ASP.NET Core. Can't you start your projetc like this https://github.com/aspnetboilerplate/aspnetboilerplate-samples/blob/master/AbpEfConsoleApp/AbpEfConsoleApp/Program.cs using AbpBootstrapper ?

  • 0
    SEB_ADMIN created

    Hi The bootstrapper works fine for the Console Application. But here I am using a .NET Core Worker Service to be deployed as Windows Service . it uses "DefaultHostBuilder". The key here is how do I define a startup module and hook it into the Host builder. There seem to be no direct way of doing it. How do I inject abp IOC Container and dependencies into my Host Builder ? I can use services.AddSingleton() as in the example below, but I cannot add entire dependency chain individually in this fashion. The only way to add all dependencies through chain of execution of Modules for each assembly which will all be made dependent on my start up module.

    Just like a Console Application example, Dont you have an example of Windows Service or Worker Service accessing all Abp's Application, Domain and Entityframework layer components ?. That would be useful..

    My key problem is "How do I attach a Startup module to my Worker Service Host Builder". If I am able to do that I can hook dependencies to other Modules ( application, Core etc.) and get all the components into IOC container automatically.

    How do I inject the entire dependency container of Abp in the code below ??

    Host.CreateDefaultBuilder(args) .UseWindowsService()

                .ConfigureServices((hostContext, services) =>
                {
                    
                    services.AddHostedService<CalculatorScheduler>();
                    services.AddSingleton<ICalculatorProfileJob, CalculatorProfileJob>();
                                         
                });
    
  • 0
    ismcagdas created
    Support Team

    Hi,

    Can you try this ?

    .ConfigureServices((hostContext, services) =>
    {
    	var abpBootstrapper = AbpBootstrapper.Create<TStartupModule>(optionsAction);
    	services.AddSingleton(abpBootstrapper);
    	WindsorRegistrationHelper.CreateServiceProvider(abpBootstrapper.IocManager.IocContainer, services);               
       
    	services.AddHostedService<CalculatorScheduler>();
    	services.AddSingleton<ICalculatorProfileJob, CalculatorProfileJob>();
    });
    
  • 0
    SEB_ADMIN created

    I tried this but it is still complaining on dependency injection for CalculatorProfileJob. it is a domain service under "core" Project and it has dependencies injected into it ( like repositories). Looks like I have to inject the entire dependency hiearchy chain here which is not correct. Is there a way out ?.

    You can try this just by creating a new .NET Core Worker service project and injecting any of Abp domain services into it

    I guess the bootstrapper is still not taking care of dependency injection for the HostedService.

  • 0
    SEB_ADMIN created

    System.AggregateException HResult=0x80131500 Message=Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: Microsoft.Extensions.Hosting.IHostedService Lifetime: Singleton ImplementationType: CalculatorSchedulerService.CalculatorScheduler': Unable to resolve service for type 'Abp.Domain.Repositories.IRepository2[SEB.FPE.Calculators.CalculatorProfile,System.Int32]' while attempting to activate 'SEB.FPE.Calculators.Jobs.CalculatorProfileJob'.) (Error while validating the service descriptor 'ServiceType: SEB.FPE.Calculators.Jobs.ICalculatorProfileJob Lifetime: Singleton ImplementationType: SEB.FPE.Calculators.Jobs.CalculatorProfileJob': Unable to resolve service for type 'Abp.Domain.Repositories.IRepository2[SEB.FPE.Calculators.CalculatorProfile,System.Int32]' while attempting to activate 'SEB.FPE.Calculators.Jobs.CalculatorProfileJob'.) Source=Microsoft.Extensions.DependencyInjection StackTrace: at Microsoft.Extensions.DependencyInjection.ServiceProvider..ctor(IEnumerable1 serviceDescriptors, ServiceProviderOptions options) at Microsoft.Extensions.DependencyInjection.ServiceCollectionContainerBuilderExtensions.BuildServiceProvider(IServiceCollection services, ServiceProviderOptions options) at Microsoft.Extensions.DependencyInjection.DefaultServiceProviderFactory.CreateServiceProvider(IServiceCollection containerBuilder) at Microsoft.Extensions.Hosting.Internal.ServiceFactoryAdapter1.CreateServiceProvider(Object containerBuilder) at Microsoft.Extensions.Hosting.HostBuilder.CreateServiceProvider() at Microsoft.Extensions.Hosting.HostBuilder.Build() at CalculatorSchedulerService.Program.Main(String[] args) in C:\Users\sesha.krishnamurthy\Source\repos\FPE\FPE\aspnet-core\src\CalculatorSchedulerService\Program.cs:line 41

    This exception was originally thrown at this call stack: [External Code]

    Inner Exception 1: InvalidOperationException: Error while validating the service descriptor 'ServiceType: Microsoft.Extensions.Hosting.IHostedService Lifetime: Singleton ImplementationType: CalculatorSchedulerService.CalculatorScheduler': Unable to resolve service for type 'Abp.Domain.Repositories.IRepository`2[SEB.FPE.Calculators.CalculatorProfile,System.Int32]' while attempting to activate 'SEB.FPE.Calculators.Jobs.CalculatorProfileJob'.

    Inner Exception 2: InvalidOperationException: Unable to resolve service for type 'Abp.Domain.Repositories.IRepository`2[SEB.FPE.Calculators.CalculatorProfile,System.Int32]' while attempting to activate 'SEB.FPE.Calculators.Jobs.CalculatorProfileJob'.

  • 0
    ismcagdas created
    Support Team

    Hi @SEB_ADMIN,

    Is it possible for you to share your project with info@aspnetzero.com ?

    Thanks,

  • 0
    SEB_ADMIN created

    Hi- The following code solved the DI Problem. Can you please check but I am getting a different error explained below. I will also post the code that causes the problem

    public static IHostBuilder CreateHostBuilder(string[] args)
    {
    
        var abpBootstrapper = AbpBootstrapper.Create<CalculatorSchedulerModule>();
        abpBootstrapper.Initialize();
    
        return Host.CreateDefaultBuilder(args)
            .UseWindowsService()
            .UseCastleWindsor(abpBootstrapper.IocManager.IocContainer)
    
            .ConfigureServices((hostContext, services) =>
            {
               services.AddHostedService<CalculatorScheduler>();
            });
    
    }
    

    ** 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: 'FPEDbContext'.**

  • 0
    SEB_ADMIN created
      public class CalculatorScheduler : BackgroundService
        {
            private readonly ILogger<CalculatorScheduler> _logger;
            private readonly ICalculatorProfileJob _job;
            private readonly IRepository<CalculatorSchedule, int> _schedule;
         
            private Timer _timer;
    
                 
            public CalculatorScheduler(ILogger<CalculatorScheduler> logger,
                                       ICalculatorProfileJob job,
                                       IRepository<CalculatorSchedule, int> schedule
                                      
                                       )
                                      
            {
                _logger = logger;
                _job = job;
                _schedule = schedule;
                       
            }
    
            protected override async Task ExecuteAsync(CancellationToken stoppingToken)
            {
                while (!stoppingToken.IsCancellationRequested)
                {
                    _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);
                    await Task.Delay(1000, stoppingToken);
                }
            }
    
            public override Task StartAsync(CancellationToken cancellationToken)
            {
                _timer = new Timer(CheckSchedule, null, 0, Convert.ToInt32(TimeSpan.FromSeconds(30).TotalMilliseconds));
    
                return Task.CompletedTask;
            }
    
            public override Task StopAsync(CancellationToken cancellationToken)
            {
                _logger.LogInformation("Worker stopping at: {time}", DateTimeOffset.Now);
    
                _timer?.Change(Timeout.Infinite, 0);
    
                return Task.CompletedTask;
            }
    
            private void CheckSchedule(object state)
            {
                List<CalculatorSchedule> lstSchedule = this._schedule.GetAll().ToList();
                foreach (CalculatorSchedule sched in lstSchedule)
                    _job.ExecuteJob(sched);
    
            }
        }
    
  • 0
    SEB_ADMIN created

    the error happens on the below line in method "CheckSchedule". List<CalculatorSchedule> lstSchedule = this._schedule.GetAll().ToList();

  • 1
    aaron created
    Support Team

    Change .GetAll().ToList() to .GetAllList(), or begin your own unit of work.

    Reference: aspnetboilerplate/aspnetboilerplate#3946 (comment 430319419)

  • 1
    SEB_ADMIN created

    Thankyou. That solved the problem.