abpframework / abp

Open Source Web Application Framework for ASP.NET Core. Offers an opinionated architecture to build enterprise software solutions with best practices on top of the .NET and the ASP.NET Core platforms. Provides the fundamental infrastructure, production-ready startup templates, application modules, UI themes, tooling, guides and documentation.
https://abp.io
GNU Lesser General Public License v3.0
12.31k stars 3.32k forks source link

add new Abp module to my solution #4679

Closed mohammed-hussein closed 3 years ago

mohammed-hussein commented 3 years ago

Hello,

I have created a new project for infrastructure under ABP solution which will contain integration with external APIs, in this project I have created new module class inherit from ABPModule and another class for a custom repository to communicate with external APIs but ABP framework not loading my project 'Infrastructure' while booted and not finding my custom repo as well.

Here my module code

namespace STCS.Framework.Infrastructure
{
    [DependsOn(
        typeof(FrameworkDomainModule),
        typeof(AbpAutofacModule),
        typeof(AbpAutoMapperModule)
        )]
    public class FrameworkInfrastructureModule: AbpModule
    {
        public override void ConfigureServices(ServiceConfigurationContext context)
        {
            context.Services.AddApplication<FrameworkInfrastructureModule>(options =>{
                options.UseAutofac();
            });

            context.Services.AddTransient(typeof(TaskRepository), typeof(ITaskRepository));

            context.Services.AddAutoMapperObjectMapper<FrameworkInfrastructureModule>();
            Configure<AbpAutoMapperOptions>(options => {
                options.AddMaps<FrameworkInfrastructureModule>();
                //options.AddProfile<FrameworkInfrastructureAutoMapperProfile>(validate: true);
            });
        }
    }
}
iyilm4z commented 3 years ago

@mohammed-hussein hi, you most probably forget to add your custom module to one of existing module’s dependson attribute. Try to add it to host module.

iyilm4z commented 3 years ago

@mohammed-hussein helped?

mohammed-hussein commented 3 years ago

@iyilm4z thanks, yes it helps to load my project but I have an issue with autofac

