ASP.NET MVC 4 + Ninject MVC 3 = No parameterless constructor defined for this object
Asked Answered
U

17

39

UPDATE - Please look at my answer for a link and explanation of the solution to this problem

Before we start, I know this is a very common question and I've been using Ninject for many moons without issues, but now it's come up and I can't figure out a fix. Also, no, none of the results on Google and SO so far have helped me.

So, consider the following bit of code running on a very, very, very simple prototype ASP.NET MVC 4 project from Visual Studio 2012 on Windows Server 2008 R2:

public class DefaultController : Controller {
    private IGroupPrincipalRepository GroupPrincipalRepository { get; set; }

    [Inject]
    public DefaultController(
        IGroupPrincipalRepository groupPrincipalRepository) {
        this.GroupPrincipalRepository = groupPrincipalRepository;
    }
}

And here's the NinjectWebCommon.cs RegisterServices method:

kernel.Bind(typeof(IGroupPrincipalRepository)).ToConstructor(
    c =>
        new GroupPrincipalRepository(new PrincipalContext(ContextType.Domain, "?", "?", "?", "?"))).InSingletonScope();

Now, this is how my other projects that use Ninject (but are ASP.NET MVC 3 on .NET 4) work and as far as I know this is what's needed to make everything work. So, why am I suddenly getting No parameterless constructor defined for this object. exceptions?

UPDATE

Here's the full NinjectWebCommon.cs file:

[assembly: WebActivator.PreApplicationStartMethod(typeof(App_Start.NinjectWebCommon), "Start")]
[assembly: WebActivator.ApplicationShutdownMethodAttribute(typeof(App_Start.NinjectWebCommon), "Stop")]

namespace App_Start {
    using System;
    using System.DirectoryServices.AccountManagement;
    using System.Repositories.ActiveDirectory;
    using System.Web;
    using Microsoft.Web.Infrastructure.DynamicModuleHelper;
    using Ninject;
    using Ninject.Web.Common;

    public static class NinjectWebCommon {
        private static readonly Bootstrapper bootstrapper = new Bootstrapper();

        public static void Start() {
            DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
            DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
            bootstrapper.Initialize(CreateKernel);
        }

        public static void Stop() {
            bootstrapper.ShutDown();
        }

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

            RegisterServices(kernel);
            return kernel;
        }

        private static void RegisterServices(
            IKernel kernel) {
            kernel.Bind(typeof(IGroupPrincipalRepository)).ToConstructor(
                c =>
                    new GroupPrincipalRepository(new PrincipalContext(ContextType.Domain, "", "", "", ""))).InSingletonScope();
        }
    }
}

UPDATE - Please look at my answer for a link and explanation of the solution to this problem

Upkeep answered 7/9, 2012 at 3:51 Comment(9)
Where are you creating your DependecyResolver and overriding the default?Poulter
I thought that's what the NinjectWebCommon.cs file is doing and if not then I guess the answer is "no where". Again, there's confusion on my end because my other projects work this way and I've double and triple checked to make sure I'm not lying...Upkeep
There is a NinjectMvcHttpApplicationPlugin in the Ninject.MVC package which takes care of the DependecyResolver... so it should just work? How do you installed Ninject.MVC ? With Nuget?Rager
Yeah, with NuGet, latest version then I change the NinjectWebCommon.cs file as the Git hub docs say. I just tried another test with a fresh MVC 4 project with only a single ActionResult in a single controller with one injection. Still fails with the same issue.Upkeep
I tried yet another test using Visual Studio 2010, MVC 4, .NET 4 on my local machine and this time the error is not happening. I'm going to assume it's either VS2012 or .NET 4.5 that's the culprit. Targeting .NET 4.0 doesn't fix the issue.Upkeep
Have a look in the Ctrl-Alt-O full build output for any reference issues. Also check the .csproj to see the assemblies being referenced add upHebbe
The output looked fine to me, in the end I think VS 2012 is the culprit.Upkeep
I am having exactly the same problem right now. It's like MVC4 doesn't even know about ninject's controller factory (although it definitely executes the code in NinjectWebCommon).Slavish
How to set up IIS 7 application pool identity correctly? my question on a similar issueSpanner
U
29

Well, I don't have an exact answer why the error is coming up, but I do know who is causing it and that is Visual Studio 2012. I installed Visual Studio 2010 on the same machine as 2012, installed ASP.NET MVC 4 for 2010 and I recreated the 2012 project into 2010 word for word, letter for letter. The final result is that when 2010 debugs the project everything works fine and Ninject injects the dependencies as it should.

