Skip navigation

Using IoC with Structure Map 2.6 and MVC 3.0

Michael K. Campbell's tips for using the StructureMap Inversion of Control (IoC) container with ASP.NET MVC 3

Inversion of Control (IoC) provides developers with a great way to componentize and modularize their code, while also serving as a fantastic resource for encouraging and enabling true unit testing. To that end, I've been using StructureMap as an IoC container. Only, I recently found that wiring it up to take advantage of ASP.NET MVC 3.0's new features that support IoC was a bit more difficult than anticipated. So, I decided to share what I've learned up to this point.

MVC 3.0 and IoC
A few months ago I contemplated what would happen if I needed or wanted to change out IoC Containers—say, to switch to Ninject or Unity instead of using StructureMap. The part of my brain (that likes to overbuild things) instantly realized that I should probably start building my applications with some sort of abstraction around IoC Containers and injection—so that I could more easily swap out different containers if or as needed. However, the more practical part of my brain (that likes to finish things) happily realized that while building such an abstraction would be fun, it wouldn't provide any immediate benefit. So, in a spirit of YAGNI and a realization that I could "burn that bridge if and when I came to it," I decided to move on to other things.

Fast forward a few months to when ASP.NET MVC 3.0 was released, and I was glad I hadn't wasted any time on abstracting IoC functionality—as the ASP.NET MVC team had done a brilliant job of it.

Specifically, MVC 3.0 provides a new DependencyResolver "intrinsic" that you can load up with your IoC container details and objects as needed; then you can just query DependencyResolver directly when you need to look up or locate services or objects instead of directly interacting with your IoC container of choice. The result, of course, is that (once again) a set of abstractions helps make code that much easier to maintain and extend when or if needed.

Getting MVC 3.0 And StructureMap 2.6 To Play Nicely Together
Only, getting all this sorted out in MVC 3.0 is more painful than I'd like to admit. A big part of the pain involved in getting IoC working with MVC 3.0 is that there just isn't much in the way of documentation yet. Yes, Brad Wilson has done a great job of providing an 11-part series in his blog on Service Location, but most of that content was written before MVC 3.0 was officially released or RTM'd.

Nor does it help that the documentation for StructureMap 2.6 is quite sparse, especially since StructureMap 2.6 represents some big changes over its predecessor. Or, more specifically: There are some big syntactical and functional changes that have made their way into StructureMap 2.6—which was officially released only very recently. Consequently, for someone like me who was only just starting to get the hang of effectively working with Service Location and Inversion of Control, getting StructureMap 2.6 and MVC 3.0 to play nicely together took more effort than I would have liked.

Happily though, I didn't have to figure everything out on my own, as I was able to pinch and crib a number of different features or facets of how to get everything working from Javier Lozano, Steven Smith, and K. Scott Allen (along with copious amounts of StackOverflow thrown into the mix).

An End-to-End Sample App
The point though, was that I had to cobble lots of different things together. So, given how much difficulty I found in locating an end-to-end sample application that showed how to use MVC 3.0 and StructureMap together, I decided to provide an end-to-end sample of my own. (Email me at [email protected] if you'd like a copy of the sample application—which includes some additional notes and info that didn't make it into this article.)



To create this sample application, I fired up Visual Studio 2010, created a new ASP.NET MVC 3 web application, then created a new "blank" Internet Application (instead of an "Empty" template/application). From there I used NuGet to "install" StructureMap 2.6.2 into my web application, then got busy coding.

The first thing I needed to touch in my new, sample, app was the Global.asax, where I added the following two lines at the bottom of the Application_Start() method:

this.InitializeContainer();
this.RegisterModelBinders();

I actually didn't implement the second of these methods—but wanted to include it as the order of operations defined here is important (as in: Wire up your IoC container, then use it (if needed) to help build out your model binders if you're using any). For the InitializeContainer() method, I ended up with something that looks like Figure 1.

The first part of this method opens up a large lamba expression that allows me to begin specifying which specific, concrete, classes should be coupled or used with specified interfaces—using the .For<>.Use<> syntax, where you can also specify scope or lifetime (caching) information as well using specific additional methods in fluent fashion. Toward the bottom of this method, though, three important things transpire. First, I inform StructureMap that whenever it gets a request for an IControllerActivator that it should use something called a SiteControllerActivator—where the implementation of that class looks like Figure 2.

As you can see, SiteControllerActivator represents a very simple implementation—that basically just implements the new IControllerActivator abstraction (part of an overall replacement to overriding the ControllerFactory), then basically just hands off control of all needed logic and functionality to the IContainer instance that was passed in. The beauty, however, is that the IContainer instance (in this case) is StructureMap—though it could easily be something else if needed because of the fact that we're dealing with abstractions.

Then, I've taken a similar approach to abstracting the instantiation of FilterAttributes by means of the new conventions provided in MVC 3.0 where you use a FilterAttributeFilterProvider, as shown in Figure 3.

The name of that provider is obviously a mouthful. But, again, the idea is that Filters end up getting routed through a Service Locator that can "build up" dependencies as needed. Everything is cleanly abstracted into a single class, which, in turn, is configured in the Global.asax in the line where I specify which IFilterProvider service or interface that StructureMap should use.

Then, once these directives have been handled, the lambda expression (in the InitializeContainer() method within the Global.asax) is wrapped up. Then the final bit of abstraction logic is handled, as the StructureMap container is bundled up and passed into the static DependencyResolver via the .Set() method. The call to this method, in turn, requires a bit of abstraction, which is handled through the use of a class that I've called a SiteDependencyResolver, shown in Figure 4.

And, this class, in turn, really just represents some additional wiring that is specific to mapping StructureMap calls against calls to the generic DependencyResolver in order to correctly manage IoC and service resolution through various .GetService() overloads.

Once those core considerations are addressed, you're then free to resolve services from within your app as needed, using calling code that's as simple as the following:

IUserRepository userRepo =
    DependencyResolver.Current.GetService<IUserRepository>();

Depending on how you end up resolving services at runtime, however, the approach listed above might constitute an anti-pattern in some cases. As such, an approach that is more readily advocated for such dependencies is to simply pass them in directly through constructor injection—or via property injection where constructor injection isn't possible (such as is the case with .NET Attributes, which are instantiated by the runtime and which can't be intercepted).



A Few Things Left to Resolve
Sadly, while I was hoping to actually be able to use StructureMap 2.6 and MVC 3.0 to address the need for property injection via StructureMap's \\[SetterPropery\\], I wasn't able to get that to work within my sample app (at least not yet). In the InitializeContainer() code listed above, in roughly the middle of the function, you'll notice that I've defined a call to factory.SetAllProperties, where I then specify the kinds of property to be set by specifying the Type of the property I want set. That code compiles, and executes—but, sadly, when my Attributes/Filters are handed out of the SiteFilterProvider, they haven't been "built-up" with the necessary property injection. I'm assuming that I'm missing something simple in that regard (maybe the SiteFilterProvider isn't doing what I think it is)—and hopefully I'll figure that out soon.

Otherwise, feel free to email me ([email protected]) if you'd like a copy of the sample application that I've created—as it provides and end-to-end sample of using StructuctureMap and MVC 3.0 together (minus property setters).

Michael K. Campbell ([email protected]) is a contributing editor for SQL Server Magazine and a consultant with years of SQL Server DBA and developer experience. He enjoys consulting, development, and creating free videos for www.sqlservervideos.com.

Hide comments

Comments

  • Allowed HTML tags: <em> <strong> <blockquote> <br> <p>

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.
Publish