it-swarm.com.de

Ninject in ASP.NET MVC4

Nach langem Durcheinander habe ich endlich Ninject in meiner MVC4-Anwendung verdrahtet und kompiliert. Das Problem, auf das ich stieß, ist, dass die IDependencyScope-Schnittstelle nicht mehr existiert, was ich sagen kann, und der Namespace System.Web.Http.Dependencies wurde abgeschafft.

Mein Problem ist nun, dass ich alles verdrahtet habe und beim Ausführen der Anwendung bekomme ich:

    Sequence contains no elements

    [InvalidOperationException: Sequence contains no elements]
   System.Linq.Enumerable.Single(IEnumerable`1 source) +379
   Ninject.Web.Mvc.NinjectMvcHttpApplicationPlugin.Start() in c:\Projects\Ninject\ninject.web.mvc\mvc3\src\Ninject.Web.Mvc\NinjectMvcHttpApplicationPlugin.cs:53
   Ninject.Web.Common.Bootstrapper.<Initialize>b__0(INinjectHttpApplicationPlugin c) in c:\Projects\Ninject\Ninject.Web.Common\src\Ninject.Web.Common\Bootstrapper.cs:52
   Ninject.Infrastructure.Language.ExtensionsForIEnumerableOfT.Map(IEnumerable`1 series, Action`1 action) in c:\Projects\Ninject\ninject\src\Ninject\Infrastructure\Language\ExtensionsForIEnumerableOfT.cs:31
   Ninject.Web.Common.Bootstrapper.Initialize(Func`1 createKernelCallback) in c:\Projects\Ninject\Ninject.Web.Common\src\Ninject.Web.Common\Bootstrapper.cs:53
   Ninject.Web.Common.NinjectHttpApplication.Application_Start() in c:\Projects\Ninject\Ninject.Web.Common\src\Ninject.Web.Common\NinjectHttpApplication.cs:81

Was ich nicht in der Lage war herauszufinden, woher es kommt.

Meine Standard-Ninject-Methoden in Global.asax.cs sehen folgendermaßen aus:

        protected override IKernel CreateKernel()
        {
            var kernel = new StandardKernel();
            kernel.Load(Assembly.GetExecutingAssembly());
            kernel.Bind<IRenderHelper>().To<RenderHelper>();

            GlobalConfiguration.Configuration.ServiceResolver.SetResolver(new NinjectDependencyResolver(kernel));
            return kernel;
        }

        protected override void OnApplicationStarted()
        {
            base.OnApplicationStarted();
            AreaRegistration.RegisterAllAreas();
            RegisterGlobalFilters(GlobalFilters.Filters);
            RegisterRoutes(RouteTable.Routes);
            BundleTable.Bundles.RegisterTemplateBundles();
        }

Und mein Custom Resolver:

public class NinjectDependencyResolver : IDependencyResolver
{
    private readonly IKernel _kernel;

    public NinjectDependencyResolver(IKernel kernel)
    {
        _kernel = kernel;
    }

    public object GetService(Type serviceType)
     {
         return _kernel.TryGet(serviceType);
     }

     public IEnumerable<object> GetServices(Type serviceType)
     {
         try
         {
             return _kernel.GetAll(serviceType);
         }
         catch (Exception)
         {
             return new List<object>();
         }
     }

     public void Dispose()
     {
         // When BeginScope returns 'this', the Dispose method must be a no-op.
     }
}

Jeder Einblick hier wäre sehr dankbar. Ich habe schon viel zu viel Zeit damit verbracht, jedes DI-Framework mit der neuesten MVC4-RC unter .NET 4.5 zu betreiben, und habe gerade meine Toleranzstufe erreicht, weil die Dinge überhaupt nicht funktionieren. 

Edit # 1 Eine etwas weitergehende Recherche in github der ExtensionsForIEnumerableOfT.cs hilft nicht viel:

https://github.com/ninject/ninject/blob/master/src/Ninject/Infrastructure/Language/ExtensionsForIEnumerableOfT.cs

Und wenn ich es selbst geschrieben hätte, würde ich das wahrscheinlich verstehen, aber Bootstrapper.cs hilft auch nicht viel.

https://github.com/ninject/Ninject.Web.Common/blob/master/src/Ninject.Web.Common/Bootstrapper.cs

Die Hoffnung auf diese Details wird es jedem von Ihnen, der möglicherweise mehr Erfahrung mit Ninject hat, erleichtern.

Edit # 2 Der aufgetretene Fehler ist spezifisch in NinjectMvcHttpApplicationPlugin.cs:

Die beleidigende Zeile lautet:

ModelValidatorProviders.Providers.Remove(ModelValidatorProviders.Providers.OfType<DataAnnotationsModelValidatorProvider>().Single());

Welches in der folgenden Methode lebt:

public void Start()
{
    ModelValidatorProviders.Providers.Remove(ModelValidatorProviders.Providers.OfType<DataAnnotationsModelValidatorProvider>().Single());
    DependencyResolver.SetResolver(this.CreateDependencyResolver());
    RemoveDefaultAttributeFilterProvider();
}

