MVC3 Controller constructor + Ninject - c#

I'm at the moment working on a MVC3 Web application and ecountered a new problem with Ninject.
I'm using the following code in my controller:
public class TestController : Controller
{
public IRepository<CustomerModel> rep;
public TestController(IRepository<CustomerModel> repository)
{
this.rep = repository;
}
public ActionResult Index()
{
return View();
}
}
And my Ninject Module:
public class RepositoryModule : NinjectModule
{
public override void Load()
{
Bind(typeof(IRepository<>)).To(typeof(Repository<>));
}
}
However this just throws me "System.MissingMethodException: No parameterless constructor defined for this object." when I try to render the Index view.
If I then add:
public TestController() : this(new Repository<CustomerModel>(new XenCRMEntities())) { }
so my actually TestController looks like:
public class TestController : Controller
{
public IRepository<CustomerModel> rep;
public TestController() : this(new Repository<CustomerModel>(new XenCRMEntities())) { }
public TestController(IRepository<CustomerModel> repository)
{
this.rep = repository;
}
public ActionResult Index()
{
return View();
}
}
It works, but as you can see the new constructor pretty much break the whole point of IoC.
How do I fix this?
Thanks in advance.

A short test showed that there is not problem with generic bindings in the MVC3 extension. I guess that the problem is not in the Controller but that the Repository can not be created because it has some unknown dependencies.
But this brought me to change the dependency resolver a bit to show the Ninject stacktrace whenever the requested type can be resolved but one of its dependencies fails to be resolved. Update to the latest version on the build server to get a better stack trace.

You will need to change the controller factory, as the regular MVC controller factory does not do DI.
You can look here for more information on how to setup MVC + Ninject: MVC3 + Ninject - How to?

It turns out that its not the Controller thats messing it up, but that Ninject dont Bind my generic Repository and IRepository correctly - I have therefore created a new post: Ninject + Bind generic repository

Don't use this binding!!!
Bind(typeof(IRepository<>)).To(typeof(Repository<>));
I changed my code use this binding and server was crashed, it works for one user but for thousands requests it's really bad
Use
Bind(typeof(IRepository<IClass>)).To(typeof(Repository<Class>))

Related

Dependency Injection in ASP.NET MVC

I've been using Dependency Injection in ASP.NET MVC the way I've explained in the below code, but I'm not sure if that is the right and standard way to do it. So I just wanna know if what I'm doing is wrong or if there is a better and more professional way to do it.
public interface IService {
public Boolean AddRecord(Object _Model);
}
public class Employee: IService {
DataBase Context = new DataBase();
public Boolean AddRecord(Object _Model) {
Context.Add((EmployeeModel) _Model);
return Context.SaveChanges() != 0;
}
}
public class DataController: Controller {
IService service;
public DataController(IService service) {
this.service = service;
}
public ActionResult AddRecord(Object _Model, String Caller) {
if (service.Add(_Model)) {
TempData["Result"] = "Data Added";
return RedirectToAction(Caller);
}
TempData["Result"] = "Please try again";
return View (Caller, _Model);
}
}
When I wanna use the controller with the DI, I do: (Is this the right way to consume the DataController)
public class TestController: Controller {
public ActionResult Index () {
return View();
}
public ActionResult TestIt (EmployeeModel _Model) {
DataController DC = new DataController(new Employee());
return DC.AddRecord(_Model, "../Test/TestIt");
}
}
You have the general concept of Dependency Injection / Inversion down. That is, you've understood that instead of this:
public class Example {
public void SomeFunc() {
var service = new Service();
service.DoStuff();
}
}
..you do this:
public class Example {
private readonly IService _service;
public Example(IService service) {
_service = service;
}
public void SomeFunc() {
_service.DoStuff();
}
}
.. and you supply the dependency manually via the calling code.. such as a Controller:
public HomeController : Controller {
[HttpGet]
public ActionResult Index() {
var example = new Example(new Service());
example.SomeFunc();
// .. the rest ..
}
}
So, the first part is Dependency Inversion. You have inverted the dependency chain from being top down to bottom up. The second part (the above code block) is Dependency Injection.
Notice in the above block of code that the Controller has no dependencies injected. This is where Inversion of Control comes in.
Inversion of Control is a pattern where code completely external to the currently running code decides how it functions. In this context, it means some external code - somewhere else - decides how to supply dependencies to your controller.
(Note, I am quite familiar with Ninject - so the below examples are using Ninject. There are plenty of other available DI/IoC containers available)
Ninject is a framework that can help with this (and many others). Ninject has an extension for ASP.NET MVC which automatically builds and supplies controller instances for you - plus your dependencies.
Without providing a full tutorial on using Ninject (which I will leave as an exercise to the OP to Google), the basics of it is this.
You declare a "module" with the configuration for your dependencies. Using the above examples, your module might look like this:
public class YourModule : NinjectModule {
public override void Load() {
Bind<IExample>().To<Example>().InRequestScope();
Bind<IService>().To<Service>().InRequestScope();
}
}
This will wire up all requests for an IExample to an Example, and IService to an instance of a Service. So your Controller would become:
public class HomeController : Controller {
private readonly IExample _example;
public HomeController(IExample example) {
_example = example;
}
[HttpGet]
public ActionResult Index() {
_example.SomeFunc();
// .. the rest ..
}
}
The container (in this case, Ninject) looks at your external code (the YourModule class) and determines what IExample should be. It sees that you've said it should be an instance of an Example class. Example also requires a dependency of type IService. So Ninject will again look at YourModule and determines that it should be an instance of Service. It continues to go down the object hierarchy until it completes the construction of the objects.
Hopefully that makes sense - it is definitely hard to explain these concepts in text.
I haven't viewed this video (I am running off of really really terrible WiFi hotspot while I wait for an internet connection!) so I can't verify it's quality, but a quick Google search turned this up for setting up Ninject and MVC: http://www.youtube.com/watch?v=w_MehI2qBTo
You would definitely benefit from Googling around some Inversion of Control and/or Ninject videos to understand what frameworks like it are for.
It is important to note too that frameworks like Ninject can also control scope. In the example above, I used InRequestScope against the bindings. This means that Ninject will instantiate the dependency at the start of the web request - and dispose of it afterward. This removes the need for you to worry about that.

