c# - ninjectwebcommon - Ninject en ASP.NET MVC4
ninject mvc example (8)
Cuando instale el último Ninject.MVC3 del paquete NuGet, encontramos el siguiente código en la parte superior del archivo NinjectWebCommon.cs
:
[assembly: WebActivator.PreApplicationStartMethod(typeof(MvcApplication1.App_Start.NinjectWebCommon), "Start")]
[assembly: WebActivator.ApplicationShutdownMethodAttribute(typeof(MvcApplication1.App_Start.NinjectWebCommon), "Stop")]
en este caso no necesitamos registrar ninject explícitamente en global.asax
Encontré un buen contenido sobre el uso de Ninject con MVC 4 here
Así que después de mucho atornillar, finalmente conecté Ninject y compilé mi aplicación MVC4. El problema que estaba encontrando es que la interfaz IDependencyScope ya no existe por lo que puedo decir y el espacio de nombres System.Web.Http.Dependencies se eliminó.
Entonces, mi problema ahora es que tengo todo conectado y, al ejecutar la aplicación, recibo:
Sequence contains no elements
[InvalidOperationException: Sequence contains no elements]
System.Linq.Enumerable.Single(IEnumerable`1 source) +379
Ninject.Web.Mvc.NinjectMvcHttpApplicationPlugin.Start() in c:/Projects/Ninject/ninject.web.mvc/mvc3/src/Ninject.Web.Mvc/NinjectMvcHttpApplicationPlugin.cs:53
Ninject.Web.Common.Bootstrapper.<Initialize>b__0(INinjectHttpApplicationPlugin c) in c:/Projects/Ninject/Ninject.Web.Common/src/Ninject.Web.Common/Bootstrapper.cs:52
Ninject.Infrastructure.Language.ExtensionsForIEnumerableOfT.Map(IEnumerable`1 series, Action`1 action) in c:/Projects/Ninject/ninject/src/Ninject/Infrastructure/Language/ExtensionsForIEnumerableOfT.cs:31
Ninject.Web.Common.Bootstrapper.Initialize(Func`1 createKernelCallback) in c:/Projects/Ninject/Ninject.Web.Common/src/Ninject.Web.Common/Bootstrapper.cs:53
Ninject.Web.Common.NinjectHttpApplication.Application_Start() in c:/Projects/Ninject/Ninject.Web.Common/src/Ninject.Web.Common/NinjectHttpApplication.cs:81
Lo cual no he podido rastrear o incluso comenzar a entender de dónde viene.
Mis métodos estándar de Ninject dentro de Global.asax.cs tienen el siguiente aspecto:
protected override IKernel CreateKernel()
{
var kernel = new StandardKernel();
kernel.Load(Assembly.GetExecutingAssembly());
kernel.Bind<IRenderHelper>().To<RenderHelper>();
GlobalConfiguration.Configuration.ServiceResolver.SetResolver(new NinjectDependencyResolver(kernel));
return kernel;
}
protected override void OnApplicationStarted()
{
base.OnApplicationStarted();
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
BundleTable.Bundles.RegisterTemplateBundles();
}
Y mi resolución personalizada:
public class NinjectDependencyResolver : IDependencyResolver
{
private readonly IKernel _kernel;
public NinjectDependencyResolver(IKernel kernel)
{
_kernel = kernel;
}
public object GetService(Type serviceType)
{
return _kernel.TryGet(serviceType);
}
public IEnumerable<object> GetServices(Type serviceType)
{
try
{
return _kernel.GetAll(serviceType);
}
catch (Exception)
{
return new List<object>();
}
}
public void Dispose()
{
// When BeginScope returns ''this'', the Dispose method must be a no-op.
}
}
Cualquier idea aquí sería muy apreciada. Ya pasé demasiado tiempo intentando que cualquier marco DI esté conectado al último MVC4 RC que se ejecuta en .NET 4.5 y acabo de alcanzar mi nivel de tolerancia para cosas que simplemente no funcionan.
Edit # 1 Un poco más de investigación investigando en github ExtensionsForIEnumerableOfT.cs no ayuda mucho:
Y posiblemente si lo hubiera escrito yo mismo, comenzaría a entender esto, pero Bootstrapper.cs tampoco ayuda demasiado.
https://github.com/ninject/Ninject.Web.Common/blob/master/src/Ninject.Web.Common/Bootstrapper.cs
Esperar estos detalles hará que sea más fácil para cualquiera de ustedes que pueda tener más experiencia con Ninject.
Edit # 2 El error encontrado está específicamente en NinjectMvcHttpApplicationPlugin.cs:
La línea ofensiva es:
ModelValidatorProviders.Providers.Remove(ModelValidatorProviders.Providers.OfType<DataAnnotationsModelValidatorProvider>().Single());
Que vive en el siguiente método:
public void Start()
{
ModelValidatorProviders.Providers.Remove(ModelValidatorProviders.Providers.OfType<DataAnnotationsModelValidatorProvider>().Single());
DependencyResolver.SetResolver(this.CreateDependencyResolver());
RemoveDefaultAttributeFilterProvider();
}
La colección ModelValidatorProviders contiene 2 elementos: {System.Web.Mvc.DataErrorInfoModelValidatorProvider} {System.Web.Mvc.ClientDataTypeModelValidatorProvider}
Y está tratando de eliminar una sola instancia de:
System.Web.Mvc.DataAnnotationsModelValidatorProvider
Que aparentemente no está cargado en la colección ModelValidationProviders.Providers. ¿Alguna idea de aquí?
Resolución de la excepción anterior y en la siguiente
Para resolver el problema en ModelValidatorProviders tuve que agregar manualmente un objeto que estaba esperando. Así que ahora mi método CreateKernel parece:
protected override IKernel CreateKernel()
{
var kernel = new StandardKernel();
kernel.Load(Assembly.GetExecutingAssembly());
kernel.Bind<IRenderHelper>().To<RenderHelper>();
kernel.Unbind<IDocumentViewerAdapter>();
GlobalConfiguration.Configuration.ServiceResolver.SetResolver(new NinjectDependencyResolver(kernel));
ModelValidatorProviders.Providers.Add(new DataAnnotationsModelValidatorProvider());
FilterProviders.Providers.Add(new FilterAttributeFilterProvider());
return kernel;
}
Ahora se ejecuta y se adentra en las entrañas reales de Ninject pero todavía tiene un problema, uno que no tiene sentido una vez más:
Exception Details: Ninject.ActivationException: Error activating IntPtr
No matching bindings are available, and the type is not self-bindable.
Activation path:
3) Injection of dependency IntPtr into parameter method of constructor of type Func{IKernel}
2) Injection of dependency Func{IKernel} into parameter lazyKernel of constructor of type HttpApplicationInitializationHttpModule
1) Request for IHttpModule
Suggestions:
1) Ensure that you have defined a binding for IntPtr.
2) If the binding was defined in a module, ensure that the module has been loaded into the kernel.
3) Ensure you have not accidentally created more than one kernel.
4) If you are using constructor arguments, ensure that the parameter name matches the constructors parameter name.
5) If you are using automatic module loading, ensure the search path and filters are correct.
Echa un vistazo al libro Pro ASP.NET MVC 3 . Acabo de portar este código de MVC3 a MVC4 anoche y funciona correctamente. Página 322 para ser exactos.
Lo que no veo es dónde está asignando su Interfaz a sus elementos concretos.
Bind<ISomething>().To<Something>();
Agregue otro constructor y agregue el método que llama a su asignación;
public NinjectDependencyResolver() {
_kernal = new StandardKernel();
RegisterServices(_kernel);
}
public static void RegisterServices(IKernel kernel) {
kernel.Bind<ISomething>().To<Something>();
}
Esto es lo que podría / debería parecer un resolutor;
public class NinjectDependencyResolver : IDependencyResolver {
private IKernal _kernel;
public NinjectDependencyResolver(){
_kernal = StandardKernal();
AddBindings();
}
public NinjectDependencyResolver(IKernel kernel)
{
_kernel = kernel;
}
public object GetService(Type serviceType)
{
return _kernel.TryGet(serviceType);
}
public IEnumerable<object> GetServices(Type serviceType)
{
return _kernal.GetAll(serviceType);
}
public IBindingToSyntax<T> Bind<T>() {
return _kernal.Bind<T>();
}
public static void RegisterServices(IKernel kernel){
//Add your bindings here.
//This is static as you can use it for WebApi by passing it the IKernel
}
}
Global.Asx -
Inicio de aplicación ()
método
DependencyResolver.SetResolver(new NinjectDependencyResolver());
Eso es.
ACTUALIZADO 14/11/2012
En una nota al margen, si está trabajando con MVC WebAPI, deseará usar WebApiContrib.IoC.Ninject de nuget. Además, consulte el "Administrador de contactos" en sus ejemplos asp.net.com . Esto ayudó a limpiar la implementación de Ninject.
Estoy usando DD4T, y encontré el mismo error.
Después de confirmar que todos los paquetes están instalados por el administrador de paquetes de nuget, encontré que faltaban algunas de las DLL / referencias (newtonsoft, etc.):
Luego, después de reinstalar Newtonsoft.Json (para reinstalar el paquete use el siguiente comando en Nuget Package Manager: Update-Package –reinstalar Newtonsoft.Json), y poner netrtsn.dll desde la bandeja de Tridion Deployer, obtuve este error - "Secuencia no contiene elementos "con exactamente el mismo seguimiento de pila que se indica en esta pregunta.
Gracias a Naga, por proporcionar esta resolución, se eliminó NinjectWebCommon.cs (el archivo generado, ya que la integración ya existe en el archivo global.ascx.cs), y wohooooo !!!! todos los errores resueltos, Tridion + MVC4 = DD4T se está ejecutando bien ahora.
Me he encontrado con el mismo problema no muy seguro de lo que se ha solucionado después de los cambios a continuación
agregado Ninject.MVC4 al proyecto
NinjectWebCommon.cs eliminado (el archivo generado, ya que la integración ya existe en el archivo global.ascx.cs)
Ok, después de golpear mi cabeza contra la pared durante demasiado tiempo, me di cuenta de lo que estaba pasando. El tipo de proyecto predeterminado para MVC4 que se ejecuta en .NET 4.5 tenía una referencia a la versión RC original de System.Web.Http en lugar de la versión actualizada.
Faltaban espacios de nombres, no existían objetos, la vida no era buena.
Pasos para la resolución:
- Elimine su referencia a System.Web.Http en su proyecto MVC4
- Añadir referencia -> System.Web.Http
- Elimine todas las áreas de trabajo que haya puesto para que funcione la versión antigua de basura de System.Web.Http
Vuelva a aplicar el proceso estándar para cablear en Ninject.
SIN EMBARGO, el error de:
Detalles de la excepción: Ninject.ActivationException: Error al activar IntPtr No hay enlaces coincidentes disponibles, y el tipo no es auto-vinculable. Ruta de activación: 3) Inyección de la dependencia IntPtr en el método de parámetro del constructor de tipo Func {IKernel} 2) Inyección de la dependencia Func {IKernel} en el parámetro lazyKernel del constructor de tipo HttpApplicationInitializationHttpModule 1) Solicitud de IHttpModule
Sugerencias: 1) Asegúrese de haber definido un enlace para IntPtr. 2) Si el enlace se definió en un módulo, asegúrese de que el módulo se haya cargado en el kernel. 3) Asegúrese de no haber creado accidentalmente más de un kernel. 4) Si está utilizando argumentos de constructor, asegúrese de que el nombre del parámetro coincida con el nombre del parámetro del constructor. 5) Si está utilizando la carga automática de módulos, asegúrese de que la ruta de búsqueda y los filtros sean correctos.
Actualización Esto se resolvió actualizando MVC de MVC4 Beta a MVC4 RC.
Simplemente elimine el archivo NinjectWebCommon.cs
de su proyecto (está en la carpeta App_Start
). y todo debería estar funcionando.
Fuente: http://mlindev.blogspot.com.au/2012/09/how-to-implement-dependency-injection.html
También tuve este problema cuando usé nuget para instalar Ninject.MVC4 en un proyecto al que hace referencia mi proyecto de sitio web MVC real.
El problema es que el archivo NinjectWebCommon.cs instalado automáticamente en el directorio App_Start del proyecto al que se hace referencia entra en conflicto con el archivo (real, útil) instalado en el proyecto de mi sitio web. La eliminación del archivo NinjectWebCommon.cs del proyecto al que se hace referencia resuelve el error.
Tiendo a mantener mi arranque de Ninject en un proyecto separado. Para utilizar el método de extensión .InRequestScope()
de IBindingInSyntax<T>
, había agregado a través de la biblioteca Nuget the Ninject.Web.Common . Por desgracia, esta biblioteca incluye el bootstrapper app_start, lo que da como resultado clases y adjuntos de NinjectWebCommon duplicados a través de WebActivator (1 en dicho proyecto y 1 en el propio proyecto MVC).
Eliminé la carpeta duplicada App_Start de mi proyecto bootstrap, y esto lo resolvió.