MVC 5 Dependency Injection

This is the seventh and last part of building line of business application using MVC 5, the remaining parts will be recorded as videos which will be more effective, you can read the previous parts through the following links

  1. Building a LOB application with MVC 5 – Part 0
  2. Building a LOB application with MVC 5 – Part 1
  3. Building a LOB application with MVC 5 – Part 2 – Models and Generic Repository
  4. Building a LOB application with MVC 5 – Part 3 – EntityFramework
  5. Building a LOB application with MVC 5 – Part 4 – Controllers, Routes and Areas
  6. Building a LOB application with MVC 5 – Part 5 – Views

In the previous part, we talked about Views, Layouts, View Engine and how to pass data from controllers to views and vice versa.

In this part we will talk about Dependency Injection (DI) and Inversion of Control (IoC).

What is DI?

You can find a lot of posts and tutorials about the definition of DI and IoC, so we are not going to detail it here, to summarize, as per our multi-tier architecture, our controllers will need a domain service which will need a repository and finally the repository will need a data context, if we let each object creates its dependencies, we will end up with a big mess, imagine if you tried to create a unit test to test the controller action logic, it will cause lead to the creation of the full chain starting from the controller down to the data context , although we only needed to test the controller logic.

To overcome this issue, all the dependencies must be injected into each depending object either through a constructor parameter or a public property, since the controller is the first object in our chain, we will start with it, but before we proceed, lets first examine how DI works in MVC.

DI in MVC 5

In the previous posts, we created a controller name ServiceTypesController under the Admin area, when we request the path /Admin/ServiceTypes, you will find an empty page as we don’t have any data created yet, but how did MVC created an object of ServiceTypesController?

MVC 5 depends on a ControllerFactory to create new controllers, simply, it instantiate a new controller object and in order for this to work, the controller must have a parameterless constructor because this is the way the default controller factory works.

Enable DI in MVC

Now, we need to inject a domain service into the ServiceTypesController controller, we will add the following code and try to run the application.

   public class ServiceTypesController : Controller
    {
        IService<ServiceType, int> _serviceTypeService;

        public ServiceTypesController(IService<ServiceType, int> serviceTypeService)
        {
            this._serviceTypeService = serviceTypeService;
        }

        // GET: Admin/ServiceTypes
        public ActionResult Index()
        {
            return View(_serviceTypeService.GetAll());
        }
    }

As you can see, our constructor now has a new parameter of type IService<ServiceType, int>, this is the generic domain service that we created and it is enough for all CRUD operations for any of our domain model classes, now try to build and run the application and you will get the following error.

Parameterless Contructor.png

Of course you can remove the parameter from the constructor but then you will have to instantiate the object itself, this means the controller class will have to know which concrete type it should create which is not its responsibility.

Custom Controller Factory

To overcome this issue, we will have to create a custom controller factory that knows how to instantiate an object that implement the IService<ServiceType,int>

To do that, create a folder named Factories under the web project and inside this folder create a class named DIControllerFactory, the code should look like the following

public class DIControllerFactory : DefaultControllerFactory
    {
        public override IController CreateController(RequestContext requestContext, string controllerName)
        {
            if (controllerName.ToLower() == "servicetypes")
                return new ServiceTypesController(new BaseService<ServiceType, int>(new EFRepository<ServiceType, int>(new AppointmentManagerContext())));

            return base.CreateController(requestContext, controllerName);
        }
    }

As you can see, the method CreateController is responsible for creating the controller class and passing all the needed dependencies that the class needs, this will be easy if we have a controller or two, but when the number of controllers grow and the tree of dependencies grows, this will be a nightmare, have a look at the return statement in the above code, we instantiated 4 classes just to create the controller, this is where we need something else to manage that for us, something called the IoC Container.

There are a lot of IoC cotnainer available like, NInject, Microsoft Unity, StructureMap and many others, you can use any framework you like, in my case I will go with StructureMap

So, run the following NuGet Command to install StructureMap package, make sure it is installed in the MVC web project

Install-Package StructureMap

