Click here to Skip to main content
15,879,474 members
Articles / Web Development / HTML

RESTful Day #2: Inversion of control using dependency injection in Web APIs using Unity Container and Bootstrapper

Rate me:
Please Sign up or sign in to vote.
4.94/5 (87 votes)
1 Mar 2016CPOL10 min read 240.5K   10.9K   100   76
My article will explain how we can make our Web API service architecture loosely coupled and more flexible.

Table of Contents

Introduction

My article will explain how we can make our Web API service architecture loosely coupled and more flexible. We already learnt that how we can create a RESTful service using Asp.net Web API and Entity framework in my last article. If you remember we ended up in a solution with a design flaw, we’ll try to overcome that flaw by resolving the dependencies of dependent components. For those who have not followed my previous article, they can learn by having the sample project attached as a test application from my first article.

Image 1

There are various methods you can use to resolve dependency of components. In my article I’ll explain how to resolve dependency with the help of Unity Container provided by Microsoft’s Unity Application Block.

We’ll not go into very detailed theory, for theory and understanding of DI and IOC you can follow the following links: Unity and Inversion of Control(IOC). We’ll straight away jump into practical implementation.

Roadmap

Image 2

Our roadmap for learning RESTful APIs remains same,

I’ll purposely use Visual Studio 2010 and .NET Framework 4.0 because there are few implementations that are very hard to find in .NET Framework 4.0, but I’ll make it easy by showing how we can do it.

Existing Design and Problem

We already have an existing design. If you open the solution, you’ll get to see the structure as mentioned below,

Image 3

The modules are dependent in a way,

Image 4

There is no problem with the structure, but the way they interact to each other is really problematic. You must have noticed that we are trying to communicate with layers, making the physical objects of classes.

For e.g.

Controller constructor makes an object of Service layer to communicate,

C#
/// <summary>
/// Public constructor to initialize product service instance
/// </summary>
public ProductController()
{
    _productServices =new ProductServices();
}

Service constructor in turn makes and object of UnitOfWork to communicate to database,

C#
/// <summary>
/// Public constructor.
/// </summary>
public ProductServices()
{
    _unitOfWork = new UnitOfWork();
}

The problem lies in these code pieces. We see Controller is dependent upon instantiation of Service and Service is dependent upon UnitOfWork to get instantiated. Our Layers should not be that tightly coupled and should not be dependant to each other.

The work of creating object should be assigned to someone else. Our layers should not worry about creating objects.

We’ll assign this role to a third party that will be called our container. Fortunately Unity provides that help to us, to get rid of this dependency problem and invert the control flow by injecting dependency not by creating objects by new but through constructors or properties. There are other methods too, but I am not going into detail.

Introduction to Unity

You can have a read about Unity from this link; I am just quoting some lines,

Image 5

"The Unity Application Block (Unity) is a lightweight, extensible dependency injection container that supports constructor injection, property injection, and method call injection. It provides developers with the following advantages:

  • It provides simplified object creation, especially for hierarchical object structures and dependencies, which simplifies application code.
  • It supports abstraction of requirements; this allows developers to specify dependencies at run time or in configuration and simplify management of crosscutting concerns.
  • It increases flexibility by deferring component configuration to the container.
  • It has a service location capability; this allows clients to store or cache the container. This is especially useful in ASP.NET Web applications where developers can persist the container in the ASP.NET session or application."

Setup Unity

Open your Visual studio, I am using VS 2010, You can use VS version 2010 or above. Load the solution.

Step 1: browse to Tools-> Library Packet Manager - > Packet manager Console,

Image 6

We’ll add package for Unity Application Block.

In the left bottom corner of Visual Studio, You’ll find where to write the command.

Type command Install-Package Unity.MVC3 and choose "WebApi" project before you fire the command.

Image 7

There after type command  Install-Package Unity.WebAPI -Version 0.10.0 to install Unity.WebApi and choose WebApi project in the same way like you did for Unity.MVC3.

You may use Unity.WebAPI and Unity.Mvc3 in the same project but you will need to correct the bootstrapper class that we got, that it should use both libraries. After installing both the packages, change the Initialise method in the Bootstrapper.cs file to the following:

C#
public static void Initialise()
{
    var container = BuildUnityContainer();

    DependencyResolver.SetResolver(new Unity.Mvc3.UnityDependencyResolver(container));
    GlobalConfiguration.Configuration.ServiceResolver.SetResolver(
      new Unity.WebApi.UnityDependencyResolver(container));
}

Step 2: Bootstrapper class

Unity.MVC3 comes with a Bootstrapper class, as soon as you run the command, the Bootstrapper class will be generated in your solution->WebAPI project,

C#
using System.Web.Http;
using System.Web.Mvc;
using BusinessServices;
using DataModel.UnitOfWork;
using Microsoft.Practices.Unity;
using Unity.Mvc3;

namespace WebApi
{
    public static class Bootstrapper
    {
        public static void Initialise()
        {
            var container = BuildUnityContainer();

            DependencyResolver.SetResolver(new UnityDependencyResolver(container));

            // register dependency resolver for WebAPI RC
            GlobalConfiguration.Configuration.DependencyResolver = new Unity.WebApi.UnityDependencyResolver(container);
        }

        private static IUnityContainer BuildUnityContainer()
        {
            var container = new UnityContainer();

            // register all your components with the container here
            // it is NOT necessary to register your controllers
            
            // e.g. container.RegisterType<ITestService, TestService>();        
            container.RegisterType<IProductServices, ProductServices>().RegisterType<UnitOfWork>(new HierarchicalLifetimeManager());

            return container;
        }
    }
}

Image 8

This class comes with an initial configuration to setup your container. All the functionality is inbuilt, we only need to specify the dependencies that we need to resolve in the "BuildUnityContainer", like it says in the commented statement,

C#
// register all your components with the container here
// it is NOT necessary to register your controllers

// e.g. container.RegisterType<ITestService, TestService>();

Step 3: Just specify the components below these commented lines that we need to resolve. In our case, it’s ProductServices and UnitOfWork, so just add,

C#
container.RegisterType<IProductServices, ProductServices>().RegisterType<UnitOfWork>(new HierarchicalLifetimeManager());

"HierarchicalLifetimeManager" , for this lifetime manager, as for the ContainerControlledLifetimeManager, Unity returns the same instance of the registered type or object each time you call the Resolve or ResolveAll method or when the dependency mechanism injects instances into other classes. The distinction is that when there are child containers, each child resolves its own instance of the object and does not share one with the parent. When resolving in the parent, the behavior is like a container controlled lifetime; when resolving the parent and the child you have different instances with each acting as a container-controlled lifetime. If you have multiple children, each will resolve its own instance.

If you don’t find "UnitOfWork", just add reference to DataModel project in WebAPI project.

So our Bootstrapper class becomes,

C#
public static class Bootstrapper
 {
     public static void Initialise()
     {
         var container = BuildUnityContainer();

         DependencyResolver.SetResolver(new UnityDependencyResolver(container));

         // register dependency resolver for WebAPI RC
         GlobalConfiguration.Configuration.DependencyResolver = new Unity.WebApi.UnityDependencyResolver(container);
     }

     private static IUnityContainer BuildUnityContainer()
     {
         var container = new UnityContainer();

         // register all your components with the container here
         // it is NOT necessary to register your controllers

         // e.g. container.RegisterType<ITestService, TestService>();
         container.RegisterType<IProductServices, ProductServices>().RegisterType<UnitOfWork>(new HierarchicalLifetimeManager());

         return container;
     }

Like this we can also specify other dependent objects in BuildUnityContainerMethod.

Step 4: Now we need to call the Initialise method of Bootstrapper class. Note , we need the objects as soon as our modules load, therefore we require the container to do its work at the time of application load, therefore go to Global.asax file and add one line to call Initialise method, since this is a static method, we can directly call it using class name,

C#
Bootstrapper.Initialise();

Our global.asax becomes,

C#
using System.Linq;
using System.Web.Http;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;
using Newtonsoft.Json;
using WebApi.App_Start;

namespace WebApi
{
    // Note: For instructions on enabling IIS6 or IIS7 classic mode, 
    // visit http://go.microsoft.com/?LinkId=9394801

    public class WebApiApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();

            WebApiConfig.Register(GlobalConfiguration.Configuration);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
            //Initialise Bootstrapper
            Bootstrapper.Initialise();

            //Define Formatters
            var formatters = GlobalConfiguration.Configuration.Formatters;
            var jsonFormatter = formatters.JsonFormatter;
            var settings = jsonFormatter.SerializerSettings;
            settings.Formatting = Formatting.Indented;
            // settings.ContractResolver = new CamelCasePropertyNamesContractResolver();
            var appXmlType = formatters.XmlFormatter.SupportedMediaTypes.FirstOrDefault(t => t.MediaType == "application/xml");
            formatters.XmlFormatter.SupportedMediaTypes.Remove(appXmlType);

            //Add CORS Handler
            GlobalConfiguration.Configuration.MessageHandlers.Add(new CorsHandler());
        }
    }
}

