c# - Ninject+MVC3 no está inyectando en el controlador
asp.net asp.net-mvc-3 (3)
He usado la extensión NuGet Ninject MVC3 y no he podido hacer que se inyecte en un controlador a pedido. Parece que no tiene límite, ya que MVC está buscando el constructor paramaterless. Aquí está el rastro de la pila:
[MissingMethodException: No parameterless constructor defined for this object.]
System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck) +0
System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache) +98
System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipVisibilityChecks, Boolean skipCheckThis, Boolean fillCache) +241
System.Activator.CreateInstance(Type type, Boolean nonPublic) +69
System.Web.Mvc.DefaultControllerActivator.Create(RequestContext requestContext, Type controllerType) +67
[InvalidOperationException: An error occurred when trying to create a controller of type ''MyApp.Presentation.Controllers.SearchController''. Make sure that the controller has a parameterless public constructor.]
System.Web.Mvc.DefaultControllerActivator.Create(RequestContext requestContext, Type controllerType) +182
System.Web.Mvc.DefaultControllerFactory.GetControllerInstance(RequestContext requestContext, Type controllerType) +80
System.Web.Mvc.DefaultControllerFactory.CreateController(RequestContext requestContext, String controllerName) +74
System.Web.Mvc.MvcHandler.ProcessRequestInit(HttpContextBase httpContext, IController& controller, IControllerFactory& factory) +199
System.Web.Mvc.<>c__DisplayClass6.<BeginProcessRequest>b__2() +49
System.Web.Mvc.<>c__DisplayClassb`1.<ProcessInApplicationTrust>b__a() +13
System.Web.Mvc.SecurityUtil.<GetCallInAppTrustThunk>b__0(Action f) +7
System.Web.Mvc.SecurityUtil.ProcessInApplicationTrust(Action action) +22
System.Web.Mvc.SecurityUtil.ProcessInApplicationTrust(Func`1 func) +124
System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, Object state) +98
System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContext httpContext, AsyncCallback callback, Object state) +50
System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, Object extraData) +16
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +8862676
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +184
Y el controlador que estoy tratando de inyectar (toma una clase base en este momento):
public class SearchController : MainBaseController
{
private readonly MyApp.Domain.Tutor.TutorSearch TutorSearch;
protected static readonly log4net.ILog _log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
[Ninject.Inject]
public SearchController(MyApp.Domain.Tutor.TutorSearch tutorSearch)
{
this.TutorSearch = tutorSearch;
}
.... (no other constructors)
}
Y la parte relevante de mi NinjectWebCommon.cs:
private static IKernel CreateKernel()
{
var kernel = new StandardKernel();
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
RegisterServices(kernel);
return kernel;
}
/// <summary>
/// Load your modules or register your services here!
/// </summary>
/// <param name="kernel">The kernel.</param>
private static void RegisterServices(IKernel kernel)
{
INinjectModule[] modules = new INinjectModule[]
{
new Domain.DomainModule()
};
kernel.Load(Assembly.GetExecutingAssembly());
kernel.Load(modules);
kernel.Bind<MyApp.Domain.Tutor.TutorSearch>().ToSelf();
// ***************
var t = kernel.Get<MyApp.Presentation.Controllers.SearchController>();
}
Finalmente, aquí está DomainModule:
public class DomainModule : NinjectModule
{
public override void Load()
{
Bind<Data.Profile.IProfileProvider>().To<Data.Profile.XmlProfileProvider>();
Bind<Data.Subject.ISubjectProvider>().To<Data.Subject.XmlSubjectProvider>();
}
}
Como puede ver en mi NinjectWebCommon.cs en la línea marcada con asteriscos, intenté construir el controlador explícitamente como una prueba. Esto funciona perfectamente bien, con los Xml ... Providers correctamente inyectados.
¿Hay algo que me he perdido? No sé lo suficiente sobre lo que sucede bajo el capó de la extensión NuGet MVC3 y, por lo tanto, no tengo idea de en qué punto fallan las conexiones del controlador.
Cualquier sugerencia sobre qué mirar sería muy apreciada, gracias.
Traw, ¿hay alguna razón particular por la que está utilizando implementaciones concretas en lugar de interfaces? Tal como están las cosas, no obtienes ningún beneficio al enviar la clase directamente (y me sorprende que estés haciendo que algo funcione) me gustaría refactorizar y poner todo detrás de una interfaz, luego unir la interfaz a la implementación concreta .
Aquí hay una vista rápida de cómo podría verse eso:
// ''imagined'' ISearchType interface
public interface ISearchType
{
int Id { get; set; }
string LastName { get; set; }
}
// ''imagined'' TutorSearch concrete class
public class TutorSearch : ISearchType
{
public int Id { get; set; }
public string LastName { get; set; }
}
// your revised controller code
private readonly ISearchType _tutorSearch;
public SearchController(ISearchType searchType)
{
_tutorSearch = searchType;
}
luego, en su registro de los servicios (ninject), agregaría:
kernel.Bind<ISearchType>().To<TutorSearch>();
Eso debería llevarte un poco más allá. Además, var t = kernel.Get<...>
realidad no hace nada, solo en caso de que te estés preguntando qué le pasó a ''it''.
Que te diviertas...
Así que después de un tiempo de retoques desesperados, finalmente encontré mi problema. Estaba haciendo referencia a las DLL de MVC4 (System.Web.Mvc) y no había redireccionado el enlace de la versión 3.0.0.0 anterior a la 4.0.0.0:
<dependentAssembly>
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="1.0.0.0" newVersion="4.0.0.0" />
<bindingRedirect oldVersion="2.0.0.0" newVersion="4.0.0.0" />
<!-- The following line was missing -->
<bindingRedirect oldVersion="3.0.0.0" newVersion="4.0.0.0" />
</dependentAssembly>
Al menos, espero que sea una solución decente.
Editar: como se sugiere a continuación, la siguiente línea es más sucinta:
<bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
Usando Visual Studio y Nuget necesitas ejecutar este comando
Install-Package Ninject.MVC3
(reemplace el 3 dependiendo de la versión de MVC que esté ejecutando)
Esto resolverá su problema