Kentico 12: Design Patterns Part 4 - Adding Dependency Injection to the CMS
Tags: kentico, dependencyinjection, csharp, autofac
Published: 2019-06-03 14:49:22

---
title: Kentico 12: Design Patterns Part 4 - Adding Dependency Injection to the CMS
published: true
description: 
tags: kentico, dependencyInjection, csharp, autofac
series: Kentico 12 - Design Patterns
---

![](https://thepracticaldev.s3.amazonaws.com/i/liul85lqvqkm9bymb72m.jpg)
<figcaption>Photo by <a href="https://unsplash.com/@richtervet">Rich Tervet</a> on <a href="https://unsplash.com">Unsplash</a></figcaption>

Now that Kentico has empowered its developers to build applications with ASP.NET MVC, we can leverage design patterns and best practices that are encouraged by the framework. 👍

As our libraries and code bases change to take advantage of these patterns and practices, can we use them in the CMS application which is built on ASP.NET Web Forms? If so, how do we accomplish this? 🤔

With the pattern of Dependency Injection, the answer is Yes and Yes! 🙌

Let's take a look!
  
## The Pattern

One of the patterns that MVC encourages is [Inversion of Control](https://en.wikipedia.org/wiki/Inversion_of_control) (IoC). This pattern can be implemented through [Dependency Injection](https://en.wikipedia.org/wiki/Dependency_injection) (DI) with both framework types and custom user defined types.

In application frameworks, the way IoC is usually accomplished is by allowing the framework to create and call specific entry point types, created by the developer — from there our code executes until it returns.

IoC allows for us to use DI in an elegant manner because the framework is responsible for calling into our code (IoC) — therefore it can also be responsible for creating the things our code depends on (DI).

### DI in MVC

In an MVC application, one of those entry point types is the `System.Web.Mvc.Controller` class, which all custom controllers inherit from.

Here is an example `UserController` with (2) dependencies, `IUserContext` and `IEmailService`:

```csharp
public class UserController : Controller
{
    public UserController(IUserContext userContext, IEmailService emailService)
    {
        // ...
    }
}
```

MVC needs to be able to construct instances of `UserController` when it decides that an HTTP request should be handled by `UserController`. MVC makes this decision based on URL or request body patterns, which map to the routing conventions or configuration in our app.

> To see a routing configuration pattern that mixes convention and configuration read my previous post in this series. 💪

> {% link https://dev.to/seangwright/kentico-12-design-patterns-part-3-tips-and-tricks-application-structure-1l2o %}

If we are using DI through constructor injection, how is MVC able to figure out how to create the dependencies of our controller class? Or the dependencies of those classes?

This recursive problem is solved by an IoC Container. IoC Containers are configured to "know" how to construct an instance of any type used in an application that is considered a dependency. This configuration of types is often known as "registration".

So, at the point in our application where MVC needs to create an instance of our `UserController`, it effectively tries to get one from the IoC Container.

The IoC Container figures out the entire chain of dependencies required to create a `UserController`, creates one, and then returns it to the framework code.

> When using IoC and DI, our code does not create its own dependencies.

> Instead all dependencies must be provided to our code from somewhere higher up. This is the "inversion" of "control" over our own code's dependencies. 😮

### DI In Web Forms

The ASP.NET Web Forms architecture is based around the `Page` and `UserControl` types.

> When working with Kentico we use the `CMSPage` and `CMSAbstractWebPart` classes, accordingly.

Both of these types require public parameter-less constructors.

What happens if we specify dependencies as constructor parameters? The Web Forms framework will fail to create an instance of the type and the request will fail with an exception! 🤦🏽‍♀️

ASP.NET Web Forms was not designed for the same patterns and practices that MVC encourages, but that doesn't mean we are at an impasse.

## The Library - Autofac

With the design pattern established, let's dive into how we configure it, not for MVC, but for ASP.NET Web Forms, which is the framework that the Kentico content management application is built on.

We will be using [Autofac](https://autofac.org/) as our IoC Container of choice.

> There are many IoC Container libraries available in .NET. This [benchmark blog by Daniel Palme](http://www.palmmedia.de/Blog/2011/8/30/ioc-container-benchmark-performance-comparison) contains a pretty thorough list of the most well known libraries.

> In the past I've mostly used [SimpleInjector](https://simpleinjector.org/index.html) because of its great performance, simple API, and container verification feature. It's a fantastic library and [container verification is awesome](https://simpleinjector.readthedocs.io/en/latest/using.html#verifying-the-container-s-configuration).👌

> That said, AutoFac provides some nice APIs for simplifying some problems .NET application frameworks require developers to face. It's also the IoC Container that Kentico uses in its example Dancing Goat site.

We will be using (2) NuGet packages (with versions specified):

1. [Autofac](https://www.nuget.org/packages/Autofac/) (`v4.9.2`) - This is the main IoC Container library which is application framework agnostic.

1. [Autofac.Web](https://www.nuget.org/packages/Autofac.Web/) (`v4.0.0`) - This is the ASP.NET Web Forms integration package for Autofac.

The Web Forms integration package allows us to perform DI in a couple of different ways.

1. Property Injection - Assigns instances resolved by the IoC Container to public properties of the Web Forms `Page` or `UserControl` instance. ✔

1. Attribute Property Injection - Same as the above, but only if a specific attribute is applied to those pages or controls. ✔

1. Null Attribute / Property Injection - Using either approach above, this assigns a resolved instance only if the property is `null` at the time of assignment. ✔

We are going to use the second option, you can explore the other two in [Autofac's documentation](https://autofac.readthedocs.io/en/latest/integration/webforms.html).

> __Update (2019/07/09)__: Kentico has issues in certain areas of the CMS (Reports Module) when using the first option above. For the most part it works but not completely, and that's not good enough! So, while I initially recommended the first option, I'm now recommending the second.

> Thanks to [Tony at Luminary](https://www.luminary.com/tony) for discovering this problem!

Go ahead and [install the NuGet packages](https://docs.microsoft.com/en-us/nuget/quickstart/install-and-use-a-package-in-visual-studio) into the `CMSApp` project.

> Managing NuGet packages in .NET Framework projects can be a lot easier if you use modern .NET features and tools. Check out my post to learn more. 💪

> {% link https://dev.to/seangwright/kentico-12-class-libraries-with-modern-net-core-features-34n5 %}

OK, now let's setup our application!

> In .NET 4.7.2 [a constructor based DI solution has been added to ASP.NET](https://docs.microsoft.com/en-us/dotnet/framework/whats-new/#aspnet) for Web Forms and this solution can be used as a hook point, with an adapter layer, to integrate an IoC Container.


> Here is an [example integrating SimpleInjector](https://gist.github.com/ndc/7334d459c3eb0be594aad3973a488cad).


> I'm going to continue using Property Injection since it's what Autofac supports without customization.

## The Implementation - Kentico 12 CMS

The [Autofac documentation has a great walkthrough](https://autofac.readthedocs.io/en/latest/integration/webforms.html) of how to configure our application to start using the library, and I will summarize the steps below.

### Configuring The Project

First, Add the following ASP.NET module entries to the application `web.config` under the `<configuration><system.webServer><modules>` node.

```xml
<add
    name="ContainerDisposal"
    type="Autofac.Integration.Web.ContainerDisposalModule, Autofac.Integration.Web"
    preCondition="managedHandler"/>
<add
    name="PropertyInjection"
    type="Autofac.Integration.Web.Forms.AttributedInjectionModule, Autofac.Integration.Web"
    preCondition="managedHandler"/>
```

Next, update our `Global` class in `Global.asax.cs` to support Autofac.

```csharp
// Add the IContainerProviderAccessor interface
public class Global : CMSHttpApplication, IContainerProviderAccessor
{
    static Global()
    {
        /// leave existing code
    }

    // Holds the application container
    private static IContainerProvider containerProvider;

    // Used by Autofac to resolve dependencies via IContainerProviderAccessor
    public IContainerProvider ContainerProvider => containerProvider;

    // Creates a container builder, builds it, and then sets the container
    protected void Application_Start(object sender, EventArgs e)
    {
        var builder = new ContainerBuilder();

        var container = builder.Build();

        containerProvider = new ContainerProvider(container);
    }
}
```

That's it! DI is now set up for our CMS application!

... except we haven't registered any types, so our IoC Container and its integration into Web Forms isn't very helpful at the moment. 😑

So, let's register some types with Autofac!

### Registering Our Types

What kind of types do we want to register?

Why don't we use the `ISiteContext` and `KenticoSiteContext` types from previous posts in this series? 😊

First, create the `ISiteContext` interface:

```csharp
public interface ISiteContext
{
    string SiteName { get; }
    int SiteId { get; }
    SiteInfo Site { get; }
}
```

And now the `KenticoSiteContext` implementation:

```csharp
public class KenticoSiteContext : ISiteContext
{
    public string SiteName => SiteContext.CurrentSiteName;

    public int SiteId => SiteContext.CurrentSiteID;

    public SiteInfo Site => SiteContext.CurrentSite;
}
```

While there is nothing preventing us from adding all the Autofac type registrations to our `Global.asax.cs` file, I'd recommend moving type registration to a different class.

I typically create a `DependencyResolverConfig.cs` class (or something similar).

In this class we can register our types and then build the container:

```csharp
public static class DependencyResolverConfig
{
    public static IContainer BuildContainer()
    {
        var builder = new ContainerBuilder();

        builder
            .RegisterSource<KenticoRegistrationSource>();

        builder
            .RegisterType<KenticoSiteContext>()
            .As<ISiteContext>();

        var container = builder.Build();

        return container;
    }
}
```

> As this file grows in registrations and complexity, I always move the registrations out into separate classes that each focus on a specific part of the application (ex: Application, Data Access, Authorization).

> You can find an [example in a gist here](https://gist.github.com/seangwright/4918a5c5488a9bb617ebdf1c2557fe6b#file-dependencyresolverconfig-cs).

Notice the line `builder.RegisterSource<KenticoRegistrationSource>();`.

This tells Autofac that when it doesn't know how to resolve a type, forward the request for an instance of that type on to Kentico. An example type that this could resolve for us would be `CMS.Ecommerce.ICurrentShoppingCartService`.

> The code for `KenticoRegistrationSource` is a bit long, so it can be [found in this gist](https://gist.github.com/seangwright/4918a5c5488a9bb617ebdf1c2557fe6b#file-kenticoregistrationsource-cs).

Now we need to update our `Global` class in the `Global.asax.cs` file to use the new `DependencyResolverConfig` class. The only change that needs to be made is to replace the `Application_Start` method with the code below.

```csharp
protected void Application_Start(object sender, EventArgs e)
{
    var container = DependencyResolverConfig.BuildContainer();

    containerProvider = new ContainerProvider(container);
}
```

### Resolving Our Types in a Page

Let's create a Web Form class and test resolving our types.

Create a new Web Form Page under `CMSApp -> CMSPages` with the name `DIPage`. Replace the contents of `DIPage.aspx.cs` with the code below.

```csharp
[InjectPropertiesAttribute]
public partial class DIPage : CMSPage
{
    public ISiteContext SiteContext { get; set; }
    public ICurrentShoppingCartService CurrentShoppingCartService { get; set; }

    protected void Page_Load(object sender, EventArgs e)
    {
        var service = CurrentShoppingCartService;

        var cart = service.GetCurrentShoppingCart(
            CurrentUser, 
            SiteContext.SiteName);
    }
}
```

We will set a breakpoint in Visual Studio on the opening brace of the `Page_Load` method, and run the CMS project with debugging.

When we hit the breakpoint and step through the code, we will see the `SiteContext` and `CurrentShoppingCartService` properties are populated with the values we would expect.

Pretty nice! 😃✨

### Resolving Our Types Outside of Pages or Controls

What should we do when we want to resolve our types from within other parts of our Kentico application, like a scheduled task?

In this case we can't use DI because Kentico creates the instances of the custom scheduled task classes. Unlike with the Autofac Web Forms integration package, we don't have a way to tell Kentico to resolve constructor parameters or class property values from an IoC Container. 🤔

> Kentico folks: If there is a way to customize creation of these types, I'd love to know!

What we can do instead is use the Autofac container as a [Service Locator](https://en.wikipedia.org/wiki/Service_locator_pattern).

> Normally, service location would be [considered an anti-pattern](https://blog.ploeh.dk/2010/02/03/ServiceLocatorisanAnti-Pattern/), but when you are only provided lemons you put on gloves, eye protection, and then start juicing! 🥤

To demo this, let's create a custom scheduled task that returns the current requesting user's shopping cart Id.

```csharp
public class GetCurrentUserShoppingCartIdTask : ITask
{
    private readonly ISiteContext siteContext;
    private readonly ICurrentShoppingCartService currentShoppingCartService;

    public GetCurrentUserShoppingCartIdTask()
    {
        // Get the instance of our application
        var application = HttpContext
                .Current
                .ApplicationInstance as IContainerProviderAccessor;

        // Get the global container from the application
        var container = application
                .ContainerProvider
                .ApplicationContainer;

        // Resolve our dependencies
        siteContext = container.Resolve<ISiteContext>();
        currentShoppingCartService = container.Resolve<ICurrentShoppingCartService>();
    }

    public string Execute(TaskInfo task)
    {
        string siteName = siteContext.SiteName;

        var cart = currentShoppingCartService.GetCurrentShoppingCart(
            MembershipContext.AuthenticatedUser, 
            siteName);

        return cart.ShoppingCartID.ToString();
    }
}
```

We take dependencies on the two types we've already seen (`ISiteContext` and `ICurrentShoppingCartService`), but instead of getting them through the class constructor or public properties, we resolve them directly from the container.

> The `IContainerProviderAccessor application` above is the instance of the application created from our `Global` class in `Global.asax.cs` and the `ILifetimeScope container` is the same thing that Web Forms uses to get instances for property injection with our custom `Page` and `UserControl` types.

So, we resolve our dependencies in the constructor of our class and then use them in the `Execute()` method.

There's a lot of glue code in that constructor. Let's move some to an extension method.

```csharp
public static class TaskExtensions
{
    public static ILifetimeScope GetContainer(this ITask task, HttpContext context)
    {
        // Get the instance of our application
        var application = context
                .ApplicationInstance as IContainerProviderAccessor;

        // Get the global container from the application
        return application
                .ContainerProvider
                .ApplicationContainer;
    }
}
```

Now our constructor looks as follows:

```csharp
public GetCurrentUserShoppingCartIdTask()
{
    var container = this.GetContainer(HttpContext.Current);

    // Resolve our dependencies
    siteContext = container.Resolve<ISiteContext>();
    currentShoppingCartService = container.Resolve<ICurrentShoppingCartService>();
}
```

> The `GetContainer()` extension method can only be called on an `ITask` which prevents the Service Locator pattern from leaking into the rest of our codebase! 👍

My final recommendation, which I won't show here, would be to move the business logic of the `Execute()` method into another class that follows our patterns and practices from MVC – DI and the [Single Reponsibility Principle](https://en.wikipedia.org/wiki/Single_responsibility_principle).

This new class will take `ISiteContext` and `ICurrentShoppingCartService` as constructor dependencies and have a simple API (only a couple of methods at most) to process the scheduled task.

We can then use the IoC Container to create an instance of it instead of its dependencies. Then we call its methods in the `ITask.Execute()` method.

## Wrap Up!

We reviewed what Inversion of Control is, how it enables Dependency Injection, and how ASP.NET MVC uses these concepts to help developers create an application. 🧐

Although ASP.NET Web Forms doesn't support either of these concepts out of the box, we can enhance the framework with Autofac to allow for Property Injection of the `Page` and `UserControl` types. 😎

We also took a look at the scenario where we want to resolve our registered dependencies inside Kentico types that we cannot integrate with our IoC Container. 🤗

Instead, we said [YOLO!](https://en.wikipedia.org/wiki/YOLO_(aphorism)), and used a Service Locator pattern to resolve our types. 😜

I hope you found this walkthrough helpful and the explanations clear!

This is my first blog post since switching my blogging from [Medium](https://medium.com/@seangwright) to DEV, and I'm looking forward to writing more in the future.

For more on Kentico Design Patterns, [checkout my series](https://dev.to/search?q=Kentico%2012%20-%20Design%20Patterns) or the Kentico tag here on DEV.

{% tag kentico %}