When 2012 debugs its project it just comes up with the No parameterless constructor defined for this object exception. Re-targeting between .NET 4.0 and .NET 4.5 in 2012 doesn't do anything. Re-installing Ninject from NuGet also doesn't do anything. I even configured both 2010 and 2012 projects to use the local IIS server to be absolutely sure and the end result is the same.

I'm going to assume that there's a bug with Visual Studio 2012 or with Ninject. The only difference I've got between the two projects is which IDE they're running from and the 2012 project is the one that's crashing so that's why I'm pointing the finger at Visual Studio 2012.

UPDATE

Guys. GUYS! I ran into this problem AGAIN, and found the solution in another SO question: Ninject + MVC3 is not injecting into controller.

Basically, this is what's missing from the Web.config which makes it work:

<dependentAssembly>
    <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
    <bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
</dependentAssembly>

I'm guessing this forces the framework to be aware of IoC containers which allows Ninject the finally be able to bind. Although, I can't help but think that the Ninject NuGet package should look for the existence of that binding redirect in the Web.config and auto-magically add it. It sure would help with a lot of hair pulling happening over this issue.

P.S. Up-vote the snot out of that post I linked because it deserves it!

Upkeep answered 7/9, 2012 at 21:19 Comment(4)
I'm seeing the same problem. Hopefully one of the two (VS 2012 or Ninject) will fix the problem.Stolon
my mvc4 project is not missing this line, but it still doesn't work.Petie
That fixed for me, except I was using Mvc 5.0.0.0Jeddy
I was missing the reference to Ninject.Web.Mvc and also there was no Ninject.Web.Mvc.dll in bin folder. Added reference and issue resolved out.Torchier
M
48

I know this is an old question but there don't seem to be any real answers and I've worked around the problem so here is my solution:

Create a custom controller factory:

public class NinjectControllerFactory : DefaultControllerFactory
{
    private IKernel ninjectKernel;
    public NinjectControllerFactory(IKernel kernel)
    {
        ninjectKernel = kernel;
    }
    protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
    {
        return (controllerType == null) ? null : (IController) ninjectKernel.Get(controllerType);
    }
}

Then, if you are using NinjectHttpApplication, add the following line to OnApplicationStarted:

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

If you aren't using NinjectHttpApplication, then add that line somewhere after you have created your kernel and pass it a reference to your freshly created kernel.

That's it.

Marquise answered 25/12, 2012 at 4:36 Comment(3)
Awesome! Man, you just saved my day. Thanks a lot! I spent time trying to fix the problem and this solved it. BTW I am really interested in knowing why this happened and what are you basically doing with this code.Johnsonjohnsonese
In my case, I must use code like this: "DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));" in the Start method of NinjectWebCommon. If I replace NinjectWebCommon by your sugestion, I don't know where to move this code. If I try to move it in global.asax, I receive an error that telling me it's to late in the process to register module in the application starting. This is why the big guy of Ninject suggest to me to stay with the solution using NinjectWebCommon.Boykin
This causes a warning with ASP MVC5, Ninject3.2, Ninject.MVC3: "Do not use Ninject as Service Locator". This solution looks like a workaround.Lafontaine
U
29

Well, I don't have an exact answer why the error is coming up, but I do know who is causing it and that is Visual Studio 2012. I installed Visual Studio 2010 on the same machine as 2012, installed ASP.NET MVC 4 for 2010 and I recreated the 2012 project into 2010 word for word, letter for letter. The final result is that when 2010 debugs the project everything works fine and Ninject injects the dependencies as it should.

When 2012 debugs its project it just comes up with the No parameterless constructor defined for this object exception. Re-targeting between .NET 4.0 and .NET 4.5 in 2012 doesn't do anything. Re-installing Ninject from NuGet also doesn't do anything. I even configured both 2010 and 2012 projects to use the local IIS server to be absolutely sure and the end result is the same.

I'm going to assume that there's a bug with Visual Studio 2012 or with Ninject. The only difference I've got between the two projects is which IDE they're running from and the 2012 project is the one that's crashing so that's why I'm pointing the finger at Visual Studio 2012.

UPDATE

Guys. GUYS! I ran into this problem AGAIN, and found the solution in another SO question: Ninject + MVC3 is not injecting into controller.

Basically, this is what's missing from the Web.config which makes it work:

<dependentAssembly>
    <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
    <bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
</dependentAssembly>

I'm guessing this forces the framework to be aware of IoC containers which allows Ninject the finally be able to bind. Although, I can't help but think that the Ninject NuGet package should look for the existence of that binding redirect in the Web.config and auto-magically add it. It sure would help with a lot of hair pulling happening over this issue.

P.S. Up-vote the snot out of that post I linked because it deserves it!

