web-dev-qa-db-fra.com

ASP.NET MVC 4 + Ninject MVC 3 = Aucun constructeur sans paramètre défini pour cet objet

UPDATE - Veuillez consulter ma réponse pour un lien et une explication de la solution à ce problème

Avant de commencer, je sais que c’est une question très courante et j’utilise Ninject depuis de nombreuses lunes sans problème, mais c’est maintenant réglé et je ne parviens pas à trouver une solution. En outre, non, aucun des résultats sur Google et SO ne m'a jusqu'à présent aidé.

Examinons donc le code ci-dessous qui s'exécute sur un très prototype de projet ASP.NET MVC 4 prototype de Visual Studio 2012 sur Windows Server 2008 R2:

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

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

Et voici la méthode NinjectWebCommon.cs RegisterServices:

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

Voilà comment mes autres projets qui utilisent Ninject (mais qui sont ASP.NET MVC 3 sur .NET 4) fonctionnent et pour autant que je sache, c’est ce qui est nécessaire pour que tout fonctionne. Alors, pourquoi suis-je subitement Aucun constructeur sans paramètre défini pour cet objet. exceptions?

METTRE À JOUR

Voici le fichier NinjectWebCommon.cs complet:

[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 - Veuillez consulter ma réponse pour un lien et une explication de la solution à ce problème

37
Gup3rSuR4c

Eh bien, je n'ai pas de réponse exacte. Pourquoi l'erreur est imminente, mais je sais que qui en est la cause et c'est Visual Studio 2012. J'ai installé Visual Studio 2010 sur la même machine que 2012, installé ASP.NET MVC 4 pour 2010 et j'ai recréé le projet 2012 en 2010 Word pour Word, lettre pour lettre. Le résultat final est que lorsque 2010 débogue le projet, tout fonctionne correctement et que Ninject injecte les dépendances comme il se doit.

Lorsque 2012 débogue son projet, il génère simplement l'exception No parameterless constructor defined for this object. Re-cibler entre .NET 4.0 et .NET 4.5 en 2012 ne fait rien. Réinstaller Ninject de NuGet ne fait rien non plus. J'ai même configuré les projets 2010 et 2012 pour qu'ils utilisent le serveur IIS local pour être absolument sûr et que le résultat final soit identique.

Je vais supposer qu'il y a un bogue avec Visual Studio 2012 ou avec Ninject. La seule différence que je connaisse entre les deux projets est l'origine de IDE et le projet 2012 est celui qui tombe en panne, c'est pourquoi je pointe le doigt vers Visual Studio 2012.

METTRE &AGRAVE; JOUR

Les mecs. LES MECS! J'ai rencontré ce problème à nouveau et j'ai trouvé la solution dans une autre question SO: Ninject + MVC3 n'injecte pas dans le contrôleur .

Fondamentalement, c’est ce qui manque dans le fichier Web.config qui le fait fonctionner:

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

J'imagine que cela oblige le framework à prendre en compte les conteneurs IoC, ce qui permet à Ninject de enfin pouvoir se lier. Cependant, je ne peux pas m'empêcher de penser que le paquet Ninject NuGet devrait rechercher l'existence de cette redirection de liaison dans le fichier Web.config et l'ajouter par magie. Cela aiderait certainement avec beaucoup d'arrachage de cheveux sur cette question.

P.S. Up-vote la morve hors de ce post que j'ai lié parce qu'il le mérite!

28
Gup3rSuR4c

Je sais que c’est une vieille question mais il ne semble pas y avoir de vraie réponse et j’ai travaillé sur le problème, voici donc ma solution:

Créer une fabrique de contrôleurs personnalisés:

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);
    }
}

Ensuite, si vous utilisez NinjectHttpApplication, ajoutez la ligne suivante à OnApplicationStarted:

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

Si vous n'utilisez pas NinjectHttpApplication, ajoutez cette ligne quelque part après la création de votre noyau et transmettez-lui une référence à votre noyau fraîchement créé.

C'est tout.

48
Jere.Jones

Ne réinventez pas la roue et essayez simplement Install-Package Ninject.MVC3

7
Juanjo

J'ai reçu le même message d'erreur après avoir reçu le MVC3 de NuGet.
Je ne sais pas si vous avez configuré votre projet de la même manière que moi, mais mon web.config est généré automatiquement en fonction de l'environnement. Le MVC de NuGet ajoute rows (<runtime>) au web.config et ces lignes ont été supprimées car la fusion de mes fichiers de configuration n’avait pas été configurée correctement.

Cordialement,

Kim

3
Kim Thörning

Tout est ridicule, je suis passé à Autofac, fatigué de ne jamais pouvoir ajouter Ninject à un projet avec succès. API Web, MVC4, MVC5 ont tous eu des problèmes.

Pour les personnes MVC5, à l'aide de Ninject MVC3, ajoutez les éléments suivants au niveau de l'application web.config:

 <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>
2
Brian Ogden

Voici une solution sale! Mettez ceci 

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

