简体   繁体   中英

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

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

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.

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.

PS Up-vote the snot out of that post I linked because it deserves it!

不要重新发明轮子,只需尝试 Install-Package Ninject.MVC3

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

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>

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.

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.

I was getting this issue but only on Web Service calls. Found my solution on this answer https://stackoverflow.com/a/12379938/129580 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;
    }
}

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 followingthis 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.

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!

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".

在此处输入图片说明

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.

通过 Nuget 添加对 Ninject.Web.MVC 的引用为我解决了这个问题。

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.

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.

通过从控制器构造函数中删除 #if #endif 指令,我能够在 MVC5 Web 项目中解决此问题。

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM