Implementing Dependency Injection With Sitecore

While we have excellent blog by Kam as well as official Sitecore documentation is available for setting up DI with Sitecore, This blog is intend to provide step by step guide for beginners to understand & implement DI with Sitecore.

I’ve used Sitecore 9 for this, but it should work with Sitecore 8.2 as well (this is when Sitecore included built-in DI).

What is Dependency Injection?

Dependency Injection is a process of supplying the required resources (dependencies) to the code which requires these resources.
DI allow developers to build loosely coupled components as we make our components depended upon the Interfaces rather than depending on the actual implementation.

See this Stackoverflow link for more information.

With Dependency Injection, instead of using direct & hard-coded instances we inject dependencies (how? we will see that later) to the components & make them aware that they will need injected dependency to serve the purpose.

Let’s try to understand DI with a simple example:

Below we have a class (or Component) Consumer, which depend on another classes called ServiceA & ServiceB.


public class Consumer
{
    // Other properties of Consumer class
    string Name;
    ...
    ...
    // Service class dependencies
    ServiceA _serviceA
    ServiceB _serviceB;;

    // Public constructor
    public Consumer()
    {
        Name="Some Name";
        // Initiating service objects
        _serviceA= new ServiceA();
        _serviceB= new ServiceB();
    }
    
    public void ConsumeService() {
        _serviceA.ExecuteService();
        _serviceB.ExecuteService();
    }
}

Both these service classes has ExecuteService method to perform some logic:

public class ServiceA
{
    public void ExecuteService()
    {
        // Some code logic for ServiceA
    }
}

public class ServiceB
{
    public void ExecuteService()
    {
        // Some code logic for ServiceB
    }
}

Here Consumer & Service classes are tightly coupled.
To abstract the above code, let’s introduce an interface, IService:


public interface IService
{
    public void ExecuteService();
}

And service classes will implement this interface:

public class ServiceA : IService
{
    public void ExecuteService() 
    {
        // Some code logic for ServiceA

    }
}

public class ServiceB : IService
{
    public void ExecuteService()
    {
        // Some code logic for ServiceB
    }
}

We will now use the IService interface in Consumer class:

public class Consumer
{
    // Other properties of Consumer class
    string Name;
    ...
    ...
    // Service class dependency using interface
    IService _service;

    // Public constructor
    public Consumer()
    {
        // Initiating other properties
        Name="Some Name";
        // Initiating service interface dependency by ServiceA
        _service= new ServiceA();
        // or if we need to initiate by ServiceB 
        // _service= new ServiceB();
    }
    
    // Method to call ExecuteService of IService interface
    public void ConsumeService()
    {
       _service.ExecuteService();
    }
}

Still Consumer class need to use either ServiceA or ServiceB to initiate the IService object, so we still have dependency on ServiceA & ServiceB.

What if we can modify our code as below:


public class Consumer
{
    // Other properties of Consumer class
    string Name;
    // No Service class dependency, instead it will depend on the interface
    IService _service;

    // Public constructor
    public Consumer(IService service)
    {
        Name="Some Name";
        // Initiating using constructor parameter
       _service= service;
    }
    // Method to call ExecuteService of IService interface
    public void ConsumeService()
    {
        _service.ExecuteService();
    }
}

We have removed the dependencies of ServiceA & ServiceB from Consumer class & now it depends on the interface IService instead of the implementation.

How we did that?

We are passing the object of IService in the constructor to initiate the IService object _service, in other words we are injecting the dependency.
Injecting dependencies can be done via different techniques such as :
Construction Injection (as we just did),
Property Injection &
Method Injection

Still, which class will initiate the IService object & which ExecuteService method will be called?

IService interface have multiple implementations & based on the our requirement (ServiceA or ServiceB), we can choose which one we want to use.

This choosing part is known as Service Registration & often done using a IoC Container such as Autofac/Castle Windsor/Unity/Simple Injector and many more OR you can use the default one).
With Service Registration, we declare how dependencies should be resolved & it is done in a separate class which will be called when the application starts.

For example, to resolve the IService dependency with ServiceA, we may register as below (done using built-in DI supported by Sitecore):


public class RegisterDependencies : IServicesConfigurator
{
    public void Configure(IServiceCollection serviceCollection)
    {
        // This is the line to register the dependency
        serviceCollection.AddTransient(typeof(IService), typeof(ServiceA));
    }
}

