Home > OS >  An exception was thrown while activating Autofac .NET Core Web API
An exception was thrown while activating Autofac .NET Core Web API

Time:10-10

I have a problem with IAfterSaleService interface and AfterSaleService Class and I used autofac IoC for these cs files. However while constructor injection ı made is working for some interface, aftersaleservice is not working for some constructor injection. For example, While IAfterService works in the constructor of AfterServiceController, it does not work in the constructor of other service(like OrderService.cs...) in the same directory

I am getting following exception response

Autofac.Core.DependencyResolutionException: An exception was thrown while activating Retail.Business.Concretes.AfterSaleService -> Retail.Business.Concretes.OrderService.
 ---> Autofac.Core.DependencyResolutionException: Circular component dependency detected: Retail.Business.Concretes.AfterSaleService -> Retail.Business.Concretes.OrderService -> Retail.Business.Concretes.AfterSaleService.
   at Autofac.Core.Resolving.Middleware.CircularDependencyDetectorMiddleware.Execute(ResolveRequestContext context, Action`1 next)
   at Autofac.Core.Resolving.Pipeline.ResolvePipelineBuilder.<>c__DisplayClass14_0.<BuildPipeline>b__1(ResolveRequestContext ctxt)
   at Autofac.Core.Pipeline.ResolvePipeline.Invoke(ResolveRequestContext ctxt)
   at Autofac.Core.Resolving.ResolveOperation.GetOrCreateInstance(ISharingLifetimeScope currentOperationScope, ResolveRequest request)
   at Autofac.Core.Resolving.Pipeline.DefaultResolveRequestContext.ResolveComponent(ResolveRequest request)
   at Autofac.Core.Activators.Reflection.AutowiringParameter.<>c__DisplayClass0_0.<CanSupplyValue>b__0()
   at Autofac.Core.Activators.Reflection.BoundConstructor.Instantiate()
   at Autofac.Core.Activators.Reflection.ReflectionActivator.ActivateInstance(IComponentContext context, IEnumerable`1 parameters)
   at Autofac.Core.Activators.Reflection.ReflectionActivator.<ConfigurePipeline>b__11_0(ResolveRequestContext ctxt, Action`1 next)
   at Autofac.Core.Resolving.Middleware.DelegateMiddleware.Execute(ResolveRequestContext context, Action`1 next)
   at Autofac.Core.Resolving.Pipeline.ResolvePipelineBuilder.<>c__DisplayClass14_0.<BuildPipeline>b__1(ResolveRequestContext ctxt)
   at Autofac.Core.Resolving.Middleware.DisposalTrackingMiddleware.Execute(ResolveRequestContext context, Action`1 next)
   at Autofac.Core.Resolving.Pipeline.ResolvePipelineBuilder.<>c__DisplayClass14_0.<BuildPipeline>b__1(ResolveRequestContext ctxt)
   at Autofac.Core.Resolving.Middleware.ActivatorErrorHandlingMiddleware.Execute(ResolveRequestContext context, Action`1 next)
   --- End of inner exception stack trace ---
   at Autofac.Core.Resolving.Middleware.ActivatorErrorHandlingMiddleware.Execute(ResolveRequestContext context, Action`1 next)
   at Autofac.Core.Resolving.Pipeline.ResolvePipelineBuilder.<>c__DisplayClass14_0.<BuildPipeline>b__1(ResolveRequestContext ctxt)
   at Autofac.Core.Pipeline.ResolvePipeline.Invoke(ResolveRequestContext ctxt)
   at Autofac.Core.Resolving.Middleware.RegistrationPipelineInvokeMiddleware.Execute(ResolveRequestContext context, Action`1 next)
   at Autofac.Core.Resolving.Pipeline.ResolvePipelineBuilder.<>c__DisplayClass14_0.<BuildPipeline>b__1(ResolveRequestContext ctxt)
   at Autofac.Core.Resolving.Middleware.SharingMiddleware.<>c__DisplayClass5_0.<Execute>b__0()
   at Autofac.Core.Lifetime.LifetimeScope.CreateSharedInstance(Guid id, Func`1 creator)
   at Autofac.Core.Lifetime.LifetimeScope.CreateSharedInstance(Guid primaryId, Nullable`1 qualifyingId, Func`1 creator)
   at Autofac.Core.Resolving.Middleware.SharingMiddleware.Execute(ResolveRequestContext context, Action`1 next)
   at Autofac.Core.Resolving.Pipeline.ResolvePipelineBuilder.<>c__DisplayClass14_0.<BuildPipeline>b__1(ResolveRequestContext ctxt)
   at Autofac.Core.Resolving.Pipeline.ResolvePipelineBuilder.<>c__DisplayClass14_0.<BuildPipeline>b__1(ResolveRequestContext ctxt)
   at Autofac.Core.Resolving.Middleware.CircularDependencyDetectorMiddleware.Execute(ResolveRequestContext context, Action`1 next)
   at Autofac.Core.Resolving.Pipeline.ResolvePipelineBuilder.<>c__DisplayClass14_0.<BuildPipeline>b__1(ResolveRequestContext ctxt)
   at Autofac.Core.Pipeline.ResolvePipeline.Invoke(ResolveRequestContext ctxt)
   at Autofac.Core.Resolving.ResolveOperation.GetOrCreateInstance(ISharingLifetimeScope currentOperationScope, ResolveRequest request)
   at Autofac.Core.Resolving.ResolveOperation.ExecuteOperation(ResolveRequest request)
   at Autofac.Core.Resolving.ResolveOperation.Execute(ResolveRequest request)
   at Autofac.Core.Lifetime.LifetimeScope.ResolveComponent(ResolveRequest request)
   at Autofac.ResolutionExtensions.TryResolveService(IComponentContext context, Service service, IEnumerable`1 parameters, Object& instance)
   at Autofac.ResolutionExtensions.ResolveOptionalService(IComponentContext context, Service service, IEnumerable`1 parameters)
   at Autofac.ResolutionExtensions.ResolveOptional(IComponentContext context, Type serviceType, IEnumerable`1 parameters)
   at Autofac.ResolutionExtensions.ResolveOptional(IComponentContext context, Type serviceType)
   at Autofac.Extensions.DependencyInjection.AutofacServiceProvider.GetService(Type serviceType)
   at Microsoft.Extensions.DependencyInjection.ActivatorUtilities.GetService(IServiceProvider sp, Type type, Type requiredBy, Boolean isDefaultParameterRequired)
   at lambda_method429(Closure , IServiceProvider , Object[] )
   at Microsoft.AspNetCore.Mvc.Controllers.ControllerActivatorProvider.<>c__DisplayClass4_0.<CreateActivator>b__0(ControllerContext controllerContext)
   at Microsoft.AspNetCore.Mvc.Controllers.ControllerFactoryProvider.<>c__DisplayClass5_0.<CreateControllerFactory>g__CreateController|0(ControllerContext controllerContext)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync()
