About the author

Steven HarmanSteven Harman is a passionate developer who believes that writing great software isn't just a job, its a craft.

ASP.NET MVP

For recent posts and more about me, scroll to the bottom.

Subscribe

  • Subscribe to my feed. via RSS
  • Subscribe via email via email

Jobs

Badges

  • Subtext Project
  • Support Subtext
  • HiddenNetwork.com Banner

TDD + DI + ASP.NET MVC Made Better with StructureMap's Fluent API, Oh My!

My God... could I put any more acronyms in that title. Yeah, I probably could. Oh, and if you just came for the code, jump to the bottom.

In his post TDD and Dependency Injection with ASP.NET MVC, Phil used a DI framework to reduce friction and increase his Test-Fu when doing the TDD thang.

How do you up your Test-Fu? By pushing the monotonous, and sometimes overbearing, work of wiring up dependencies off to a tool - in this case, a Dependency Injection tool called StructureMap.

Angle bracket madness

Phil was good enough to show us how to configure StructureMap via it’s default mechanism, the StructureMap.config file. And while I’m all for outsourcing the boring work so I can work less yet do more, one thing I really hate is angle-brackets. And the one thing I hate even more than angle bracket programming is programming with magic strings.

<?xml version="1.0" encoding="utf-8" ?>
<StructureMap>
    <Assembly Name="MvcApplication" />
    <Assembly Name="System.Web.Extensions
              , Version=3.6.0.0
              , Culture=neutral
              , PublicKeyToken=31bf3856ad364e35" />

    <PluginFamily Type="System.Web.Mvc.IController"
                  Assembly="System.Web.Extensions
                  , Version=3.6.0.0
                  , Culture=neutral
                  , PublicKeyToken=31bf3856ad364e35"
                  DefaultKey="HomeController">
        <Plugin Type="MvcApplication.Controllers.HomeController"
                ConcreteKey="HomeController"
                Assembly="MvcApplication" />
        <Plugin Type="MvcApplication.Controllers.BlogController"
                ConcreteKey="BlogController"
                Assembly="MvcApplication" />
    </PluginFamily>

    <PluginFamily Type="MvcApplication.Models.IPostRepository"
                  Assembly="MvcApplication"
                  DefaultKey="InMemory">
        <Plugin Assembly="MvcApplication"
                Type="MvcApplication.Models.InMemoryPostRepository"
                ConcreteKey="InMemory" />
    </PluginFamily>

</StructureMap>

The bold lines are changes I had to make to the original configuration file to get the demo application to actually run.

And what do we see all over the config file? Angle brackets and magic strings. Lucky for us, Jeremy added a fluent interface to StructureMap 2.0 that lets us leave all of those ugly angel brackets behind... and we can even get rid of some of those magic strings!

Using the fluent interface

To keep it simple, and because I’m lazy, I decided to grab Phil’s demo source code and modify it to use the fluent API rather than the default XML configuration. Savvy?

With code in hand I fired up Visual Studio and headed straight for the Application_Start method. I’m really just using that method to call my own ConfigureContainer method, which actually does the work of configuring StructureMap. For consistency sake I want my fluent configuration code to do the same thing that Phil’s XML based configuration did.

It ended up looking like this (I used a screen shot too keep it more readable):

StructureMap Fluent API

As you can see there are no only a few angle brackets, use for Generics, but that’s a heck of a lot less than the XML had. I was also able to get rid of a few of the magic strings by using

.UsingConcreteType<MyClassHere>().WithName(typeof(MyClassHere).Name)

And with that we now have the IoC container configured and working exactly like it was using the StructureMap.config file. Don’t believe me? Grab the code (below) and take a look for yourself. I even added an AppSettings key to the web.config that allows you to switch back and forth between how StructureMap gets configured.

Resources

Want to take a spin thru the code? Grab it here: [DOWNLOAD]

Also, don’t forget to check out Phil’s original post for way more information about using TDD + DI to make mvc.net easier for U.

What others are saying.

# re: TDD + DI + ASP.NET MVC Made Better with StructureMap's Fluent API, Oh My!
Gravatar Haacked
Dec 13, 2007
Here's my one complaint about the fluent interface. You now have a dependency on the concrete type from your web project.

Probably not a problem in 90% of the cases, so I agree, I'm nitpicking. But if you're doing a real plug-in architecture, then it's a problem.

However, for demo purposes, I really should be using that! It's WAY less code which is sweet.
# re: TDD + DI + ASP.NET MVC Made Better with StructureMap's Fluent API, Oh My!
Gravatar Steven Harman
Dec 13, 2007
@Phil, So your concern about coupling our web project to a particular concrete class is only really a concern if we're using the IoC container to build a plug-in framework, right?

But in the demo code, similar the 90% case, that is not a concern b/c we're just wiring together our own, well-known classes. Right?

