Question

I am learning how to setup a repository. I am going for simple and dumb just to make it work. Good thing is that may make it easy to debug for you guys.

HomeController:

public IUserRepository UserRepository { get; set; }

public HomeController(IUserRepository userRepo)
{
    UserRepository = userRepo;
}

public ActionResult Index()
{
    var users = UserRepository.GetUsers();
    return View(users);
}

UserModel:

public class UserModel
{
    public int Id { get; set; }
    public string UserName { get; set; }
    public string PasswordHash { get; set; }
    public string PasswordSalt { get; set; }
}

Repository:

public interface IUserRepository
{
    List<UserModel> GetUsers();
}

public class UserRepository : IUserRepository
{
    private GameAlertDBDataContext db = new GameAlertDBDataContext();

    public List<UserModel> GetUsers()
    {
        var userList = from u in db.Users where u.Id == 1 select u;
        var users = new List<UserModel>();

        if (userList.Any())
        {
            foreach (var user in userList)
            {
                users.Add(new UserModel() { Id = user.Id, UserName = user.Username, PasswordHash = user.PasswordHash, PasswordSalt = user.PasswordSalt});
            }

        }
        return users;
    }
}

When I run my application I get the error No parameterless constructor defined for this object.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. 

Exception Details: System.MissingMethodException: No parameterless constructor defined for this object.

[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 'FriendAlert.Controllers.HomeController'. 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

I am trying to figure out what I am doing wrong? Why is my repository not working?

Was it helpful?

Solution

You have to use Dependency Injection. I use Ninject IoC container. You can install to your visual studio by Tools -> library package manager -> Manage NuGet Packages

Then add a class like this

 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);
    }
    private void AddBindings()
    {
        ninjectKernel.Bind<IUserRepository>().To<UserRepository>();
    }
}

then in the Global.asax

 protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();

        WebApiConfig.Register(GlobalConfiguration.Configuration);
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);

        ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory());
    }

It will solve the issue

OTHER TIPS

The Asp.NET MVC framework cannot instantiate your controller because it does not have information to pass the constructor parameter.

The next step here is to use Dependency Injection to construct the appropriate Repository instance and inject it to create the controller instance.

Take a look at DI framework like Autofac and how to integrate it with MVC.

This error occurs because mvc framework can't find parameterless constructor in your HomeController. In order to fix this issue, you just simply add a parameterless constructor so mvc framework can instantiate HomeController

public HomeController()
{        
}

Edit to complete my answer, as @Eranga suggested, you should consider to use Dependency Injection framework to inject your dependency into HomeController. You can refer to this question for more information about which framework should be used

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top