Half of the job is done. We now need to touchbase our controller and Service class constructors to utilize the instances already created for them at application load.

Setup Controller

We have already set up unity in our application. There are various methods in which we can inject dependency, like constructor injection, property injection, via service locator. I am here using Constructor Injection, because I find it best method to use with Unity Container to resolve dependency.

Just go to your ProductController, you find your constructor written as,

C#
/// <summary>
/// Public constructor to initialize product service instance
/// </summary>
public ProductController()
{
    _productServices =new ProductServices();
}

Just add a parameter to your constructor that takes your ProductServices reference, like we did below

C#
/// <summary>
 /// Public constructor to initialize product service instance
 /// </summary>
 public ProductController(IProductServices productServices)
 {
     _productServices = productServices;
 }

And initialize your "productServices" variable with the parameter. In this case when the constructor of the controller is called, It will be served with pre-instantiated service instance, and does not need to create an instance of the service, our unity container did the job of object creation.

Setup Services

For services too, we proceed in a same fashion. Just open your ProductServices class, we see the dependency of UnitOfWork here as,

C#
/// <summary>
/// Public constructor.
/// </summary>
public ProductServices()
{
    _unitOfWork = new UnitOfWork();
}

Again, we perform the same steps ,and pass a parameter of type UnitOfWork to our constructor,

Our code becomes,

C#
/// <summary>
/// Public constructor.
/// </summary>
public ProductServices(UnitOfWork unitOfWork)
{
    _unitOfWork = unitOfWork;
}

Here also we’ll get the pre instantiated object on UnitOfWork. So service does need to worry about creating objects. Remember we did .RegisterType<UnitOfWork>() in Bootstrapper class.

We have now made our components independent.

Image 9

Running the application

Our job is almost done.We need to run the application, Just hit F5. To our surprise we’ll end up in an error page,

Image 10

Do you remember we added a test client to our project to test our API in my first article. That test client have a controller too, we need to override its settings to make our application work.Just go to Areas->HelpPage->Controllers->HelpController in WebAPI project like shown below,

Image 11

Comment out the existing constructors and add a Configuration property like shown below,

C#
//Remove constructors and existing Configuration property.

  //public HelpController()
  //    : this(GlobalConfiguration.Configuration)
  //{
  //}

  //public HelpController(HttpConfiguration config)
  //{
  //    Configuration = config;
  //}

  //public HttpConfiguration Configuration { get; private set; }

  /// <summary>
  /// Add new Configuration Property
  /// </summary>
  protected static HttpConfiguration Configuration
  {
      get { return GlobalConfiguration.Configuration; }
  }

Our controller code becomes,

C#
using System;
using System.Web.Http;
using System.Web.Mvc;
using WebApi.Areas.HelpPage.Models;

namespace WebApi.Areas.HelpPage.Controllers
{
    /// <summary>
    /// The controller that will handle requests for the help page.
    /// </summary>
    public class HelpController : Controller
    {
        //Remove constructors and existing Configuration property.

        //public HelpController()
        //    : this(GlobalConfiguration.Configuration)
        //{
        //}

        //public HelpController(HttpConfiguration config)
        //{
        //    Configuration = config;
        //}

