designing technology that makes business sense

During the keynote of the #mvcconf virtual conference, Scott Hanselman said that only 3 contributions have been made to the open source Nerd Dinner project.  3?!  No wonder my Java friends scoff when I say there is open source in the .Net world.  We (.Netters) should be ashamed.  Most of us either cut our MVC teeth on Nerd Dinner, or we at least refined our skills by reviewing its implementation.

I will be conducting a series of experiments in dependency injection for perso

del.icio.us Tags: ,
nal reasons, and I will be using Nerd Dinner as my reference MVC application.  It’s simple, it’s a known quantity, and perhaps something over the coming weeks will be worthy of contribution to the project.  This post will not likely be worthy of contribution; I am offering nothing new.  I am adding dependency injection using StructureMap to an MVC project.  This has been done before, but I have to get to step one before I can get to step 2.

Others have demonstrated StructureMap on MVC, and I will be borrowing heavily from Jimmy Bogard of LosTechies.com.  Jimmy has forgotten more about dependency injection than I will ever know, and he has an in-depth series on dependency injection in .Net MVC. Jimmy goes deep into MVC to isolate dependencies, and my interest will be in looking a various alternatives to dependency injection applied to a well known reference implementation.  I am not a purest.  I believe DI and TDD are critical to quality code, I am believe DI frameworks and mocking are better than fakes and “poor man’s DI, and I agree with Jimmy’s position that the ActionResult is a kind of black box with too much responsibility.  However, beyond that, I do not (yet) care.  I want my code to be good, but I want my code to get to market.  An application only has value when it is being used to solve a problem.  While I am a developer, I have also run development companies, and I am looking for quality with efficiency.

Nerd Dinner

Nerd Dinner does not use a dependency injection framework, rather it uses a default constructor to enable dependency injection of the form:

        IDinnerRepository dinnerRepository;
        public DinnersController()
            : this(new DinnerRepository()) {
        }
        public DinnersController(IDinnerRepository repository) {
            dinnerRepository = repository;
        }

The empty constructor is required by the default MVC controller factory. The second constructor allows dependencies to be injected. In small applications this type of dependency injection works fine.  However, in even moderately sized applications, the inherent dependency on the concrete classes (DinnerRepository in this case) becomes a problem.  If you decide to use a NewDinnerRepository, you may be facing code changes in many places instead of a single configuration or registry.  Let’s apply StructureMap.

Assuming you have installed StructureMap and added a refernce in your project to StructureMap.dll, the first thing you want to do is to tell the application to use StructureMap.

	void Application_Start()
	{
	   RegisterRoutes(RouteTable.Routes);
            //initialize structuremap container
            Bootstrapper.Initialize();
            //let structuremap handle creating controllers
            ControllerBuilder.Current.SetControllerFactory(new StructureMapControllerFactory());
	   ViewEngines.Engines.Clear();
	   ViewEngines.Engines.Add(new MobileCapableWebFormViewEngine());
	}

Step 1 is to initialize StructureMap. A common solution is to use a Bootstrapper class to handle the initialization. Following initialization, we tell the ControllerBuilder to use the StructureMapControllerFactory as its controller factory.  Now for the Bootstrapper initialization:

    public class Bootstrapper
    {
        public static void Initialize()
        {
            ObjectFactory.Initialize(x => x.AddRegistry<NerdModelRegistry>());
        }
    }

 

In the initialize method, StructureMap’s ObjectFactory is called to configure the default mapping of Interface objects to concrete objects.  For a project of any size, using one or more registries will help keep your configuration organized.

    public class NerdModelRegistry : Registry
    {
        public NerdModelRegistry()
        {
            //Repositories
            For<IDinnerRepository>().Use<DinnerRepository>();
        }
    }

A registry can be used to map interface definitions to default concrete classes.  So now we have configured StructureMap to provide dependency injection for Nerd Dinner, at least the controllers, and we have told the application to use the StructureMapControllerFactory instead of the default ControllerFactory.  However, we have not defined a StructureMapControllerFactory.  That’s next.

    public class StructureMapControllerFactory: DefaultControllerFactory
    {
        protected override IController GetControllerInstance(System.Web.Routing.RequestContext requestContext, Type controllerType)
        {
            if (controllerType == null)
            {
                return base.GetControllerInstance(requestContext, controllerType);
            }
            return ObjectFactory.GetInstance(controllerType) as Controller;
        }
    }

 

