1

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();
    }
}
Community
  • 1
  • 1
melkisadek
  • 1,043
  • 1
  • 14
  • 33

1 Answers1

0

You need to tell the MVC runtime to use Ninject to resolve your controllers, the easiest way to do this is install the MVC extension for Ninject

Trevor Pilley
  • 16,156
  • 5
  • 44
  • 60
  • I already have that installed. I have a test project that isn't using a generic interface and that works okay. I'm assuming I need to do something to tie the generic interface to the actual class in the domain model? – melkisadek Sep 10 '13 at 18:11
  • @melkisadek this line `System.Web.Mvc.DefaultControllerActivator.Create` suggests that you are not actually using the Ninject Kernel to resolve the controller. – Trevor Pilley Sep 11 '13 at 07:49
  • I've just redone a project from scratch and I'm getting the same problem. I'll have to go back and work out what is preventing Ninject from working. I've noticed that the Twitter Bootstrap version has changed since I last worked on this sort of thing so there may be something in the setup from Twitter Bootstrap to MVC causing a conflict. – melkisadek Sep 11 '13 at 15:50
  • Marking this as the answer as it pointed me in the right direction. See edits to original post for explanation. Thanks – melkisadek Sep 17 '13 at 16:33