        //public HttpConfiguration Configuration { get; private set; }

        /// <summary>
        /// Add new Configuration Property
        /// </summary>
        protected static HttpConfiguration Configuration
        {
            get { return GlobalConfiguration.Configuration; }
        }

        public ActionResult Index()
        {
            return View(Configuration.Services.GetApiExplorer().ApiDescriptions);
        }

        public ActionResult Api(string apiId)
        {
            if (!String.IsNullOrEmpty(apiId))
            {
                HelpPageApiModel apiModel = Configuration.GetHelpPageApiModel(apiId);
                if (apiModel != null)
                {
                    return View(apiModel);
                }
            }

            return View("Error");
        }
    }
}

Just run the application, we get,

Image 12

We alreay have our test client added, but for new readers, I am just again explaining on how to add a test client to our API project.

Just go to Manage Nuget Packages, by right clicking WebAPI project and type WebAPITestClient in searchbox in online packages,

Image 13

You’ll get "A simple Test Client for ASP.NET Web API", just add it. You’ll get a help controller in Areas-> HelpPage like shown below,

Image 14

I have already provided the database scripts and data in my previous article, you can use the same.

Append "/help" in the application url, and you’ll get the test client,

Image 15

You can test each service by clicking on it. Once you click on the service link, you'll be redirected to test the service page of that particular service.On that page there is a button Test API in the right bottom corner, just press that button to test your service,

Test API

Service for GetAllProduct,

Image 17

For Create a new product,

Image 18

In database, we get new product,

Image 19

Update product:

Image 20

We get in database,

Image 21

Delete product:

Image 22

In database:

Image 23

Job done.

Image 24

Design Flaws

What if I say there are still flaws in this design, the design is still not loosely coupled.

Do you remember what we decided while writing our first application?

Our API talks to Services and Services talk to DataModel. We’ll never allow DataModel talk to APIs for security reasons. But did you notice that when we were registering the type in Bootstrapper class, we also registered the type of UnitOfWork that means we added DataModel as a reference to our API project. This is a design breach. We tried to resolve dependency of a dependency by violating our design and compromising security.

In my next article, we’ll overcome this situation, we’ll try to resolve dependency and its dependency without violating our design and compromising security. In fact we’ll make it more secure and loosely coupled.

In my next article we’ll make use of Managed Extensibility Framework(MEF) to achieve the same.

Conclusion

We now know how to use Unity container to resolve dependency and perform inversion of control.

But still there are some flaws in this design. In my next article I’ll try to make system more strong. Till then Happy Coding :) You can also download the source code from GitHub. Add the required packages, if they are missing in the source code.

My other series of articles:

MVC: http://www.codeproject.com/Articles/620195/Learning-MVC-Part-Introduction-to-MVC-Architectu

OOP: http://www.codeproject.com/Articles/771455/Diving-in-OOP-Day-Polymorphism-and-Inheritance-Ear

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Architect https://codeteddy.com/
India India
Akhil Mittal is two times Microsoft MVP (Most Valuable Professional) firstly awarded in 2016 and continued in 2017 in Visual Studio and Technologies category, C# Corner MVP since 2013, Code Project MVP since 2014, a blogger, author and likes to write/read technical articles, blogs, and books. Akhil is a technical architect and loves to work on complex business problems and cutting-edge technologies. He has an experience of around 15 years in developing, designing, and architecting enterprises level applications primarily in Microsoft Technologies. He has diverse experience in working on cutting-edge technologies that include Microsoft Stack, AI, Machine Learning, and Cloud computing. Akhil is an MCP (Microsoft Certified Professional) in Web Applications and Dot Net Framework.
Visit Akhil Mittal’s personal blog CodeTeddy (CodeTeddy ) for some good and informative articles. Following are some tech certifications that Akhil cleared,
• AZ-304: Microsoft Azure Architect Design.
• AZ-303: Microsoft Azure Architect Technologies.
• AZ-900: Microsoft Azure Fundamentals.
• Microsoft MCTS (70-528) Certified Programmer.
• Microsoft MCTS (70-536) Certified Programmer.
• Microsoft MCTS (70-515) Certified Programmer.

