Autofac and ASP .Net MVC 4 Web API

11,919

You have registered your IRepository wrong. With the line:

builder.RegisterType<SharePointRepository<IEntity>>().As<IRepository<IEntity>>();

You told Autofac that whenever somebody will request an IRepository<IEntity> give them a SharePointRepository<IEntity>, but you are requesting a concrete IRepository<Integration> so you get an exception.

What you need is the open generic registration feature of Autofac. So change your registration to:

builder.RegisterGeneric(typeof(SharePointRepository<>))
       .As(typeof(IRepository<>));

It will work as you would expect you when you ask for a IRepository<Integration> it will give a SharePointRepository<Integration>.

You also have a second unrelated problem: your SharePointRepository has only an internal constructor.

Autofac by default only looks for public constructors so you either change your constructor and class to public or you need to tell to Autofac to look for NonPublic constructors with the FindConstructorsWith method:

builder
    .RegisterType<SharePointRepository<IEntity>>()
    .FindConstructorsWith(
       new DefaultConstructorFinder(type => 
          type.GetConstructors(BindingFlags.NonPublic | BindingFlags.Instance))) 
    .As<IRepository<IEntity>>();
Share:
11,919
Moon
Author by

Moon

I am hands-on software architect / engineer and effective manager with over 11 years of experience in software craftsmanship and cloud infrastructure. I have a degree in Computer Science. Key Skills Technical Leadership Team Building / Mentoring Software Architecture &amp; Engineering Business Management Systems Implementation &amp; Optimization Software Engineering Project Management Cloud Based Enterprise Solutions IT Infrastructure Management Quality Assurance Personal Favorites Kubernetes, Docker, Python, Golang (Google Go), RabbitMQ, RethinkDB, Google Cloud Platform, Webpack, React, ES6, Atom, Erlang/Elixir (currently learning), gRPC Background An entrepreneur at heart, I have dedicated my career to developing efficient and scalable solutions to problems faced by many organizations and governments across the world. I believe that educating and empowering individuals and teams to use cutting edge technical inventions help improve efficiency, reduce redundancy, and ultimately push the upward boundaries of potential that is the underlying key to success in any venture. I have an insatiable attitude towards learning and creating solutions that are aesthetically pleasing yet architecturally efficient and scalable. I have a solid background in microservices based enterprise applications development for systems related to business automation, such as Project Portfolio Management (PPM), Enterprise Resource Planning (ERP), Enterprise Content Management (ECM), and Customer Relationship Management (CRM). I am a balanced advocate and practitioner of design patterns with expertise in architecture and engineering of enterprise grade, scalable, real-time solution infrastructure on Microsoft Azure and Amazon Web Services (AWS). I have extensive experience managing teams of in-house and off-shore Software and QA Engineers. Over past few years, I have help build amazing products used and loved by many organizations and Governments worldwide.

Updated on July 20, 2022