Oh, and to help maintain loose coupling you could take advantage of StructureMap's Registry class to make programmatic changes to the StructureMap configuration at runtime. Using the Registry you can have each assembly configure itself and then at runtime those configuration settings will get loaded into StructureMap. Take a look at Jeremy's Plugging UserControl's with StructureMap 2.0 post for more details.
# re: TDD + DI + ASP.NET MVC Made Better with StructureMap's Fluent API, Oh My!
Gravatar Steven Harman
Dec 13, 2007
@Phil, I just re-read my previous comment and if I came off a bit bitchy, that wasn't my intention. The first two paragraphs were just me trying to make sure I understood what your concern was... and when it was applicable. :)
# Links (12/13/2007)
Gravatar Member Blogs
Dec 13, 2007
.NET Object oriented JavaScript class library in C#/.NET style Building Multi-Tier Web Application in
# re: TDD + DI + ASP.NET MVC Made Better with StructureMap's Fluent API, Oh My!
Gravatar Jeffrey Palermo
Dec 16, 2007
There is a StructureMapControllerFactory in MvcContrib, so you might check it out: http://mvccontrib.org
# re: TDD + DI + ASP.NET MVC Made Better with StructureMap's Fluent API, Oh My!
Gravatar Steven Harman
Dec 17, 2007
@Jeffrey, Thanks for the link to MvcContrib. I actually checked out the project (I <3 SVN) the day after you announced it and I've been pulling down the latest bits on a regular basis in an attempt to stay in the loop. :)

But regarding the StructureMaptControllerFactory... don't we still need to register our concrete implementations with StructureMap at some point?

I suppose you could do something similar to how you'd normally wire up a Windsor container... looping through each Type in the assembly and finding all implementations of IController and registering it with the container.
# re: TDD + DI + ASP.NET MVC Made Better with StructureMap's Fluent API, Oh My!
Gravatar okubi
Dec 28, 2007
thanks for resources
nice docs.
# re: TDD + DI + ASP.NET MVC Made Better with StructureMap's Fluent API, Oh My!
Gravatar Chris Stewart
Jan 10, 2008
I'm afraid I simply "don't get" what DI is all about yet. I've been reading a lot of blog entries about it, but none of them have explained why I'd want to use this. I'm also curious to know whether it's useful only with ASP.NET MVC or in traditional Web Forms as well. Thoughts?
# re: TDD + DI + ASP.NET MVC Made Better with StructureMap's Fluent API, Oh My!
Gravatar Jay R. Wren
Jan 17, 2008
@Chris Stewart

it took me a while to grok DI/IoC too. Just keep reading and more than anything, do an example. Work through a demo.
# re: TDD + DI + ASP.NET MVC Made Better with StructureMap's Fluent API, Oh My!
Gravatar Tuna Toksoz
Jan 22, 2008
DI is "imitated" in webforms, unfortunately. Since the Page instances are created by microsoft's own handler directly, you have no chance but imitate the DI by using a base class.
# re: TDD + DI + ASP.NET MVC Made Better with StructureMap's Fluent API, Oh My!
Gravatar Chris Stewart
Feb 08, 2008
Can you explain that further? I've yet to find an example of DI using Web Forms, only ASP.NET MVC.
# re: TDD + DI + ASP.NET MVC Made Better with StructureMap's Fluent API, Oh My!
Gravatar Tuna Toksoz
Feb 19, 2008
I've heard that web client software factory is able to do injection. But i'd go for Rhino Igloo.
# re: TDD + DI + ASP.NET MVC Made Better with StructureMap's Fluent API, Oh My!
Gravatar John
Feb 28, 2008
I'm struggling with the same problem Phil is; I want to cycle throught types and register the different concrete types, but the fluent interface only allows generics. The frustrating thing is that looking at it in reflector, it's just doing typeof(T) under the hood...why can't I pass in a type?!

I like StructureMap for the same reasons; it's IoC only and doesn't require a config file. I just find it hard to believe that I can't do something as simple as register a Type rather than knowing the concrete class and coding a line for every one.

Can anyone help?
# re: TDD + DI + ASP.NET MVC Made Better with StructureMap's Fluent API, Oh My!
Gravatar Steven Harman
Feb 28, 2008
@John, I noticed the same thing when trying to setup the container for a project at work. And as it turns out, I think I can help!

Jeremy gave me commit access to the StructureMap repository and I've been meaning to go in and add non-generic methods to compliment the ones currently there. I've just not had time to get around to it.

I'll try to get it done early next week since it'd be nice to have for my current project as well. I'll blog about it when its done, so keep your eyes peeled... or your aggregator subscribed. ;)
# re: TDD + DI + ASP.NET MVC Made Better with StructureMap's Fluent API, Oh My!
Gravatar John
Feb 28, 2008
@Steven, Glad to hear that there are plans to extend the configuration to allow types in addition to generics. I'll definately be watching for that update. Do you think it'll make it into the 2.5 release of StructureMap?

In the mean time, I think I've got a solution that works. It's a bit on the ugly side, but seems to work.
Comments have been closed on this topic.