0
votes

I am getting an error. I am using Moq and Ninject. Here are the detailed error message:

[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) +66 System.Web.Mvc.DefaultControllerActivator.Create(RequestContext requestContext, Type controllerType) +55

[InvalidOperationException: An error occurred when trying to create a controller of type 'EF.Controllers.ProductController'. 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) +193 System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, Object state) +49
System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContext httpContext, AsyncCallback callback, Object state) +49
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

Here is my Controller :

public class ProductController : Controller
{
    private IProductRepository repository;

    public ProductController(IProductRepository productRepository)
    {
        this.repository = productRepository;
    }

    public ViewResult List()
    {
        return View(repository.Products);
    }

}

RouteConfig points out the List ActionMethod. Here is the content of the IProductRepository:

public interface IProductRepository
{
    IQueryable<Product> Products { get; }
}

Here is the definition of the Product:

public class Product
{
    public int ProductID { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public decimal Price { get; set; }
    public string Category { get; set; }
}

And here is the NinjectControllerFactory class:

public class NinjectControllerFactory : DefaultControllerFactory
{

    private IKernel ninjectKernel;

    public NinjectControllerFactory()
    {
        ninjectKernel = new StandardKernel();
        AddBindings();
    }

    protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
    {
        return controllerType == null
        ? null
        : (IController)ninjectKernel.Get(controllerType);
    }

    /// <summary>
    /// An binding has been implemented there. I am creating a Mock object, and I embedded it.
    /// </summary>
    private void AddBindings()
    {
        Mock<IProductRepository> mock = new Mock<IProductRepository>();

        mock.Setup(m => m.Products).Returns(new List<Product> {
        new Product { Name = "Football", Price = 25 },
        new Product { Name = "Surf board", Price = 179 },
        new Product { Name = "Running shoes", Price = 95 }
        }.AsQueryable());

        ninjectKernel.Bind<IProductRepository>().ToConstant(mock.Object);
    }
}

What I am missing? Could you please help me? Thanks in advance.

1
How did you register your NinjectControllerFactory in MVC? It seems from the stack trace that your custom controller factory isn't used at all. - Steven
@Steven is right. You probably didn't set correctly your factory: ControllerBuilder.Current.SetControllerFactory(typeof (NinjectControllerFactory ). Understanding and Extending Controller Factory in MVC - Old Fox
Steven, The Old Fox. You were right. In the Application_Start() I shall add the code : ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory()); After I wrote it, problem is solved. Your point is right. I can not accept your answers due to the web site. - tahasozgen

1 Answers

0
votes

Your use of Moq is incorrect. You don't use Moq for dependency injection, you use it for mocking an interface (ideally) when unit testing another class that has a dependency on that interface. You shouldn't even be using Moq in the NinjectControllerFactory.

Your AddBindings() method should simply be:

ninjectKernel.Bind<IProductRepository>().To<ProductRepository>();

Also, usually DI containers have a convention by default approach, which should allow you to not even need to use the Bind<>().To<>() statement there. I'm not as familiar with Ninject, but I will try to find a sample for you.