Click here to monitor SSC
  • Av rating:
  • Total votes: 32
  • Total comments: 13
Dino Esposito

ASP.NET MVC: Resolve or Inject? That’s the Issue…

23 April 2012

Classes should have dependencies only on abstract, rather then concrete, classes. To get around this, you can choose between Service Locator and Dependency Injection techniques. ASP.NET MVC  uses 'Dependency Resolvers' which are Service Locators. When designing ASP.NET MVC applications it is open to you to decide whether to resolve or inject, so what are the pros and cons? Dino explains.

I  teach a class about the principles and patterns of effective software design. I often disconcert the attendees by saying that, although I perceive a great deal of emphasis in the value of Dependency Injection, I don’t believe that Dependency Injection justifies all of the attention. Dependency Injection is just an implementation detail; what really matters is the principle behind it—the Dependency Inversion principle. If you’re familiar with the acronym SOLID, well, the Dependency Inversion principle is just the “D” in the acronym. By the way, SOLID results from the initials of five design principles that are reckoned to be essential in Object-Oriented software design. These five principles are:

  • Single Responsibility
  • Open/Closed
  • Liskov’s principle
  • Interface Segregation
  • Dependency Inversion

Nearly all of these principles are mere vectors in the sense that they show you the direction but don’t give you concrete guidance on how to do things. Let’s take the Single Responsibility principle as an example. All it says is that you should endeavor to write your classes so that you later have just one reason to change them. The idea behind the principle is that classes should be much more cohesive than they often are. The methods they are made of should be logically related and form a single chain of responsibility. As you can see, the principle heralds a clear and shared idea but it doesn’t give you a step by step procedure on how to accomplish it.

Inside the Dependency Inversion Principle

The Dependency Inversion principle, instead, has a fairly obscure formulation but can be translated into an extremely detailed set of implementation steps. The Dependency Inversion principle says that classes should not have dependencies on concrete classes but only to abstractions. Translated for humans, it means that you should be using interfaces to abstract all of the critical dependencies of a given class. If, for example, your class needs to use a Logger component, then the best you can do is to make your class aware of an ILogger interface rather than a Logger class. In this way, you can change the implementation of the logger class at any time (and for how many times you want) without breaking the host code.

The implementation of the Dependency Inversion principle is bound to an algorithm that passes a list of dependencies to the core code. Let’s have a look at the following code:

public class MyComponent
{
    public MyComponent()
    {
       :
    }
    public void DoSomeWork()
    {
        var logger = new Logger();
        :
    }
}

Clearly, the MyComponent class has a dependency on the Logger class. If we decide to change it to ILogger, how can we get a reference to an actual class that implements the interface?

public class MyComponent
{
    public MyComponent()
    {
       :
     }
     public void DoSomeWork()
     {
          ILogger logger = ...; // who’s going to provide this?
          :
     }
}

To implement the Dependency Inversion principle, you have the choice of two main patterns: Service Locator and Dependency Injection. The former allows you “resolve” a dependency within a class; the latter allows you to “inject” a dependency from outside the class. The following listing exemplifies what it means to resolve a dependency:

public class MyComponent
{
    public MyComponent()
    {
        :
    }
    public void DoSomeWork()
    {
        ILogger logger = ServiceLocator.GetService();
        :
    }
}

You have a dependency resolver component that typically takes a type (commonly an interface) and returns an instance of a concrete type that implements that interface. The match between the type that is passed and the concretely-instantiated type is hidden in the implementation of the locator component. This pattern is known as the Service Locator pattern. Here’s another approach:

public class MyComponent
{
    private ILogger _logger;
    public MyComponent(ILogger logger)
    {
        _logger = logger;
    }
    public void DoSomeWork()
    {
        // Use the logger component here
        _logger.Log();
        :
    }
}

In this case, the MyComponent class receives the ILogger component to use from the outside world. Surrounding classes will take care of the initialization of the logger before passing it down to MyComponent. This is the essence of the Dependency Injection pattern.

What’s the difference (if any) between Dependency Injection and Service Locator? Both patterns are good at implementing the Dependency Inversion principle. The Service Locator pattern is easier to use in an existing codebase as it makes the overall design looser without forcing changes to the public interface. For this same reason, code that is based on the Service Locator pattern is less readable than equivalent code that is based on Dependency Injection.