Host terminated unexpectedly! System.Exception: An object accessor is registered before for type: Autofac.ContainerBuilder, Autofac, Version=4.9.4.0, Culture=neutral, PublicKeyToken=17863af14b0044da at Microsoft.Extensions.DependencyInjection.ServiceCollectionObjectAccessorExtensions.AddObjectAccessor[T](IServiceCollection services, ObjectAccessor`1 accessor)

iyilm4z commented 3 years ago

@mohammed-hussein if it's possible, please share the solution reproduces the issue.

mohammed-hussein commented 3 years ago

@maliming , it's a huge solution to share with you, I follow steps on documentation Autofac and get this issue

maliming commented 3 years ago

hi @mohammed-hussein

You can share a simple project to reproduce the problem.

https://abp.io/get-started

mohammed-hussein commented 3 years ago

hi @iyilm4z & @maliming ,

thanks for your support,

sure I will create a new project and share it with you later but I have a question as in my issue description above,

I created new Abp Module (infrastructure project from type class library[.net core]) which contain an implementation 'MycustomRepository ' of interface IcustomRepository<Book, Guid> and this interface located in domain module and inject this interface in application module but Autofac can't find MycustomRepository which inside infrastructure module and got an exception in stack trace above, so the question is how to enforce application module to inject an actual implementation of IcustomRepository in runtime, what I miss in this process, another note I reference 'infrastructure module' in dependencies client.Host module

mohammed-hussein commented 3 years ago

Hi,

you can find simple code here

maliming commented 3 years ago

you can find simple code here

hi @mohammed-hussein Please provide steps.

mohammed-hussein commented 3 years ago

Hi @maliming , run code and try to navigate to api '/api/app/tasks/myTasks' Tasks api

mohammed-hussein commented 3 years ago

Hi @maliming , did you check?

maliming commented 3 years ago

image

mohammed-hussein commented 3 years ago

Hi @maliming, please check it again.

mohammed-hussein commented 3 years ago

Hi @maliming any updates?

maliming commented 3 years ago

hi @mohammed-hussein

I can't understand your solution and codes, Have you read the document of the repository? Because your code does not follow the documentation recommendations.

https://docs.abp.io/en/abp/latest/Entity-Framework-Core

mohammed-hussein commented 3 years ago

Hi @maliming , yes i read documentation.

simply I need to reference and interface in Application service and implementation of this interface in a different project called 'infrastructure' and added depends on web.host project but application service throw this expectation what missing to enable autofac to register implementation in runtime

An exception was thrown while activating Castle.Proxies.TasksAppServiceProxy. Autofac.Core.DependencyResolutionException: An exception was thrown while activating Castle.Proxies.TasksAppServiceProxy. ---> Autofac.Core.DependencyResolutionException: None of the constructors found with 'Autofac.Core.Activators.Reflection.DefaultConstructorFinder' on type 'Castle.Proxies.TasksAppServiceProxy' can be invoked with the available services and parameters: Cannot resolve parameter 'STCS.Framework.Repositories.ITaskRepository repository' of constructor 'Void .ctor(Castle.DynamicProxy.IInterceptor[], STCS.Framework.Repositories.ITaskRepository)'. at Autofac.Core.Activators.Reflection.ReflectionActivator.GetValidConstructorBindings(IComponentContext context, IEnumerable1 parameters) at Autofac.Core.Activators.Reflection.ReflectionActivator.ActivateInstance(IComponentContext context, IEnumerable1 parameters) at Autofac.Core.Resolving.InstanceLookup.Activate(IEnumerable1 parameters, Object& decoratorTarget) --- End of inner exception stack trace --- at Autofac.Core.Resolving.InstanceLookup.Activate(IEnumerable1 parameters, Object& decoratorTarget) at Autofac.Core.Resolving.InstanceLookup.Execute() at Autofac.Core.Resolving.ResolveOperation.GetOrCreateInstance(ISharingLifetimeScope currentOperationScope, IComponentRegistration registration, IEnumerable1 parameters) at Autofac.Core.Resolving.ResolveOperation.Execute(IComponentRegistration registration, IEnumerable1 parameters) at Autofac.ResolutionExtensions.TryResolveService(IComponentContext context, Service service, IEnumerable1 parameters, Object& instance) at Autofac.ResolutionExtensions.ResolveService(IComponentContext context, Service service, IEnumerable1 parameters) at Microsoft.AspNetCore.Mvc.Controllers.ServiceBasedControllerActivator.Create(ControllerContext actionContext) at Microsoft.AspNetCore.Mvc.Controllers.ControllerFactoryProvider.<>c__DisplayClass5_0.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 where exception was thrown ---

maliming commented 3 years ago

your application module has not been dependent on the FrameworkInfrastructureModule.

image

    [Dependency(ServiceLifetime.Transient,ReplaceServices = true)]
    [ExposeServices(typeof(ITaskRepository))]
    public class TaskRepository : ITaskRepository
iyilm4z commented 3 years ago

@maliming As i see, my first comment was the solution to this issue, right?:)

mohammed-hussein commented 3 years ago

Hi @maliming your solution doesn't work and still the same issue and I have push updates on the repo you can check, also I think your proposed solution break DDD design as application service shouldn't depend on the infrastructure layer, please advise

@iyilm4z , thanks man for your support your comment helped me to load the project in Abp but still have the same issue as I mentioned before.

Thanks

minitoma commented 3 years ago

@mohammed-hussein did you try replacing your interface manually in the module code, see abpdoc

context.Services.Replace(
    ServiceDescriptor.Transient<IIdentityUserAppService, MyIdentityUserAppService>()
);

You can write this inside the ConfigureServices method of your module.

i had the same problem as you and manage to get it worked this way without breaking DDD design

mohammed-hussein commented 3 years ago

@minitoma Thanks so much it solved my problem without breaking DDD , appreciated your help :)

I added below code inside ConfigureServices method context.Services.AddTransient<ITaskRepository, TaskRepository>();