Getting property from injected type during registration - asp.net-mvc-3

Hopefully I can explain this to where someone might understand it enough to help :)
Anyways, I want to take a property from an injected type and use that in another injection. So imagine you have MVC model state on a controller that you want to inject into a service the controller uses.
public class MyController
{
public MyController(IService service)
{
....
}
}
public class MyService : IService
{
public MyService(IModelStateWrapper modelState)
{
....
}
}
How can I accomplish basically this:
public class MyController
{
public MyController(IService service)
{
service.ModelState = new ModelStateWrapper(ModelState);
}
}
Using an injection with Autofac or whatever DI container.

You can do this, but you have to unravel a couple of design problems before it's possible.
First, it appears that your IService implementation requires you pass the IModelStateWrapper in during construction only to be overwritten later during the creation of the controller. You have to make it so the IService implementation only has it as a property, not as a constructor requirement.
Second, you have to make sure it's OK that the service.ModelState setting happens just after construction of the controller. If there is other constructor logic that assumes the service.ModelState is set, then you have something that can't really be done via DI.
If you do that unraveling, Autofac will let you do some pretty cool stuff. When you register your controller type, register a lambda instead of just a type.
var builder = new ContainerBuilder();
builder.RegisterType<MyService>().As<IMyService>();
builder.Register(
c=>
{
var service = c.Resolve<IMyService>();
var controller = new MyController(service);
service.ModelState = new ModelStateWrapper(controller.ModelState);
return controller;
}).As<IController>();
var container = builder.Build();
Note the circular logic thing is handled in the lambda of the registration. Now when you resolve a controller...
var controller = container.Resolve<IController>();
...that logic will run and you'll get the effect you're looking for.
Again, I'll voice some concern over the circular reference stuff going on here. If there's a way to remove that circular dependency between the controller and the service, you'd be in a better spot to let DI work for you.

Related

How to make Ninject return a mock object

