kinda new to MVC, and kinda new with Ninject. Playing around...
I've defined ninject in my MVC application as follows:
private static void RegisterServices(IKernel kernel)
{
kernel.Bind(
x => x.FromThisAssembly()
.SelectAllClasses()
.BindAllInterfaces()
);
}
I have controller with a form and this ActionResult:
public ActionResult Index(IMember Member)
{
return View();
}
and it's returning an error: "Cannot create an instance of an interface."
Now I understand that it might not like the interface but isn't Ninject supposed to inject the real class in there? do I need to put in the actual class? if so, doesn't that take the point out of using interfaces and building a lossly-cuppuled apps?
BTW in my Index.cshtml file I have the following as the first line:
#model IMember
Thanks
You seem to be confusing constructor dependency injection with action method parameters, they are not the same thing.
In your case you seem to want Ninject to somehow inject a concrete IMember implementation whenever a client (browser, etc) calls the Index action.
Bear in mind that any parameters that are going to be passed into an Action method are going to be coming from the client and not from the framework, so it wouldn't make sense to do this.
I am sure there is a hack you could do to make it work for e.g decorate the parameter with [Inject] or something but you've already lost at that point because you have just "revealed your sources" to the controller which is against the point of Inverting control - you might as well just pass the Ninject IKernel to the controller.
Anyway in your case, Ninject will only inject into the Controller constructor (assuming you have correctly wired it up) and in that respect, Doug's answer here is actually correct - if that IMember is some kind of controller dependency, then you must inject it into the constructor, and store it in for e.g. a private member so that you can later refer to it from within action methods.
If the IMember is not a controller dependency but is instead just a model-bound parameter that you want passed to your controller, then Dependency Injection is not the answer - the parameter should be coming from the caller.
Also, there might be another problem even if you do end up using constructor injection.
The convention-based binding you are using requires that there is a single class called Member that implements IMember, i.e that the class name differs from the interface name only by lack of the initial "I". If this isn't the case for your class, then the convention-based binding will not work anyway and you need to use something explicit like
kernel.Bind<IMember>.To<MyMemberImplementationClassName>();
Hope that helps.
Is your RegisterServices method in the NinjectWebCommon.cs file located in the App_Start folder?
You'll also need to pass the Member object into the view kind of like below:
public class HomeController : Controller
{
private IMember _member;
public HomeController(IMember member)
{
_member = member;
}
public ActionResult Index()
{
return View(_member);
}
}
Related
Hope this makes sense:
I have two classes:
ZombieRequest
VampireRequest
They both have to dependency inject:
ICreatureRequest
(which holds endpoints that ZombieRequest and VampireRequest must use)
They both derive from abstract class:
MonsterRequest
(which includes a common method for both ZombieRequest & VampireRequest (validates the response sent back from ICreatureRequest). Also defines how it should be used as an API (success variable, error variable, and a sendRequest() method))
Here's like the pseudo code of how it looks:
ZombieRequest : MonsterRequest
~~ use ICreatureRequest API endpoint~~
~~ use MonsterRequest method to validate the response~~
VampireRequest: MonsterRequest
~~ use ICreatureRequest API endpoint~~
~~ use MonsterRequest method to validate the response~~
In my controller I want to use ZombieRequest and/or VampireRequest, but I am getting lost with how to actually get it in there and use it.
Do I make an IMonsterRequest and inject that in the controller's constructor? But then how do I use a ZombieRequest or a VampireRequest from that?
Controller:
Get(string someVariable, string anotherVariable)
{
ZombieRequest z = new ZombieRequest();
if (z.SendRequest(someVariable, anotherVariable).Success)
string zombieData = z.ResponseData
}
ZombieRequest:
class ZombieRequest : MonsterRequest
{
ICreatureRequest m_CreatureRequest;
public ZombieRequest(ICreatureRequest c)
{
m_CreatureRequest = c;
}
public MakeRequest(someVar, anotherVar)
{
var response = m_CreatureRequest.GetZombie(someVar, anotherVar);
ValidateAndSetResponseData(response);
}
}
MonsterRequest:
abstract class MonsterRequest
{
public bool Success;
public string Data;
public abstract MakeRequest(someVar, anotherVar);
public void ValidateAndSetResponseData(var response)
{
// read response and:
// set Success
// set Data
}
}
But apparently I still need to supply a 'ICreatureRequest' when I make the object. Little confused.
Okay, this is starting to make sense so I'll take a crack at an answer. You need to learn the difference between Dependency Injection and a Dependency Injection Framework (sometimes called an Inversion of Control Container or IoC Container).
Your VampireRequest and ZombieRequest classes are set up to allow dependency injection. Your constructors accept the dependencies needed by the code. Your Controller, however, is clearly not set up for dependency injection since you are newing up a request.
So, focusing on the Vampire and Zombie classes..
First, I'll suggest you could move the ICreatureRequest up the hierarchy into MonsterRequest.
More importantly, in order to use dependency injection and create a VampireRequest, you have no choice but to create an instance of ICreatureRequest first. Since you are doing the newing in your controller, you will have to get an instance of the ICreatureRequest there too.
As you identified, why should the controller know about a specific instance of ICreatureRequest just to use MonsterRequest? It probably shouldn't. So you have a few choices: 1) ignore this rule and just have your controller create the ICreatureRequest. 2) inject an ICreatureRequest into the controller. 3) inject a fully created MonsterRequest into the controller. 4) Use an IoC Container to create all your dependencies for you automatically.
You've already made it clear you don't like the sounds of option 1. If you go with option 2 or 3 you'll soon notice that someone needs to new up the ICreatureRequest to pass to the Controller, so you'll probably be back in a few hours. Option 4 is probably the gap in your understanding and pretty much what everyone is talking about when they say dependency injection. It's also a much larger topic than I want to broach here, so instead I'll just refer you to documentation for one of my personal favourites: https://simpleinjector.readthedocs.io/en/latest/index.html
What is best way to get injections in base controller when using C# StructureMap.Mvc?
I can think of these 2 ways and don't know which is better.
From controller arguments to base controller arguments
(Nice approach but becomes a mess when there are many controllers with many properties to be injected)
Don't use child controller and initiate all injections using ObjectFactory.CreateInstance() in base controller constructor
(Very less code and manageable but not considered as good practice when Controller Injection is available)
thanks in advance.
I think bother approaches are fine and you can use the mix of both. Of course depending in the situation.
A. I believe if your child Controller require a dependency to be injected, then use the Constructor injection. This way you Controller's constructor API is explicit and it should state what has been injected into the Controller. Easy to read, and easy for discoverability. If you try to hide your DI types in a factory you lose this nice API/discoverability. Use property injection when the dependencies are optional if you think so. You don't really have pass these to the base Controller unless all your Child Controllers use them.
If you think you overloading the types in your Controller, try to aggreagate those interfaces to a single types.
B. It is not advisable to directly use the Structure map ObjectFactory in your Controller. Your Controllers should be agnostics of any infrastructure DI work. You can make use a generic factory (in infrastructure) to create types which uses the ObjectFactory within. If your DI types are required by the base Controller you may use this factory to resolve those types.
The ideas, inject types only when/where they need. Avoid injecting types to Controllers when they don't use/need.
Another option you available to you is setter injection via StructureMap's ObjectFactory.BuildUp() method.
It's worth mentioning that in StructureMap 3.1 the ObjectFactory has been deprecated in favour of injecting an instance of IContainer.
The examples would look like this:
StructureMap 3.0 and below:
public class BaseController {
protected IMyExampleServer MyExampleService { get; set; };
public BaseController() {
ObjectFactory.BuildUp(this);
}
....
}
StructureMap 3.1+:
public class BaseController {
protected IMyExampleServer MyExampleService { get; set; };
public BaseController(IContainer container) {
container.ObjectFactory.BuildUp(this);
}
....
}
Using StructureMap 3.1 would mean you'd only need to inject an instance of IContainer into your derived controller rather than each individual dependency that your base class requires.
Sorry for the vague title. I'll explain what I'm trying to get working.
My Admin View uses an Admin ViewModel which in turn calls an Admin Service which is a collection of Admin Repositories. For the sake of simplicity lets say that there is only one repository referenced by the Admin Service.
When constructing my Admin View Model the top of my class looks like this
public class adminMenuVM
{
private readonly IAdminMenuService menuService;
public adminMenuVM(IAdminMenuService adminMenuService)
{
this.menuService = adminMenuService;
}
public adminMenuVM()
{
menuItems = getMenuItems();
menuCats = getMenuCats();
}
}
Where getMenuItems and getMenuCats are two methods that use the service to retrieve data which is then set for the view model.
My problem is that when I run the app I get the error "Object Reference not set to instance of an object". Now I know that this is because the adminMenuVM() is called by the viwModel and not the constructor initializing the service.
My question is how can I ensure that the service constructor is called and does its thing when my view model is called?
I've tried using :this on the parameterless constructor but it wont allow me to assign an interface since you can't create a new instance of an interface.
Edit # 18:49
I've had a thought but don't know how to implement it. Can anyone advise on how I could "Constructor Chain" or if it is possible? My thought is to chain the parameterless constructor to service constructor this ensuring it gets called. I may be way off but would be grateful for yer help.
The first constructor looks like it should be used by some Dependency Injection container.
You can use just one constructor to create an instance. When that DI creates an instance with a supplied "IAdminMenuService", then you can create a new instance by using the second constructor, but as that's a new instance, the "menuService" will be empty (null).
You will need to find out how to get tan instance of your adminMenuVM from the DI container (if that is what you use).
Remove that default constructor and put its contents into the constructor with the parameter.
Managed to figure this one out. Its not the cleanest solution but I can't see any other way to do it. I'll stick this in to help anyone else who comes across this issue.
The issue boiled down to passing the current instance of the service interface to the ViewModel. The only place I could find that the instance was being set was the constructor of my controller. So very simply I declared a public global variable of the interface service type and saved the instance to that. The current instance persits and can be passed to the constructor of my viewmodel and satisfy the viewmodel constructors requirement. To clarify I've included an example of the controller and a viewmodel.
Controller:
public class AdminController : Controller
{
private readonly IAdminMenuService lmService;
public IAdminMenuService testService;
public AdminController(IAdminMenuService layoutMarkupService)
{
this.lmService = layoutMarkupService;
testService = lmService;
}
public ActionResult Index()
{
return View();
}
public PartialViewResult menuPartial()
{
return PartialView("_AdminMenuPartial", new adminMenuVM(testService));
}
ViewModel:
public class adminMenuVM
{
private readonly IAdminMenuService menuService;
public adminMenuVM(IAdminMenuService AdminMenuService)
{
this.menuService = AdminMenuService;
menuItems = getMenuItems();
menuCats = getMenuCats();
}
}
I have the following Interface
interface IProfileRepo {
}
And it's implementation
public class DBProfileRepo : IProfileRepo {
string _specialValue;
public DBProfileRepo(IAuthorizedController authController) {
_specialValue = authController.SomeValue;
}
}
My binding is
Bind<IProfileRepo>()
.To<DBProfileRepo>()
.InRequestScope();
My MVC controller which implements IAuthorizedController, is receiving this injection of DBProfileRepo, however, DBProfileRepo requires this controller as a constructor argument. How can I do this?
I am using Ninject 2.2.1.0
You have circular dependency between your objects and this is something you should avoid when designing your object hierarchy. A repository should not require a controller instance, that simply doesn't make sense. A repository is a data access class which could be reused in different kind of applications such as Desktop or Silverlight where there are no controllers. It is the controller which should require a repository and that's pretty much all.
If you need to pass some information to this repository which is available only in the controller, like for example a request parameter, simply design an object and pass this object to the repository method from the controller but don't pass an entire controller.
I am fairly new to DI with Autofac and wonder if the following is possible
I want to create a generic controller and action that receives an
injected type.
I do not want an instance of the injected type, but just need its
type, which would be an inplementation of an expected interface.
I would also like to pass that generic type on to a ViewModel, but that is another subject altogether, however if some genious out there can solve both that would be excellent.
public ContractorController<T> : Controller
where T : IContractor{
public ViewResult New() {
var vNewModel = new NewViewModel<T>();
return View(vNewModel);
}
}
This controller should be called through
http://mysite.com/Contractor/New
I have been looking into registering generics with AutoFac, but it
seems that the problem is that the AutofacControllerFactory only implements GetControllerInstance(), expecting the controller Type passed to it from either GetController() or CreateController(), not sure which or what the diffirence is between them. These methods receive the controller's name as a string from RoutData and return the corresponding .NET type which, give the url, http://mysite.com/Contractor/New is controller=Contractor and thus ContractorController cannot be matched by GetController() or CreateController() and therfore passing null to GetControllerInstance() which mean AutofacControllerFactory does not attempt to resolve the type.
I figured that I would have to create a custom Controller Factory
deriving from AutofacControllerFactory, override GetController() or CreateController() and
perform my own mapping from the controller names to the generic types.
Something like
if (controllerName == "Contractor")
return System.Type.GetType(
"UI.Controllers." + controllerName + "Controller`1");
When I debug this I can see that this code is finding the generic controller and returning it.
I thought I could then just register the types like
builder.RegisterType<FakeContractor>().As<IContractor>();
builder.RegisterGeneric(typeof(ContractorController<>));
But I am getting the following error
The Autofac service
'UI.Controllers.ContractorController`1'
representing controller
'ContractorManagement.UI.Controllers.ContractorController`1'
in path '/Contractor/New' has not been registered.
So I think I may be barking up the wrong tree.
Can anyone please shed some light on how I can do this without pulling
my teeth
Thank you
I'm not entirely sure why you want a controller using a generic. Using a generic on a Controller isn't really supported in Mvc - or at least the supporting routing path would be involved. Perhaps you can provide more info on the reasoning behind the approach?
What it looks like is that you want a controller that supports model binding against varying types. The next question is whether these types vary across a common interface or base class.
If that's the case, for Mvc2 check out the IocModelBinder information. This will work with Autofac quite well. This will allow the type to be model bound on post or get allowing you to inject services with autofac.
If you want to vary the types by a common base - supporting a variety of concrete view model - then check out the DerivedTypeModelBinder in MvcContrib. There is a version that works in Mvc 1, 2 and now MvcContrib for Mvc3 has a good sample app to accompany it. The Mvc3 implementation is also faster - speed wasn't a problem before, it's just a more efficient identification process.
Maybe it's not a direct answer to your question, but this is the only possible way to use generic controllers that I ever seen and used:
public abstract class ContractorControllerBase<T> : Controller where T : IContractor {
public ViewResult New() {
var vNewModel = new NewViewModel<T>();
return View(vNewModel);
}
}
public class FakeContractorController : ContractorControllerBase<FakeContractor> {
}