Best practice for dependency injection

I am creating a new project in ASP.net using MVC 4.
I want to setup dependency injection using Ninject. But before I proceed what are the best practices when setting up dependency injection?
Currently I have a binder class setup within the webproject which will reference data projects within the solution.
The binder class is as shown below:
Public static class Binder
{
static Ninject.IKernel _kernel;
static Binder()
{
_kernel = new Ninject.StandardKernel();
_kernel.Bind<IConfig>().To<AppSettingsConfig>();
_kernel.Bind<IDocuments>().To<DocumentsClass.Documents>();
}
public static T GetImplementation<T>()
{
return _kernel.Get<T>();
}
}
Then within my controller i use the GetImplementation method to use the exact require dependency rather than registering all on application startup.
Example code from controller:
Public ActionResult Get (int id)
{
var repository = Binder.GetImplementation<IDocuments>();
// do some stuff with the repository here
}
Not sure if this would be a good approach? Any advice would be good.
What you have now is an example of the Service Locator anti-pattern. Google for more details as it has been discussed many times.
In short, rather than relying on the service locator
public class SomeController
{
public ActionResult Get (int id)
{
var repository = Binder.GetImplementation<IDocuments>();
// do some stuff with the repository here
}
}
you should have your service injected into the client class (rely on constructor injection)
public class SomeController
{
private IDocuments documentService { get; set; }
public SomeController( IDocuments documentService )
{
this.documentService = documentService;
}
public ActionResult Get (int id)
{
var repository = documentService;
// do some stuff with the repository here
}
}
In this specific case, you could set up your controller factory to use your IoC container to resolve your controllers.
Best practice for Ninject is to use the MVC extension for Ninject: https://github.com/ninject/ninject.web.mvc/wiki/MVC3
You are linked to the instance of your Binder class inside controller. It makes your class not reusable and it must be refactored, because it is not resposibility of controller to get correct instance of IDocuments implementation.
There is must be some external dependency resolver(like example - Ninject) which have to make constructor injection or property injection.

DependencyResolver.Current.GetService always returns null

According to this tutorial, to use Ninject in my Asp.net MVC 3 application , all I have to do is install package via Nuget and configure dependencies.
Follow these steps
Install Package-Ninject.MVC3
In NinjectMVC3.cs
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IReCaptchaValidator>().To<ReCaptchaValidate>();
}
In Controller
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Registe(RegisterModel model)
{
var myObject = DependencyResolver.Current.GetService<IReCaptchaValidator>(); //always null
}
myObject always returns null.
I've tried kernel.Bind<IReCaptchaValidator>().To<ReCaptchaValidate>().InRequestScope(), but not effect!
myObject continues null
In this post here on StackOverflow, I was told to use DependencyResolver.Current.GetService(TYPE) to retrieve the instance of an object.
In the post you refer to, you were not told to use DependencyResolver, just that it's possible to use it. You shouldn't use it, as it's a well known anti-pattern.
While using the DependencyResolver directly should work, you really shouldn't do it that way.
Instead, you should use Constructor Injection, which would be to have your class take the type as a parameter of your constructor.
public class MyController : Controller {
IReCaptchaValidator _validator;
public MyController(IReCaptchaValidator validator)
{
_validator = validator;
}
}
Then, in your method:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Registe(RegisterModel model)
{
var myObject = _validator;
}
I had the same problem.
On the same function, I could resolve an interface just fine, while another interface did not resolve. They were both registered!
When resolving manually, it seems that you don't get errors!
Pretty funny, but I just found about!
Once I injected the interface in a controller constructor and enabled all exceptions, then I get an exception saying that there was no public constructor for my implementation!
Try that and you will most likely find the root cause.

