error: Make sure that the controller has a parameterless public constructor webapi

26,221

From your code, I can see you are using Unity as your IoC Container. IoC Container will handle the initialization of controller class.

To make IoC container to create a instance of your controller, your controller class needs to have a parameterless public constructor(aka default constructor).

public class EmployeeApiController : ApiController
{
    private readonly IEmployeeService employeeService;

    public EmployeeAPIController() : base()
    {
    }

    public EmployeeApiController(IEmployeeService employeeService)
    {
        this.employeeService = employeeService;
    }
}

UPDATE 1: 18 Feb 2015 From your code I have not seen a implementation of IUnitOfWork interface. The unit of work is pattern that is widely used in domain central modeling. Normally, unit of work pattern is used with repository pattern together. The purpose of of unit of work, is to make multiple repository can working on a same database context.

From your code, you register

//container.RegisterType<IUnitOfWork>();
container.RegisterType<UnitOfWorkHouseDB>();

However, I think you should have register code like this: (I assume UnitOfWorkHouseDB is the implementation of IUnitOfWork)

container.RegisterType<IUnitOfWork, UnitOfWorkHouseDB>();

Which is similar as: (EmployeeRepository is the implementation of IEmployeeRepository)

// repositories
container.RegisterType<IEmployeeRepository, EmployeeRepository>();

Normally, when I use unit of work and repository pattern, I will do following structure:

IUnitOfWork interface

public interface IUnitOfWork
{
    void Commit();
}

IUnitOfWork implementation:

public class UnitOfWork : IUnitOfWork
{
    //DBContext could your own db context, or a interface, like IDatabaseFactoryHouseDB 
    private DBContext _ctx;

    public UnitOfWork(DbContext ctx)
    {
        _ctx = ctx;
    }

    private IEmployeeRepository _EmployeeRepository;
    public IEmployeeRepository EmployeeRepository
    {
        get { return _EmployeeRepository ?? (_EmployeeRepository = new EmployeeRepository(_ctx)); }
    }

    private ICustomerRepository _CustomerRepository;
    public ICustomerRepository CustomerRepository
    {
        get { return _CustomerRepository ?? (_CustomerRepository = new CustomerRepository(_ctx)); }
    }

    public void Commit()
    {
        _ctx.SaveChange();
    }
}
Share:
26,221
steveareeno
Author by

steveareeno

Updated on February 18, 2020