--- End of stack trace from previous location ---
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|19_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
   at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
   at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
   at Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext)
   at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

HEADERS
=======
Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: tr
Connection: close
Content-Length: 88
Content-Type: application/json
Host: localhost:44394
Referer: https://localhost:44394/swagger/index.html
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.71 Safari/537.36
sec-ch-ua: "Chromium";v="94", "Google Chrome";v="94", ";Not A Brand";v="99"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
origin: https://localhost:44394
sec-fetch-site: same-origin
sec-fetch-mode: cors
sec-fetch-dest: empty

My IoC Like as follows. I said that IAfterService does not work in the constructor of following services

public class ContainerModule : Module
{
    protected override void Load(ContainerBuilder builder)
    {

        builder.RegisterType<AfterSaleService>().As<IAfterSaleService>().SingleInstance();
        builder.RegisterType<EfAfterSaleDal>().As<IAfterSaleDal>().SingleInstance();

        builder.RegisterType<ProductService>().As<IProductService>().SingleInstance();
        builder.RegisterType<EfProductDal>().As<IProductDal>().SingleInstance();

        builder.RegisterType<CustomerService>().As<ICustomerService>().SingleInstance();
        builder.RegisterType<EfCustomerDal>().As<ICustomerDal>().SingleInstance();

        builder.RegisterType<OrderService>().As<IOrderService>().SingleInstance();
        builder.RegisterType<EfOrderDal>().As<IOrderDal>().SingleInstance();

        builder.RegisterType<EfOrderDetailDal>().As<IOrderDetailDal>().SingleInstance();
        builder.RegisterType<OrderDetailService>().As<IOrderDetailService>().SingleInstance();
    }
}

But it works in the constructor of controllers

private IAfterSaleService _afterSaleService;

public AfterSalesController(IAfterSaleService afterSaleService)
{
    _afterSaleService = afterSaleService;
}

and it does not work following service same directory with AfterService.cs and I want it to work this in OrderService.cs because ı need it Note: other services(like ICustomerService, IProductService...) works in the constructor of OrderService only IAfterSaleService does not work

    public class OrderService : IOrderService
    {
        private IOrderDal _orderDal;
        private ICustomerService _customerService;
        private IProductService _productService;
        private IOrderDetailService _orderDetailService;
        private IAfterSaleService _afterSaleService;

        public OrderService(IOrderDal orderDal, ICustomerService customerService, IProductService productService, IOrderDetailService orderDetailService, IAfterSaleService afterSaleService)
        {
            _orderDal = orderDal;
            _customerService = customerService;
            _productService = productService;
            _orderDetailService = orderDetailService;
            _afterSaleService = afterSaleService;
        }
}

AfterService.cs

    public class AfterSaleService : IAfterSaleService
    {
        private IAfterSaleDal _afterSaleDal;
        private IOrderService _orderService;

        public AfterSaleService(IAfterSaleDal afterSaleDal, IOrderService orderService)
        {
            _afterSaleDal = afterSaleDal;
            _orderService = orderService;
        }
}

CodePudding user response:

The error is pretty clear:

Circular component dependency detected

Your AfterSaleService depends on IOrderService and OrderService depends on IAfterSaleService which for obvious reasons will make it impossible for DI container to resolve the dependencies during construction. Personally I try not to inject dependecies of the same "level", i.e. repositories does not accept repositories, services - services and controllers do not depend on the other controllers so my recommendation would be to refactor your application so you don't need such injections (maybe introduce one more layer or move common code to static helpers or something else).

If it is not feasible ATM to rewrite due to ammount of work you can use work around the issue for now - inject same level dependencies as Func's. Autofac provides Func resolutioins out of the box (i.e. if you register IService you can resolve Func<IService> without any extra registrations), so you can do something like this:

public OrderService(..., Func<IAfterSaleService> afterSaleServiceFactory)
{
    .... 
    _afterSaleService = new Lazy<IAfterSaleService>(afterSaleServiceFactory);
}

And

public AfterSaleService(IAfterSaleDal afterSaleDal, 
     Func<IOrderService> orderServiceFactory)
{
    _afterSaleDal = afterSaleDal;
    _orderService = new Lazy<IAfterSaleService>(orderServiceFactory);
}

And use lazily resolved dependencies - _afterSaleService .Value, _orderService.Value

UPD

Actually it seems that Autofac also supports Lazy out of the box so this can be even easier:

public OrderService(..., Lazy<IAfterSaleService> afterSaleServiceFactory)
{
    .... 
    _afterSaleService = afterSaleService;
}
  • Related