it-swarm.com.de

ASP.NET-Web-API-Bindung mit Ninject

Ich habe gerade das mvc4 rc-Update installiert und versuche mit wenig Glück eine API-Anwendung zu erstellen.

Ich verwende ninject, kann aber meine Controller nicht laden. Ich bekomme immer einen Fehler

Der Typ 'Api.Controllers.ConsumerController' hat keinen Standardkonstruktor

Ich bin sehr neu bei mvc und verwende die Injektion, also bitte ertrage mich.

Ich habe nichts Besonderes an der Standardbindung gemacht, die über Nuget erstellt wird

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

    /// <summary>
    /// Starts the application
    /// </summary>
    public static void Start() 
    {
        DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
        DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
        bootstrapper.Initialize(CreateKernel);
    }

    /// <summary>
    /// Stops the application.
    /// </summary>
    public static void Stop()
    {
        bootstrapper.ShutDown();
    }

    /// <summary>
    /// Creates the kernel that will manage your application.
    /// </summary>
    /// <returns>The created kernel.</returns>
    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;
    }

    /// <summary>
    /// Load your modules or register your services here!
    /// </summary>
    /// <param name="kernel">The kernel.</param>
    private static void RegisterServices(IKernel kernel)
    {
        kernel.Bind<IConsumerRepository>().To<ConsumerRepository>();
    }        
}

Mein Controller sieht aus wie

   private readonly IConsumerRepository _repository;

    public ConsumerController(IConsumerRepository repository)
    {
        _repository = repository;
    }

    [HttpGet]
    public IQueryable<Consumer> Get(Guid id)
    {
        return _repository.Get(id).AsQueryable();
    }

Was muss ich tun, damit die API-Controller mit ninject arbeiten können?

Entschuldigung, wenn es sich um einfache Sachen handelt

Ich habe deinen Vorschlag Michael jedoch ausprobiert, nachdem ich die webcommon.cs darauf geändert habe

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

        RegisterServices(kernel);
        GlobalConfiguration.Configuration.DependencyResolver = new NinjectDependencyResolver(kernel);
        return kernel;
    }

    /// <summary>
    /// Load your modules or register your services here!
    /// </summary>
    /// <param name="kernel">The kernel.</param>
    private static void RegisterServices(IKernel kernel)
    {
        kernel.Bind<IConsumerRepository>().To<ConsumerRepository>();
    }

Ich bekomme einen Fehler wenn 

var kernel = new StandardKernel();

wird genannt

Die Methode 'GetFilters' vom Typ 'Ninject.Web.WebApi.Filter.DefaultFilterProvider' von Assembly 'Ninject.Web.piA, Version = 3.0.0.0, Culture = neutral, PublicKeyToken = c7192dc5380945e7' hat keine Implementierung.

Was vermisse ich?

36
Diver Dan

Ich fragte Brad Wilson darüber und es hat sich in MVC4 RC geändert.

GlobalConfiguration.Configuration.ServiceResolver wurde in GlobalConfiguration.Configuration.DependencyResolver verschoben.

Verwenden Sie diese Implementierung, um einen Ninject DependencyResolver für Ihre Web-API zu erstellen: https://Gist.github.com/2417226

In NinjectWebCommon.cs:

// Register Dependencies
RegisterServices(kernel);

// Set Web API Resolver
GlobalConfiguration.Configuration.DependencyResolver = new NinjectDependencyResolver(kernel);
60
Michael Baird

Sie können das NuGet-Paket WebApiContrib.IoC.Ninject installieren und die folgende Codezeile zu NinjectWebCommon.cs hinzufügen

GlobalConfiguration.Configuration.DependencyResolver = new NinjectResolver(kernel);
6
Ryan Spears

Diese generische Fehlermeldung

Der Typ 'Api.Controllers.ConsumerController' hat keinen Standardkonstruktor

kann auch vorkommen, wenn Sie Ihren Konstruktor nicht öffentlich machen oder die Abhängigkeit vom IoC-Container möglicherweise aufgrund eines fehlenden Arguments nicht aufgelöst werden kann.

Die Fehlermeldung ist, gelinde gesagt, irreführend.

6
badikumar

Für jemanden, der während der Suche hier landet:

  1. Entfernen Sie vom Konstruktor injizierte Objekte, bis der Konstruktor aufgerufen werden kann
  2. Rufen Sie für jedes zuvor injizierte, jetzt nicht initialisierte Objekt Folgendes auf:

ServiceLocator.Current.GetInstance<[OBJ-TYPE]>()

Das fehlerhafte Objekt verursacht eine ActivationException mit einer beschreibenden Meldung. Sie haben etwas zu tun.

Denken Sie daran, den Aufruf von ServiceLocator nach dem Fix zu entfernen. Dh Dies ist nicht eine Empfehlung, das Service Locator Anti Pattern außerhalb des Debuggens zu verwenden.

1
corolla