Upkeep answered 7/9, 2012 at 21:19 Comment(4)
I'm seeing the same problem. Hopefully one of the two (VS 2012 or Ninject) will fix the problem.Stolon
my mvc4 project is not missing this line, but it still doesn't work.Petie
That fixed for me, except I was using Mvc 5.0.0.0Jeddy
I was missing the reference to Ninject.Web.Mvc and also there was no Ninject.Web.Mvc.dll in bin folder. Added reference and issue resolved out.Torchier
W
7

Don't reinvent the wheel and just try Install-Package Ninject.MVC3

Wrinkle answered 9/7, 2014 at 13:40 Comment(2)
This is the right answer. I did Install-Package Ninject.MVC5 and it worked.Irvingirwin
Nailed it. Just uninstall Ninject MVC 3, install it again, rebuild entire solution, run it and fixedKeheley
M
3

I got the same error message after getting the MVC3 from NuGet.
I don't know if you got your project setup the same way as I do but my web.config is auto generated depending on environment. The MVC from NuGet is adding rows (<runtime>) to the web.config and those rows were removed since my merging config-files wasn't setup correctly.

Regards,

Kim

Mongoose answered 19/9, 2012 at 14:41 Comment(2)
I had to add the <runtime> element to my web config. As well as ensure <httpRuntime> had the targetFramework="4.5" attribute. This was my runtime element. <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>Ketti
Liked @Michael, I needed to add runtime as well as assemblybinding element. Ninject.MVC4Hutchison
A
2

The whole thing is just ridiculous, I switched to Autofac, tired of never one time being able to add Ninject to a project successfully. Web API, MVC4, MVC5 all had problems.

For MVC5 people, using Ninject MVC3, add the following to web.config app level:

 <runtime>
        <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
            <dependentAssembly>
                <assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35"/>
                <bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0"/>
            </dependentAssembly>
            <dependentAssembly>
                <assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35"/>
                <bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0"/>
            </dependentAssembly>
            <dependentAssembly>
                <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35"/>
                <bindingRedirect oldVersion="1.0.0.0-5.1.0.0" newVersion="5.1.0.0"/>
            </dependentAssembly>
        </assemblyBinding>
    </runtime>
Aztec answered 14/6, 2014 at 6:19 Comment(0)
P
1

Here is a dirty solution! Put this

var type = typeof(Ninject.Web.Mvc.MvcModule);

in the beginning of the AppStart event (or anywhere else )

Now let me explain what it means if someone didn't get trick yet. Thing is our http application class could reside anywhere in solution. Not only in web application. And this is very important because asp.net compilation routine is different from usual library applications. It eagerly loads ALL referenced libraries via BuildManager helper, while usually clr doesn't load types from start unless they're directly used.

Now let's get back to our situation: Ninject.Web.Mvc work as dynamic plugin, which doesn't require any mention within a code. And thus is not loaded if it was referenced inside Class library which leads to broken Mvc.Dependancy initialization.

Poleaxe answered 28/7, 2013 at 15:6 Comment(0)
I
1

The Problem seems to occur when one uses Visual Studio 2012/2013 with ASP.NET 4.0/4.5. The version of System.Web.Mvc was set to 4.0.0.0 in the Web.config file. It did not work.

My solution was to

  1. delete NinjectWebCommon.cs
  2. copy Dere Jone's NinjectControllerFactory class into the project:

    public class NinjectControllerFactory : DefaultControllerFactory
    {
       private IKernel ninjectKernel;
       public NinjectControllerFactory(IKernel kernel)
       {
          ninjectKernel = kernel;
       }
    
       protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
       {
          return (controllerType == null) ? null : (IController) ninjectKernel.Get(controllerType);
       }
    }
    
  3. change the content of Global.asax to:

    public class MvcApplication : NinjectHttpApplication
    {
       protected override IKernel CreateKernel()
       {
           IKernel kernel = new StandardKernel();
    
           // kernel.Load(Assembly.GetExecutingAssembly());
    
           // kernel.Bind<ISomeClass>().To<SomeClass>();
    
           return kernel;
       }
    
       protected override void OnApplicationStarted()
       {
           AreaRegistration.RegisterAllAreas();
    
           WebApiConfig.Register(GlobalConfiguration.Configuration);
           FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
           RouteConfig.RegisterRoutes(RouteTable.Routes);
           BundleConfig.RegisterBundles(BundleTable.Bundles);
    
           ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory(Kernel));
       }
    }
    

    after that your injections should work.

Integument answered 9/1, 2014 at 2:55 Comment(0)
D
1

I was getting this issue but only on Web Service calls. Found my solution on this answer https://mcmap.net/q/245461/-ninject-w-asmx-web-service-in-a-mvc3-ninject-3-environment below is the sample code provided

