I'm trying to use a fairly simple generic repository for a number of administration lists in an application. Functionality for the admin users is just CRUD to keep the lists up to date for use elsewhere as lookups.
I keep getting an error of the form:
An error occurred when trying to create a controller of type 'WhatWorks.Controllers.AchievementController'. Make sure that the controller has a parameterless public constructor.
I've read an awful lot of posts on SO and blogs found through Google but I can't find an answer (at least nothing that makes sense to me as an answer which may be another problem...)
My code is as follows:
Controller
public class AchievementController : BootstrapBaseController
{
private readonly IAdminRepository<tAchievement> _repo;
public AchievementController(IAdminRepository<tAchievement> _repo)
{
this._repo = _repo;
}
ViewModel
public partial class AchievementListViewModel
{
public int Id { get; set; }
public string achievement { get; set; }
}
Interface
public interface IAdminRepository<TEntity> : IDisposable
where TEntity : class
{
IEnumerable<TEntity> Get();
TEntity GetByID(int id);
void Insert(TEntity entity);
void Delete(TEntity entity);
void Update(TEntity entity);
void Save();
}
Repository
public class AdminRepository<T> : IAdminRepository<T>
where T : class
{
private WhatWorksEntities objContext;
public AdminRepository()
{
objContext = new WhatWorksEntities();
}
public IEnumerable<T> Get()
{
return objContext.Set<T>().ToList();
}
etc.
Binding
kernel.Bind(typeof(IAdminRepository<>)).To(typeof(AdminRepository<>));
I've also tried binding with an additional line to no effect:
kernel.Bind<IAdminRepository<tAchievement>>().To<AdminRepository<tAchievement>>();
I'm assuming I'm missing something simple.
I have Ninject, Ninject.Web.MVC and Ninject.Web.Common in my references - all taken from NuGet.
Stack Trace is as follows:
[MissingMethodException: No parameterless constructor defined for this object.]
System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck) +0
System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark) +113
System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark) +232
System.Activator.CreateInstance(Type type, Boolean nonPublic) +83
System.Activator.CreateInstance(Type type) +6
System.Web.Mvc.DefaultControllerActivator.Create(RequestContext requestContext, Type controllerType) +55
[InvalidOperationException: An error occurred when trying to create a controller of type 'WhatWorks.Controllers.AchievementController'. Make sure that the controller has a parameterless public constructor.]
System.Web.Mvc.DefaultControllerActivator.Create(RequestContext requestContext, Type controllerType) +179
System.Web.Mvc.DefaultControllerFactory.GetControllerInstance(RequestContext requestContext, Type controllerType) +80
System.Web.Mvc.DefaultControllerFactory.CreateController(RequestContext requestContext, String controllerName) +74
System.Web.Mvc.MvcHandler.ProcessRequestInit(HttpContextBase httpContext, IController& controller, IControllerFactory& factory) +197
System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, Object state) +49
System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContext httpContext, AsyncCallback callback, Object state) +50
System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, Object extraData) +16
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +301
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +155
_____________EDIT with partial answer_____________
Having recreated a project from scratch and hit the same error I noticed that the versions of a few of the additional packages I was using had changed. I'm using "Twitter Bootstrap for MVC" by Eric Hexter as my main display and this is pulling in a later version of Twitter Bootstrap than I've used previously. I'm not sure if this is causing the problem but the layout of the folders in an older working project are different from the new one.
This answer has given me a decent pointer after the comments by Trevor Pilley: Ninject + MVC3 is not injecting into controller
In my older working project the following was in the Web.config file but is not in the new project. If I add it, the code works but there is still a problem with the Twitter Bootstrap layout - probably from the new .css files - I'll leave the question open for in case anyone can improve on this as an answer.
(Entity Framework closing tag left in to show location in Web.config)
</entityFramework>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
_________EDIT global.asax______________________
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BootstrapSupport.BootstrapBundleConfig.RegisterBundles(System.Web.Optimization.BundleTable.Bundles);
WhatWorksRouteConfig.RegisterRoutes(RouteTable.Routes);
AutoMapperConfiguration.Configure();
}
}