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?"