At Valtech we recently upgraded a dated Sitecore 6.6 platform to Sitecore 8.2 initial release. The platform contained multiple websites developed with Microsoft WebForms technology and used Autofac as the Inversion of Control container.
Integrating the Autofac modules
The comprehensive Autofac documentation contains a topic on how to integrate the latest Autofac in a WebForms application. Adding the modules to the web.config was easy, it’s our best practice to use config transformations per environment for any necessary changes to the default Sitecore files which include the Web.config file.
An example of the XDT transformation used to include Autofac in the Web.config file:
<modules runAllManagedModulesForAllRequests="true" xdt:Transform="SetAttributes"> [@name='SitecoreHttpModule'])" /> <add name="ContainerDisposal" type="Autofac.Integration.Web.ContainerDisposalModule, Autofac.Integration.Web" preCondition="managedHandler" xdt:Transform="InsertBefore(/configuration/system.webServer/modules/add[@name='SitecoreHttpModule'])" /> <add name="PropertyInjection" type="Autofac.Integration.Web.Forms.PropertyInjectionModule, Autofac.Integration.Web" preCondition="managedHandler" xdt:Transform="InsertBefore(/configuration/system.webServer/modules/add[@name='SitecoreHttpModule'])" /> <add name="AttributedInjection" type="Autofac.Integration.Web.Forms.AttributedInjectionModule, Autofac.Integration.Web" preCondition="managedHandler" xdt:Transform="InsertBefore(/configuration/system.webServer/modules/add[@name='SitecoreHttpModule'])" /> </modules>
Implementing Autofac container initialization at startup
The next step involves implementing the IContainerProviderAccessor interface in Global.asax. The Autofac dependency injection modules expects that the HttpApplication instance supports the IContainerProviderAccessor interface. And this is a bit tricky to implement in a Sitecore 8 solution.
Normally you would create a custom HttpApplication sub class, include the Autofac magic in this class and point your Global.asax file to this class like this:
<%@Application Language="C#" Inherits="My.Custom.HttpApplication.SubClass" >
When using Sitecore 8.2 initial release we noticed that the Autofac container was not being properly initialized at startup and therefor dependencies could not be resolved at run-time.
After some research we noticed that the Application_Start event handling method did not fire at all in our custom HttpApplication class and which is responsible for setting up the Autofac container when using WebForms technology. According to Sitecore support the reason is that if we have several Application_Start methods (like in this case), only one will be called. It’s Sitecore.Web.Application.Application_Start method, since it’s declared first in the chain of derived types. Ideal solution would be to override that method, unfortunately we can’t do that since it’s marked as internal in the base class. This Sitecore behavior has been registered as a bug with the reference #126372.
We didn’t want this bug to be a showstopper and we discovered a simple workaround. The workaround consists of simply copying the whole Sitecore.Web.Application class to our custom class. And suddenly the event methods do get picked up at start up. Tooling like dotPeek can be used to decompile the Sitecore assemblies.
Getting Autofac 4.x to work with Sitecore 8.2 & Solr
If you are using Solr for your scalable Sitecore 8 platform then your are most probably aware of the official Sitecore documentation on how to setup Solr. The documentation also describes how to configure an IOC container like Autofac.
Unfortunately, the documentation and the supplied Sitecore support DLLs are verified to work with AutoFac v2.5.2. But as you can imagine Autofac v4.x contains breaking changes compared to Autofac v2.x.
If you want to use the latest AutoFac then you will need to include the sources of the by Sitecore supplied AutofacContrib project in your own project. The classes include AutoFacInitializeSolrProvider, AutoFacSolrStartUp & AutofacServiceLocator.
Also change the type in Sitecore.ContentSearch.Solr.DefaultIndexConfiguration.IOC.Autofac.config to your own AutoFacInitializeSolrProvider class, for example: My.Namespace.AutoFacInitializeSolrProvider, My.Namespace
A small refactoring in the AutoFacSolrStartup class was also needed.
ServiceLocator.SetLocatorProvider((ServiceLocatorProvider)(() => (IServiceLocator)new AutofacServiceLocator((IComponentContext)this.container)));
var csl = new AutofacServiceLocator(container); ServiceLocator.SetLocatorProvider(() => csl);
Soon we will start the upgrade to Sitecore 8.2 update-2 and then we will know for sure if the Global.asax startup bug has been resolved.