Comments

  • Moon
    Moon almost 2 years

    I am using Autofac for IoC in my ASP .Net MVC 4 project. Autofac is having some trouble initializing the repository and passing it to the API Controller.

    I am sure I am missing something in my configuration.

    Here is the error I get when I navigate to: https://localhost:44305/api/integration

    <Error>
        <Message>An error has occurred.</Message>
        <ExceptionMessage>
            None of the constructors found with 'Autofac.Core.Activators.Reflection.DefaultConstructorFinder' 
            on type 'EL.Web.Controllers.API.IntegrationController' can be invoked with 
            the available services and parameters: Cannot resolve parameter 
            'EL.Web.Infrastructure.IRepository`1[EL.Web.Models.Integration] repository' of 
            constructor 'Void .ctor(EL.Web.Infrastructure.IRepository`1[EL.Web.Models.Integration])'.
        </ExceptionMessage>
        <ExceptionType>Autofac.Core.DependencyResolutionException</ExceptionType>
        <StackTrace>
            at Autofac.Core.Activators.Reflection.ReflectionActivator.ActivateInstance(IComponentContext context, IEnumerable`1 parameters) 
            at Autofac.Core.Resolving.InstanceLookup.Activate(IEnumerable`1 parameters) 
            at Autofac.Core.Resolving.InstanceLookup.Execute() 
            at Autofac.Core.Resolving.ResolveOperation.GetOrCreateInstance(ISharingLifetimeScope currentOperationScope, IComponentRegistration registration, IEnumerable`1 parameters) 
            at Autofac.Core.Resolving.ResolveOperation.ResolveComponent(IComponentRegistration registration, IEnumerable`1 parameters) 
            at Autofac.Core.Resolving.ResolveOperation.Execute(IComponentRegistration registration, IEnumerable`1 parameters) 
            at Autofac.Core.Lifetime.LifetimeScope.ResolveComponent(IComponentRegistration registration, IEnumerable`1 parameters) 
            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.Integration.WebApi.AutofacWebApiDependencyScope.GetService(Type serviceType) 
            at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.GetInstanceOrActivator(HttpRequestMessage request, Type controllerType, Func`1& activator) 
            at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)
        </StackTrace>
    </Error>
    

    Here are some relevant bits of code:

    IoC Bootstrapper:

    public static class Bootstrapper
    {
        public static void Initialize()
        {
            var builder = new ContainerBuilder();
    
            builder.RegisterControllers(Assembly.GetExecutingAssembly());
            builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
    
            builder.Register(x => new SharePointContext(HttpContext.Current.Request)).As<ISharePointContext>().SingleInstance();
            builder.RegisterType<SharePointRepository<IEntity>>().As<IRepository<IEntity>>();
            builder.RegisterType<SharePointContextFilter>().SingleInstance();
    
            builder.RegisterFilterProvider();
    
            IContainer container = builder.Build();
            DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
    
            var resolver = new AutofacWebApiDependencyResolver(container);
            GlobalConfiguration.Configuration.DependencyResolver = resolver;
        }
    }
    

    IRepository:

    public interface IRepository<T>
    {
        void Add(T entity);
    
        void Delete(int id);
    
        IEnumerable<T> Find(Expression<Func<T, bool>> filter = null);
    
        void Update(int id, T entity);
    }
    

    SharePointRepository:

    internal class SharePointRepository<T> : IRepository<T> where T : IEntity
    {
        private readonly ISharePointContext _context;
        private readonly string _listName;
    
        internal SharePointRepository(ISharePointContext context)
        {
            _context = context;
    
            object[] attributes = typeof (T).GetCustomAttributes(typeof (SharePointListAttribute), false);
    
            if (!attributes.Any())
            {
                throw new Exception("No associated SharePoint list defined for " + typeof (T));
            }
    
            _listName = ((SharePointListAttribute) attributes[0]).ListName;
        }
    
        public void Add(T entity)
        {
            throw new NotImplementedException();
        }
    
        public void Delete(int id)
        {
            throw new NotImplementedException();
        }
    
        public IEnumerable<T> Find(Expression<Func<T, bool>> filter)
        {
            throw new NotImplementedException();
        }
    
        public void Update(int id, T entity)
        {
            throw new NotImplementedException();
        }
    }
    

    IntegrationController:

    public class IntegrationController : ApiController
    {
        private readonly IRepository<Integration> _repository;
    
        public IntegrationController(IRepository<Integration> repository)
        {
            _repository = repository;
        }
    
        public void Delete(Guid integrationId)
        {
            _repository.Delete(Get(integrationId).Id);
        }
    
        public IEnumerable<Integration> Get()
        {
            return _repository.Find();
        }
    
        public Integration Get(Guid integrationId)
        {
            return _repository.Find(i => i.IntegrationId == integrationId).FirstOrDefault();
        }
    
        public void Post([FromBody] Integration integration)
        {
            _repository.Add(integration);
        }
    
        public void Put(Guid integrationId, [FromBody] Integration integration)
        {
            _repository.Update(Get(integrationId).Id, integration);
        }
    }
    

    IEntity:

    internal interface IEntity
    {
        int Id { get; }
    }
    

    Entity:

    public abstract class Entity : IEntity
    {
        protected Entity(int id)
        {
            Id = id;
        }
    
        public int Id { get; private set; }
    }
    

    Integration:

    [SharePointList("Integrations")]
    public class Integration : Entity
    {
        public Integration(int id) : base(id)
        {
        }
    
        public string ApiUrl { get; set; }
    
        public bool DeletionAllowed { get; set; }
    
        public Guid IntegrationId { get; set; }
    
        public string Key { get; set; }
    
        public string List { get; set; }
    
        public bool OutgoingAllowed { get; set; }
    
        public string RemoteWeb { get; set; }
    
        public string Web { get; set; }
    }
    
  • Moon
    Moon about 11 years
    this did help me resolve the issue I was initially having. But, now I get a new error: No constructors on type 'EL.Web.Infrastructure.SharePointRepository1[EL.Web.Models.I‌​ntegration]' can be found with the constructor finder 'Autofac.Core.Activators.Reflection.DefaultConstructorFinder‌​'. I am a little confused here. I have already defined to use SharePointContext` as ISharePointContext -- and this is the only parameter the repository needs.
  • nemesv
    nemesv about 11 years
    Your problem is that your SharePointRepository1 class only has internal constructors. See my updated answer.