Dependency Injection – Unity and MVC with .NET

I have spent most of my career developing solutions in .NET and will always have a soft spot for C#.  I decided to create a fun blog on Dependency Injection since most of my earlier blogging have been leveraging Java.

The first time I was trying to apply or even understand the abstract concept of Dependency Injection (DI) or Inversion of Control (IoC), I was completely lost.  If you are the same person who I was then I hope this blog really helps you out.

So our objective in this blog is to create a quick .NET MVC project and add Dependency Injection to it.  We will then go over the benefits of doing this; hopefully you will quickly understand why most if not all projects should have some sort of DI or IoC.

Lets get started by creating a basic MVC Application using Visual Studio.  If you need Visual Studio then please google “Visual Studio Community Edition”!  Its free!

Now that we have a basic project created, we need to add Unity to our project using NuGet.  (Tools –> NuGet Package Manager –> Manage NuGet Packages for Solution…)

Search for “Unity.MVC”, select and install it on your website project

We have all of the tools we need installed so lets go over our objective now.  We are going to create a Business Layer that we will return some data from our pretend database since the data layer is the most common object that is put into DI.   You know you have a good solution if you can completely unplug your PC from the network and still run all of your test scripts for your database methods, etc.  This is our goal in this Blog.

Lets start by adding a simple business layer to our application. (Right click your solution, Add –> New Project)

Now we will create a quick interface and class.  The interface will be used by the Web Project and the Test Project.  The class in the business layer will implement the interface on the Web project which is where you would wire up your database.

A couple of house cleaning items after you create the project; it will automatically put a class in your project called “Class1.cs”.  I am renaming that to DataLayer.cs for this demo.  For the sake of simplicity, I will not be wiring this up to an actual database but creating a function that will return data.  The data source at this point is irrelevant mostly because we are demonstrating how to put a class/object into DI and overriding it for our test project.

Lets just create a super basic data layer that delivers data from an int constant and pretend that it got that data from the worlds largest and fastest database server!  Here is the code for our DataLayer and Interface that we need to toss into our business layer.

Interface: (IDataLayer.cs)

namespace MVC_DI_BL
{
    public interface IDataLayer
    {
        int giveRecordCount();
    }
}

DataLayer Class: (DataLayer.cs)

namespace MVC_DI_BL
{
    public class DataLayer : IDataLayer
    {
        private const int recCount = 10;

        public int giveRecordCount()
        {
            return recCount;
        }
    }
}

Now lets wires this bad boy up to our MVC Website!  Sadly this is where the fun really begins for nerds like me.  Open the UnityConfig.cs file under the “App_Start” folder and look for the RegisterTypes method.

UnityConfig.cs – > public static void RegisterTypes (IUnityContainer container)

We want to add this line at the bottom of this method.

container.RegisterType<IDataLayer, DataLayer>();

Super Duper Important Note About the Code Above!
This is the most important part of this; we are essentially adding an instance of our DataLayer class which is aligned to our IDataLayer interface directly to our Unity Container.  Everytime Unity is asked to fulfill the dependency of IDataLayer, it will reach into this container and give that instance the DataLayer class which it instantiates on app start.  This is the black magic of dependency injection!

Lets test our implementation and make sure it works.  We have 2 super easy ways to test it.  We can perform property injection or constructor injection.  I will quickly show you how to do both.

Property Injection:
1. Create a property:   public IDataLayer dl { get; set; }
2. Add the [Dependency] attribute to the property.

The unity framework will automatically bind your DataLayer : IDataLayer instance from the Unity Container to this property.  Easy right?

Alternatively you can use Constructor Injection which typically makes building your test cases easier.  I personally prefer this because I am a little lazy and like to reduce the number of lines of code in my test cases.

Constructor Injection:
1.  Create a property: public IDataLayer dl { get; set; }
–We don’t need to add the [Dependency] attribute to this for constructor injection
2. Create a new Constructor with a parameter and update our property here.
public HomeController(IDataLayer _dl) { dl = _dl; }
3. Add the [InjectionConstructor] attribute to our new constructor.

I have added my code for the HomeController and Index view below for you to test this out.  The example uses both Property and Constructor Injection; to test each individually you will just need to comment out the appropriate decoration/attribute.

using Microsoft.Practices.Unity;
using MVC_DI_BL;
using System;
using System.Web.Mvc;

namespace MVC_DI.Controllers
{
    public class HomeController : Controller
    {
        //Property + Property Injection
        [Dependency]
        public IDataLayer dl { get; set; }

        #region Constructors and Disposal of objects
        //Modified the constructor for Unit Testing... Constructor Injection will 
        //populate this value in real-time.
        public HomeController() { }

        [InjectionConstructor]
        public HomeController(IDataLayer _dl)
        {
            dl = _dl;
        }
        //Clean up
        protected override void Dispose(bool disposing)
        {
            if (dl is IDisposable)
            {
                ((IDisposable)dl).Dispose();
            }
            base.Dispose(disposing);
        }
        #endregion

        public ActionResult Index()
        {
            return View(dl.giveRecordCount());
        }
    }
}
@model int
@{
    ViewBag.Title = "Home Page";
}

<div class="jumbotron">
    <h1>Record Count - @Model </h1>
</div>

Below is what your output should look like once you run your project.

If you get the same output then you have successfully implemented dependency injection into your MVC project.  Now we need to stay course and follow up with our test project.  We do not need to use dependency injection on our tests because we can bind our data manually; we don’t need any of the black magic that Unity performs in the background.

The first thing we need to do is create our Test Project Data Source; I have created a new class called TestDataLayer which inherits IDataLayer.  I then implemented the interface and had it return the number 9 instead of 10.  This way I can guarantee that I have bound my interface to our test data source.  Ideally your test data source should not be wired up to any external dependency so you can automatically test/build your projects offline.

Test DataLayer Code

using MVC_DI_BL;

namespace MCV_DI.Tests
{
    public class TestDataLayer : IDataLayer
    {
        private const int recCount = 9;

        public int giveRecordCount()
        {
            return recCount;
        }
    }
}

Test Class

using System.Web.Mvc;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MVC_DI.Controllers;
using MVC_DI_BL;
using MCV_DI.Tests;

namespace MVC_DI.Tests.Controllers
{
    [TestClass]
    public class HomeControllerTest
    {
        [TestMethod]
        public void Index()
        {

            //Setup our test datalayer that we can easily create fake data that can be accessed offline, etc.
            IDataLayer dl = new TestDataLayer();

            // Arrange
            HomeController controller = new HomeController(dl);

            // Act - Does it still work with our custom datalayer?
            ViewResult result = controller.Index() as ViewResult;

            // Assert that our page still works
            Assert.IsNotNull(result);

            //Make sure we are using the test data layer and getting back the exact value we want.
            Assert.AreEqual(dl.giveRecordCount(), 9);  //the value 10 is returned from the datalayer we are using on our web project
        }

    }
}

As you can see all I have to do is call our HomeController with the constructor that takes our parameter and “poof” we have passed in our test datalayer.  Now all of our tests will automagically work.

Test – > Run – All Tests

Adding dependency injection may feel like yet another step to over architect your projects but after doing this a few times when developing an end to end solution you will quickly see how much of a requirement this is in order to build real-world solutions.  Unity is probably the easiest solution I have found for .NET MVC and it works great!  I hope this helps out someone who is newer to this concept; I know when I first was introduced to this that I was completely lost.  We all will have to go through this milestone on our way to becoming professional developers!  Good Luck!

Leave a comment

Leave a Reply

Your email address will not be published. Required fields are marked *