MVC5, WebAPI2 and Ninject Parameterless constructor error - dependency-injection

So I have the exact opposite problem as MVC5, Web API 2 and Ninject
I have a new MVC5/WebAPI2 project, that has both "Controller"s and "ApiControllers".
I'm using the latest unstable version of Ninject.Web.WebAPI with no code changes to NinjectDependencyResolve.cs and Ninject.WebCommom.cs (besides binding my dependency) the ApiController's constructor injection works. However, when I call a MVC Controller I get:
No parameterless constructor defined for this object.

The issue is you need a Dependency Resolver for both MVC and WebAPI. Depending on which set of Ninject libraries you use, you only get one of those wired in for you.
i.e. if you use the Ninject.Web.WebAPI library you will need to manually set the MVC resolver:
System.Web.Mvc.DependencyResolver.SetResolver(new NinjectResolver(kernel));
(I did this in NinjectWebCommon.cs CreateKernel())
Your Ninject resolver can inherit the interface for both WebAPI and MVC:
public class NinjectResolver : NinjectScope,
System.Web.Http.Dependencies.IDependencyResolver,
System.Web.Mvc.IDependencyResolver

Related

How do I read the connectstring from asp.net 5 project

I have a asp.net 5 web application with an appsettings.json file. My data access layer is the old 4.5.1 project style with an app.config, using EF 6.
How can I get the connectString from my asp.net 5 applicaiton.json to the DbContext class in the old style?
Here is what I am currently trying:
My DbContext class takes an IDbConnectString parameter in it's constructor.
In startup (of the asp.net 5 project) I load my connect string class from appsettings.json with this:
services.Configure<Models.Security.MyConnectString>(Configuration.GetSection("Data:MyConnection"));
This creates allows the injection of an IOptions object with the type MyConnectString. However, the DAL project has no reference to IOptions (it's not asp.net 5).
Then I setup dependency injection with this:
services.AddTransient<IMyConnectString, Models.Security.MyConnectString>
When the MyConnection class is injected, it's a new class - not the one I loaded from appsettings.
Any advice on how to do this?
I am also using AutoFac dependency injection. It has the ability set the return valueof a property like this:
builder.RegisterType<MyConnectString>()
.As<IMyConnectString>()
.WithProperty("ConnectionString", "--- what goes here ---");
I set this up in the ASP.net 5 project. If I could get an instance of the MyConnectString class with the appsettings.data (from startup) I could use it here.

ASP.NET Web API and Ninject not working

I started a new ASP.NET MVC project and I'm using Ninject as my IOC controller.
As far as regular MVC Controllers goes - everything work fine and binding is done to the controller constructor as expected.
I've added a WEB API to my project and did pretty much the same thing. here is the API constructor:
public class DetailsController : ApiController
{
private IClientInfoRetriever _clientInfoRetriever;
public DetailsController(IClientInfoRetriever clientInfoRetriever)
{
_clientInfoRetriever = clientInfoRetriever;
}
.
.
.
// The rest of my methods
}
here is the Ninject binding:
Bind<IClientInfoRetriever>().To<ClientInfoRetriever>();
but when I try to access my API (just putting the URL in the browser for a get action) I get the following error:
An error occurred when trying to create a controller of type 'DetailsController'. Make sure that the controller has a parameterless public constructor.
It's expecting to get an empty constructor, but if I give it an empty constructor to use - it won't be initializing the object I need.
What am I doing wrong? does Ninject support web api?
Thanks
Install the proper Ninject Nuget package for WebAPI:
PM> Install-Package Ninject.Web.WebApi -Version 3.0.0.2

Using Ninject with MVC3 controllers that are in external assemblies

I have MVC3 controllers in external assemblies using MVC contrib's portable areas but I'm having a problem getting Ninject to inject the constructor dependencies.
The controller is found but I get an exception of "No parameterless constructor defined for this object". I can see that ninject's controller factory is being called in the call stack but for external assemblies it just does not pass my database session.
Why could this be?
Probably you should update Ninject. RegisterAllControllersIn is from a version that is outdated since a long time.
You need to register the controllers in the other assemblies using Ninject's RegisterAllControllersIn method.
This is my implementation in the applicationstarted method of global.asax:
foreach (var ass in BuildManager.GetReferencedAssemblies().Cast<Assembly>())
{
RegisterAllControllersIn(ass);
}

How does ninject doing Dependency injection in Asp.net MVC

i studying by the book Pro asp.net mvc2 by apress, In the book the author uses ninject for dependency injection.
He inherits the default control factory :
public class NinjectControllerFactory : DefaultControllerFactory
and then overrides : GetControllerInstance
I have 2 questions.
how does the DefaultControllerFactory knows what controller to load ? i assume he uses the route table and then loads it with reflection. am i correct ?
and how the ninject knows to do it, the only line i wrote is :
private IKernel kernel = new StandardKernel();
return (IController)kernel.Get(controllerType);
Ninject can't possibly know about my route table and which control he should load ..
so how does he knows ?
ps.
i use the regular ninject, not some specific version that created for MVC (which i believe they have on their website also)
this is for mvc3 but a good article about ninject and mvc.
http://dotnetslackers.com/articles/aspnet/Experience-ASP-NET-MVC-3-Beta-the-New-Dependency-Injection-Support-Part1.aspx
NinjectControllerFactory.GetControllerInstance gets called by MVC. This means it is MVC that evaluates which controller type is required to process a request and it get it from the routing table.
If you want to use this I recommend using https://github.com/ninject/ninject.web.mvc It will save you time and work as it is maintained together with Ninject. Otherwise you will have to update to new Ninject versions yourself.

How does Ninject create controller in ASP.NET MVC?

This may be stupid question, but I am looking at Ninject sources and don't see NInject registering its own controller factory. I also don't see any IControllerFactory class in Ninject.Web.Mvc assembly. Am I missing something? How does Ninject create controller and inject parameters into constructor?
Lets say we are looking for "/Task/Index".
Ninject MVC applications use now DefaultControllerFactory, the same as non-Ninject applications.
DefaultControllerFactory finds type for controller (TaskController).
DefaultControllerFactory has internal class called DefaultControllerActivator. DefaultControllerActivator has method called Create, which returns controller instance. DefaultControllerFactory asks DefaultControllerActivator for TaskController type instance.
DefaultControllerActivator.Create uses IDependencyResolver. This is where Ninject comes in. Since Ninject implements its own resolver and sets it at the start of application, he gets request for TaskController instance.
The rest is easy. Ninject finds constructor for this type, injects parameters, returns controller instance.
MVC3 now recommends the usage of the IDependencyResolver interface instead of the good old IControllerFactory when dealing with DI. You can look at more details of this interface here.
This is the new Ninject class responsible for injecting the dependencies.
Since controllers are concrete types, Ninject will do self bind. Below is a snippet from ninject.complex.com
Bear in mind that only concrete types can be self-bound; abstract
types and interfaces won't work. Also, if you request an instance of a
type that can be self-bound, and there are no bindings defined for the
type, Ninject will automatically create an implicit self-binding. It's
up to you whether you want to define your bindings explicitly, or let
Ninject figure it out.
If you do need to inject parameters into the constructor. You can create a class inherits from INinjectModule and do the binding there.

Resources