NInject and MVC 3 - Should I use DependencyResolver instead of [Inject] attribute? - asp.net-mvc

Recently I moved to MVC 3 and Ninject 2. In most of the code, I use constructor injection, but there are some places, where I had to use Inject attribute. Ninject 2 registers its own IDepencyResolver interface. I don't like DependencyResolver class being part of System.Web.Mvc namespace, because its function is not really strictly related to MVC, but now, when it is there, I can do
public SomeClass
{
public IUserService UserService { get; set; }
public SomeClass()
{
UserService = DependencyResolver.Current.GetService<IUserService>();
instead of
public SomeClass
{
[Inject]
public IUserService UserService { get; set; }
so I don't have to reference Ninject namespace in my classes. Should DependencyResolver be used like that?

I use property injection only for dependencies that are not required for the proper working of the class but could add some functionality if the user sets them. Example of such functionality is logging. So you could have a property which represents a logger where the user can supply his own implementation and if he doesn't the class continues to work normally but it simply doesn't log.
For everything else I use constructor injection. This way you indicate to the consumer that this class has a required dependency on some other service.
So to answer your question about the property injection I would simply have:
public SomeClass
{
public IUserService UserService { get; set; }
public void SomeMethodWhichDoesntEnforceUserService()
{
if (UserService != null)
{
// Provide some additional functionality
}
}
}
and if your class cannot function properly without the user service:
public SomeClass
{
private readonly IUserService _userService;
public SomeClass(IUserService userService)
{
_userService = userService;
}
public void SomeMethodWhichRequiresTheService()
{
_userService.DoSomething();
}
}
So in both cases no reference to any DI specifics. That's what Inversion of Control is all about.

First question I would ask is why you can not perform constructor injection of the IUserService into SomeClass? It may indicate an issue with the design.
To avoid direct reference to the DependencyResolver you could implement some form of abstraction of a Service Locator over the DI framework, e.g. CommonServiceLocator, but as the answer to this question indicates, such abstractions shouldn't be necessary when doing DI correctly. Instead you should adjust the design of the application.

I believe the ninject.web.mvc version for mvc3 now supports constructor injection on filter attributes. Have you tried it?

Related

Dependency injection with multiple-layered application

I'm currently struggling a bit to understand how I can use the dependency injection pattern outside of my controller classes.
Say for instance that I have the following controller:
public class TestController : Controller {
ILog logger;
public TestController(ILog log) {
logger = log;
}
public string TestMethod() {
businessLayer businessLayer = new businessLayer();
return businessLayer.DoSomethingAndLogIt();
}
}
I understand that in most cases it is not possible to use constructor injection outside of the controller-classes. So it would not be possible to directly use the ILog-implementation insdie the "businesslayer"-class.
One simple solution I could imagine is the following:
public class TestController : Controller {
ILog logger;
public TestController(ILog log) {
logger = log;
}
public string TestMethod() {
businessLayer businessLayer = new businessLayer(logger);
return businessLayer.DoSomethingAndLogIt();
}
}
So passing on the dependencies from the controller to the underlaying layers. But is this the best way? Are there better solutions to have my businessLayer-class access to the ILog-implementation?
Thx!
I understand that in most cases it is not possible to use constructor
injection outside of the controller-classes.
This is incorrect. You should use constructor injection for all your components (every class in your application that contains behavior).
Dependency injection is about injecting dependent services/components into consuming components. So this means that you should not new up the businesslayer class in your controler; you should inject it using the constructor. By newing up this dependency you are violating the Dependency Inversion Principle, which causes high coupling. This again makes your code harder to test and makes it harder to change the controller and makes it much harder to apply cross-cutting concerns (such as logging, audit trailing, transaction management, etc) to the system.
So it would not be possible to directly use the ILog-implementation
insdie the "businesslayer"-class.
Incorrect. The ILog implementation should be injected into the constructor of your businesslayer class.
Long story short, your controller should look like this:
public class TestController : Controller {
IBusinessLayer businessLayer;
public TestController(IBusinessLayer bl) {
this.businessLayer = bl;
}
public string TestMethod() {
return businessLayer.DoSomethingAndLogIt();
}
}
Since TestController doesn't seem to use ILog directly, it should not be injected into its constructor. ILog is an implementation detail of the business layer class and implementation details should not leak to the consumer (this would again be a violation of the Dependency Inversion Principle).

Managing Constructor Dependency Injection (MS Unity)

I am building a multi-layered application and trying to keep the layers as much as possible so I'm using an IoC container for this purpose. Anyway, I'm trying to expand on this article to move my business logic validation into the service layer. I managed to resolve all dependency issues except the dependency of the ModelStateWrapper class on the ModelState itself. Here are my classes:
public interface IValidationDictionary
{
void AddError(string key, string errorMessage);
bool IsValid { get; }
}
public class ModelStateWrapper : IValidationDictionary
{
private ModelStateDictionary _modelState;
public ModelStateWrapper(ModelStateDictionary modelState)
{
_modelState = modelState;
}
public void AddError(string key, string errorMessage)
{
_modelState.AddModelError(key, errorMessage);
}
public bool IsValid
{
get { return _modelState.IsValid; }
}
}
The ModelStateWrapper class resides in a Services folder in my MVC3 application. While the IValidationDictionary is inside an Abstract folder inside my Services layer. In my Unity configuration I did the following:
.RegisterType<IValidationDictionary, ModelStateWrapper>(
new HttpContextLifetimeManager<IValidationDictionary>())
So, now is there anything I could do to inject the ModelState object into the ModelStateWrapper class using the IoC? Or do I have to explicitly/manually instantiate the ModelStateWrapper in the controllers and pass in the ModelState as an argument?
Thanks in advance!
I think you need to move your modelstatewrapper class to a common assembly. You can reference this common assembly from your service layer, business logic layer, etc. The common assembly can contain your domain classes, dto's, service definitions, etc etc You create a bootstrapper class which registers all types from the common assembly into your container. Call this bootstrapper from the service, BL layer, etc.
I hope this helps
Greetings

structuremap Property Injection

How to do Dependency Injection on Property of a class Using Structure Map
public class ContactController : Controller
{
public IContactService Service { get; set; }
public ContactController()
: this(null,null)
{
}
[SetterProperty]
public MembershipProvider Provider { get; private set; }
}
Here when i Create instance of ContactController i want provider to be set to Mock<MembershipProvider> please help me how to go about doing this? Mock is Moq Framework class
If you are using a Mock, you are most likely writing test code. If thats the case, you likely don't need a dependency injection tool like StructureMap involved. Just set the Provider property manually to your MembershpProvider in your test setup code.
controller.Provider = Mock<MembershipProvider>
If you really want to configure setter injection using StructureMap, see this answer:
Property Injection into an Action Filter

Is it possible to use Dependency Injection/IoC on an ASP.NET MVC FilterAttribute?

I've got a simple custom FilterAttribute which I use decorate various ActionMethods.
eg.
[AcceptVerbs(HttpVerbs.Get)]
[MyCustomFilter]
public ActionResult Bar(...)
{ ... }
Now, I wish to add some logging to this CustomFilter Action .. so being a good boy, I'm using DI/IoC ... and as such wish to use this pattern for my custom FilterAttribute.
So if i have the following...
ILoggingService
and wish to add this my custom FilterAttribute .. i'm not sure how. Like, it's easy for me to do the following...
public class MyCustomFilterAttribute : FilterAttribute
{
public MyCustomFilterAttribute(ILoggingService loggingService)
{ ... }
}
But the compiler errors saying the attribute which decorates my ActionMethod (listed above...) requires 1 arg .. so i'm just not sure what to do :(
I've got property injection working with Ninject and the Ninject.Web.MVC.
As long as you've got the controller factory from Ninject.Web.MVC, it's rather simple.
E.g.
public class EventExistsAttribute : FilterAttribute, IActionFilter
{
[Inject]
public IEventRepository EventRepo { private get; set; }
public void OnActionExecuting(ActionExecutingContext filterContext)
{
//Do stuff
}
public void OnActionExecuted(ActionExecutedContext filterContext)
{
//Do something else if you so wish...
}
}
It has the drawback of essentially having a 'hidden' dependency, so to say... but there ain't much you can do about that.
HTHs,
Charles
You need to write your own IActionInvoker and do property injection. Have a look at this post by Jimmy Bogard for ideas.
Yes it is possible to use dependency injection on a FilterAttribute. However it not possible to use constructor injection on a FilterAttribute. This is not a limitation of ASP.NET MVC, it is a common to all .Net code, as the values passed into an attributes constuctor are limited to simple types.
[MyFilter(ILogger logger)] // this will not compile
public ActionResult Index()
{
return View();
}
So the common practice is to make the dependency a property of your filter, as in #Charlino's example. You can then use property injection. You can use Ninject to decorate the filter property as in #Charlino's example. Or as suggested by #mrydengren, you can do this in a custom subclass of ControllerActionInvoker.

Constructor Dependency Injection in a ASP.NET MVC Controller

Consider:
public class HomeController : Controller
{
private IDependency dependency;
public HomeController(IDependency dependency)
{
this.dependency = dependency;
}
}
And the fact that Controllers in ASP.NET MVC must have one empty default constructor is there any way other than defining an empty (and useless in my opinion) constructor for DI?
If you want to have parameterless constructors you have to define a custom controller factory. Phil Haack has a great blog post about the subject.
If you don't want to roll your own controller factory you can get them pre-made in the ASP.NET MVC Contrib project at codeplex/github.
You don't have to have the empty constructor if you setup a custom ControllerFactory to use a dependency injection framework like Ninject, AutoFac, Castle Windsor, and etc. Most of these have code for a CustomControllerFactory to use their container that you can reuse.
The problem is, the default controller factory doesn't know how to pass the dependency in. If you don't want to use a framework mentioned above, you can do what is called poor man's dependency injection:
public class HomeController : Controller
{
private IDependency iDependency;
public HomeController() : this(new Dependency())
{
}
public HomeController(IDependency iDependency)
{
this.iDependency = iDependency;
}
}
Take a look at MVCContrib http://mvccontrib.github.com/MvcContrib/. They have controller factories for a number of DI containers. Windsor, Structure map etc.
You can inject your dependency by Property for example see: Injection by Property
Using Ninject looks like this:
[Inject]
public IDependency YourDependency { get; set; }

Resources