au début de l'événement AppStart (ou ailleurs)

Maintenant, laissez-moi vous expliquer ce que cela signifie si quelqu'un n'a pas encore eu d'astuce ……. Notre classe d'applications http pourrait résider n'importe où dans la solution. Pas seulement dans l'application web. Et ceci est très important, car la routine de compilation asp.net est différente des applications de bibliothèque habituelles. Il charge avec impatience TOUTES les bibliothèques référencées via l’assistant BuildManager, alors que généralement clr ne charge pas les types à partir du début, sauf s’ils sont utilisés directement.

Revenons maintenant à notre situation: Ninject.Web.Mvc fonctionne comme un plugin dynamique, qui ne nécessite aucune mention dans un code. Et ainsi, il n'est pas chargé s'il a été référencé à l'intérieur de la bibliothèque de classes, ce qui entraîne l'initialisation cassée de Mvc.Dependancy. 

1
wallice

Le problème semble se produire lorsque l'on utilise Visual Studio 2012/2013 avec ASP.NET 4.0/4.5. La version de System.Web.Mvc a été définie sur 4.0.0.0 dans le fichier Web.config. Cela n'a pas fonctionné. 

Ma solution était de 

  1. supprimer NinjectWebCommon.cs 
  2. copier la classe NinjectControllerFactory de Dere Jone dans le projet: 

    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. remplacez le contenu de Global.asax par: 

    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));
       }
    }
    

    après cela, vos injections devraient fonctionner. 

1
MovGP0

J'ai le même problème et la seule chose qui fonctionne pour moi est de changer le "serveur Web local IIS" dans les propriétés du projet Web en "Utiliser le serveur de développement Visual Studio".

enter image description here

Je ne sais pas pourquoi mais quand je fais cela, mon point de rupture dans NinjectWebCommon est atteint. Comme @Alex l'a dit, Visual Studio 2012 n'est pas assez brillant pour exécuter le code dans NinjectWebCommon chaque fois que vous créez votre application. Il est également possible que ce ne soit pas moi assez brillant pour comprendre comment cela fonctionne sous le capot.

Je n'aime pas ma solution car je préférerais utiliser mon serveur Web local IIS mais, pour le moment, je dois créer une application et prendre beaucoup de temps avec ce $%? !!/bug..feature ..pas certain.

0
Samuel

J'ai corrigé le mien en supprimant Ninject MVC5 et en installant Ninject MVC3, à partir de Nuget.

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

Vérifiez la version de System.Web.MVC dans les références pour savoir quelle version de MVC vous utilisez actuellement.

0
MiloTheGreat

J'ai essayé toutes ces solutions, mais aucune n'a fonctionné. 

Voici comment je l'ai résolu: Supprimé tous mes fichiers asp.net temporaires. Après cela, j'ai eu de nouvelles erreurs de configuration. Je les ai réparés. La dernière et vraie erreur est survenue: new Bootstrapper () essayait de charger une version plus ancienne d'une dll ninject . la version est installée.

0
dawidg

Cela a été résolu pour moi en ajoutant une référence via Nuget à Ninject.Web.MVC.

0
hanzolo

Je tirais mes cheveux dessus pendant plusieurs heures sur un projet récent qui est passé de MVC 3 à MVC 4. Avec le manque de réponses ponctuelles, j’ai pensé que c’était quelque chose que j’avais fait car il semble que le nuget Ninject.MVC3 le paquet fonctionnera bien avec MVC 4 - et en effet il fonctionne.

Dans mon cas, je n'étais pas en train de mettre à niveau le projet MVC3. Après avoir suivi ce guide j’ai fait fonctionner les choses comme prévu. J'imaginais qu'il me manquait une redirection de liaison d'assemblage.

Donc, si vous mettez à niveau un projet MVC 3 vers MVC 4, utilisez Ninject et obtenez l'erreur définie par le constructeur sans paramètre, espérez que cela vous aidera.

0
JasonCoder

Comme toutes les affiches précédentes l'ont déclaré, cela m'a causé des cheveux gris. Dans mon cas, j'avais trop "optimisé" mes références. Ninject. * Était là mais il avait été mutilé. J'ai supprimé toutes les références et nettoyé packages.conf manualli et ajouté à nouveau les packages - victoire!

0
juhan_h

J'ai pu résoudre ce problème dans un projet Web MVC5 en supprimant une directive #if #endif du constructeur de mon contrôleur.

0
James Blake

J'obtenais ce problème, mais uniquement lors d'appels de service Web. J'ai trouvé ma solution à cette réponse https://stackoverflow.com/a/12379938/129580 ci-dessous, le code fourni 

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

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

que j’ai fini par devenir, espérons que cela aide ...

/// <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;
    }
}
0
Geovani Martinez

J'ai essayé de configurer Ninject avec MVC 5. Enfin, je devais d'abord utiliser une solution avec une usine de contrôleur, puis une solution avec liaison de redirection. Après cela tout fonctionne comme prévu. Serveur local IIS utilisé.

0
n0ne