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();
}
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
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é
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 WebCela a installé d'autres dépendances Ninject et m'a permis de RegisterServices
à NinjectWebCommon.cs
.
Voici la solution simple qui me convient:
Dans la console du gestionnaire de packages, exécutez-les un par un:
Install-Package Ninject
Install-Package Ninject.MVC5
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
}
}
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>();
}
}
}
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";
}
}
}
La structure finale devrait ressembler à:
Faites maintenant quelques tests dans le navigateur. Pour moi, c'était:
Et c'est tout.
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/ .
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