public class Service : WebService
{
  public IContextProvider ContextProvider {get;set;}

  public Service()
  {
    ContextProvider = DependencyResolver.Current.GetService<IContextProvider>();
  }
}

which I then ended up turning into, hope this helps...

/// <summary>
/// Summary description for PartMarking
/// </summary>
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
// To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line.
[System.Web.Script.Services.ScriptService]
public class PartMarking : System.Web.Services.WebService
{
    private readonly IUnitOfWork _unitOfWork;

    public PartMarking()
    {
        _unitOfWork = DependencyResolver.Current.GetService<IUnitOfWork>();
    }

    [WebMethod]
    public DataSet GetParentConfigurations(string engineModel, string componentCode)
    {
        var results = _unitOfWork.PartMarking.GetParentSicMarkings(engineModel, componentCode);
        return results;
    }
}
Drisko answered 8/8, 2018 at 13:34 Comment(0)
A
0

I was pulling my hair out on this for several hours on a recent project that I moved from MVC 3 to MVC 4. With the lack of on point answers I figured it had to be something I did as it appears that the Ninject.MVC3 nuget package will work fine with MVC 4 - and indeed it does.

In my case I wasn't fully upgrading the MVC3 project. After following this guide I got things to work as expected. My guess was that I was missing an assembly binding redirect.

So if you're upgrading an MVC 3 project to MVC 4, using Ninject and getting the no parameterless constructor defined error, hope this helps.

Antonia answered 13/6, 2013 at 13:56 Comment(0)
G
0

As all of the previous posters have stated this caused me some gray hairs. In my case I had "optimised" my references too much. Ninject.* stuff was there but had gotten mangled up. I deleted all the references and cleaned packages.conf manualli and added the packages again - victory!

Gloucester answered 9/7, 2013 at 10:14 Comment(0)
B
0

I have the same problem and the only thing that works for me is to change the "Local IIS Web server" in the Web project properties to "Use Visual Studio Development Server".

enter image description here

I don't know why but when I do this, my break point in NinjectWebCommon is hited. Like @Alex said, it's something with Visual Studio 2012 not enough bright to execute the code in NinjectWebCommon each time you build your application. It's also possible that it's me not enough bright to understand how it works under the hood.

I don't like my solution because I would prefer to use my Local IIS Web Server but for the moment, I have an application to create and to much time took with this $%?!!/ bug..feature..not sure.

Boykin answered 23/2, 2014 at 4:0 Comment(1)
Make sure to have the <dependentAssembly> section in your Web.config. My projects run just fine with the local IIS and that setting. Of course, the binding redirect should be <bindingRedirect oldVersion="0.0.0.0-5.1.0.0" newVersion="5.1.0.0" /> now since MVC 5.1 is out.Upkeep
C
0

This was solved for me by adding a reference via Nuget to Ninject.Web.MVC.

Chlorite answered 28/4, 2014 at 21:6 Comment(0)
D
0

I tried all these solutions, but none worked.

This is how I resolved it: Deleted all my temp asp.net files. After I'd done this, I got new config errors. I fixed them. The last, and real error came out: new Bootstrapper() was trying to load an older version of a ninject dll. Removed all ninject packages. Installed ninject nuget packages one by one, make triply sure that the correct version is installed.

Doorkeeper answered 16/5, 2014 at 3:48 Comment(0)
M
0

I tried to set up Ninject with MVC 5. Finally i had to use solution with controller factory first, and solution with binding redirect then. After that all works as expected. Used Local IIS server.

Malaspina answered 30/5, 2014 at 22:45 Comment(1)
The project I'm working on right now is for MVC 5 (5.1.2) and I have not had to use a controller factory. I just have the binding redirects and it all works perfectly fine. I'm also using a local IIS server as well. I did split the Ninject code out of the MVC project and into its' own project though.Upkeep
I
0

I was able to resolve this issue in an MVC5 web project by removing an #if #endif directive from my controllers constructor.

Iodous answered 2/12, 2015 at 21:25 Comment(0)
O
0

Shortcut for all this: Download one of the following Nuget Pacakges:

  • Ninject.MVC3
  • Ninject.MVC5

That will take care of the binding that you need.

Outbid answered 25/5, 2016 at 21:57 Comment(0)
S
0

I fixed mine by Removing Ninject MVC5 and installing Ninject MVC3, from Nuget.

MVC5 == Ninject.MVC5
MVC4 == Ninject.MVC3
MVC3 == Ninject.MVC3

Check the version of the System.Web.MVC in the references to be sure which version of MVC you are currently on.

Speechless answered 29/3, 2017 at 16:14 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.