Replacing the Default DI Container in Sitecore 8.2

Dmytro Shevchenko
Nov 11, 2017 · 4 min read

With the release of 8.2, out-of-the-box Sitecore now uses IServiceProvider — ASP.NET’s own dependency injection abstraction, as well as its default implementation. If you haven’t yet, go read Kam’s article “Dependency Injection in Sitecore 8.2” that describes how to use the built-in capabilities of the new Sitecore DI.

Since Sitecore has become DI-aware, its internals have undergone significant rewiring, allowing for a more seamless implementation swapping — not only for its internal components, but even for some parts of its infrastructure.

Why replace the default container?

So you already have a dependency injection container coming with Sitecore. Why would you want to substitute it with something else? Well, your reasons could be many:

  • IServiceProvider is a conforming container, which is considered an anti-pattern. As a matter of fact, there was a very thought-provoking discussion thread involving ASP.NET Core developers from one side and dependency injection library authors from the other side, going back and forth on whether or not the IServiceProvider abstraction should be removed altogether (spoiler alert: it wasn’t removed).
  • You may already be using another container and don’t want to migrate to IServiceProvider.
  • The default implementation of IServiceProvider may not have enough features for your needs. Being a conforming container, its capabilities are the lowest common denominator of the modern DI containers, and so things like SimpleInjector’s diagnostic and verification abilities or Autofac’s resolve-time parameters are unavailable with the default container. Even such a simple thing as automatic registration of all MVC controllers will require 90 lines of custom code.

I do believe that using one of the leading DI libraries will provide an overall better development experience, compared to using the default container.

Replacing the DI implementation via <initialize>

If you wanted to use a Dependency Injection container with Sitecore 8.1, there was, essentially, one best way of doing that:

  1. Create an <initialize> pipeline processor and use it to configure your custom DI container;
  2. Replace the dependency resolvers of ASP.NET MVC and WebAPI with dependency resolvers provided by your DI container.

You could additionally use tricks like initializing each module’s services separately via custom pipeline and falling back to Sitecore’s dependency resolver for improved results.

Of course, you can still use a similar approach in 8.2, and there’s nothing wrong with that. But given Sitecore’s new DI-related features, you should consider using the new and simpler approach.

Replacing the DI implementation via <serviceProviderBuilder>

Disclaimer: Most modern DI containers provide IServiceProvider adapters; I will use Autofac in this example. You’ll need to install the following NuGet packages: Autofac, Autofac.Mvc5, and Autofac.Extensions.DependencyInjection.

If you look at the Sitecore.config included with 8.2, you’ll see a new configuration node added at the very bottom:

This node references the class that will return an implementation of IServiceProvider. That service provider instance will then be used everywhere throughout the application, including Sitecore’s internal components.

Let’s make our own service provider builder using the class below.

Inheriting from Sitecore.DependencyInjection.BaseServiceProviderBuilder ensures that Sitecore's internal service configurators are utilized.

Notice the use of builder.Populate(serviceCollection)—this is an extension method included in Autofac.Extensions.DependencyInjection. It goes through all existing services (registered so far by Sitecore) and registers them in Autofac, which makes them available in your DI container. If Sitecore registers more services later on, they will be registered in Autofac through the IServiceProvider adaptor we returned from BuildServiceProvider().

Now that we have our own builder class, let’s replace the DefaultServiceProviderBuilder. To do that, create a configuration patch file with the following contents and put it under /App_Config/Include.

And this is it! No need for custom controller factories, or chained dependency resolvers.

An attentive reader may have already noticed that we din’t even have to touch DependencyResolver.Current. This is because Sitecore's MVC dependency resolver will internally use IServiceProvider—the one we provided when we overrode the <serviceProviderBuilder>.

By the way, you can see all service registrations on a new administrative page: /sitecore/admin/ShowServicesConfig.aspx. It will list all available services — registered either by you and by Sitecore.

Registering services in .config files

There’s a bonus: since we’ve completely replaced the default container, we can now use Sitecore XML configuration to register services in our DI container:

This syntax has even fewer features than IServiceProvider’s API, but still, XML configuration may work for simple cases — if that’s something you’re into.

Conclusion

The approach defined above is very clean and straightforward. The way in which Sitecore allows to swap its internal dependency resolution is definitely a big step forward. Your custom services, along with Sitecore’s internal services, are now easily accessible, replaceable and injectable through your DI container of choice. All with minimal code and configuration.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch

Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore

Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store