ASP.NET MVC 4 Ninject MVC 4 No default constructor found for type 'App.Controller'

I have installed a new ASP.NET MVC 4 app in Xamarin Studio / monodevelop-opt on Ubuntu 14.04 LTS (Mono 3.10.0 mod-mono-server4 / xsp when running in IDE). Installed packages:

Install-Package Microsoft.AspNet.Mvc -Version 4.0.40804

      

  • Microsoft.AspNet.MVC
  • Microsoft.AspNet.Razor
  • Microsoft.AspNet.WebPages
  • Microsoft.Web.Infrastructure

I also had to install the Optimization Platform:

Install-Package Microsoft.AspNet.Web.Optimization

      

I decided to implement IoC Ninject container from NuGet and the following packages were installed:

Install-Package Ninject.Mvc4

      

  • Ninject
  • Ninject.MVC4
  • Ninject.Web.Common.WebHost
  • Ninject.Web.Common

Since I installed Ninject.Mvc4 it created a nice file for me in App_Start called NinjectWebCommon.cs

Here is the Create Kernal method:

    private static IKernel CreateKernel ()
    {
        var kernel = new StandardKernel ();
        try {
            kernel.Bind<Func<IKernel>> ().ToMethod (ctx => () => new Bootstrapper ().Kernel);
            kernel.Bind<IHttpModule> ().To<HttpApplicationInitializationHttpModule> ();

            RegisterServices (kernel);
            return kernel;
        } catch {
            kernel.Dispose ();
            throw;
        }
    }

      

Here is the registration services method:

    private static void RegisterServices (IKernel kernel)
    {
        kernel.Bind<IResourceEntryService> ().To<ResourceEntryService> ();

        var modules = new List<INinjectModule> {
            new ConfigModule (),
            new RepositoryModule (),
            new LoggingModule ()
        };

        kernel.Load (modules);
    }

      

Service and resource input interface:

public interface IResourceEntryService
{
    IEnumerable<ResourceEntry> GetResourceEntries ();

    IEnumerable<ResourceEntry> GetResourceEntriesByNameAndCulture (string name, string culture);
}

public class ResourceEntryService : IResourceEntryService
{
    IResourceEntryRepository _resourceEntryRepository;

    public ResourceEntryService (IResourceEntryRepository resourceEntryRepository)
    {
        _resourceEntryRepository = resourceEntryRepository;
    }

    #region IResourceEntryService implementation

    public System.Collections.Generic.IEnumerable<ResourceEntry> GetResourceEntries ()
    {
        IEnumerable<ResourceEntry> resourceEntries = _resourceEntryRepository.GetResourceEntries ();
        return resourceEntries;
    }

    public System.Collections.Generic.IEnumerable<ResourceEntry> GetResourceEntriesByNameAndCulture (string name, string culture)
    {
        IEnumerable<ResourceEntry> resourceEntries = _resourceEntryRepository.GetResourceEntriesByNameAndCulture (name, culture);
        return resourceEntries;
    }

    #endregion
}

      

Controller for injecting resources, passing a new model object to the view:

public class ResourceEntryController : Controller
{
    IResourceEntryService _resourceEntryService;

    public ResourceEntryController (IResourceEntryService resourceEntryService)
    {
        _resourceEntryService = resourceEntryService;
    }

    public ActionResult Index ()
    {
        ResourceEntryViewModel viewModel = new ResourceEntryViewModel ();

        return View (viewModel);
    }
}

      

Here is my ~ / Views / ResourceEntry / Index.cshtml file:

@model App.Web.UI.ViewModels.ResourceEntryViewModel

<h1>Resource Page</h1>

      

So now everything looks good? Well, not so! When you try to view this page, you receive the following error message.

System.MissingMethodException
Default constructor not found for type App.Web.UI.Controllers.ResourceEntryController

at System.Activator.CreateInstance (System.Type type, Boolean nonPublic) [0x00094] in /usr/src/packages/BUILD/mcs/class/corlib/System/Activator.cs:326 
at System.Activator.CreateInstance (System.Type type) [0x00000] in /usr/src/packages/BUILD/mcs/class/corlib/System/Activator.cs:222 
at System.Web.Mvc.DefaultControllerFactory+DefaultControllerActivator.Create (System.Web.Routing.RequestContext requestContext, System.Type controllerType) [0x00000] in <filename unknown>:0 

Version Information: 3.10.0 (tarball Sat Oct 4 16:28:24 UTC 2014); ASP.NET Version: 4.0.30319.17020
Powered by Mono

      

Does anyone have any ideas how to set up a Ninject app for MVC 4 running on a mono stack.

I have had good google'ing and stackoverlow'ing and cannot find a definitive answer. All are web API references and they are really not interested in web APIs as I will be using ServiceStack if that happens.

I just want this web app to work. Anyone have any suggestions?

Update: 12/20/2014

Works fine under windows, but not Ubuntu

I created a simple application that can be found here:

Sample application

Any ideas?

Update 21/12/2014

I tried another IoC container implementation.

The same is happening, I think it could be Mono MVC 4 Thing. I still don't know why.

Update 22/12/2014

It looks like App_Start doesn't start on startup.

I did Console.WriteLine

in CreateKernel

and out RegisterServices

and didn't print anything.

I could get SimpleInjector working by setting up the Container in the Global.ascx.cs file. It won't work if initialized to App_Start with the next line at the top.

[assembly: WebActivator.PostApplicationStartMethod (typeof(App.Web.UI.App_Start.SimpleInjectorInitializer), "Initialize")]

      

I wonder if there is a problem with WebActivator with Mono.

+3


source to share


1 answer


Looking at the stack trace, I can see the DefaultControllerFactory at the bottom, which will install the controller instance inside, like so:

return Activator.CreateInstance(YourControllerType);

      

This call will be pissed off because your controller doesn't have a parameterless constructor and you haven't provided a list of parameter values ​​to find a suitable constructor to use ... hence an exception. Also, you don't want to provide a parameter list that is inflexible and defeats the purpose of IoC, you want the IoC core to instantiate it instead.

Now I have no experience with Ninject, so maybe a more "Ninjecty" way to do this (and if you know what it is, add to that :), but you need to create your own DefaultControllerFactory that can type and use Ninject for its creation. Something like that:



// NOTE: Something like this, not exactly, I've not used Ninject!

public class YourControllerFactory : DefaultControllerFactory
{
    public override IController CreateController(RequestContext requestContext, string controllerName)
    {
        var type = GetControllerType(requestContext, controllerName);

        return kernel.Get(type);
    }
}

      

Register it in Global.asax:

ControllerBuilder.Current.SetControllerFactory(new YourControllerFactory());

      

You now have control over the instantiation process!

+1


source







All Articles