Implementing IOC in Umbraco 7- Inversion of Control Like a Boss
Published 27/05/2016 - Updated 27/07/2023
Table of Contents
I’ve devoted a significant amount of time this week to finding the best way to implement inversion of control for proper dependency injection in Umbraco.
After much brow-furrowing and much to-ing and fro-ing with some of the Umbraco devs (shout out to @clausjnsn for all the help) I think I have it.
I’m using Autofac because I’ve used it before, and @shazwazza‘s original IOC documentation on our.umbraco used it. If you’re confident with your container’s api you should be able to follow my instructions with any container you like.
Step 1: Setup
Step one is to add some custom startup code to Umbraco with a custom OnApplicationStarted
method. For those familiar with dependency-injection lingo, this is our application’s composition root, or where we will register the dependencies with our container. My preferred way to do this is by implementing IApplicationEventHandler
. The mere presence of this class somewhere in your code should cause your OnApplicationStarted
method to be run, well… on application started. If that makes any grammatical sense.
Step 2: Injecting an IContentService
Let’s suppose we’re doing some fancy stuff with Umbraco and have written a class that depends on ContentService
. Nothing too fancy that the docs won’t be able to help you with.
ApplicationContext.Current.Services.ContentService.CreateContent(name, parentID, contentTypeAlias);
Your trusty copy of Mark Seeman’s Dependency Injection in .NET should have just dislodged itself from the shelf, wiggled free, and hurled itself at the back of your head at the sight of the above code. I hope it hurt. How could you be so naive? You’ve just gone and created an explicit dependency on ApplicationContext.Current.Services.ContentService
. How are you going to unit test that? What happens when your boss tells you to rewrite the whole thing with EntityFramework and you have explicit references to Umbraco services all over the place?
Since the content service implements IContentService
anyway, you should be writing your own wrappers around Umbraco’s core services, and then using your dependency injection mojo to inject an instance of IContentService
into them. Here’s an example of a “wrapper” class.
Notice how it doesn’t depend on Umbraco’s ContentService
directly? It only depends on the interface IContentService
. Providing our own implementation of IContentService
for unit testing should now be a piece of cake. Depending on this class will appease the SOLID gods and guarantee you a place in programmer paradise.
We just need to make sure that our IContentService
is being injected properly at our app’s composition root, which takes only a few lines of code in our IApplicationEventHandler
implementation.
This shouldn’t be spectacular to you, but all we’re doing is telling Autofac to use applicationContext.Services.ContentService
, the instance of IContentService
that’s helpfully setup by Umbraco, whenever one of our classes asks for an IContentService
as a dependency, like our MyAppContentService
wrapper does in the constructor.
Lastly, we tell ASP.NET MVC to use Autofac as a dependency resolver.
// Set up MVC to use Autofac as a dependency resolver
var container = builder.Build();
System.Web.Mvc.DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
Now you can live out the rest of your days in the endless bliss of dependency injection paradise.
OR CAN YOU?
Step 3: Trouble in Para-DI-se
If you’re smart, you will have noticed that the above code has broken the Umbraco backoffice. If you’re not smart, you will have shipped your code and upset your colleagues/clients/boss/deity. Well done. Yes, I’ll have fries with that.
It looks like the code that sets the DependencyResolver
for ASP.NET MVC causes the Umbraco backoffice to freak out when it tries to work with API controllers. Or something like that.
Happily, we can resolve this issue with very few lines of code by registering all the mvc controllers and web api controllers in Umbraco’s assembly with our IOC. Autofac has quite a slick API for doing this.
In case you missed it, we added two LOC:
builder.RegisterControllers(typeof(Umbraco.Web.UmbracoApplication).Assembly);
builder.RegisterApiControllers(typeof(Umbraco.Web.UmbracoApplication).Assembly);
Step 4: …. Profit?
That’s all there is to it folks. IOC in Umbraco. I’ve experience the pain of the many gotchas during this process so that you don’t have to.
Thanks for reading! If you enjoyed this post, have anything to add, or would otherwise like to get in touch you can do so on Twitter @glcheetham.
Expert advice
You're reading the GL Digital blog, where auto marketing experts share proven tactics to grow your dealership.
Struggling to make good video?
Sometimes it feels like posting on TikTok is a waste of time.
Build a powerful local brand and watch customers roll in from TikTok.