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();
}
Creo que el problema es que no estás registrando un ControllerFactory que usa Ninject para construir los controladores (y resolver sus dependencias), ¿has intentado implementar tu propio ControllerFactory? Consulte también aquí http://bubblogging.wordpress.com/2012/06/04/mvc-controller-factory-ninject/ .
He escrito algunas ideas para ayudarme a configurar Ninject con MVC y Web Api. Simplemente incluya el archivo (s):
- https://gist.github.com/odytrice/5821087 (para MVC)
- https://gist.github.com/odytrice/5842010 (para WebApi)
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í:
- 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:
En la consola del administrador de paquetes, ejecute uno por uno:
Install-Package Ninject
Install-Package Ninject.MVC5
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 } }
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>();
}
}
}
- 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";
}
}
}
La estructura final debería verse así:
Ahora haz algunas pruebas en el navegador. Para mí fue:
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