The Dependency Injection pattern makes it clear since the signature  which dependencies a class (or a method) is going to have. For this reason, the resulting code is cleaner and more readable. What about ASP.NET MVC?

Dependency Inversion in ASP.NET MVC

ASP.NET MVC is designed with several extensibility points, but generally it lacks a comprehensive support for dependency injection. A service locator is probably the most effective way of making an existing framework more loosely coupled by the addition of new extensibility points, because it is the least intrusive solution. A service locator acts as a black box that you install in a specific point and let it figure out what contract is required and how to get it. ASP.NET MVC has a number of extensibility points, which are system components that can be replaced with custom components. Table 1 lists the known extensibility points as of ASP.NET MVC 3.

Provider Description
Action Invoker // In the constructor of a controller class controller.ActionInvoker = new YourActionInvoker();
Controller factory // In global.asax, Application_Start var factory = new YourControllerFactory(); ControllerBuilder.Current.SetControllerFactory(factory);
Dictionary values // In global.asax, Application_Start var providerFactory = new YourValueProviderFactory(); ValueProviderFactories.Factories.Add(providerFactory);
Model binder // In global.asax, Application_Start ModelBinders.Binders.Add(typeof(YourType), new YourTypeBinder());
Model binder provider // In global.asax, Application_Start var provider = new YourModelBinderProvider(); ModelBinderProviders.BinderProviders.Add(provider);
Model metadata // In global.asax, Application_Start ModelMetadataProviders.Current = new YourModelMetadataProvider();
Model validator // In global.asax, Application_Start var validator = new YourModelValidatorProvider(); ModelValidatorProviders.Providers.Add(validator);
TempData // In the constructor of a controller class controller.TempDataProvider = new YourTempDataProvider();
View engine // In global.asax, Application_Start ViewEngines.Engines.Clear(); ViewEngines.Engines.Add(new YourViewEngine());

Table 1. Extensibility points in ASP.NET MVC.

Until ASP.NET MVC 3, there was no standard way to register custom components. Each component listed in Table 1 requires its own API to be integrated in a user application. Starting with version 3, ASP.NET MVC introduces a new (optional) model based on dependency resolvers. To replace a system component, you can either take the route described in Table 1 or register a dependency resolver for the type. The ASP.NET runtime will then detect the dependency resolver and invoke it whenever appropriate.

A dependency resolver is just a service locator integrated with the ASP.NET MVC codebase. Resolvers are a way to add the implementation of the Dependency Inversion principle into an existing (large) codebase. For the size and complexity of the codebase, the use of Dependency Injection is less appropriate because it would have required changes at various levels in the public API. This just isn’t an option for a framework such as ASP.NET MVC. Let’s find out more details about the implementation of dependency resolvers in ASP.NET MVC.

Defining Your Dependency Resolver

An ASP.NET MVC dependency resolver is an object that implements the following interface:

{
    Object GetService(Type serviceType);
    IEnumerable<Object> GetServices(Type serviceType);
}

The logic you put in the resolver is entirely up to you. It can be as simple as a switch statement that checks the type and returns a newly created instance of a fixed type. It can be made more sophisticated by reading information from a configuration file and using reflection to create instances. Finally, it can be based on Unity or any other IoC framework. Here’s a very simple, yet functional, resolver:

public class SampleDependencyResolver : IDependencyResolver
{
    public object GetService(Type serviceType)
    {
        if (serviceType == typeof(ISomeClass))
            return new SomeClass();
        :
    }
    public IEnumerable<object> GetServices(Type serviceType)
    {
        return Enumerable.Empty<Object>();
    }
}

The code next shows a resolver that uses Unity (and its configuration section) to resolve dependencies.

public class UnityDependencyResolver : IDependencyResolver
{
  private readonly IUnityContainer _container;

  public UnityDependencyResolver() : this(new UnityContainer().LoadConfiguration())
  {
  }

  public UnityDependencyResolver(IUnityContainer container)
  {
    _container = container;
  }

  public Object GetService(Type serviceType)
  {
    return _container.Resolve(serviceType);
  }