The StructureMapControllerFactory creates a controller and does not require a controller with an empty constructor.  This implementation of the StructureMapControllerFactory is fairly common, but Jimmy Bogard would take this a step farther.  He recommends injecting the container into the factory, and then use the container to get an instance of the controller.  I believe Jimmy is more right than I am, and I encourage you to review his compelling argument.  However, I am not yet convinced there is a return on code (R.O.C.) for container injection.

With StructureMap in place and configured, let’s revisit our controller constructor.  Effectively, the empty constructor with the default dependency on the concrete repository goes away.

    IDinnerRepository dinnerRepository;
    //public DinnersController()
    //    : this(new DinnerRepository()) {
    //}
    public DinnersController(IDinnerRepository repository) {
        dinnerRepository = repository;
    }

Pretty trivial change to the controller, huh?  However, consider that this same change will be made to the Dinner, RSVP, Search, and Services controllers.  Now mentally scale this out to a large real-life production application.  If you want to change a repository, a service, a logger, etc., changing references to the concrete types can occur all over your code, or it can happen at a single location in your Registry class.  Further, consider what this type of change could mean for regression testing.  Dependency injection frameworks make unit testing and TDD much easier as we shall see in coming weeks.

Now there’s one gotcha remaining.  I excluded the AccountController from the dependency injection.  MVC will use the still use the empty constructor of the Account controller, and I don’t want to invest effort into the AccountController.  I expect to experiment with authentication alternatives in the near future.  For now I need a band-aid.

[StructureMap.DefaultConstructor]
public AccountController()
  : this(null, null) {
}

For now we’ll use the StructureMap DefaultConstructorAttribute. Yes, this is technical debt that will need to be repaid, but I am considering the AccountController as technical debt that needs to be addressed.

This implementation of StructureMap is not new, and DI purists may dismiss its simplicity.  However, I argue that this implementation achieves a significant dependency injection benefit with very little code and very little effort.  Next we will build upon this sample to use automocking with Moq.


Comments

August 6. 2010 05:38

Hi. I just noticed that your site looks like it has a few code problems at the very top of your website's page. Is it an older version of Blog Engine?  I'm not sure if everybody is getting this same bugginess when browsing your site? I am employing a totally different browser than most people, referred to as Chrome, so that is what might be causing it? I just wanted to make sure you know. Thanks for posting some great postings and I'll try to return back with a completely different browser to check things out!

Hypercom T7Plus Manual United States

August 6. 2010 12:35

@Hypercom I did just upgrade both my website and blog.  But both appear to look fine in Chrome (and FireFox and IE).  What kind of issues do you see?

wilk United States

August 12. 2010 22:09

What would it take to for me to create a blog like yours?

435508-B21 United States

August 13. 2010 10:27

It looks like one-of-a-kind. Thank you for the information and a present on top of that! I love it! A round of applause to everyone ...I am so grateful for this.

Bryanna Willette United States

August 13. 2010 16:13

We do have to read more blogs like this one for sure !!

impotenza Ireland

August 17. 2010 17:16

Just wanted to say your Blog is in my rss you do magic on words.. Cheers,

Blackhat SEO Forum India

August 17. 2010 22:47

I enjoyed this post and also wanted to point out that i truly such as the design and really feel of one's website. I am utilizing wordpress as well on my weblog but happen to be looking for a template like this that is a lot much better than what I've. I see the theme is listed about the footer so I will take a better look at it.

Here United States

August 19. 2010 06:18

Sir, I got to your site by browsing in search engine. I hope I find any information from this site. Thanks

disease Iraq

August 23. 2010 18:14

Good to know... thanks for sharing

tech jobs United States

August 25. 2010 03:14

Hey, this can be a super website. I'm continuously searching for blogs similar to this. Continue the great effort!

renovate United States

August 25. 2010 12:46

i've added your RSS feed to my reader, thanks.

used stationary bikes United States

August 25. 2010 23:05

Great website! I'll be back for sure...

tech jobs LA United States

August 26. 2010 09:51

Are any of you even reading what was posted? It seems people are just posting because they can. Nothing makes sense.

flash pro United States

August 27. 2010 16:03

@Flashpro, it does seem to be filled up with a lot of spammers.

Amy Sanders United States

August 28. 2010 22:09

This is a great blog I really loved it.I am bookmarking and definetely come back.

Sosby9@gmail.com United States

August 31. 2010 15:25

This article was really helpful and interesting. Thank you for sharing this. Those commented before me could have given some interesting views.

Gregory @ web design shanghai Canada

August 31. 2010 18:36

Guys this is a great blog, I really find it very usefull and enjoyed it.

SEO Firm, Affordable SEO Service Lao P.D.R.

Comments are closed