Click here to Skip to main content
15,880,392 members
Articles / All Topics
Article

Using Dependency Injection on OpenAccess ORM MVC Project

Rate me:
Please Sign up or sign in to vote.
5.00/5 (2 votes)
14 Dec 2013CPOL4 min read 11.5K   11  
sing Dependency Injection on OpenAccess ORM MVC Project

Introduction

You might be starting a new project using OpenAccess ORM and wondering how to implement dependency injection to prevent hard-coded dependencies and enable the possibility of changing them at run-time. Well, it’s not that hard especially with the new Dependency Injection Framework available today where all you need to do is get them on Nuget, reference it to your project then you are all good to go.

I will explain this in the easiest way possible and I will start by explaining my sample architecture first by defining the different layers I used. We will also concentrate on one database table called Departments. Let's start.

Let's say your architecture is simply composed of 4 layers for now, namely:

  • Domain – This contains the models of your business objects.
  • Infrastructure – This contains the abstraction layer you put on your data access layer.
  • Web – This is your presentation layer.
  • Tests – I think I don’t need to explain this.

01 Overview

For the Domain, we don’t need coding as it’s all generated for you by Telerik so let’s go straight ahead to the Infrastructure Layer. Let's concentrate on 4 files:

Repository.cs – This contains your generic repository codes to extract and/or process information from your domain:

C#
using EmployeesDemo.Domain;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Web;

namespace EmployeesDemo.Infrastructure.Repositories
{
    public abstract class Repository<T> : IDisposable, IRepository<T>
        where T : class
    {
        protected IEntitiesModelUnitOfWork Context
        {
            get;
            private set;
        }

        protected Repository(IEntitiesModelUnitOfWork context)
        {
            this.Context = context;
        }

        public IList GetAll()
        {
            return this.Context.GetAll().ToList();
        }

        public T Find(Expression<Func<T, bool>> predicate)
        {
            return this.Context.GetAll().FirstOrDefault(predicate);
        }

        public void Add(T order)
        {
            this.Context.Add(order);
        }

        public void Remove(T order)
        {
            this.Context.Delete(order);
        }

        public void Dispose()
        {
            this.Context = null;
        }
    }
}

IRepository.cs - The interface for your Repository.cs:

C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Web;

namespace EmployeesDemo.Infrastructure.Repositories
{
    public interface IRepository<T>
        where T : class
    {
        T Find(Expression<Func<T, bool>> predicate);

        void Add(T order);
        IList GetAll();
        void Remove(T order);
    }
}

DepartmentRepository.cs - This contains abstraction only for the Department Entity, if it’s a generic method, it should be placed in the Repository.cs:

C#
using EmployeesDemo.Domain;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace EmployeesDemo.Infrastructure.Repositories
{
    public class DepartmentRepository : Repository<Department>, IDepartmentRepository
    {
        public DepartmentRepository(IEntitiesModelUnitOfWork context)
            : base(context)
        {
        }

        public Department GetBy(string name)
        {
            return this.Context.GetAll<Department>().FirstOrDefault(x => x.Name == name);
        }
    }
}

IDepartmentRepository.cs - This is the interface for DepartmentRepository.

C#
using EmployeesDemo.Domain;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace EmployeesDemo.Infrastructure.Repositories
{
    public interface IDepartmentRepository : IRepository<Department>
    {
        Department GetBy(string name);
    }
}

Now let's go to the presentation layer, first we define a view model which eventually we will be using later on in our Controller and Views.

DepartmentsViewModel.cs – Basically a model for a list of all Departments.

C#
using EmployeesDemo.Domain;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace EmployeesDemo.Web.Models
{
    public class DepartmentsViewModel
    {
        public DepartmentsViewModel()
        {
            this.Departments = new List<Department>();
        }
        public IList<Department> Departments { get; set; }
    }
}

DepartmentViewModel.cs – A model used for an individual Department:

C#
using EmployeesDemo.Domain;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace EmployeesDemo.Web.Models
{
    public class DepartmentViewModel
    {
        public string Name { get; set; }

        public string Description { get; set; }
    }
}

DepartmentService.cs – Now this is the class used to communicate with your repository:

C#
using EmployeesDemo.Web.Models;
using EmployeesDemo.Infrastructure.Repositories;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace EmployeesDemo.Web.Services
{
    public class DepartmentService
    {
        private readonly IDepartmentRepository departmentRepository;
        public DepartmentService(
            IDepartmentRepository departmentRepository)
        {
            this.departmentRepository = departmentRepository;
        }

        public DepartmentsViewModel GetAll()
        {
            return new DepartmentsViewModel
            {
                Departments = departmentRepository.GetAll().ToList()
            };
        }

        public DepartmentViewModel GetBy(string name)
        {
            var department = departmentRepository.GetBy(name);
            return new DepartmentViewModel
            {
                Name = department.Name
            };
        }
    }
}

HomeController.cs – This controls Home View and it is here we will use the service we need, in this case, the Department Service. Once a constructor is created, we can now use the services on the code.

C#
using EmployeesDemo.Web.Services;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace EmployeesDemo.Web.Controllers
{
    public class HomeController : Controller
    {
        public DepartmentService departmentService;

        public HomeController(
            DepartmentService departmentService)
        {
            this.departmentService = departmentService;
        }

        public ActionResult Index()
        {
            ViewBag.Message = "Welcome to ASP.NET MVC!";

            var technologyDepartment = departmentService.GetBy("Technology");
            var allDepartment = departmentService.GetAll();

            return View();
        }
    }
}

But not run it yet, though it will compile error free, you will get this error during runtime.

Server Error in ‘/’ Application.


No parameterless constructor defined for this object.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.MissingMethodException: No parameterless constructor defined for this object.

Source Error:

An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.

Why??? This is because by default, ASP.NET MVC requires that the controllers have a public parameter-less constructor, in turn creating an instance of the controller. So in our example, our constructor requires the DepartmentService instance and we need something to pass such an instance to our controller. This is now where you need dependency injection framework, up to you what you use there are lots of options like Unity, Castle.Windsor, Autofac, StructureMap, etc. I had used Castle.Windsor before and had no complaints with it, but for now let's use Ninject.

Now to do that, first you need to download it in nugget. Just search for Ninject and install the Ninject.MVC3 first, I said that because this makes it easier as its dependencies are the other two so it installs them as well automatically.

02 Add Ninject

Once installed, we need to create a NinjectModule and let ninject glue it together for you. What I have done is create a folder called IoC, in that folder, we create a class called ControllerModule.

07 IoC

Now let’s do the binding:

C#
using EmployeesDemo.Domain;
using EmployeesDemo.Infrastructure.Repositories;
using EmployeesDemo.Web.Services;
using Ninject.Modules;
using Ninject.Web.Common;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace EmployeesDemo.Web.IoC
{
    public class ControllerModule : NinjectModule
    {
        public override void Load()
        {
            this.Bind<IEntitiesModelUnitOfWork>().To<EntitiesModel>()
                .InRequestScope()
                .WithConstructorArgument
                ("connectionId", "TestingDatabaseConnection");

            this.Bind<IDepartmentRepository>().To<DepartmentRepository>()
                .InRequestScope();

            this.Bind<DepartmentService>().To<DepartmentService>()
                .InRequestScope();
        }
    }
}

Now, we are done with the binding. Let's modify our Global.asax so everything registers on ApplicationStart. First let's inherit NinjectHttpApplication and replace the default HttpApplication.

04 Inherit NinjectHttpApplication

Next is replacing the...

C#
void Application_Start()

with...

C#
override void OnApplicationStarted()

then call...

C#
base.OnApplicationStarted();

We also need to override the CreateKernel method of the NinjectHttpApplication:

C#
protected override IKernel CreateKernel()
{
    IKernel kernel = new StandardKernel();
    kernel.Load(Assembly.GetExecutingAssembly());

    return kernel;
}

05 Overrides

Finally, since we created it in Global.asax, we don’t need the ninject generated codes called NinjectWebCommon.cs which was created in the App_Start folder, so delete them.

03 Ninject Generated

Now you’re good to go. Run your application, then see the results.

06 Results

Filed under: Architecture, CodeProject, Programming Tagged: ASP.NET MVC, C#, Dependency injection, Dependency Injection Framework, MVC, ninject

License

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


Written By
Technical Lead
New Zealand New Zealand
http://nz.linkedin.com/in/macaalay
http://macaalay.com/

Comments and Discussions

 
-- There are no messages in this forum --