Object reference not set to an instance of an object error!

Can anyone see what I'm doing wrong here? I'm trying to learn how to have specs/ services and domain projects in general but in this case it's ASP.NET MVC.
I have the following code in my controller but I getting Object reference not set to an instance of an object on the following line of code. I would appreciate any suggestions where I'm going wrong!?
// Error
Line 22: var profiles = _profileService.GetProfile();
// code below
namespace Whitepages.Controllers
{
[HandleError]
public class HomeController : Controller
{
private readonly IProfileService _profileService;
public HomeController(IProfileService profileService)
{
_profileService = profileService;
}
public HomeController()
{
}
public ActionResult Index()
{
var profiles = _profileService.GetProfile();
return View("Index");
}
}
}
using Domain;
namespace Services.Spec
{
public interface IProfileService
{
Profile GetProfile();
}
}
Many thanks,
It looks like the controller factory you are using to build your controllers passes null at the constructor of HomeController. In ASP.NET MVC controllers are built by a controller factory which by default is the DefaultControllerFactory class which simply invokes the default constructor.
The fact that you are getting a NullReferenceException instead of the class HomeController doesn't have a default constructor indicates that you have setup a custom controller factory in your Global.asax which is supposed to provide instances of your controllers but this custom controller factory doesn't passes null to the HomeController constructor, so when later you try to access this service _profileService.GetProfile() you get the exception. You are probably using some dependency injection framework and in your Application_Start you have something like this:
ControllerBuilder.Current.SetControllerFactory(new SomeCustomControllerFactory());
So if you are using a DI framework you need to setup this framework to pass a specific implementation of the IProfileService interface to the constructor. How this is done would totally depend on the framework you are using.

ASP.MVC and mvccontrib fluent test with IOC

I am trying to use the fluent test helpers to test an AbstractRestfulFluentController
public class CustomerController : AbstractRestfulFluentController
{
private readonly IService<Customer> _customerService;
private readonly IService<CustomerAddress> _addressService;
public CustomerController(IService<Customer> customerService, IService<CustomerAddress> addressService)
{
//Assume we use these in other actions
_customerService = customerService;
_addressService = addressService;
}
public ActionResult Index()
{
return View();
}
}
As you can see I am injecting some services into the controller and resolving them using IOC. My problem is that all the examples I have found using the fluent test methods in mvccontrib don't work without a paramaterless controller.
public void SuccessfulIndex()
{
GivenController.As<CustomerController>()
.ShouldRenderItself(RestfulAction.Index)
.WhenCalling(x => x.Index());
}
I'm not sure what I need to do in order to be able to use IOC with the fluent test techniques in mvccontrib. I have found a few comments that it is possible but haven't found anything. What can I do in order to actually use IOC and fluent tests?
You could write a method which allows you to provide the instance of the controller:
public static class GivenController
{
public static ActionExpectations<T> As<T>(T controller) where T: Controller, new()
{
return new ActionExpectations<T> { MockController = controller };
}
}
And then in your unit test:
var controller = CreateMockedCustomerController();
GivenController
.As<CustomerController>(controller)
.ShouldRenderItself(RestfulAction.Index)
.WhenCalling(x => x.Index());
The requirement is that the controller should be a mock object which in my opinion is not a very clean approach (testing a mocked object). You could create it like this:
var controller = MockRepository
.GeneratePartialMock<CustomerController>(new object[] { dep1, dep2 });
Notice how dependencies are passed to the constructor.
Have you tried property injection instead of constructor injection?
http://ninject.codeplex.com/wikipage?title=Injection%20Patterns
I am currently having a weird ninject issue that I just posted about, but this should at least point you in the right direction...all the code is there for setting up the dependency injection.
https://stackoverflow.com/questions/3909452/unit-testing-asp-net-mvc-controllers-with-ninject

Categories