Sitecore 8.2: Setting up custom DI using Autofac

I’ve spent quite a while looking for a straight forward guide on how to set this up so I thought it might be helpful to put up one based on what I’ve gathered from the interweb. Credits to Dmytro Shevchenko.

Sitecore’s latest version is 8.2 (upon this writing) and while we were just starting on a new project using 8.1 might as well move to the latest version, why not? We already had an existing solution using the following:

  • Sitecore 8.1
  • .Net 4.5.2
  • Castle Windsor 3.3.0
  • No Glass mapper?!

While new version of Sitecore now uses .Net 4.6.1 I decided to stick with .Net 4.5.2 to spare myself from all the dll dependency fiasco, after all 8.2 will still run on it. After installing our solution to a vanilla 8.2 instance everything seems to work fine until I checked on the web api part. It is with the IHttpController Dependency injection that I had issues with.Couple of things to note:

  • Sitecore 8.2 now abstracts Application_Start method in Global.asax.cs so I need to stay away from it, plus it’s a good practice to use pipelines instead.
  • However for some reason adding a pipeline under initialize does not work regardless where I patch it in the sequence, perhaps Castle Windsor 4 has a solution but I’m stuck with my current version. Either I find a solution or use a different IoC completely.

Sitecore 8.2 is IoC aware with it’s own DI implementation which you can customize to a framework of your liking. An elegant way to do this is to patch <serviceProviderBuilder> which you will find under Sitecore.config. You will need to create a class that will return an implementation of IServiceProvider. I found using Autofac much straightforward but this is completely personal preference. Here’s what I did:

  1. Install the following nuget packages
    • install-package Sitecore.Kernel (if you haven’t yet)
    • install-package Sitecore.Mvc
    • install-package Autofac
    • install-package Autofac.Mvc5
    • install-package Autofac.Extensions.DependencyInjection
    • Install-Package Autofac.WebApi2
  2. Create an autofac module to register your service. My ServicesModule class inherits from Autofac.Module. This is where we do registrations. So you can have multiple modules to organize all your services and domains.
        public class ServicesModule : Module
        {
            protected override void Load(ContainerBuilder builder)
            {
                builder.RegisterType<TestService>().As<ITestService>();
            }
        }
    
        public class TestService : ITestService
        {
            public string CallService(string text)
            {
                return $"{text} - went through service";
            }
        }
    
        public interface ITestService
        {
            string CallService(string text);
        }
    
  3. Create a class that returns an Implementation of IServiceProvider
        public class AutofacServiceProviderBuilder : BaseServiceProviderBuilder
        {
            protected override IServiceProvider BuildServiceProvider(IServiceCollection serviceCollection)
            {
                var builder = new ContainerBuilder();
    
                builder.Populate(serviceCollection);
    
                builder.RegisterModule<ServicesModule>();
    
                builder.RegisterControllers(Assembly.GetExecutingAssembly());
                builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
    
                var container = builder.Build();
    
                return container.Resolve<IServiceProvider>();
            }
        }
    
  4. Create the config to patch your Builder class and replace Sitecore’s default Service Provider. This will go under App_Config/include
    <configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
      <sitecore>
        <serviceProviderBuilder>
          <patch:attribute name="type" value="[namespace].AutofacServiceProviderBuilder, [assembly]" />
        </serviceProviderBuilder>
      </sitecore>
    </configuration>
    
  5. You now have your IoC setup as simple as that, you can try injecting both to Controllers and ApiControllers. Here sample base on the test api above.
        public class AutofacTestController : GlassController
        {
            private readonly ITestService _testService;
    
            public AutofacTestController(ITestService testService)
            {
                _testService = testService;
            }
    
            public override ActionResult Index()
            {
                var parameters = GetRenderingParameters<Parameter>();
                var datasource = GetDataSourceItem<AutofacTest>();
                var model = new AutofacTestViewModel
                {
                    AutofacTestDataSource = datasource,
                    ValuefromControllerInjection = _testService.CallService(datasource.ComponentLabel),
                    Display = parameters.Display
                }; 
    
                return View(model);
            }
        }
    
        [RoutePrefix("api/test")]
        public class TestApiController : ApiController
        {
            private readonly ITestService _testService;
    
            public TestApiController(ITestService testService)
            {
                _testService = testService;
            }
    
            [Route("get")]
            public string Get(string text)
            {
                return _testService.CallService(text);
            }
        }
    

As you can see there’s reference to GlassController, I’ll share my very basic implementation on my next post. Here are the outputs of above test codes:

untitled

untitled

Happy coding everyone! –sesebon

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s