I have used the NuGet Ninject MVC3 extension and have been unable to get it to inject into a controller upon request. It doesn't seem to have bound, as MVC is looking for the paramaterless constructor. Here's the stack trace:
[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
And the controller i'm trying to inject into (it takes a base class at the moment):
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)
}
And the relevant part of my 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>();
}
Finally, here is 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>();
}
}
As you can see in my NinjectWebCommon.cs at the line marked with asterisks, I have tried constructing the controller explicitly as a test. This works perfectly fine, with the properly injected Xml..Providers.
Is there something I have missed? I don't know enough about what goes on under the hood of the NuGet MVC3 extension and so have no idea at which point the controller bindings are failing.
Any pointers on what to look at would be very much appreciated, thanks.
The Dependency Injection (DI) Design Pattern The Dependency Resolver in ASP.NET MVC can allow you to register your dependency logic somewhere else (e.g. a container or a bag of clubs). The advantages of using Dependency Injection pattern and Inversion of Control are the following: Reduces class coupling.
Dependency Resolution in MVC3. MVC 3 introduced a new concept called a "Dependency Resolver", which greatly simplified the use of. dependency injection in your applications. This made it easier to decouple application components,making them more configurable and easier to test.
So after quite a while of desperate tinkering, I finally found my problem. I was referencing the MVC4 (System.Web.Mvc) DLLs and had not redirected the binding of the older 3.0.0.0 version to 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>
At least, I hope that's a decent solution.
Edit: as suggested below, the following line is more succinct:
<bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
Using Visual Studio and Nuget you need to run this command
Install-Package Ninject.MVC3
(replace the 3 depending on which MVC version you are running)
This will solve your problem
Traw, is there a particular reason that you're using concrete implementations rather than Interfaces.?? As it stands, you are gaining zero benefit from DI'ing the class straight in (and i'm surprised that you're getting anything to work) i would refactor and put everything behind an interface, then bind the interface to the concrete implementation.
Here's a quick shot at how that might look:
// '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;
}
then, in your registering of the services (ninject), you'd add:
kernel.Bind<ISearchType>().To<TutorSearch>();
That should get you a little further. Also, var t = kernel.Get<...>
actually does nothing at all - just in case you were wondering about what had happened to 'it'.
Have fun...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With