This code could vary as per the IoC container we choose (don’t worry about this).
With the example code above, when our application starts, it will know that IService objects needs to be initiated by ServiceA.

Consumer class now only depends on interface IService & in case we now want to resolve dependency by ServiceB, we can update the service registration as below:


public class RegisterDependencies : IServicesConfigurator
{
    public void Configure(IServiceCollection serviceCollection)
    {
        serviceCollection.AddTransient(typeof(IService), typeof(ServiceB));
    }
}

How this is loosely coupled?

In case we want to delete ServiceA or ServiceB OR if we want to introduce a new class ServiceC, we don’t need to change anything in the Consumer class & it doesn’t need to know what’s going in the background.

Consumer class is a high-level component, which is loosely coupled with low level components (ServiceA or ServiceB) through the interface IService.
This is Inversion Of Control (IoC) principal.
DI follows IoC principal & often these terms are used interchangeably.

As I mentioned before, with Sitecore 8.2 onward, we can use the built-in DI to register our dependencies.

In the example above it would seem like that we are adding the complexity just for a small piece of code but in real case, you will have tonnes of components to deal with and DI will help to make the application decoupled & flexible.

I hope I was able to give you some basic information about the Dependency Injection, in case you want to read more follow this link.

In terms of setting up DI with Sitecore, we mainly do three things:

First thing – Use interfaces & implement them.
Secondly- Register dependencies &
Lastly – Injecting dependencies.

We will now perform these 3 steps & see things happening.

In our example we will show the list of employees from Sitecore.

I created a Controller “EmployeeListingController“, added an Controller Action “GetAllEmployees” and lastly created associated Controller rendering.

Now we will perform our first step of DI – use interface & implement it.
I’m going to create the Repository folder in the project & define an interface called IEmployeeListing.

This is what interface has:


public interface IEmployeeListing
{

    List<Item> GetEmployees();
}

We will implement this interface using EmployeeListing class & here is how it looks:


public class EmployeeListing : IEmployeeListing
{

    public List<Item> GetEmployees()
    {
        List<Item> employees = new List<Item>();

        var home = Sitecore.Context.Database.GetRootItem();

        foreach (Item employeeItem in home.Children)
        {
             employees.Add(employeeItem);
        }

        return employees;

    }
}

Now we will register our dependency IEmployeeListing.

For this Sitecore has two ways:
Register dependencies in configuration:

<configuration>
    <sitecore>
        <services> 
            <register serviceType="IEmployeeListing, SCDemo.Web" implementationType="EmployeeListing, SCDemo.Web" />          
        </services>
    </sitecore>
</configuration>

We can register dependencies via code using a Configurator class, we implement the IServicesConfigurator as below:


public class RegisterDependencies : IServicesConfigurator
{
    public void Configure(IServiceCollection serviceCollection)
    {
        serviceCollection.AddTransient(typeof(IEmployeeService), typeof(EmployeeService));

    }
}

We can register these dependencies with different lifetimes such as AddTransient or AddScoped or AddSingleton.
Next we need to add configuration to register the RegisterDependencies  Configurator class as below:


<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
    <sitecore>
        <services>
            <configurator type="SCDemo.Web.ServiceConfigurator.RegisterDependencies,SCDemo.Web" />

        </services>
    </sitecore>
</configuration>

With built in IoC container we have few limitations when injecting dependency in controllers:

We may only have one public constructor for controller or any other registered dependency.

And controller class must be registered with the container to be resolvable (e.g. you must register it such as serviceCollection.AddTransient<EmployeeListingController>()).

What if we have too many Controllers to be registered ?
Option one would be to register each and every one.

Option two would be to use this extension class & register in bulk.

When we use the extension class, we can register out Controllers & services as below:


public class RegisterDependencies : IServicesConfigurator
{
    public void Configure(IServiceCollection serviceCollection)
    {
         serviceCollection.AddMvcControllers("*.SCDemo.Web.*");

        serviceCollection.AddTransient(typeof(IEmployeeService), typeof(EmployeeService));

    }
}

Here we are registering all the Controllers which has *SCDemo.Web.* in the namespace.
We can also add Extension methods to resolve service registration in bulk (hint : see Habitat solution).

 

