tag pagina net mvc establecer asp asp.net asp.net-mvc dependency-injection ninject repository-pattern

asp.net - net - establecer pagina principal mvc



Configurando Ninject con Asp.Net MVC y Web Api (6)

configuré mi proyecto con Ninject IoC .
Mi proyecto tiene controladores Asp.Net MVC regulares y controladores Web Api . Ahora, Ninject funciona con Web Api pero Ninject no funciona con controladores Asp.MVC regulares.
Mi implementación regular de controlador MVC ;

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

Error cuando se usa con un controlador regular

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

Sin embargo, cuando intento el mismo código con Web Api, funciona

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

mi interfaz que contiene repositorios de diferencias (el patrón de fábrica)

public interface IUow { // Save pending changes to the data store. void Commit(); //Repositoryries IRepository<Gallery> Gallery { get; } IMenuRepository Menus { get; } }

Clase NinjectDependencyScope ;

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

Clase NinjectDependencyResolver ;

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

Configuración de Ninject para 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(); }



He escrito algunas ideas para ayudarme a configurar Ninject con MVC y Web Api. Simplemente incluya el archivo (s):

Para agregar enlaces para tipos concretos, simplemente colóquelos en el método Load() del MainModule. Puede crear tantos módulos como quiera para mantener organizadas las encuadernaciones. pero también deberá agregarlos a la matriz que se devuelve en la propiedad Modules .

A continuación, agregue al método Application_Start()

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

Tenga en cuenta que puede usar los mismos NinjectModules.Modules para el registro MVC y WebApi. Simplemente lo separé por claridad

ACTUALIZACIÓN : recuerde eliminar NinjectWebCommon.cs de su proyecto mientras se carga y arranca un nuevo kernel en Runtime, que desafortunadamente es solo para MVC.

ACTUALIZACIÓN : también puede usar

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

Esto escaneará su ensamblaje actual para todos los módulos. De esta forma puedes poner tus módulos en cualquier lugar de tu proyecto y se registrarán


Con MVC 5 y Web API 2.2 resolví este problema asegurándome de haber incluido los siguientes paquetes NuGet:

  • Ninject.MVC5
  • Ninject.Web.WebApi.WebHost para la API web

Esto instaló otras dependencias Ninject y me permitió RegisterServices través de NinjectWebCommon.cs .


Después de buscar mucho, resulta que no podemos usar Ninject con la API web y el mvc normal. Quiero decir, tenemos que configurar los repositorios por separado.

Luego encontré un buen artículo que explica cómo puedes usar Ninject con asp.net mvc y web api: http://www.codeproject.com/Articles/412383/Dependency-Injection-in-asp-net-mvc4-and- webapi-us

Y ahora, no entiendo el error y funciona: D

Actualización 1:

También intente escribir una implementación simple de inyección de dependencia en MVC 4 Web API con .NET Framework 4.5


Aquí está la solución simple que funciona bien para mí:

  1. En Visual Studio, cree un nuevo proyecto de aplicación web llamado DemoApp y asegúrese de haber seleccionado Plantilla vacía con referencias de MVC y Web API:
  2. En la consola del administrador de paquetes, ejecute uno por uno:

    Install-Package Ninject

    Install-Package Ninject.MVC5

  3. Agregue NinjectDependencyResolver.cs a la carpeta 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. Realice los siguientes cambios en App_Start / NinjectWebCommon.cs:

    • Agregue estas líneas en el método CreateKernel:

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

    • Agregue sus enlaces en el método RegisterServices como:

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

Ahora NinjectWebCommon.cs debería verse así:

[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. Solo por la integridad del ejemplo, agregue algunos controladores Mvc y Api, y codifique 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 estructura final debería verse así:

    Ahora haz algunas pruebas en el navegador. Para mí fue:

    http: // localhost: 51156 / home / index

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

Y eso es.


Hay una solución más elegante para esto por Nenad: me llevó 3 horas adicionales porque primero intenté implementar las soluciones aquí en conflicto con la infraestructura existente que tenía. Es en respuesta a otra pregunta de desbordamiento de pila . Estoy duplicando esa respuesta aquí en caso de que ayude a otros a ahorrar el tiempo que perdí.

Hay una forma de compartir el mismo contenedor entre MVC y ASP.NET Web API. Solo necesita implementar ambas 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()); } }

Verifique la solución en este artículo: forma sencilla de compartir los resutados de dependencias entre MVC y la API web