Enlace de API web ASP.NET con ninject

Acabo de instalar la actualización de mvc4 rc y estoy intentando construir una aplicación api con poca suerte.

Estoy usando ninject pero no puedo hacer que mis controladores se carguen. Sigo recibiendo un error

El tipo ‘Api.Controllers.ConsumerController’ no tiene un constructor predeterminado

Soy muy nuevo en mvc y estoy usando inyección, así que tenga paciencia.

No he hecho nada especial para el enlace predeterminado que se crea a través de nuget

public static class NinjectWebCommon { private static readonly Bootstrapper bootstrapper = new Bootstrapper(); ///  /// Starts the application ///  public static void Start() { DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule)); DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule)); bootstrapper.Initialize(CreateKernel); } ///  /// Stops the application. ///  public static void Stop() { bootstrapper.ShutDown(); } ///  /// Creates the kernel that will manage your application. ///  /// The created kernel. private static IKernel CreateKernel() { var kernel = new StandardKernel(); kernel.Bind<Func>().ToMethod(ctx => () => new Bootstrapper().Kernel); kernel.Bind().To(); RegisterServices(kernel); return kernel; } ///  /// Load your modules or register your services here! ///  /// The kernel. private static void RegisterServices(IKernel kernel) { kernel.Bind().To(); } } 

Mi controlador se ve como

  private readonly IConsumerRepository _repository; public ConsumerController(IConsumerRepository repository) { _repository = repository; } [HttpGet] public IQueryable Get(Guid id) { return _repository.Get(id).AsQueryable(); } 

¿Qué debo hacer para que los controladores api funcionen con ninject?

Lo siento si esto es algo simple.

Intenté tu sugerencia de Michael, sin embargo, después de cambiar el webcommon.cs a este

  private static IKernel CreateKernel() { var kernel = new StandardKernel(); kernel.Bind<Func>().ToMethod(ctx => () => new Bootstrapper().Kernel); kernel.Bind().To(); RegisterServices(kernel); GlobalConfiguration.Configuration.DependencyResolver = new NinjectDependencyResolver(kernel); return kernel; } ///  /// Load your modules or register your services here! ///  /// The kernel. private static void RegisterServices(IKernel kernel) { kernel.Bind().To(); } 

Me sale un error cuando

 var kernel = new StandardKernel(); 

se llama

El método ‘GetFilters’ en el tipo ‘Ninject.Web.WebApi.Filter.DefaultFilterProvider’ del ensamblado ‘Ninject.Web.WebApi, Version = 3.0.0.0, Culture = neutral, PublicKeyToken = c7192dc5380945e7’ no tiene una implementación.

¿Qué me estoy perdiendo?

Le pregunté a Brad Wilson acerca de esto y ha cambiado en MVC4 RC.

GlobalConfiguration.Configuration.ServiceResolver se ha movido a GlobalConfiguration.Configuration.DependencyResolver

Use esta implementación para crear un Ninject DependencyResolver para su Web Api: https://gist.github.com/2417226

En NinjectWebCommon.cs :

 // Register Dependencies RegisterServices(kernel); // Set Web API Resolver GlobalConfiguration.Configuration.DependencyResolver = new NinjectDependencyResolver(kernel); 

Este mensaje de error genérico

El tipo ‘Api.Controllers.ConsumerController’ no tiene un constructor predeterminado

también puede ocurrir si no hace que su constructor sea público, o la dependencia no puede ser resuelta por el contenedor IoC tal vez debido a un argumento faltante.

El mensaje de error es engañoso por decir lo menos.

Puede instalar el paquete NuGet WebApiContrib.IoC.Ninject y agregar la siguiente línea de código a NinjectWebCommon.cs

 GlobalConfiguration.Configuration.DependencyResolver = new NinjectResolver(kernel); 

Para alguien que aterriza aquí mientras busca ‘… no tiene un constructor predeterminado’ que busca una manera fácil de depurar configuraciones que fallan silenciosamente:

  1. Eliminar los objetos inyectados por el constructor hasta que se pueda invocar al constructor
  2. Para cada uno de los objetos previamente inyectados, ahora sin inicializar, invoque usando:

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

El objeto infractor causará una excepción de activación con un mensaje descriptivo. Tendrás algo para lo que ir.

Recuerde eliminar la llamada a ServiceLocator post-fix. Es decir. esta no es una recomendación para usar el localizador de servicios anti patrón fuera de la depuración.

¿Has registrado el contenedor con el frawework? Prefiero usar autofac, aquí hay un ejemplo de cómo usar autofac con API. http://alexmg.com/post/2012/03/08/Autofac-ASPNET-Web-API-%28Beta%29-Integration.aspx

Además, Mark Seeman tiene un buen post en DI en general con WebAPI

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

De Ploeh:

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

Lo anterior tiene que ser realizado en el global.asax.

Esperemos que esto ayude a alguien más …

Tenía el mismo problema y estaba relacionado con mi clase de movimiento responsable de registrar el ensamblaje a cargo de la inicialización de los controladores. Se mudó de la web al proyecto marco.

Usando Autofac pero lo mismo se aplicaría para otros contenedores.

Estaba llamando:

 builder.RegisterApiControllers(Assembly.GetExecutingAssembly()); 

Lo que funciona bien cuando está dentro de la aplicación web, pero arrojó la excepción anterior cuando se movió al proyecto del marco, ya que el ensamblaje en ejecución ya no contiene los controladores.

En su lugar tuvo que actualizar a:

 builder.RegisterApiControllers(Assembly.GetCallingAssembly()); 

Parece que Ninject no lanzó una excepción como generalmente lo hace cuando las dependencias de IOC no están bien configuradas. En su lugar, parecía que no había registrado la resolución de dependencias WebAPI, lo que ciertamente hice. Aquí estaba mi solución a este problema pero, por lo que he encontrado, podría haber MUCHOS TIPOS DIFERENTES de problemas de configuración. Solo vuelve a revisar todo en la cadena de dependencia. Esperemos que ayude a alguien!

El controlador:

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

La dependencia:

 public class ContestEntryService : IContestEntryService { public ContestEntryService(IContestsContext contestsContext) { 

La configuración incorrecta:

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

La configuración correcta:

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

En general, Ninject es bastante bueno al reportar este tipo de errores, ¡así que realmente me echaron a rodar en este caso!

Sé que es una publicación antigua, pero encontré la solución en algún enlace, así que la comparto aquí. Espero eso ayude.

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

Si alguien sigue teniendo problemas, escuche por alguna razón. ninject no funciona como esperábamos con mvc 4. En su api web, debe escribir este código

 public DefaultController() : base() { } 

Esto elimina el error que dice que no hay un constructor predeterminado, luego, cuando necesite obtener sus datos del método get, escriba este código:

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

Tenga en cuenta que también tendrá que acceder a su clase de db aquí, por ejemplo:

 DefaultConnection context = new DefaultConnection(); 

simplemente instale el paquete Ninject.MvcXXX, donde XXX – versión de MVC …

También tuve este mensaje de error, pero resultó que una de mis interfaces no estaba implementada por ninguna clase (olvidé agregarla a la statement de la clase).