Die ModelValidatorProviders-Auflistung enthält 2 Elemente: {System.Web.Mvc.DataErrorInfoModelValidatorProvider} {System.Web.Mvc.ClientDataTypeModelValidatorProvider}

Und es wird versucht, eine einzelne Instanz von zu entfernen:

System.Web.Mvc.DataAnnotationsModelValidatorProvider

Was anscheinend nicht in der ModelValidationProviders.Providers-Auflistung geladen ist. Irgendwelche Ideen von hier?

Auflösung, um die Ausnahme zu übertreffen und auf die nächste

Um das Problem in den ModelValidatorProviders zu beheben, musste ich manuell ein Objekt hinzufügen, das erwartet wurde. Nun sieht meine CreateKernel-Methode so aus:

protected override IKernel CreateKernel()
{
    var kernel = new StandardKernel();
    kernel.Load(Assembly.GetExecutingAssembly());

    kernel.Bind<IRenderHelper>().To<RenderHelper>();
    kernel.Unbind<IDocumentViewerAdapter>();

    GlobalConfiguration.Configuration.ServiceResolver.SetResolver(new NinjectDependencyResolver(kernel));
    ModelValidatorProviders.Providers.Add(new DataAnnotationsModelValidatorProvider());
    FilterProviders.Providers.Add(new FilterAttributeFilterProvider());
    return kernel;
}

Nun läuft es und gerät in den eigentlichen Bauch von Ninject, hat aber immer noch ein Problem, das wieder keinen Sinn macht:

Exception Details: Ninject.ActivationException: Error activating IntPtr
No matching bindings are available, and the type is not self-bindable.
Activation path:
 3) Injection of dependency IntPtr into parameter method of constructor of type Func{IKernel}
 2) Injection of dependency Func{IKernel} into parameter lazyKernel of constructor of type HttpApplicationInitializationHttpModule
 1) Request for IHttpModule

Suggestions:
 1) Ensure that you have defined a binding for IntPtr.
 2) If the binding was defined in a module, ensure that the module has been loaded into the kernel.
 3) Ensure you have not accidentally created more than one kernel.
 4) If you are using constructor arguments, ensure that the parameter name matches the constructors parameter name.
 5) If you are using automatic module loading, ensure the search path and filters are correct.
20
VulgarBinary

Ok, nachdem ich meinen Kopf viel zu lange gegen die Wand geschlagen hatte, wusste ich, was los war. Der Standardprojekttyp für MVC4, der unter .NET 4.5 ausgeführt wird, hatte einen Verweis auf die ursprüngliche RC-Version von System.Web.Http anstelle der aktualisierten Version.

Namensräume fehlten, Objekte existierten nicht, das Leben war nicht gut. 

Schritte zur Lösung:

  1. Entfernen Sie Ihren Verweis auf System.Web.Http in Ihrem MVC4-Projekt
  2. Referenz hinzufügen -> System.Web.Http
  3. Löschen Sie alle Workarounds, die Sie einsetzen, damit die alte Müllversion von System.Web.Http funktioniert
  4. Wenden Sie den Standardprozess erneut an, um Ninject zu verdrahten.

    JEDOCH der Fehler von:

    Ausnahmedetails: Ninject.ActivationException: Fehler beim Aktivieren von IntPtrEs sind keine übereinstimmenden Bindungen verfügbar, und der Typ ist nicht selbstbindbar . Aktivierungspfad:. 3) Injektion der Abhängigkeit IntPtr in die Parametermethode des Konstruktors vom Typ Func {IKernel} 2) Injektion der Abhängigkeit Func {IKernel} in den Parameter lazyKernel des Konstruktors vom Typ HttpApplicationInitializationHttpModule 1) Anfrage für IHttpModule

    Vorschläge: 1) Stellen Sie sicher, dass Sie eine Bindung für IntPtr ..__ definiert haben. 2) Wenn die Bindung in einem Modul definiert wurde, stellen Sie sicher, dass das Modul in den Kernel geladen wurde . 3) Stellen Sie sicher, dass Sie nicht versehentlich mehr als einen Kernel erstellt haben. 4) Wenn Sie Konstruktorargumente verwenden, stellen Sie sicher, dass der Parametername mit dem Konstruktorparameternamen ..__ übereinstimmt. 5) Wenn Sie das automatische Laden der Module verwenden, stellen Sie sicher, dass der Suchpfad und die Filter korrekt sind.

Update Dieses Problem wurde durch ein Update von MVC von MVC4 Beta auf MVC4 RC behoben.

18
VulgarBinary

Schauen Sie sich das Pro ASP.NET MVC 3-Buch an . Ich habe diesen Code letzte Nacht von MVC3 auf MVC4 übertragen und funktioniert ordnungsgemäß. Um genau zu sein. 

Was ich nicht sehe, ist, wo Sie Ihre Schnittstelle Ihren konkreten Elementen zuordnen. 

Bind<ISomething>().To<Something>();

Fügen Sie einen anderen Konstruktor hinzu und fügen Sie die Methode hinzu, die Ihr Mapping aufruft.