Ich weiß, es ist ein alter Beitrag, aber ich habe die Lösung bei einem Link gefunden, der hier geteilt wird. Ich hoffe es hilft.

http://weblogs.asp.net/hajan/archive/2013/03/16/quick-tip-how-to-make-ninject-work-with-asp-net-web-api.aspx?CommentPosted= true # commentmessage

0
Rasshme Chawla

wenn jemand noch Probleme hat, hören Sie bitte auf einen Grund, warum ninject nicht so funktioniert, wie wir es mit mvc 4 erwarten würden 

public DefaultController() : base() { }  

Dadurch wird die Fehlermeldung entfernt, dass kein Standardkonstruktor angegeben ist. Wenn Sie Ihre Daten von der get-Methode abrufen müssen, schreiben Sie diesen Code: 

public IEnumerable<YourModelGoesHere> Get() 
{
    return context.YourData;  
} 

Denken Sie daran, dass Sie auch hier auf Ihre Datenbankklasse zugreifen müssen: 

DefaultConnection context = new DefaultConnection(); 
0
user3247368

Hoffentlich hilft das jemand anderem ...

Ich hatte das gleiche Problem, und es bezog sich darauf, dass ich die Klasse bewegte, die für die Registrierung der für die Initialisierung der Controller zuständigen Assembly zuständig war. Aus dem Web in ein Rahmenprojekt verschoben.

Die Verwendung von Autofac gilt jedoch auch für andere Container.

Hat gerufen:

builder.RegisterApiControllers(Assembly.GetExecutingAssembly());

Das funktioniert gut, wenn es sich innerhalb der Webanwendung befindet, hat aber beim Verschieben in ein Framework-Projekt die Ausnahme geworfen, da die ausführende Assembly die Controller nicht mehr enthält.

Stattdessen musste aktualisiert werden auf:

builder.RegisterApiControllers(Assembly.GetCallingAssembly());
0
timothyclifford

Es scheint, dass Ninject keine Ausnahme ausgelöst hat, wie es im Allgemeinen der Fall ist, wenn Ihre IOC Abhängigkeiten nicht richtig eingerichtet sind. Stattdessen sah es so aus, als hätte ich den WebAPI-Abhängigkeits-Resolver nicht registriert, was ich mit Sicherheit getan habe. Hier war meine Lösung für dieses Problem, aber von dem, was ich festgestellt habe, könnten es VIELE VERSCHIEDENE Arten von Einrichtungsproblemen sein. Überprüfen Sie einfach alles in der Abhängigkeitskette erneut. Hoffentlich hilft es jemandem!

Der Controller:

public class ContestsController : ApiController
{
    //Ninject wouldn't inject this CTOR argument resulting in the error
    public ContestsController(IContestEntryService contestEntryService)
    {

Die Abhängigkeit:

public class ContestEntryService : IContestEntryService
{

    public ContestEntryService(IContestsContext contestsContext)
    {

Die falsche Konfiguration:

    private static void RegisterServices(IKernel kernel)
    {
        kernel.Bind<IContestsContext>()
              .To<ContestsContext>()
              .InRequestScope();

        kernel.Bind(x =>
            x.FromAssembliesMatching("MyNameSpace.*")
             .SelectAllClasses()
             .BindAllInterfaces()
         );

Die richtige Konfiguration:

    private static void RegisterServices(IKernel kernel)
    {
         kernel.Bind(x =>
            x.FromAssembliesMatching("MyNameSpace.*")
             .SelectAllClasses()
             .BindAllInterfaces()
         );

         kernel.ReBind<IContestsContext>()
              .To<ContestsContext>()
              .InRequestScope();

Im Allgemeinen ist Ninject ziemlich gut darin, diese Art von Fehlern zu melden, also habe ich mich wirklich auf eine Schleife gefreut!

0
John Culviner

installieren Sie einfach das Ninject.MvcXXX-Paket, wobei die XXX-Version von MVC ...

0
Andrey Burykin

Ich hatte auch diese Fehlermeldung, aber es stellte sich heraus, dass eines meiner Interfaces nicht von Klassen implementiert wurde (ich habe vergessen, es der Klassendeklaration hinzuzufügen).

0
Mark Cidade

hast du den container beim frawework registriert? Ich bevorzuge autofac, hier ein Beispiel, wie man autofac mit API verwendet. http://alexmg.com/post/2012/03/08/Autofac-ASPNET-Web-API-%28Beta%29-Integration.aspx

Außerdem hat Mark Seeman mit WebAPI einen guten Beitrag zu DI im Allgemeinen

http://blog.ploeh.dk/2012/03/20/RobustDIWithTheASPNETWebAPI.aspx

Von Ploeh: 

GlobalConfiguration.Configuration.ServiceResolver.SetResolver(
    t => this.container.Kernel.HasComponent(t) ?
        this.container.Resolve(t) :
        null,
    t => this.container.ResolveAll(t).Cast<object>());

Das obige muss in global.asax ausgeführt werden 

0
jflood.net