web-dev-qa-db-fra.com

Configuration de Ninject avec Asp.Net MVC et Web Api

j'ai configuré mon projet avec Ninject IoC.
Mon projet a régulièrement Asp.Net MVC contrôleurs et Web Api contrôleurs. Maintenant, Ninject fonctionne avec Web Api mais Ninject ne fonctionne pas avec le Asp.MVC contrôleurs.
Mon contrôleur MVC standard implémentation;

public class GalleryController : BaseController
{
    public GalleryController(IUow uow)
    {
        Uow = uow;
    }
    ........
}

Erreur lors de l'utilisation avec un contrôleur standard

An error occurred when trying to create a controller of type 'Web.Controllers.HomeController'. Make sure that the controller has a parameterless public constructor.]

Cependant, lorsque j'essaie le même code avec Web Api, cela fonctionne

public class GalleryController : BaseApiController
{
    public GalleryController(IUow uow)
    {
        Uow = uow;
    }
    ......
}

mon interface qui contient les référentiels de différences (le modèle d'usine)

public interface IUow
{
    // Save pending changes to the data store.
    void Commit();

    //Repositoryries
    IRepository<Gallery> Gallery { get; }
    IMenuRepository Menus { get; }
}

NinjectDependencyScope classe;

public class NinjectDependencyScope : IDependencyScope
{
    private IResolutionRoot resolver;

    internal NinjectDependencyScope(IResolutionRoot resolver)
    {
        Contract.Assert(resolver != null);

        this.resolver = resolver;
    }

    public void Dispose()
    {
        var disposable = resolver as IDisposable;
        if (disposable != null)
            disposable.Dispose();

        resolver = null;
    }

    public object GetService(Type serviceType)
    {
        if (resolver == null)
            throw new ObjectDisposedException("this", "This scope has already been disposed");

        return resolver.TryGet(serviceType);
    }

    public IEnumerable<object> GetServices(Type serviceType)
    {
        if (resolver == null)
            throw new ObjectDisposedException("this", "This scope has already been disposed");

        return resolver.GetAll(serviceType);
    }
}

NinjectDependencyResolver classe;

public class NinjectDependencyResolver : NinjectDependencyScope, IDependencyResolver
{
    private IKernel kernel;

    public NinjectDependencyResolver(IKernel kernel)
        : base(kernel)
    {
        this.kernel = kernel;
    }

    public IDependencyScope BeginScope()
    {
        return new NinjectDependencyScope(kernel.BeginBlock());
    }
}

Ninject configuration pour Global.asax;

public class IocConfig
{
    public static void RegisterIoc(HttpConfiguration config)
    {
        var kernel = new StandardKernel(); // Ninject IoC
        //kernel.Load(Assembly.GetExecutingAssembly()); //only required for asp.net mvc (not for webapi)
        // These registrations are "per instance request".
        // See http://blog.bobcravens.com/2010/03/ninject-life-cycle-management-or-scoping/

        kernel.Bind<RepositoryFactories>().To<RepositoryFactories>()
            .InSingletonScope();

        kernel.Bind<IRepositoryProvider>().To<RepositoryProvider>();
        kernel.Bind<IUow>().To<Uow>();

        // Tell WebApi how to use our Ninject IoC
        config.DependencyResolver = new NinjectDependencyResolver(kernel);
    }
}

Global.asax

protected void Application_Start()
{

    // Tell WebApi to use our custom Ioc (Ninject)
    IocConfig.RegisterIoc(GlobalConfiguration.Configuration);
    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
    RouteConfig.RegisterRoutes(RouteTable.Routes);
    BundleConfig.RegisterBundles(BundleTable.Bundles);

    GlobalConfig.CustomizeConfig(GlobalConfiguration.Configuration);
    AreaRegistration.RegisterAllAreas();
}
37
DotNet Dreamer

Après beaucoup de recherches, il s'avère que nous ne pouvons pas utiliser Ninject avec l'API Web et le MVC standard. Je veux dire, nous devons configurer les référentiels séparément.

J'ai ensuite trouvé un article sympa qui explique comment utiliser Ninject avec asp.net mvc & web api: http://www.codeproject.com/Articles/412383/Dependency-Injection-in-asp-net- mvc4-et-webapi-us

Et maintenant, je ne reçois pas l'erreur et ça fonctionne: D

Mise à jour 1:

Essayez également Écriture d'une implémentation simple de l'injection de dépendance dans MVC 4 Web API avec .NET Framework 4.5

13
DotNet Dreamer

J'ai écrit quelques informations essentielles pour aider à configurer Ninject avec MVC et Web Api. Incluez simplement le ou les fichiers:

Pour ajouter des liaisons pour des types concrets, placez-les simplement dans la méthode Load() du MainModule. Vous pouvez créer autant de modules que vous le souhaitez pour organiser les liaisons. mais vous devrez également les ajouter au tableau renvoyé dans la propriété Modules.

Ensuite, ajoutez à la méthode Application_Start()

  • NinjectContainer.RegisterModules(NinjectModules.Modules) (pour MVC)
  • NinjectHttpContainer.RegisterModules(NinjectHttpModules.Modules) (pour WebApi)

Notez que vous pouvez utiliser le même NinjectModules.Modules Pour l'enregistrement MVC et WebApi. Je viens de le séparer pour plus de clarté

[~ # ~] mise à jour [~ # ~] : N'oubliez pas de supprimer NinjectWebCommon.cs de votre projet pendant qu'il charge et amorce un nouveau noyau à l'exécution qui n'est malheureusement que pour MVC.

[~ # ~] mise à jour [~ # ~] : vous pouvez également utiliser

  • NinjectContainer.RegisterAssembly() (pour MVC)
  • NinjectHttpContainer.RegisterAssembly() (pour WebApi)

Cela analysera votre assemblage actuel pour tous les modules. De cette façon, vous pouvez placer vos modules n'importe où dans votre projet et il sera enregistré

34
Ody

Avec MVC 5 et Web API 2.2, j'ai résolu ce problème en m'assurant d'avoir inclus les packages NuGet suivants:

  • Ninject.MVC5
  • Ninject.Web.WebApi.WebHost pour l'API Web

Cela a installé d'autres dépendances Ninject et m'a permis de RegisterServices à NinjectWebCommon.cs.

15
DigitalDan

Voici la solution simple qui me convient:

  1. Dans Visual studio, créez un nouveau projet d'application Web nommé DemoApp et assurez-vous que vous avez sélectionné un modèle vide avec des références MVC et API Web: enter image description here
  2. Dans la console du gestionnaire de packages, exécutez-les un par un:

    Install-Package Ninject

    Install-Package Ninject.MVC5

  3. Ajoutez NinjectDependencyResolver.cs au dossier IoC:

    using Ninject;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Http.Dependencies;
    
    namespace DemoApp.IoC
    {
        public class NinjectDependencyResolver : IDependencyResolver, System.Web.Mvc.IDependencyResolver
        {
            private readonly IKernel kernel;
    
            public NinjectDependencyResolver(IKernel kernel)
            {
                this.kernel = kernel;
            }
    
            public IDependencyScope BeginScope()
            {
                return this;
            }
    
            public object GetService(Type serviceType)
            {
                return kernel.TryGet(serviceType);
            }
    
            public IEnumerable<object> GetServices(Type serviceType)
            {
                return kernel.GetAll(serviceType);
            }
    
            public void Dispose() { } //it is not necessary to implement any dispose logic here
        }
    }
    
  4. Apportez les modifications suivantes dans App_Start/NinjectWebCommon.cs:

    • Ajoutez ces lignes dans la méthode CreateKernel:

      NinjectDependencyResolver ninjectResolver = new NinjectDependencyResolver (noyau); DependencyResolver.SetResolver (ninjectResolver); // MVC GlobalConfiguration.Configuration.DependencyResolver = ninjectResolver; // API Web

    • Ajoutez vos liaisons dans la méthode RegisterServices comme:

      kernel.Bind <IHelloService> (). To <HelloService> ();

Maintenant, NinjectWebCommon.cs devrait ressembler à:

[Assembly: WebActivatorEx.PreApplicationStartMethod(typeof(DemoApp.App_Start.NinjectWebCommon), "Start")]
[Assembly: WebActivatorEx.ApplicationShutdownMethodAttribute(typeof(DemoApp.App_Start.NinjectWebCommon), "Stop")]

namespace DemoApp.App_Start
{
    using System;
    using System.Web;

    using Microsoft.Web.Infrastructure.DynamicModuleHelper;

    using Ninject;
    using Ninject.Web.Common;
    using DemoApp.IoC;
    using System.Web.Mvc;
    using System.Web.Http;
    using DemoApp.Config;

    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();
            try
            {
                kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
                kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();

                RegisterServices(kernel);

                NinjectDependencyResolver ninjectResolver = new NinjectDependencyResolver(kernel);
                DependencyResolver.SetResolver(ninjectResolver); //MVC
                GlobalConfiguration.Configuration.DependencyResolver = ninjectResolver; //Web API

                return kernel;
            }
            catch
            {
                kernel.Dispose();
                throw;
            }
        }

        /// <summary>
        /// Load your modules or register your services here!
        /// </summary>
        /// <param name="kernel">The kernel.</param>
        private static void RegisterServices(IKernel kernel)
        {
            kernel.Bind<IHelloService>().To<HelloService>();
        }        
    }
}
  1. Juste pour l'exhaustivité de l'exemple, ajoutez des contrôleurs Mvc et Api et du code pour IHelloService, HelloService:

HomeController.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using DemoApp.Config;
namespace DemoApp.Controllers
{
    public class HomeController : Controller
    {
        private IHelloService helloService;

        public HomeController(IHelloService helloService)
        {
            this.helloService = helloService;
        }

        // GET: /Home/
        public string Index()
        {
            return "home/index: " + helloService.GetMessage();
        }
    }
}

UserController.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Http;
using DemoApp.Config;
namespace DemoApp.Controllers
{
    public class UserController : ApiController
    {
        private IHelloService helloService;

        public UserController(IHelloService helloService)
        {
            this.helloService = helloService;
        }

        [HttpGet]
        public string Data()
        {
            return "api/user/data: " + helloService.GetMessage();
        }
    }
}

IHelloService.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace DemoApp.Config
{
    public interface IHelloService
    {
       string GetMessage();
    }
}

HelloService.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace DemoApp.Config
{
    public class HelloService : IHelloService
    {
        public string GetMessage()
        {
            return "Hi";
        }
    }
}
  1. La structure finale devrait ressembler à: enter image description here

    Faites maintenant quelques tests dans le navigateur. Pour moi, c'était:

    http: // localhost: 51156/home/index

    http: // localhost: 51156/api/user/data

Et c'est tout.

6
r23

Je pense que le problème est que vous n'enregistrez pas un ControllerFactory qui utilise Ninject pour construire les contrôleurs (et résoudre leurs dépendances), avez-vous déjà essayé d'implémenter votre propre ControllerFactory? Voir aussi ici http://bubblogging.wordpress.com/2012/06/04/mvc-controller-factory-ninject/ .

0
PermaFrost

Il y a une solution plus élégante pour cela par Nenad - cela m'a pris 3 heures supplémentaires parce que j'ai d'abord essayé de mettre en œuvre les solutions ici en conflit avec l'infrastructure existante que j'avais. C'est en réponse à une autre question de débordement de pile . Je reproduis cette réponse ici au cas où cela aiderait les autres à gagner du temps.


Il existe un moyen de partager le même conteneur entre MVC et l'API Web ASP.NET. Vous avez juste besoin d'implémenter les deux interfaces.

public class NinjectDependencyResolver : NinjectDependencyScope, IDependencyResolver, System.Web.Mvc.IDependencyResolver
   {
       private readonly IKernel kernel;

       public NinjectDependencyResolver(IKernel kernel)
           : base(kernel)
       {
           this.kernel = kernel;
       }

       public IDependencyScope BeginScope()
       {
           return new NinjectDependencyScope(this.kernel.BeginBlock());
       }
   }

Consultez cet article pour trouver une solution: moyen simple de partager des résolveurs de dépendances entre MVC et l'API Web

0
user3141326