Configurer Ninject avec Asp.Net MVC & Api Web

j'ai mis en place mon projet avec Ninject IoC .

Mon projet a des contrôleurs réguliers Asp.Net MVC et Web Api . Maintenant, Ninject fonctionne avec Web Api mais Ninject ne fonctionne pas avec les contrôleurs réguliers Asp.MVC .

Mon régulier MVC contrôleur "1519240920 la mise en œuvre";

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

erreur lors de l'utilisation avec le contrôleur régulier

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, quand j'essaie le même code avec Api Web, ça marche

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

mon interface qui détient différence des référentiels (le modèle de fabrique)

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

Mondial.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();
}
35
demandé sur DotNet Dreamer 2013-05-05 13:03:40

6 réponses

j'ai écrit quelques gists pour aider à configurer Ninject avec MVC et Api Web. Il suffit d'inclure le(S) fichier (s):

pour ajouter des liants pour les types de béton, il suffit de les mettre dans la méthode Load() du module principal. Vous pouvez Créez autant de modules que vous voulez pour garder les reliures organisées. mais vous devrez aussi les ajouter au tableau qui est retourné dans la propriété Modules .

puis Ajouter à la "méthode 151920920

  • 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 l'ai juste séparé pour clearity

mise à JOUR : n'oubliez pas de Retirer NinjectWebCommon.cs de votre projet car il charge et bootstraps 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)

ceci scannera 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
répondu Ody 2014-07-21 10:18:15

avec MVC 5 et L'API Web 2.2 j'ai résolu ce problème en m'assurant d'inclure les paquets NuGet suivants:

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

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

14
répondu DigitalDan 2015-05-29 17:15:27

après beaucoup de recherches, il s'avère que nous ne pouvons pas utiliser Ninject avec l'api web et mvc régulier. On doit configurer les dépôts séparément.

j'ai alors trouvé un bel article qui explique comment vous pouvez utiliser Ninject avec asp.net MVC & api web: http://www.codeproject.com/Articles/412383/Dependency-Injection-in-asp-net-mvc4-and-webapi-us

et maintenant, je ne comprends pas l'erreur et ça marche: d

mise à Jour 1:

aussi essayer écrire une simple mise en œuvre de l'injection de dépendance dans MVC 4 API Web avec .net Framework 4.5

13
répondu DotNet Dreamer 2016-11-30 09:40:43

Voici la solution simple qui fonctionne très bien pour moi:

  1. dans Visual studio, créez un nouveau projet D'application Web appelé DemoApp et assurez-vous que vous avez sélectionné Empty template avec MVC et les références de L'API Web.: enter image description here
  2. Dans le gestionnaire de paquets de la console exécuter un par un:

    Install-Package Ninject

    Install-Package Ninject.MVC5

  3. Add NinjectDependencyResolver.dossier cs to CIO:

    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. apporter les modifications suivantes À App_Start/NinjectWebCommon.cs:

    • ajouter ces lignes dans la méthode CreateKernel:

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

    • ajouter vos reliures dans Registervices méthode comme:

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

Now 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 que l'exemple soit complet, ajouter quelques MVC et API contrôleurs, et le 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

    Maintenant faire quelques tests dans le navigateur. Pour moi c'était:

    http://localhost:51156/home/index

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

et c'est tout.

4
répondu r23 2016-12-27 03:04:01

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

0
répondu PermaFrost 2013-05-05 09:25:53

il y a une solution plus élégante pour cela par Nenad - il m'a fallu 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. Il s'agit de en réponse à une autre question sur le débordement de la pile . Je reprends ici cette réponse au cas où cela aiderait les autres à sauver le temps que j'ai perdu.


il y a un moyen de partager le même conteneur entre MVC et ASP.NET Web API. Vous avez juste besoin d' mettre en œuvre 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());
       }
   }

voir cet article pour la solution: Moyen Simple de partager de la Dépendance des Résolveurs entre MVC et Web API

0
répondu user3141326 2017-05-23 12:10:35