Configuring Dependency Injection in Umbraco

Layer One Media, Technical Lead // February 02, 2018

What is Dependency Injection in Umbraco?

Dependency injection is a well adopted implementation of the Inversion of Control (IoC) principle. While there are many other blogs describing IoC and dependency injection, the basic idea to invert the flow control. Such that the client does not build what it needs. The client is told what services it depends on or is given the ability to locate those dependencies. Utilizing a dependency injection container allows the development team to build modular components that can be consumed easily across the application.

Utilizing a dependency injection container gives the development team tons of freedom. First, it empowers the development team to implement re-usable components. With a low barrier to entry registering types within the dependency injection container. The development team will find it easy to follow the other SOLID principles. Separating concerns into a single responsibility. Decreasing the coupling between components. Lastly, empowering the development team to reduce the barrier to entry for unit testing. With dependencies being injected into the client, the development team can easily mock the client dependencies, prescribing the desired behavior for test purposes.

Next, let us talk about the "how". First, create a new class and extend Umbraco.Web.UmbracoApplication specifically overriding the OnApplicationStarted method:

namespace MyCool.New.UmbracoApp 
{
  public class CustomApplication : Umbraco.Web.UmbracoApplication
  {
    protected override void OnApplicationStarted(object sender, EventArgs e) 
    { 
      base.OnApplicationStarted(sender, e);
    }
  }
}

We will come back to this class later in the post, first lets get it hooked up. Open Global.asax modify the Inherits attribute. The new value should be the fully qualified name of CustomApplication.

<%@ Application Inherits="MyCool.New.UmbracoApp.CustomApplication" Language="C#" %>

At this point, the project should build and execute as it did before changes. Do yourself a favor and test that theory. 

Now, adding the dependency injection container. First, add NuGet references to the implementation of your choice. In this example, we will be using Autofac.

The remainder of the work will all be in CustomApplication. To use the Autofac dependency injection container, you must first instantiate an instance of ContainerBuilder. Next, register all Umbraco controllers in the container. Then, register all custom controllers in the container. Finally, the container will have to be set in 2 places:

  • DependencyResolver.SetResolver(new AutofacDependencyResolver(containerBuilder.Build())
  • GlobalConfiguration.Configuration.DependencyResolver = new AutofacWebApiDependencyResolver(containerBuilder.Build())

Here is the updated CustomApplication with the above changes:

namespace MyCool.New.UmbracoApp 

{
  public class CustomApplication : Umbraco.Web.UmbracoApplication
  {
    protected override void OnApplicationStarted(object sender, EventArgs e) 
    { 
      base.OnApplicationStarted(sender, e);

      var containerBuilder = new ContainerBuilder();

      // Register all the controllers found in the Umbraco namespace
      containerBuilder.RegisterControllers(typeof(UmbracoApplication).Assembly);
      containerBuilder.RegisterApiControllers(typeof(UmbracoApplication).Assembly);
 
      // Register all the controllers found in the custom namespace
      containerBuilder.RegisterControllers(typeof(CustomApplication).Assembly);
      containerBuilder.RegisterApiControllers(typeof(CustomApplication).Assembly);

      // Register types within the IoC container here

      DependencyResolver.SetResolver(new AutofacDependencyResolver(containerBuilder.Build());
      GlobalConfiguration.Configuration.DependencyResolver = new AutofacWebApiDependencyResolver(containerBuilder.Build());
   }
  }
}

 

Again, at this point, the project should build and execute as it did before changes.

Lastly, registering the new data types defined by the development team. This should be done before building the container and setting the resolver and registering all the custom controllers.  One example of registration could be this:

containerBuilder.RegisterType<ServiceImpl>().As<IService>()

 

Consuming, this new service is just as easy as the registration. In the client that depends on the service. Update the constructor, adding an argument for IService. Then assigning a variable or property with the value passed to the constructor.

 public class NewController 

{
  private readonly IService _service;  

  public NewController(IService service)
  {
    _service = service;
  }  
}

With these couple of changes, a dependency injection container is all ready for the development team to run with.

 

Web Experience Platforms

back to impulse