public NinjectDependencyResolver() {
    _kernal = new StandardKernel();
    RegisterServices(_kernel);
}

public static void RegisterServices(IKernel kernel) {
    kernel.Bind<ISomething>().To<Something>();
}

So könnte/sollte ein Resolver aussehen;

   public class NinjectDependencyResolver : IDependencyResolver {
    private IKernal _kernel;

    public NinjectDependencyResolver(){
        _kernal = StandardKernal();
        AddBindings();
    }

    public NinjectDependencyResolver(IKernel kernel)
    {
        _kernel = kernel;
    }

    public object GetService(Type serviceType)
     {
         return _kernel.TryGet(serviceType);
     }

     public IEnumerable<object> GetServices(Type serviceType)
     {
        return _kernal.GetAll(serviceType);
     }

    public IBindingToSyntax<T> Bind<T>() {
      return _kernal.Bind<T>();
    }

     public static void RegisterServices(IKernel kernel){
      //Add your bindings here. 
      //This is static as you can use it for WebApi by passing it the IKernel
     }
}

Global.Asx -

Anwendungsstart ()

methode

DependencyResolver.SetResolver(new NinjectDependencyResolver());

Das ist es.


AKTUALISIERT 14.11.2012

Wenn Sie mit MVC WebAPI arbeiten, sollten Sie WebApiContrib.IoC.Ninject von nuget verwenden. Schauen Sie sich auch den "Contact Manager" in ihren Samples asp.net.com an. Dies half, die Implementierung von Ninject zu bereinigen 

5
anAgent

Löschen Sie einfach die NinjectWebCommon.cs-Datei aus Ihrem Projekt (sie befindet sich im Ordner App_Start). und alles sollte funktionieren.

Quelle: http://mlindev.blogspot.com.au/2012/09/how-to-implement-dependency-injection.html

4
1_bug

Wenn Sie das neueste Ninject.MVC3-Paket von NuGet installieren, finden Sie folgenden Code über der NinjectWebCommon.cs-Datei:

[Assembly: WebActivator.PreApplicationStartMethod(typeof(MvcApplication1.App_Start.NinjectWebCommon), "Start")]

[Assembly: WebActivator.ApplicationShutdownMethodAttribute(typeof(MvcApplication1.App_Start.NinjectWebCommon), "Stop")]

in diesem Fall müssen wir ninject nicht explizit in global.asax registrieren

Ich habe einen guten Inhalt über die Verwendung von Ninject mit MVC 4 gefunden hier

1
user2035720

Ich bin über das gleiche Problem nicht ganz sicher gekommen, was nach den folgenden Änderungen behoben wurde

ninject.MVC4 zum Projekt hinzugefügt

ninjectWebCommon.cs wurde gelöscht (die generierte Datei, da die Integration bereits in der Datei global.ascx.cs vorhanden ist)

0
Naga

Ich verwende DD4T und bin auf denselben Fehler gestoßen.

Nach der Bestätigung, dass alle Pakete vom nuget package manager installiert wurden, stellte ich fest, dass einige der DLLs/Verweise fehlten (newtonsoft usw.):

Nach der Neuinstallation von Newtonsoft.Json (um das Paket erneut zu installieren, verwenden Sie den folgenden Befehl im Nuget Package Manager: Update-Package - Installieren Sie Newtonsoft.Json) und setzen Sie netrtsn.dll aus der Tridion Deployer-Bin enthält keine Elemente "mit genau demselben Stack-Trace wie in dieser Frage angegeben.

Dank an Naga für die Bereitstellung dieser Auflösung Löschte NinjectWebCommon.cs (die generierte Datei, da die Integration bereits in der Datei global.ascx.cs vorhanden ist) und wohooooo !!!! Alle Fehler behoben, Tridion + MVC4 = DD4T läuft jetzt einwandfrei.

0

Dieses Problem hatte ich auch, als ich Ninject.MVC4 mit Nuget in einem Projekt installierte, auf das mein aktuelles MVC-Website-Projekt verweist.

Das Problem ist, dass die NinjectWebCommon.cs-Datei, die automatisch im Verzeichnis App_Start des referenzierten Projekts installiert wird, mit der in meinem Websiteprojekt installierten (tatsächlichen, nützlichen) Datei in Konflikt steht. Durch das Entfernen der NinjectWebCommon.cs-Datei aus dem referenzierten Projekt wird der Fehler behoben.

0
fordareh

Ich neige dazu, mein Ninject-Bootstrapping in einem separaten Projekt aufzubewahren. Um die .InRequestScope()-Erweiterungsmethode von IBindingInSyntax<T> zu verwenden, hatte ich über Nuget die Ninject.Web.Common -Bibliothek hinzugefügt. Leider enthält diese Bibliothek den Bootstrapper app_start, der dazu führt, dass NinjectWebCommon-Klassen und der Anhang über WebActivator doppelt angelegt werden (1 in diesem Projekt und 1 im MVC-Projekt selbst). 

Ich habe den doppelten Ordner "App_Start" aus meinem Bootstrap-Projekt gelöscht, und das Problem wurde behoben.