  public IEnumerable<Object> GetServices(Type serviceType)
  {
    return _container.ResolveAll(serviceType);
  }
}

You register your own resolver with the ASP.NET MVC framework through the SetResolver method of the DependencyResolver class, as shown below:

protected void Application_Start()
{
   // Prepare and configure the IoC container
   var container = new UnityContainer();
   :

   // Create and register the resolver
   var resolver = new UnityDependencyResolver(container);
   DependencyResolver.SetResolver(resolver);
}

If you use an IoC framework from within the resolver then you need to figure out the best way to provide it with the list of registered types. If you prefer to pass this information via fluent code, then you need to fully configure the IoC container object before you create the resolver. If you intend to configure the IoC using the web.config file then, as far as Unity is concerned, you can use the default constructor of the resolver which includes a call to load configuration data. Note, however, that you may need to change this code if you target a different IoC framework.

Overall, the dependency resolver is an internal tool that developers can optionally use to roll their own customized components instead of system components. The power of dependency resolvers is limited by the use of them that ASP.NET MVC makes. Resolvers are invoked in well- known places to achieve well known goals. In other words, if ASP.NET MVC doesn’t invoke the resolver before creating, say, the controller cache, there’s not much you can do to replace the built-in cache with your own one.

Using Resolvers in Applications

It turns out that a dependency resolver is nothing more than the name that ASP.NET MVC uses for a service locator. How would you write one for a real application? The answer is that you have one resolver per application and write it to serve as many as customizations as you like. Here’s a slightly more specific version of the sample dependency resolver that we considered a moment ago.

public class SampleDependencyResolver : IDependencyResolver
{
    public object GetService(Type serviceType)
    {
        try
        {
            return serviceType == typeof(ModelMetadataProvider)
                ? new ExtendedAnnotationsMetadataProvider()
                : Activator.CreateInstance(serviceType);
            }
            catch
            {
            return null;
        }
    }

    public IEnumerable<object> GetServices(Type serviceType)
    {
        return Enumerable.Empty<object>();
    }
}

The GetService method receives a type to resolve, and checks it against a list of known types. For some known interface types, it may simply return a manually-created instance of a known type. For other types it may return nothing, meaning that the resolver is not able to resolve that type.

An ASP.NET MVC dependency resolver has no way to resolve the same type in different ways during the lifetime of the application. While this may be a significant limitation in the implementation of a generic service locator, it is much less of a problem in the specific context of ASP.NET MVC. Dependency resolvers are an internal feature of ASP.NET MVC and only the internal code of ASP.NET MVC decides when and how to call application-registered resolvers. In the end, your resolvers will be called only in a limited number of circumstances, and the interface is more than acceptable.

So Should You Resolve or Should You Inject?

Should You Resolve or Should You Inject? If you look at this question in terms of the effectiveness of the design, then Dependency Injection is preferable to service location because it results in a cleaner design and a crystal-clear assignment of responsibilities. To use Dependency Injection, though, you may need to take the liberty of modifying the public interface of the API. This may or may not be acceptable depending on the context; it was not acceptable, for example, in the transition from ASP.NET MVC 2 to ASP.NET MVC 3. For this reason, Microsoft opted for the use of dependency resolvers, a fancy name for a classic service locator component. More realistically, a service locator is the only option you have to add an extensibility point to a large existing codebase that you don’t want (or are not allowed) to refactor significantly.

Dino Esposito

Author profile:

A long-time trainer and consultant, Dino is the author of many popular books for Microsoft Press for .NET developers.including “Architecting Mobile Solutions for the Enterprise“ and “Programming ASP.NET MVC” both for Microsoft Press. CTO of Crionet, a firm specializing in Web-based and mobile solutions for sport events across Europe (http://www.crionet.com), at the moment Dino is also technical evangelist for JetBrains, where he focuses on Android and Kotlin development, and member of the team that manages WURFL—the database of mobile devices used by organizations such as Google and Facebook. Follow Dino through his blog at http://software2cents.wordpress.com or at http://twitter.com/despos

Search for other articles by Dino Esposito

Rate this article:   Avg rating: from a total of 32 votes.


Poor

OK

Good

Great

Must read
Have Your Say
Do you have an opinion on this article? Then add your comment below:
You must be logged in to post to this forum

Click here to log in.


Subject: Finally understood dependency injection
Posted by: jhonatantirado (view profile)
Posted on: Tuesday, April 24, 2012 at 10:13 AM
Message: Excellent post! And good examples. I've been trying to understand this DI thing and finally got it thanks to your explanation.

Subject: A post about DI
Posted by: jhonatantirado (view profile)
Posted on: Tuesday, April 24, 2012 at 12:11 PM
Message: Given I think I've finally understood this DI stuff, I wrote a post as an excercise and to check if I really got it.
http://jhonatantirado.wordpress.com/2012/04/24/dependency-inversion-service-locator-or-dependency-injection/

Subject: Premature Generalization at its finest
Posted by: Jonathan Allen (view profile)
Posted on: Tuesday, April 24, 2012 at 1:49 PM
Message: > If, for example, your class needs to use a Logger component, then the best you can do is to make your class aware of an ILogger interface rather than a Logger class. In this way, you can change the implementation of the logger class at any time (and for how many times you want) without breaking the host code.

What?

I change the implementation details of my logger all the time, yet I've never once found the need to expose an ILogger abstract interface.

Subject: Why?
Posted by: Jonathan Allen (view profile)
Posted on: Tuesday, April 24, 2012 at 1:59 PM
Message: > The Dependency Inversion principle says that classes should not have dependencies on concrete classes but only to abstractions.

Why?

What is the specific problem you are trying to overcomes? Does that problem occur for ALL classes or only a very small subset?

Back when we used COM we literally couldn't reference a class by its name except to create it. Literally everything else we did was through one or more abstract interfaces that it implemented. Or in other words, the Dependency Inversion Principal was forced upon us.

When .NET was created we made a conscious decision to abandon that principal. Numerous reasons were cited including issues such as how it impacts forwards compatibility and the proliferation of interfaces such as IFooEx2.

Now this isn't to say the it is completely useless. There are specific places where the dependency inversion design pattern are applicable. But to say that we should blindly apply that design pattern as if it were a universal principal is completely irresponsible.


Subject: Re: What and Why?
Posted by: nick harrison (view profile)
Posted on: Wednesday, April 25, 2012 at 8:49 AM
Message: This may seem like over kill, but following a Test Driven Development methodology, you will always be guaranteed two implementations of the interfaces defined. The initial concrete implementation that you will run in production and mock test objects that you will use in unit testing.

Starting with this principle and defining the interfaces from the beginning makes it easier to develop with testability in mind.

As for the specific example that you refer to in your comments, the underlying implementation of something as nebulous as logger should never be tightly coupled to any logic. Code using a logging service should be oblivious to the implementation details of the specific logging service used. As soon as you have logic relying on using log4net or any implementation, you will have problems.

Subject: Dependency Resolvers
Posted by: Neil (view profile)
Posted on: Thursday, April 26, 2012 at 2:01 PM
Message: Great article, but just to add that if using Castle Windsor the IDependencyResolver lacks a release method which could cause memory leaks, (http://stackoverflow.com/questions/4140860/castle-windsor-dependency-resolver-for-mvc-3).

If you manually Resolve with Windsor you're expected to Release.

Subject: Are both
Posted by: Rippo (not signed in)
Posted on: Saturday, April 28, 2012 at 3:15 AM
Message: I use D.I. in my controllers CTOR and find it is very easy to unit test my controllers. If I use the Service Locator method above is unit testing just as easy? Thanks

Subject: Logging and problems
Posted by: Anonymous (not signed in)
Posted on: Monday, April 30, 2012 at 12:13 AM
Message: "As soon as you have logic relying on using log4net or any implementation, you will have problems."

What are these problems? The only time you would have a problem is if you decided to switch Logging tools - and I have yet to find a reason to switch once I've picked a logging tool - mostly because the logging tools available typically are pluggable anyway (so you can switch from text file to database logging, etc, with some configuration already). Or if you rolled your own logger - you could add that configurability in. The interface to any logging tool is generally pretty straight-forward as is.

Logging is so often used as an example for DI, and I believe it is a bad example because it really isn't that useful for that case. Now, avoiding writing a bunch of boilerplate logging code with AOP is a much better area where logging is a good example.

There is certainly a place for DI and/or Service Location, but claiming that if you don't use it for your logging code you will run into "problems" seems a bit naive to me.

Subject: RE: Logging and problems
Posted by: nick harrison (view profile)
Posted on: Monday, April 30, 2012 at 7:51 AM
Message: I have had to switch logging once.

I had everything hard coded to my own custom logger and thought that I would never need to change it. Calls to this logger were sprinkled through out my code.

Then someone saw the logging application block from the enterprise library and thought that we had to adopt it. We were already adopting several pieces from the enterprise library.

It took a solid week of hunting and changing and testing to find all of the points that needed to be changed.

Then all was happy.

Until we started using nhibernate which came with log4net. We opted to switch to log4net. Now this time it was a much simpler. In part because the enterprise library forced us to use an adapter layer because they do not guarantee forwards or backwards compatibility. So this time, all we had to change was the adapter layer much like we would have had to do in upgrading the version for EL.

I have found that logging strategies is one area that is often changed. Applications probably have their RDBMS set in stone before the project is even a gleam in anyone's eye, but how logging and instrumentation will be implemented is often subject to the winds of change.

Subject: Dino great stuff here DI is all the rage here in the greater Portland area.
Posted by: Anonymous (not signed in)
Posted on: Monday, April 30, 2012 at 11:33 AM
Message: I actually can't remember a non injected application anymore.

I will say injected applications can be a bit interesting to debug at times.

Subject: provider model for data
Posted by: M. Lang (not signed in)
Posted on: Sunday, May 06, 2012 at 8:40 PM
Message: I just use provider model for abstracting away where i get my data. It is much easier than di frameworks to code, debug, and configure.

I don't see the need to inject MVC controllers. I am not going to swap out controller implementations. Action methods just need to get data from an abstraction and pass it to a view or return it as json.

What i do need to swap out is whether i load from the Db, AppFabric, a webservice or something else. Provider model is perfect for that.

Subject: how to resolve in mvc
Posted by: panos.roditakis (not signed in)
Posted on: Monday, May 07, 2012 at 12:29 PM
Message: In mvc i would use actionfilters as service providers and not DI controllers because it does not feel right from the framework's prespective.

Subject: Great Article!
Posted by: turibbio (view profile)
Posted on: Tuesday, May 08, 2012 at 8:51 AM
Message: Very good article! Thanks Dino.

 

Top Rated

Acceptance Testing with FitNesse: Multiplicities and Comparisons
 FitNesse is one of the most popular tools for unit testing since it is designed with a Wiki-style... Read more...

Acceptance Testing with FitNesse: Symbols, Variables and Code-behind Styles
 Although FitNesse can be used as a generic automated testing tool for both applications and databases,... Read more...

Acceptance Testing with FitNesse: Documentation and Infrastructure
 FitNesse is a popular general-purpose wiki-based framework for writing acceptance tests for software... Read more...

TortoiseSVN and Subversion Cookbook Part 11: Subversion and Oracle
 It is only recently that the tools have existed to make source-control easy for database developers.... Read more...

TortoiseSVN and Subversion Cookbook Part 10: Extending the reach of Subversion
 Subversion provides a good way of source-controlling a database, but many operations are best done from... Read more...

Most Viewed

A Complete URL Rewriting Solution for ASP.NET 2.0
 Ever wondered whether it's possible to create neater URLS, free of bulky Query String parameters?... Read more...

Visual Studio Setup - projects and custom actions
 This article describes the kinds of custom actions that can be used in your Visual Studio setup project. Read more...

.NET Application Architecture: the Data Access Layer
 Find out how to design a robust data access layer for your .NET applications. Read more...

Calling Cross Domain Web Services in AJAX
 The latest craze for mashups involves making cross-domain calls to Web Services from APIs made publicly... Read more...

Web Parts in ASP.NET 2.0
 Most Web Parts implementations allow users to create a single portal page where they can personalize... Read more...

Why Join

Over 400,000 Microsoft professionals subscribe to the Simple-Talk technical journal. Join today, it's fast, simple, free and secure.