What next? Try to setup DI in Sitecore Helix based solution.

Advertisements

Sitecore & DI – “Unable to resolve service for type …” Error

While I was setting up Dependency Injection in my Sitecore Helix solution, I was greeted with below YSOD :

Unable to resolve service for type 'SCDemo.Feature.Navigation.Repositories.INavRepo' while attempting to activate 'SCDemo.Feature.Navigation.Controllers.NavigationController'.

Unable to resolve service for type ‘SCDemo.Feature.Navigation.Repositories.INavRepo’ while attempting to activate ‘SCDemo.Feature.Navigation.Controllers.NavigationController’.

This is the Controller code:


public class NavigationController  :  Controller
{
    INavRepo _navRepo;

    public NavigationController (INavRepo navRepo)
    {
        _navRepo= navRepo;
    }

    // Action methods

}

Error message was load & clear – my service registration failed, so I started to look into the code which actually register these services.
I started to debug the Foundation project I’m having for Dependency Injection.
This Foundation project (or module) facilitate us to have single Composition Root by registering all the dependencies & Controllers using the Microsoft Dependency Injection Abstractions library. 

This Foundation project is replica of Sitecore Habitat’s Dependency project & it has one class “MvcControllerServicesConfigurator” which register services & Controllers:


public void Configure(IServiceCollection serviceCollection)
{
    serviceCollection.AddMvcControllers("*.Feature.*");
    serviceCollection.AddClassesWithServiceAttribute("*.Feature.*");
    serviceCollection.AddClassesWithServiceAttribute("*.Foundation.*");
}

The code above registers all the MVC Controllers which matches the *.Feature.* as well as services which matches *.Feature.* & *.Foundation.*.

This is done using an Extension class “ServiceCollectionExtensions” where these AddMvcControllers and AddClassesWithServiceAttribute methods along with few Helper methods are defined.

While looking into the this Extension class, I noticed that “AddClassesWithServiceAttribute” method is not getting any services for registration from Feature projects.


public static void AddClassesWithServiceAttribute(this IServiceCollection serviceCollection, params Assembly[] assemblies)
{
    var typesWithAttributes = assemblies
                              .Where(assembly => !assembly.IsDynamic)
                              .SelectMany(GetExportedTypes)
                              .Where(type => !type.IsAbstract && !type.IsGenericTypeDefinition)
                              .Select(type => new { type.GetCustomAttribute<ServiceAttribute>()?.Lifetime, ServiceType = type, ImplementationType = type.GetCustomAttribute<ServiceAttribute>()?.ServiceType })
                              .Where(t => t.Lifetime != null);

    foreach (var type in typesWithAttributes)
    {
        if (type.ImplementationType == null)
            serviceCollection.Add(type.ServiceType, type.Lifetime.Value);
        else
            serviceCollection.Add(type.ImplementationType, type.ServiceType, type.Lifetime.Value);
    }
}

This method uses reflection & filters all the classes with Service attribute, so any service which needs to be register must have the Service attribute.

What is this Service attribute?

This is a custom class, which inherit Attribute class & can be used as Attribute for other classes.


[AttributeUsage(AttributeTargets.Class, Inherited = false)]
public class ServiceAttribute : Attribute
{
    public ServiceAttribute()
    {

    }

    public ServiceAttribute(Type serviceType)
    {
        this.ServiceType = serviceType;
    }

    public Lifetime Lifetime { get; set; } = Lifetime.Singleton;
    public Type ServiceType { get; set; }
}

Here default Lifetime is used as Singleton, but you can use Transient Lifetime while defining the attribute.

All these classes are included with DI project I used from Sitecore Habitat.

I noticed  that I didn’t have Service attribute on my Repo class (which I wanted to register):


public class NavRepo : INavRepo
{
    public void DoStuff()
    {

        // Do stuff

    }

So I added the Service attribute to the implementation of INavRepo:


[Service(typeof(INavRepo))]
public class NavRepo : INavRepo
{
    public void DoStuff()
    {
        // Do stuff
    }
}

This way our service registration code in Foundation DI project will know that INavRepo is resolved with NavRepo class.
Everything worked after this, so if you are getting the same error, probably you forgot to add the Service Attribute.

Hope this will help.