Umbraco and Structure Map

Dependency Injection (DI) or Inversion of Control (IoC) has become a defacto standard for many developers. I used to be a hold out. I used to be one of those developers that said use interfaces when you need them; not just for the sake of using interfaces. However, with methods of development, such as, Test Driven Development, I found myself more and more following DI pattern for my development. Now, I cannot imagine developing without DI.

So when I started coding with Umbraco, one of the very first questions to resolve was how to use DI with Umbraco. Umbraco is a large, open source application. As such, some of the code follows a pattern supportive of dependency injection, while some follows more traditional methods.

I had been using Structure Map, so out of comfort decided to use Structure Map with Umbraco. There was really no need other than that. Using Structure Map with Umbraco turned out to be somewhat of an exercise in troubleshooting. I found several articles on the subject, but none seemed to work completely for me.

The Initial Bootstrap

For Umbraco, the global asax inherits from UmbracoApplication instead of System.Web.HttpApplicaion. Like most DI frameworkds, the creation and configuration of the container occurs here

public class MvcApplication : UmbracoApplication
    {
        public static IContainer Container { get; set; }
        public static StructureMapDependencyResolver StructureMapResolver { get; set; }

        protected override void OnApplicationStarting(object sender, EventArgs e)
        {
            base.OnApplicationStarting(sender, e);
            Container = StructureMapConfiguration.Configure();
            GlobalConfiguration.Configuration.DependencyResolver = new StructureMapWebApiResolver(Container);
            StructureMapResolver = new StructureMapDependencyResolver(Container);
            DependencyResolver.SetResolver(StructureMapResolver);  
            FilteredControllerFactoriesResolver.Current.InsertType<StructureMapFilteredControllerFactory>(0);

 

So, the first configuration (StructureMapConfiguration.Configure()) is a standard configuration for dependency injection. The second section relates to getting structure map to work with API controllers. The third section configures DI for MVC.

StructureMapConfiguration.Configure


The configure method first adds the Umbraco Registy, which follows the standard structure map pattern. Then the configure method provides specific methods to return an instance for four Umbraco classes. These four configurations were identified by a combination of exceptions (No default instance found) and reviewing Umbraco code.

        public static IContainer Configure()
        {
            var container = new Container(x => x.AddRegistry(new UmbracoRegistry()));

            container.Configure(x => x.For<LegacyTreeController>().Use(() => new LegacyTreeController()));
            container.Configure(x => x.For<UmbracoContext>().Use(() => UmbracoContext.Current));
            container.Configure(x => x.For<IHttpControllerActivator>().Use<UmbracoWebApiHttpControllerActivator>());
            container.Configure(x => x.For<ApplicationContext>().Use(ApplicationContext.Current));

            return container;
        }

 

The UmbracoRegistry method is just standard StructureMap code:

       public UmbracoRegistry()
        {
            Scan(
                assemblyScanner =>
                {
                    assemblyScanner.AssembliesFromApplicationBaseDirectory(
                         x => x.FullName.StartsWith("GD")

                   assemblyScanner.AddAllTypesOf<Controller>();
                    assemblyScanner.WithDefaultConventions();
                });
        }

 

The StructureMapWebApiResolver

I am including the following code as I cannot find the original source; my apologies to the original writer. Although it is possible that I modified an AutofacWebApiResolver, I do not recall at this point. I needed the StructureMapWebApiResolver in order to be able handle both custom built as well as the Umbraco web api calls. I plugged this in and it resolved my web api issues:

    public class StructureMapWebApiResolver : IDependencyResolver
    {
        private readonly IContainer _container;
        private readonly bool _isContainerOwner;

        public StructureMapWebApiResolver(IContainer container) : this(container, false)
        {
        }

        public StructureMapWebApiResolver(IContainer container, bool isContainerOwner)
        {
            _container = container;
            _isContainerOwner = isContainerOwner;
        }

        public IDependencyScope BeginScope()
        {
            return new StructureMapWebApiResolver(_container.GetNestedContainer(), true);
        }

        public object GetService(Type serviceType)
        {
            if (serviceType == null)
            {
                return null;
            }

            if (serviceType.IsAbstract || serviceType.IsInterface)
            {
                return _container.TryGetInstance(serviceType);
            }

            return _container.GetInstance(serviceType);
        }

        public IEnumerable<object> GetServices(Type serviceType)
        {
            return _container.GetAllInstances(serviceType).Cast<object>();
        }

        public void Dispose()
        {
            if (_isContainerOwner)
            {
                _container.Dispose();
            }
        }
    }

 

The MVC Dependency Resolver and Filtered Controller Factory

Finally, the MVC Dependency Resolver and Filtered Controller Factory work together to provide instances of the controller from the correct contoller factory. You can find an example of the dependency resolver here:

http://www.webadvanced.com/blog/asp.net-mvc-4-web-api-and-structuremap

Once this was in place, we needed the filtered controller factory to tell the application when Umbraco should provide the controller versus when StructureMap should provide the controller. This simply inherites from StructureMapControllerFactory and then implements the method CanHandle of the IFilteredControllerFactory interface. This filter controller factory is inserted into the first position, thus allowing it to determine if it can provide a controller instance. Otherwise, the process passes the request to the Umbraco Controller Factory.

public class StructureMapFilteredControllerFactory : StructureMapControllerFactory, IFilteredControllerFactory
    {
        public bool CanHandle(RequestContext request)
        {
            var controllerType = GetControllerType(request, request.RouteData.Values["controller"].ToString());
            if (controllerType.FullName.StartsWith("Umbraco.Web"))
                return false;
            return MvcApplication.Container.Model.HasImplementationsFor(controllerType);
        }
    }

 

Conclusions

This was an exercise in troubleshooting. I would fix one piece and think everything was working correctly, but then found bugs (usually related to Unable to Create Default Instance). This turned out to be somewhat time consuming, but still clearly worth the effort. I was not about to rewrite a lot of base libraries to do without DI. In the future, hopefully, Umbraco can move to a fully DI agnostic code model.

 

 

 

 

 

 

 

 

 

 



About The Author

Avatar
Jonathan Folland

Jonathan Folland is technologist with over 20 years experience in a variety of capacities. He held the position of Vice President of Operations of one of the fastest growing companies in the world. He has led high volume e-Commerce operations and is an expert at mixing technology and finance to produce high return results.


Related Articles