I have a code that looks like this
public class EmployeeController : Controller
{
public ContextWrapper contextWrapper;
public EmployeeController (IContextWrapper wrapper)
{
contextWrapper = wrapper;
}
In my dependency resolver I have the binding for IContextWrapper
kernel.Bind<IContextWrapper>().To<ContextWrapper>();
The implementation of ContextWrapper has an object which is of type Linq DataContext.
public class ContextWrapper : IContextWrapper
{
public MyDataContext dataContext;
public ContextWrapper(MyDataContext context)
{
this.dataContext = context;
}
Now my action method in this controller looks like this
var empRepository = new EmployeeRepository(contextWrapper);
//do some tests with this repository.
some values = contextWrapper.datacontext.get some values from the database table
//do some tests with these values.
To be able to test this method
I should be able to provide some sort of mock database(not literally) or
make the contextWrapper.datacontext return mocked values or
I even thought of creating another implementation of the IContextWrapper that doesn't use a Linq DataContext object. And creating another constructor for this controller and pass that fake implementation. Also in my dependency resolver I would bind the fake object to the IContextWrapper. Although I do not know how to make Ninject
As a last resort test my method against a test database since it all boils down to this Linq DataContext object and it seems I cannot get rid of it past a certain level.
Problem is the more I read about it, more I get confused. I have tried to give as much detail as possible to explain my problem. If any one has a clear cut idea about how to get this, please suggest.

How to inject ISession into Repository correctly?

Please correct me on the following scenario. ( Question is at the end)
(I asked a similar question that was un-organized and it was voted to close. So I have summarized the question here into a scope that can be replied with exact answers.)
I am developing a web application with multiple layers using nhibernate as ORM. My layer structure is as follow
Model Layer
Repository Layer
Services Layer
UI Layer
with the above layers, the classes and interfaces are placed as below.
ProductController.cs (UI Layer)
public class ProductController : Controller
{
ProductServices _ProductServices;
NHibernate.ISession _Session;
public ProductController()
{
_Session = SessionManager.GetCurrentSession();
_ProductServices = new ProductServices(
new ProductRepository(), _Session);
}
// Cont..
}
ProductServices.cs (Service Layer)
public class ProductServices : IProductServices
{
protected IProductRepository _ProductRepository;
protected NHibernate.ISession _Session;
public ProductServices(IProductRepository productRepository,
NHibernate.ISession session)
{
_ProductRepository = productRepository;
_Session = session;
_ProductRepository.SetSession(_Session);
}
// cont...
}
ProductRepository.cs (Repository Layer)
public class ProductRepository : IProductRepository
{
NHibernate.ISession _Session;
public void SetSession(NHibernate.ISession session)
{
_Session = session;
}
public IEnumerable<Product> FindAll()
{
return _Session.CreateCriteria<Product>().List<Product>();
}
//cont..
}
From the UI layer, I create the session as request per session and inject into service layer with the help of class constructor. Then set the session of repository with a help of a method.
I am afraid if I pass the _Session directly to repository as constructor, I will not have the control over it under the service layer. Also there is a future extension plan for using a webservice layer.
** Is there a way to ensure in each method of ProductRepository class that _Session is set already, without writing the piece of code if(_Session==null) in each and every method as it is repeating the same code.
** If the above pattern is wrong, Please show me a right way to achieve this goal.
What you are doing amazed me a bit. You applying the constructor injection pattern in the ProductService, which is definitely the way to go. On the other hand you are not injecting the dependencies into the ProductController, but that class is requesting one of those dependencies through a static class (this is the Service Locator anti-pattern) and creates a ProductServices class itself. This makes this class hard to test and makes your application less flexible and maintainable, since you can't easily change, decorate or intercept the use of the ProductServices class, when it's been used in multiple places.
And although you are (correctly) using constructor injection for the dependencies in the ProductServices, you are passing those dependencies on to the product repository, instead of applying the constructor injection pattern on the ProductResopistory as well.
Please show me a right way to achieve this goal.
The right way is to apply the constructor injection pattern everywhere. When you do this, your code will start to look like this:
public class ProductController : Controller
{
private ProductServices _ProductServices;
public ProductController(ProductServices services)
{
_ProductServices = services;
}
// Cont..
}
public class ProductServices : IProductServices
{
private IProductRepository _ProductRepository;
public ProductServices(
IProductRepository productRepository)
{
_ProductRepository = productRepository;
}
// cont...
}
public class ProductRepository : IProductRepository
{
private ISession _Session;
public ProductRepository (ISession session)
{
_Session = session;
}
public IEnumerable<Product> FindAll()
{
return _Session
.CreateCriteria<Product>().List<Product>();
}
//cont..
}
See how each class only takes in dependencies that it uses itself. So the ProductController and ProductServices don't depend on ISession (I made the assumption that only ProductRepoistory needs ISession). See how -from a class's perspective- everything is much simpler now?
Did we actually solve a problem here? It seems like we just moved the problem of wiring all classes together up the dependency graph. Yes we did move the problem. And this is a good thing. Now each class can be tested in isolation, is easier to follow, and the application as a whole is more maintainable.
Somewhere in the application however, a ProductController must be created. This could look like this:
new ProductController(
new ProductServices(
new ProductRepository(
SessionManager.GetCurrentSession())));
In its normal configuration, ASP.NET MVC will create controller classes for you, and it needs a default constructor to do so. If you want to wire up controllers using constructor injection (which you should definitely do), you need to do something 'special' to get this to work.
ASP.NET MVC allows you to override the default ControllerFactory class. This allows you to decide how to create controller instances. However, when your application starts to grow, it will get really awkward very quickly when you are creating your dependency graphs by hand (as my last example shows). In this case, it would be much better to use a Dependency Injection framework. Most of them contain a feature / package that allows you to integrate it with ASP.NET MVC and automatically allows to use constructor injection on your MVC controllers.
Are we done yet? Well... are we ever? There's one thing in your design that triggered a flag in my brain. Your system contains a class named ProductServices. Although a wild guess, the name Services seems like you wrapped all product related business operations inside that class. Depending on the size of your system, the number of people on your team, and the amount of changes you need to make, this might get problematic. For instance, how to you effectively apply cross-cutting concerns (such as logging, validation, profiling, transaction management, fault tolerance improvements) in such way that to system stays maintainable?
So instead of wrapping all operations in a single ProductServices class, try giving each business transaction / use case its own class and apply the same (generic) interface to all those classes. This description might be a bit vague, but it is a great way to improve the maintainability of small and big systems. You can read more about that here.
You can use a dependency injection container such as Autofac to instantiate your session and manage the lifetime of it. Leave the responsibility of instantiating the session to Autofac and simply inject the ISession interface into any classes that require the dependency. Have a look at this post: Managing NHibernate ISession with Autofac
You will also find this wiki page useful about configuring Autofac with MVC3: http://code.google.com/p/autofac/wiki/MvcIntegration3

Dependency Injection with Interface implemented by multiple classes

Update: Is there a way to achieve what I'm trying to do in an IoC framework other than Windsor? Windsor will handle the controllers fine but won't resolve anything else. I'm sure it's my fault but I'm following the tutorial verbatim and objects are not resolving with ctor injection, they are still null despite doing the registers and resolves. I've since scrapped my DI code and have manual injection for now because the project is time sensitive. Hoping to get DI worked out before deadline.
I have a solution that has multiple classes that all implement the same interface
As a simple example, the Interface
public interface IMyInterface {
string GetString();
int GetInt();
...
}
The concrete classes
public class MyClassOne : IMyInterface {
public string GetString() {
....
}
public int GetInt() {
....
}
}
public class MyClassTwo : IMyInterface {
public string GetString() {
....
}
public int GetInt() {
....
}
}
Now these classes will be injected where needed into layers above them like:
public class HomeController {
private readonly IMyInterface myInterface;
public HomeController() {}
public HomeController(IMyInterface _myInterface) {
myInterface = _myInterface
}
...
}
public class OtherController {
private readonly IMyInterface myInterface;
public OtherController() {}
public OtherController(IMyInterface _myInterface) {
myInterface = _myInterface
}
...
}
Both controllers are getting injected with the same interface.
When it comes to resolving these interfaces with the proper concrete class in my IoC, how do I differentiate that HomeController needs an instance of MyClassOne and OtherController needs an instance of MyClassTwo?
How do I bind two different concrete classes to the same interface in the IoC? I don't want to create 2 different interfaces as that breaks the DRY rule and doesn't make sense anyway.
In Castle Windsor I would have 2 lines like this:
container.Register(Component.For<IMyInterface>().ImplementedBy<MyClassOne>());
container.Register(Component.For<IMyInterface>().ImplementedBy<MyClassTwo>());
This won't work because I will only ever get a copy of MyClassTwo because it's the last one registered for the interface.
Like I said, I don't get how I can do it without creating specific interfaces for each concrete, doing that breaks not only DRY rules but basic OOP as well. How do I achieve this?
Update based on Mark Polsen's answer
Here is my current IoC, where would the .Resolve statements go? I don' see anything in the Windsor docs
public class Dependency : IDependency {
private readonly WindsorContainer container = new WindsorContainer();
private IDependency() {
}
public IDependency AddWeb() {
...
container.Register(Component.For<IListItemRepository>().ImplementedBy<ProgramTypeRepository>().Named("ProgramTypeList"));
container.Register(Component.For<IListItemRepository>().ImplementedBy<IndexTypeRepository>().Named("IndexTypeList"));
return this;
}
public static IDependency Start() {
return new IDependency();
}
}
I hope you can use service overrides.
Ex.
container.Register(
Component.For<IMyService>()
.ImplementedBy<MyServiceImpl>()
.Named("myservice.default"),
Component.For<IMyService>()
.ImplementedBy<OtherServiceImpl>()
.Named("myservice.alternative"),
Component.For<ProductController>()
.ServiceOverrides(ServiceOverride.ForKey("myService").Eq("myservice.alternative"))
);
public class ProductController
{
// Will get a OtherServiceImpl for myService.
// MyServiceImpl would be given without the service override.
public ProductController(IMyService myService)
{
}
}
You should be able to accomplish it with named component registration.
container.Register(Component.For<IMyInterface>().ImplementedBy<MyClassOne>().Named("One"));
container.Register(Component.For<IMyInterface>().ImplementedBy<MyClassTwo>().Named("Two"));
and then resolve them with
kernel.Resolve<IMyInterface>("One");
or
kernel.Resolve<IMyInterface>("Two");
See: To specify a name for the component
Typically DI containers follow Register, Resolve and Release patterns. During the register phase there are two steps. The first is to specify the mapping as you are doing. The second step is to specify the rules which govern which to inject where.
This problem is very common when we try to address Cross cutting concerns using decorators. In these situations, you have multiple classes(decorators) implementing a single interface.
Briefly, we need to implement IModelInterceptorsSelector which allows you to write imperative code that decides which Interceptor to apply to which types or members.
This is elaborately described in the book Dependency Injection in .Net book by Mark Seemann. Look for chapter 9 interception or search for the above interface.
I am not an expert at this, but was searching for the exact same problem and found the ans in the above book.
Hope this helps.
Regards
Dev1

Unittesting MVC controller

Im trying to learn MVC combined with IoC and DI. In my project I also use Castle, Automapper, NHibernate, NHibernateIntegration.
Thanks to the excellent example "ToBeSeen" app by Kozmic I think I have the solution pretty much set up now. But now I want to unittest basic save operation at the controller method level. I just dont get how to go about this. I expect my problem is pretty simple but Im a novice at this and any help is appreciated.
I have a dossiercontroller like this:
[Authorize]
[Transactional]
public class DossierController : BaseController
{
private readonly IRepository repository;
private readonly IMappingEngine mappingEngine;
private readonly ILogger logger;
public DossierController(IRepository repository, IMappingEngine mappingEngine, ILogger logger)
{
this.repository = repository;
this.mappingEngine = mappingEngine;
this.logger = logger;
}
As you can see it needs a repostitory, mappingengine and logger. As I understand all this is configured and wired up at runtime.
Next I have a controller method that is used to save a dossier:
[HttpPost]
[ActionName("Dossier")]
[Transaction]
[AcceptVerbs(HttpVerbs.Post)]
[AcceptParameter(Name = "button", Value = "save")]
public ActionResult Dossier_Save(string button, DossierModel dossierModel, string returnUrl)
{
if (!Request.IsAuthenticated)
return RedirectToAction("Index", "Home");
if (!ModelState.IsValid) return View(dossierModel);
Dossier dossier = mappingEngine.Map<DossierModel, Dossier>(dossierModel);
repository.Save(dossier);
return View();
}
Here I just want to automap the dossiermodel into a dossier and save it using the repository.
Now I want to unit test this using Nunit. I dont want to mock anything, I want a real persistence test from the controller level. For this I have to create a new dossiercontroller and pass in the correct arguments. Now Im lost. How do I create and configure the arguments so they work exactly like in the web application. For instance: How do I create a correctly configured Automapper in a Unittest? How do I create a correctly configured repository? Should I use a container?
Any help, especcialy a code example is highly appreciated!
Thanks in advance.
If you don't want to mock anything, you will need to instantiate concrete versions of the services required by the constructor of your controller.
e.g.
IRepository repository = GetRepository();
IMappingEngine mappingEngine = GetMappingEngine();
ILogger logger = GetLogger();
DossierController controller = new DossierController(repository, mappingEngine, logger);
ActionResult rsult = controller.Save(...etc...);
As to how you are to configure and instantiate these, you will essentially need to do this in exactly the same way that your MVC app is doing this.
If you are unsure where in your MVC app these are being configured, I'd suggest that the first place to look is in the IoC configuration and work backword from there.

Property Injection without attributes using Ninject in an abstract base controller in MVC3

I have the following code:
public abstract class BaseController : Controller
{
public IUserService UserService { get; set; }
}
All my controllers inherit from this base controller. I started out by configuring it in Ninject using the following code:
kernel.Bind<BaseController>()
.ToSelf()
.WithPropertyValue("UserService", x => x.Kernel.GetService(typeof(IUserService)));
This did not work. I assume it is because of the fact that the BaseController is an abstract class (please confirm my assumption). So I moved on to modify the configuration to:
kernel.Bind<HomeController>()
.ToSelf()
.WithPropertyValue("UserService", x => x.Kernel.GetService(typeof(IUserService)));
This does work. The minor downside is that I now have to configure every controller the same way.
Since I also have DependencyResolver setup in my ASP.NET MVC 3 project I could also remove the above Ninject configuration and modify my base controller to look like:
public IUserService UserService
{
get
{
return DependencyResolver.Current.GetService<IUserService>();
}
}
Is there any benefit to using the fluent configuration as opposed to using the DependencyResolver approach? Is one better than the other? Which approach would be considered a better practice?
It is worth mentioning that I did not want to do constructor injection in my base controller.
A better practice in MVC it is to use constructor injection over property injection. Why did you make your choice like this ?
Using Constructor Injection you states that all dependencies in constructor are necessary for the class to do its job.
Property injection means that the dependencies are optional or that there are the local defaults implementations, so all will work even if you don't provide necessary implementations yourself.
You should really know what you're doing using Property injection or you have no other choice, so the safer approach is to rely on constructor injection.
Now I'll give you my point of view. Other may have other opinions.
DependencyResolver was introduced in MVC 3 for "convenient" service location but for me it's a regular Service locator which for me is also an anti-pattern http://blog.ploeh.dk/2010/02/03/ServiceLocatorIsAnAntiPattern.aspx. I don't use it because I don't like it and there is no benefit in using it.
I prefer to user my controller factory like before and pass the dependencies through constructor.
More the IDependencyResolver has somme issues with some IoC containers (I don't know if it's the case with Ninject). You can read more here : http://mikehadlow.blogspot.com/2011/02/mvc-30-idependencyresolver-interface-is.html
If you need the same dependency in each controller then there seems to be something wrong in your design. Most likely you are handling some kind of cross cutting concern in your base controller. In this case Doing property injection is just treating sympthoms instead of cureing the disease. This should rather be handled by an aspect (e.g. a filter or an interceptor) so that you do not have to pollute your controller with something that does not belong there.
There are many ways to skin the cat they say. You could use conventions-based bindings with .WithPropertyValue() or with .OnActivaction() (as described here).
public class ControllerModule : NinjectModule
{
public override void Load()
{
// Get all controller types derived from the base controller.
IEnumerable<Type> controllerTypes = // ...
foreach (var controllerType in controllerTypes)
{
Bind(controllerType).ToSelf().InRequestScope()
.WithPropertyValue(...);
}
}
}
You could create your own custom implementation of the IInjectionHeuristic interface as described here or your own custom implementation of the IControllerActivator interface.
public class CustomNinjectControllerActivator : IControllerActivator
{
private readonly IKernel kernel;
public CustomNinjectControllerActivator(IKernel kernel)
{
this.kernel = kernel;
}
public IController Create(RequestContext context, Type controllerType)
{
var baseController = kernel.TryGet(controllerType) as BaseController;
if (baseController == null)
{
return null;
}
baseController.UserService = kernel.Get<IUserService>();
return baseController;
}
}
Heck, you could even use the service locator pattern if you are comfortable using it.
public IUserService UserService
{
get { return DependencyResolver.Current.GetService<IUserService>(); }
}
You should choose whichever solution is easiest to implement, test and maintain, and of course provides the desired behavior.

Resources