This is, yet, another blog post on the topic of dependency injection with Sitecore Controller Renderings as well as API Controllers. Let me start by saying that the most helpful blog post I’ve read on the topic is by Kam Figy – https://kamsar.net/index.php/2016/08/Dependency-Injection-in-Sitecore-8-2/. I encourage you to read this blog post because it is still applicable to Sitecore 9.
My inspiration for this blog post came from the fact that when you Google the terms “sitecore dependency injection”, one of the first results is the official Sitecore documentation on the topic – https://doc.sitecore.net/sitecore_experience_platform/developing/developing_with_sitecore/dependency_injection.
So you go to this page and read about the different ways that you can register your dependencies, service resolution, viewing your dependency injection configuration, etc… And you think, “hmm… looks like all of the info is here. Let me give this is a try”. And you go through everything, and it doesn’t work.
I’m going to try and show you the easiest way possible to implement dependency injection following Sitecore’s official documentation and I’m going to point out the missing pieces of information. And we’re going to start from scratch – absolute scratch! For this walkthrough, I’m assuming you haven’t even installed Sitecore yet.
The steps:
- Install Sitecore
- I’m using 9.0.2 but you can use any version starting at 8.2, I believe.
- Login to Sitecore
- Create an MVC Layout and call it My Solution Main Layout
- I placed my layout in the following folder structure
- \Views\_Layouts\MySolution\MySolutionMainLayout.cshtml
- I placed my layout in the following folder structure
- Create a controller rendering in Sitecore and specify the Controller and Action
- for my example, I created a Generic Callout
- Right-click Home and create a Sample Item
- Update the presentation details of the item you created to use the new Layout and Controller Rendering you created
- Push the item through workflow
- Publish the site
- Go to this item in a new tab
- You should get an error saying something like, “Sitecore can’t find the controller”
- Create a solution in Visual Studio
- Create a web app
- I called it Feature.GenericCallout
- I chose the empty web app template
- Install the following NuGet packages
- Sitecore.Kernel.NoReferences (whatever version matches your instance of Sitecore)
- Microsoft.AspNet.Mvc (whatever version matches your instance of Sitecore)
- Set the build action of the main web.config to None
- so you don’t accidentally deploy your vanilla MVC web.config and destroy your Sitecore site
- Create a Services folder
- Add an interface and a class
- I called my interface and class, IGenericCalloutService, GenericCalloutService, respectively
- Add an interface and a class
- Create a Controllers folder
- Add a Controller
- I called my controller GenericCalloutController
- Add a private variable of type IGenericCalloutService
- Add a constructor that takes in a parameter of type IGenericCalloutService and set the private variable
- You know, inject the dependency
- Make sure this is the only constructor in your Controller
- Add a method to the controller called Default and return the View
- Add a Controller
- Create a Views folder
- In there, create a folder called GenericCallout
- In there, create a partial view and name it Default.cshtml
- I just added this to my View to make sure it was deploying, <h2>Generic Callout</h2>
- Deploy this project to your local Sitecore site
- Reload the Sample Item page
- You should now get an error saying something like:
- Constructor on type ‘Feature.GenericCallout.Controllers.GenericCalloutController’ not found.
- You should now get an error saying something like:
At this point, your solution should look something like this:

This is when we start following the Sitecore documentation.
The first thing we have to do is register our dependencies. I’m going with the option of Registration in configuration.
The steps:
- Add an App_Config folder
- In there, add an Include folder
- In there, add a config file
- I called my config, Feature.GenericCallout.config
- Add the following XML to your config:
<?xml version="1.0" encoding="utf-8"?> <configuration xmlns:patch="http://www.sitecore.net/xmlconfig/"> <sitecore> <services> <register serviceType="Feature.GenericCallout.Services.IGenericCalloutService, Feature.GenericCallout" implementationType="Feature.GenericCallout.Services.GenericCalloutService, Feature.GenericCallout" /> </services> </sitecore> </configuration>
As described on the Sitecore documentation page, this config will register your concrete implementation of your interface with the class you created.
Deploy this config to your site and reload your page.
At this point, I thought, “this should work!” To my surprise, it didn’t. I still got the same error:
Constructor on type ‘Feature.GenericCallout.Controllers.GenericCalloutController’ not found.
What was I missing? So I continued reading the Sitecore documentation. In the next section, Service resolution, it talks about how you can inject dependencies into processors, which is really cool and there’s a line that says:
To use dependency injection in an MVC controller, add this processor to the pipeline:<processor type=”Sitecore.Mvc.Pipelines.Loader.InitializeDependencyResolver, Sitecore.Mvc”/>
So I thought, “that must be the processor I’m missing”. So I went to my /sitecore/admin/showconfig.aspx page to confirm that this processor was missing but it was there!
So that was not my problem. So what could be the problem? This is when I went to Kim’s blog post again. Remember at the beginning I said you should read it?
In his blog post, Kim mentions that:
The controller class must be registered with the container to be resolvable (e.g. you must register it such as container.AddTransient<FooController>()).
So I thought, “worth a try”. But where does this code go? This code goes into a Sitecore Services Configurator class.
The steps:
- Add a class to the project called GenericCalloutServicesConfigurator.cs
- Have the class implement Sitecore.DependencyInjection.IServicesConfigurator
- you will need to include this NuGet package as well – Microsoft.Extensions.DependencyInjection.Abstractions
- In the Configure method, add a line for your Controller
- serviceCollection.AddTransient(typeof(GenericCalloutController));
- notice I’m not calling the exact same method Kim is calling.
- serviceCollection.AddTransient(typeof(GenericCalloutController));
Your class should look something like this:
using Feature.GenericCallout.Controllers; using Microsoft.Extensions.DependencyInjection; using Sitecore.DependencyInjection; namespace Feature.GenericCallout { public class GenericCalloutServicesConfigurator : IServicesConfigurator { public void Configure(IServiceCollection serviceCollection) { serviceCollection.AddTransient(typeof(GenericCalloutController)); } } }
And to get this class to run, we need to patch it into the services section of the Sitecore configuration:
<?xml version="1.0" encoding="utf-8"?> <configuration xmlns:patch="http://www.sitecore.net/xmlconfig/"> <sitecore> <services> <configurator type="Feature.GenericCallout.GenericCalloutServicesConfigurator, Feature.GenericCallout"/> <register serviceType="Feature.GenericCallout.Services.IGenericCalloutService, Feature.GenericCallout" implementationType="Feature.GenericCallout.Services.GenericCalloutService, Feature.GenericCallout" /> </services> </sitecore> </configuration>
Deploy your code to your site again, reload your page and… voilà! It worked! That was the missing piece! Why this is not called out on the Sitecore documentation page, I’m not sure, but this piece is very important.
One thing to clarify, in my example above, I am using the AddTransient method. This is one of 3 methods you can use:
- AddScoped
- scoped objects are the same within a request, but different across different requests.
- AddSingleton
- singleton objects are the same for every object and every request.
- AddTransient
- transient objects are always different; a new instance is provided to every controller and every service.
You can find more information about this on this StackOverflow answer – https://stackoverflow.com/a/38139500/195335.
Finally, I wanted to see how easy it would be to enable dependency injection in an API controller.
The steps:
- Install NuGet package Microsoft.AspNet.WebApi
- This package will install NuGet package Newtonsoft.Json
- You’ll need to update this NuGet package to the version that matches the version that came with your instance of Sitecore. To find out your version of Newtonsoft:
- Go to \website\bin
- Right-click Newtonsoft.Json.dll
- Go to the Details tab
- You’ll need to update this NuGet package to the version that matches the version that came with your instance of Sitecore. To find out your version of Newtonsoft:
- This package will install NuGet package Newtonsoft.Json
- Create a Controller in the Controllers folder
- I called my controller GenericCalloutApiController.cs
My Api controller looks like this:
using Feature.GenericCallout.Services; using System.Web.Http; namespace Feature.GenericCallout.Controllers { public class GenericCalloutApiController : ApiController { private IGenericCalloutService _genericCalloutService; public GenericCalloutApiController(IGenericCalloutService genericCalloutService) { _genericCalloutService = genericCalloutService; } [Route("my-solution-api/feature/generic-callout")] public string GetGenericCallout() { return "This is the response."; } } }
And, since I know I had to register my “regular” controller, I’m going to go ahead and register my API controller as well. So that will look like this:
using Feature.GenericCallout.Controllers; using Microsoft.Extensions.DependencyInjection; using Sitecore.DependencyInjection; namespace Feature.GenericCallout { public class GenericCalloutServicesConfigurator : IServicesConfigurator { public void Configure(IServiceCollection serviceCollection) { serviceCollection.AddTransient(typeof(GenericCalloutController)); serviceCollection.AddTransient(typeof(GenericCalloutApiController)); } } }
To test this, I wrote some JavaScript using jQuery to make an AJAX call to my API controller. I didn’t have to do this – I could’ve tested it by simply requesting the API route in a browser tab.
Here’s the super basic JavaScript I wrote:
$(function () { $.get('/my-solution-api/feature/generic-callout', function (response) { console.log(response); }); });
This also worked as expected!
If you’ve been following this post and building your solution as I described above, your solution should now look something like this:
So, to summarize, we were able to get dependency injection working following the Sitecore documentation with one additional detail – registering our controllers.
I hope this helps you in your adventures with dependency injection with Sitecore.
Amazing!! This is the best article written for DI in Sitecore. Apt to the Title “POSSIBLY SIMPLEST WAY OF ENABLING DEPENDENCY INJECTION IN SITECORE CONTROLLERS AND APICONTROLLERS”
LikeLike
In real life scenario the Application will have multiple Controller, could you please suggest how to achieve registration for multiple Controllers?
Thanks,
Debaparna
LikeLike
Right. The way I’ve done it is, by referencing the multiple Controllers (and their dependencies) in the various files I mentioned in the post. So you need to register each of your individual services and controllers in the configs and classes I mentioned in the post.
I’ve come across a few solutions that just scan your assemblies for classes that match a certain naming convention, such as, “…Controller”, “…Service”, and then automatically register those.
I understand the benefits of that approach but I prefer to define these registration explicitly.
LikeLike
I am getting the below error.”ExceptionMessage”:”An error occurred when trying to create a controller of type ‘GenericCalloutApiController’. Make sure that the controller has a parameterless public constructor.”
LikeLike
Make sure you have a ServicesConfigurator class that is properly patched in and make sure to add the GenericCalloutApiController to it as a Transient.
LikeLiked by 1 person