LinkedIn: https://www.linkedin.com/in/akhilmittal/
This is a Collaborative Group

780 members

Comments and Discussions

 
QuestionPlease upgrade this blog with the updated Unity package Pin
Member 448231211-Aug-19 18:36
Member 448231211-Aug-19 18:36 
GeneralMy vote of 5 Pin
shahidrider8217-Dec-18 19:48
shahidrider8217-Dec-18 19:48 
QuestionCorsHandler() problem - the type or namespace could not be found Pin
Member 1301542214-Jun-18 7:43
Member 1301542214-Jun-18 7:43 
QuestionCORS class defination Pin
Roshan Ghangare14-Jul-17 18:40
Roshan Ghangare14-Jul-17 18:40 
QuestionExcelente articulo Pin
polaniavera15-Feb-17 9:26
polaniavera15-Feb-17 9:26 
AnswerRe: Excelente articulo Pin
Nelek15-Feb-17 9:27
protectorNelek15-Feb-17 9:27 
GeneralRe: Excelente articulo Pin
Akhil Mittal15-Feb-17 17:02
professionalAkhil Mittal15-Feb-17 17:02 
AnswerRe: Excelente articulo Pin
Akhil Mittal15-Feb-17 17:04
professionalAkhil Mittal15-Feb-17 17:04 
QuestionThe type Unity.WebApi.UnityDependencyResolver does not appear to implement Microsoft.Practices.ServiceLocation.IServiceLocator. Pin
chetan.gupta216-Feb-17 19:53
chetan.gupta216-Feb-17 19:53 
QuestionRe: The type Unity.WebApi.UnityDependencyResolver does not appear to implement Microsoft.Practices.ServiceLocation.IServiceLocator. Pin
Member 1318848830-Aug-17 19:02
Member 1318848830-Aug-17 19:02 
QuestionHow to use StructureMap in place of unity? Pin
Member 799813819-Oct-16 4:56
Member 799813819-Oct-16 4:56 
AnswerRe: How to use StructureMap in place of unity? Pin
Akhil Mittal6-Nov-16 16:55
professionalAkhil Mittal6-Nov-16 16:55 
QuestionTrying to implement it with MVC5 and web API Pin
xainu3113-Aug-16 4:46
xainu3113-Aug-16 4:46 
AnswerRe: Trying to implement it with MVC5 and web API Pin
rishi.kasnia29-Nov-16 18:54
rishi.kasnia29-Nov-16 18:54 
AnswerRe: Trying to implement it with MVC5 and web API Pin
polaniavera15-Feb-17 9:15
polaniavera15-Feb-17 9:15 
QuestionBootstrapper.cs File Not Found Pin
Craig Gers30-May-16 21:24
Craig Gers30-May-16 21:24 
QuestionERROR UNEXPECTED and others Pin
kasheer13-May-16 22:06
kasheer13-May-16 22:06 
QuestionEntry point was not found. Pin
tara_sh50024-Apr-16 17:43
tara_sh50024-Apr-16 17:43 
QuestionRe: Entry point was not found. Pin
mahendra prabhu5-Oct-17 2:09
mahendra prabhu5-Oct-17 2:09 
SuggestionAmazing work Pin
chavikaM5-Apr-16 21:24
chavikaM5-Apr-16 21:24 
GeneralRe: Amazing work Pin
Akhil Mittal6-Apr-16 17:40
professionalAkhil Mittal6-Apr-16 17:40 
GeneralMy vote of 5 Pin
ravi398430-Mar-16 0:14
ravi398430-Mar-16 0:14 
GeneralRe: My vote of 5 Pin
Akhil Mittal30-Mar-16 0:18
professionalAkhil Mittal30-Mar-16 0:18 
QuestionWhat is REST Pin
Tridip Bhattacharjee1-Mar-16 21:11
professionalTridip Bhattacharjee1-Mar-16 21:11 
AnswerRe: What is REST Pin
Akhil Mittal1-Mar-16 21:18
professionalAkhil Mittal1-Mar-16 21:18 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.