ASP.NET MVC3 has built in mechanisms to support an Inversion of Control container for the framework. Let us look at how to use StructureMap and tie it into MVC3’s framework for use with providing Controller classes as well as how we would normally use it to provide our custom classes.

If you’re using NuGet, you’ll find it automatically includes a reference to WebActivator, which is something that allows for calling startup code without having to edit the global.asax file. This post is for those that don’t want to use WebActivator for whatever reason.

Inside of the global.asax file add a method to perform the container initialization.

		private static void InitializeContainer()
		{
			// Configure IoC 
			DependencyRegistrar.EnsureDependenciesRegistered();

			StructureMapDependencyResolver structureMapDependencyResolver = new StructureMapDependencyResolver();
			DependencyResolver.SetResolver(structureMapDependencyResolver);
		}

In the first bit of code, the DependencyRegistrar class contains configures StructureMap once and only once.

		public static void EnsureDependenciesRegistered()
		{
			if (alreadyRegistered)
			{
				return;
			}

			lock (SyncronizationLock)
			{
				if (alreadyRegistered)
				{
					return;
				}

				RegisterDependencies();
				alreadyRegistered = true;
			}
		}

		private static void RegisterDependencies()
		{
			ObjectFactory.Initialize(
				x => x.Scan(
					scan =>
						{
							scan.TheCallingAssembly();
							scan.WithDefaultConventions();
							scan.LookForRegistries();
						}));
#if DEBUG
			// Place a breakpoint on the line and see the configuration of StructureMap.
			string configuration = ObjectFactory.WhatDoIHave();
#endif
		}

The line in the InitializeContainer method instantiates an instance of the StructureMapDependencyResolver class.  This class implements the MVC frameworks IDependencyResolver interface, which is how StructureMap will interact with the MVC DependencyResolver.

	public class StructureMapDependencyResolver : IDependencyResolver
	{
		#region Implementation of IDependencyResolver

		/// <summary>
		/// Resolves singly registered services that support arbitrary object creation.
		/// </summary>
		/// <returns>
		/// The requested service or object.
		/// </returns>
		/// <param name="serviceType">The type of the requested service or object.</param>
		public object GetService(Type serviceType)
		{
			if (serviceType == null)
			{
				return null;
			}

			try
			{
				return ObjectFactory.GetInstance(serviceType);
			}
			catch
			{
				return null;
			}
		}

		/// <summary>
		/// Resolves multiply registered services.
		/// </summary>
		/// <returns>
		/// The requested services.
		/// </returns>
		/// <param name="serviceType">The type of the requested services.</param>
		public IEnumerable<object> GetServices(Type serviceType)
		{
			return ObjectFactory.GetAllInstances(serviceType).Cast<object>();
		}

		#endregion
	}

At this point, your Controller classes will be provided using StructureMap. Not too bad! In order to use it for other types of injection, just go about it in the same process as usual. You can see below the use of injecting an ILog implementation. In the source code you can see that I use log4Net and a StructureMap Registry class.

	[HandleError]
    public class DemoController : Controller
    {
        private static ILog log;

        /// <summary>
        /// Initializes a new instance of the <see cref="DemoController"/> class. 
        /// </summary>
        /// <param name="injectedLog">
        /// ILog implementation injected from the IoC container
        /// </param>
        public DemoController(ILog injectedLog)
        {
            log = injectedLog;
        }

		public ActionResult Index()
		{
			log.Debug("The default page has been requested!");
			return View();
		}
    }

I wanted to make sure that my HttpScoped objects are disposed of when the request ends, so I also added a call to the built in StructureMap method ReleaseAndDisposeAllHttpScopedObjects.

		protected void Application_EndRequest(object sender, EventArgs e)
		{
			ObjectFactory.ReleaseAndDisposeAllHttpScopedObjects();
		}

Not too much code in order to get the full power out of StructureMap with ASP.NET MVC.

Tools Used:

  • Visual Studio 2010
  • StructureMap 2.6.3.0
  • ASP.NET MVC3
  • NuGet
  • log4Net 1.2.11.0

Download the Source:

StructureMap MVC3 Demo

Followin Up Reading on the Service Locator Anti-Pattern/Code Smell

2 thoughts on “StructureMap and ASP.NET MVC3

    • Using the Service Locator here is unnecessary, so I’ve removed it and updated the post. When I was putting together this post I was pulling ideas together from several places and at first pass it seemed okay. After your comment and a second look, you’ve helped me realize my mistake. Whether or not it is an anti-pattern or a just a code smell in certain situations appears to still be a point of contention. I’ve included some links for those readers that wish to research.

      Thanks for the comment!
      -Greg

Comments are closed.