Now, it is time to setup the IoC container and let it know about our interfaces and its implementation, this will help when we ask it for an instance of the controller, then it will be able to resolve all the dependencies for it.

Setup StructureMap

Under App_Start, create a file called StructureMapConfig and add the following code

 public class StructureMapConfig
    {
        public static Container Container;

       public static IContainer Config()
        {
            Container = new Container();

            Container.Configure(c =>
            {
                c.Scan(s =>
                {
                    s.TheCallingAssembly();
                    s.WithDefaultConventions();
                });

                c.For(typeof(IService<,>)).Use(typeof(BaseService<,>));
                c.For(typeof(IRepository<,>)).Use(typeof(EFRepository<,>));
                c.For<ServiceTypesController>();
                c.For<DbContext>().Use<AppointmentManagerContext>();
            });

            return Container;
        }
    }

In the Config method, we created a container that will hold the information about the different interfaces and its implementation, notice that we registered all teh types for the IService and IRepository with only one call, this is why we use typeof(IService<,>), this will enable StructureMap to return any instance requested with the IService, for ex: IService<Appointment,int>, so you don’t have to register all the different combinations.

Call the Config method in the method Application_Start in the file Global.asax.cs

Now, back to the DIControllerFactory class, replace the code with the one below.

public class DIControllerFactory : DefaultControllerFactory
    {
        public override IController CreateController(RequestContext requestContext, string controllerName)
        {
            if (controllerName.ToLower() == "servicetypes")
            {
                return StructureMapConfig.Container.GetInstance<ServiceTypesController>();
            }

            return base.CreateController(requestContext, controllerName);
        }
    }

The difference is huge, only one line to build the object instead of creating 4 objects, but still we have to know the controller name and figure out the type, of course we can append the namespace to the controller name and build the controller type name but this won’t be neat.

MVC Dependency Rresolver

MVC Comes with a dependency resolver that can be replaced by calling the following line at the application start.

 DependencyResolver.SetResolver(new CustomDependencyResolver());

MVC asks the default depdnency resolver to create a new object/service that it may need, if we managed to inject our own depdenecy resolver, then all the controllers will be created automatically without the need for a controller factory, to do that, create a class called StructureMapDependencyResolver under the Factories folder, add the following code to it.

 public class StructureMapDependencyResolver : IDependencyResolver
    {
        private static IContainer _container;

        public StructureMapDependencyResolver(IContainer container)
        {
            _container = container;
        }

        public object GetService(Type serviceType)
        {
            if (serviceType == null)
                return null;

            try
            {
                return serviceType.IsAbstract || serviceType.IsInterface
                         ? _container.TryGetInstance(serviceType)
                         : _container.GetInstance(serviceType);
            }
            catch
            {
                return null;
            }
        }

        public IEnumerable<object> GetServices(Type serviceType)
        {
            return _container.GetAllInstances(serviceType).Cast<object>();
        }
    }

The class implements two methods, the GetService and GetServices,these methods are use to return instances for services that MVC uses, such as IControllerFactory, IControllerActivator, so this class is the top level for all teh DI work in MVC, the controller Factory class was just a small part of it.

Now update the code in the Application_Start method to register the new dependency resolver as below

 public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            StructureMapConfig.Config();

            //ControllerBuilder.Current.SetControllerFactory(typeof(DIControllerFactory));
            DependencyResolver.SetResolver(new StructureMapDependencyResolver(StructureMapConfig.Container));

            AreaRegistration.RegisterAllAreas();
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
        }
    }

Notice the first line of the Configure block, it scans the current assembly to find any classes and interfaces and it does what with the default conventions as instructed by teh second line, this will make StructureMap to resolve automatically any reference to an interface that has a name like IService with a class that implements it with a name like Service

If you run the application now, it will work fine and all dependencies will be resolved automatically.

To conclude, always develop against an interface and leave the resolving of the actual implementation to an IoC container which as you can see, it is very easy to setup with MVC 5.

I hope this post was useful, if you have any questions, please leave a comment and you can get the code from the GitHub repository https://github.com/haitham-shaddad/AppointmentManager

Advertisements