Dependency Injection in Web API using NInject

ASP.NET provides an extension point (IDependencyResolver) in the web API framework, which allows us to resolve the dependencies of the web API controller. Let’s see where and how it can be used in real life.

Generally, it is a common practice that one or some repository objects is used in the web api controller which takes care of the performing CRUD operations in data store. This is done to decouple the domain logic and DAL code as separation of concerns. Also it just make the controller to have only domain specific logic instead of not concerned with how and where to get the data from.

Know more about repository pattern here. But by doing so, the controller becomes very dependent on instance of the repository class.

For Instance :

public class BookingOrdersController : ApiController
     {
         public BookingOrderRepository bookingOrderRepository;   

 public BookingOrdersController()
    {
        bookingOrderRepository = new BookingOrderRepository();
    }

    // GET: api/BookingOrders
    public IEnumerable GetBookingOrders()
    {
        return bookingOrderRepository.GetAll();
    }

    // GET: api/BookingOrders/5
    [ResponseType(typeof(BookingOrder))]
    public async Task GetBookingOrder(int id)
    {
        BookingOrder bookingOrder = await bookingOrderRepository.GetBy(id);
        if (bookingOrder == null)
        {
            return NotFound();
        }

        return Ok(bookingOrder);
    }
}

Now let’s say that you need to get the data from different data store like No-SQL instead of SQL Server. Then you need to change code in the controller to initialize and use the instance of different repository. And what if you deliver the API to different clients who prefers to use different data store or get data from another API. Then you want to switch between at the run time as per the configuration.

So it’s not good idea to make the controller and its dependencies tightly coupled and the controller has responsibility to create instance of them. In the above code, controller initialize the instance of repository class inside the constructor of the controller. The repository class gets the data from SQL server using Entity framework. But when you want to use instance of different repository class, you need to change the code.

Instead it is recommend to use dependency injection, hence the dependent objects for the controller are injected via constructor. It is also popularly called constructor injection. To be able to do that, first all the dependency classes must be designed with interface which contains the method contracts. The concrete classes will have the actual implementation of the interface as per the requirement.

In our case, the BookingOrderRepository is implementing Interface IRepository, and the same is used as params Type in controller’s constructor.

Public interface IRepository where T : class
 {
    Task AddAsync(T t);    
    Task DeleteAsync(T t);
    Task UpdateAsync(T t);
    Task GetBy(long id);
    IQueryable GetAll();
    IQueryable GetAll(Expression<Func<T, bool>> predicate);
}
 Public class BookingOrderRepository : IRepository, IDisposable
 {     
        private TicketBookingServiceContext db = new 
             TicketBookingServiceContext();

        public BookingOrderRepository()
        { }      
        public async Task GetBy(long id)
        {
           return await db.BookingOrders.FindAsync(id);
        }
        public IQueryable GetAll()
        {
           return db.BookingOrders;
        }
        public async Task AddAsync(BookingOrder t)
        {
           db.BookingOrders.Add(t);
           return await db.SaveChangesAsync();
        }
        public async Task DeleteAsync(BookingOrder t)
        {
            db.BookingOrders.Remove(t);
            return await db.SaveChangesAsync();
        }
        public async Task UpdateAsync(BookingOrder t)
        {
            db.Entry(t).State = EntityState.Modified;
            try
            {
              return await db.SaveChangesAsync();
            }
            catch(DbUpdateConcurrencyException ex)
            {
                throw ex;
            }
        }
       public IQueryable 
            GetAll(Expression<Func> predicate)
       {
            if (predicate != null)
               return db.BookingOrders.Where(predicate);            
            else
                throw new ArgumentNullException("Predicate value must be passed to FindSingleBy.");
        }

        public void Dispose()
        {            
            GC.SuppressFinalize(db);
        }
    }

Hence it allows us to pass an instance of any Type (class) which is implementing the interface IRepository to the controller at runtime.

So I change the controller implementation to..

public class BookingOrdersController : ApiController
    {
        public BookingOrderRepository bookingOrderRepository;
        public BookingOrdersController(IRepository repository)
        {
            bookingOrderRepository = 
                (BookingOrderRepository)repository;
        }
        // GET: api/BookingOrders
        public IEnumerable GetBookingOrders()
        {
            return bookingOrderRepository.GetAll();
        }
        // GET: api/BookingOrders/5
        [ResponseType(typeof(BookingOrder))]
        public async Task GetBookingOrder(int id)
        {
            BookingOrder bookingOrder = await 
                 bookingOrderRepository.GetBy(id);
            if (bookingOrder == null)
            {
                return NotFound();
            }
            return Ok(bookingOrder);
        }
}

That is, now you can have different implementation of IRespository which likely to get data from different source. And that can be injected to controller at runtime , the controller really need not to care the object initialization of dependencies.

Note that web API does not comes with any default IoC framwork. Hence you need to use some external IoC libraries available in the market.

Some of the well-known and widely used frameworks are Castle WindsorSpring.NetAutofacNinject, and StructureMap.

Here we will see how to use Ninject library to resolve the dependencies , and you will need the following  nugget packages.

Ninject Nugget packages

Once you add “Ninject.Web.Common.WebHost” as nugget to your project, you will see “NinjectWebCommon” class has been created under start up folder. The generated class (NinjectWebCommon) will contain few methods with default implementation which take care of registering Ninject Modules and bootstrapping it when web api application is initialized.

But it’s not done yet 🙂 . You need to configure to use Ninject Dependency resolver.

private static IKernel CreateKernel()
 {
            var kernel = new StandardKernel();
            try
            {
               kernel.Bind<Func>().ToMethod(ctx => () => new 
                Bootstrapper().Kernel);
                kernel.Bind().To();
                RegisterServices(kernel);

                //Add the below code to register the Ninject 
                //dependency resolver with webapi
                GlobalConfiguration.Configuration.DependencyResolver 
                = new NinjectDependencyResolver(kernel);
                return kernel;
            }
            catch
            {
                kernel.Dispose();
                throw;
            }
 }

And add the dependencies as bindings in the kernel like below.

private static void RegisterServices(IKernel kernel)
 {
            kernel.Bind<IRepository>().To();
 } 

Now when the “BookingOrderController” is being called from client, the web api framework takes care of invoking Ninject library which in turns look up for the registered bindings and create the instance of registered dependencies and pass on to the controller through the constructor. This happens every time whenever controller object is created by web api framework

Note : In this post, i just took an example of repository class as dependent as it is widely practiced one. A controller may have multiple dependencies like Logger, external component for file operation (PDF Reader), etc. But in principle, any dependency can be resolved in same manner.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.