Comments

  • steveareeno
    steveareeno about 4 years

    I am using webapi, unity, and mvc. I am getting the error "Make sure that the controller has a parameterless public constructor". I have seen treads on similar problems but still can't get it to work. I have installed unity.webapi and seem to have all the necessary references:

    • Microsoft.Practices.Unity - runtime: v4.0.30319, version: 3.5.0.0
    • Microsoft.Practices.Unity.Mvc - runtime: v4.0.30319, version: 3.5.0.0
    • Unity.WebApi - runtime: v4.0.30319, version: 5.1.0.0
    • System.Web.Http - runtime: v4.0.30319, version: 5.2.2.0
    • System.Web.Mvc - runtime: v4.0.30319, version: 5.2.2.0

    I verified everything matches what is on this site:

    http://www.asp.net/mvc/overview/releases/how-to-upgrade-an-aspnet-mvc-4-and-web-api-project-to-aspnet-mvc-5-and-web-api-2

    Here is what I have:

    Bootstrapper:

    public static class Bootstrapper
    {
        public static IUnityContainer Initialise()
        {
            var container = BuildUnityContainer();
    
            DependencyResolver.SetResolver(new UnityDependencyResolver(container));
            return container;
        }
    
        private static IUnityContainer BuildUnityContainer()
        {
            var container = new UnityContainer();
    
            container.RegisterType<IDatabaseFactoryHouseDB, DatabaseFactoryHouseDB>(new HierarchicalLifetimeManager());
            container.RegisterType<UnitOfWorkHouseDB>();
    
            // repositories
            container.RegisterType<IEmployeeRepository, EmployeeRepository>();
    
            // services
            container.RegisterType<IEmployeeService, EmployeeService>();
            RegisterTypes(container);
    
            return container;
        }
        public static void RegisterTypes(IUnityContainer container) { }
    }
    

    Global.asax:

    public class WebApiApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
    
            WebApiConfig.Register(GlobalConfiguration.Configuration);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
            Database.SetInitializer<HouseDBContext>(null);
    
            Bootstrapper.Initialise();
            //required for setting routes in the attributes of a controller method
            GlobalConfiguration.Configuration.EnsureInitialized();
        }
    }
    

    Api controller:

    public class EmployeeApiController : ApiController
    {
        private readonly IEmployeeService employeeService;
    
        public EmployeeApiController(IEmployeeService employeeService)
        {
            this.employeeService = employeeService;
        }
    
        // rest of controller
    }
    

    WebApiConfig:

        public static void Register(HttpConfiguration config)
        {
            config.MapHttpAttributeRoutes();
    
            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );
    
            // use json strings as the default return value for the app
            config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));
    
            // Uncomment the following line of code to enable query support for actions with an IQueryable or IQueryable<T> return type.
            // To avoid processing unexpected or malicious queries, use the validation settings on QueryableAttribute to validate incoming queries.
            // For more information, visit http://go.microsoft.com/fwlink/?LinkId=279712.
            //config.EnableQuerySupport();
    
            // To disable tracing in your application, please comment out or remove the following line of code
            // For more information, refer to: http://www.asp.net/web-api
            config.EnableSystemDiagnosticsTracing();
        }
    

    UnityConfig:

    public static class UnityConfig
    {
        public static void RegisterComponents()
        {
            var container = new UnityContainer();
    
            GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container);
        }
    }
    

    Not sure what I am missing.

    Edit: I noticed I had a UnityConfig class in my App_Start folder. After looking into the comment by Sarathy, I realized it wasn't be called. I commented out my bootstrapper initialization in the global.asax and added the line UnityConfig.RegisterComponents(), so now my global.asax looks like this:

    public class WebApiApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            UnityConfig.RegisterComponents();  //  <--- added
            AreaRegistration.RegisterAllAreas();
    
            GlobalConfiguration.Configure(WebApiConfig.Register);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
            Database.SetInitializer<HouseDBContext>(null);
    
            //Bootstrapper.Initialise(); <-- not using bootstrapper anymore
            //required for setting routes in the attributes of a controller method
            GlobalConfiguration.Configuration.EnsureInitialized();
        }
    }
    

    and my UnityConfig looks like this:

    public static class UnityConfig
    {
        public static void RegisterComponents()
        {
            var container = new UnityContainer();
    
            // register all your components with the container here
            // it is NOT necessary to register your controllers
    
            // e.g. container.RegisterType<ITestService, TestService>();    
            container.RegisterType<IDatabaseFactoryHouseDB, DatabaseFactoryHouseDB>(new HierarchicalLifetimeManager());
            //container.RegisterType<IUnitOfWork>();
            container.RegisterType<UnitOfWorkHouseDB>();
    
            // repositories
            container.RegisterType<IEmployeeRepository, EmployeeRepository>();
    
            // services
            container.RegisterType<IEmployeeService, EmployeeService>();
    
            GlobalConfiguration.Configuration.DependencyResolver = new Unity.WebApi.UnityDependencyResolver(container);
        }
    }
    

    Yet I still get the parameterless constructor error. What is funny is even though I have added a parameterless constructor:

        public class EmployeeApiController : ApiController
        {
            private readonly IEmployeeService employeeService;
    
            public EmployeeApiController()
                : base()
            {
            } 
    
            public EmployeeApiController(IEmployeeService employeeService)
            {
                this.employeeService = employeeService;
            }
    }
    

    I still get the error when using the unityconfig approach. With bootstrapper, I didn't get the error but my services were not initialized.

    I am totally confused. Somehow I feel I am mixing MVC and WebApi and things are not resolving correctly...

    EDIT 2:

    I looked at the inner exception of my parameterless constructor error and noticed it is mentioning my IUnitOfWork class:

    "Resolution of the dependency failed, type = \"AngularMVC.Controllers.EmployeeApiController\", name = \"(none)\".\r\nException occurred while: while resolving.\r\nException is: InvalidOperationException - The current type, AngularMVC.Models.Interfaces.IUnitOfWork, is an interface and cannot be constructed. Are you missing a type mapping?\r\n-----------------------------------------------\r\nAt the time of the exception, the container was:\r\n\r\n Resolving AngularMVC.Controllers.EmployeeApiController,(none)\r\n Resolving parameter \"employeeService\" of constructor AngularMVC.Controllers.EmployeeApiController(AngularMVC.Services.IEmployeeService employeeService)\r\n Resolving AngularMVC.Services.EmployeeService,(none) (mapped from AngularMVC.Services.IEmployeeService, (none))\r\n Resolving parameter \"unitOfWork\" of constructor AngularMVC.Services.EmployeeService(AngularMVC.Models.Repositories.IEmployeeRepository employeeRepository, AngularMVC.Models.Interfaces.IUnitOfWork unitOfWork)\r\n Resolving AngularMVC.Models.Interfaces.IUnitOfWork,(none)\r\n"

    which is only this:

    public interface IUnitOfWork
    {
        void Commit();
    }
    

    When I do the following in my UnityConfig:

            container.RegisterType<IUnitOfWork>();
            IUnitOfWork sm = container.Resolve<IUnitOfWork>();
    

    I get the same error stating "The current type, AngularMVC.Models.Interfaces.IUnitOfWork, is an interface and cannot be constructed. Are you missing a type mapping?"

  • steveareeno
    steveareeno about 9 years
    DOH! Your absolutely right! I found my UnitOfWork class was not implementing IUnitOfWork. No wonder it was giving me fits. I don't know how I missed that. Thanks again!