Translate

Monday, December 31, 2012

Autofac Intermediate level Tutorial (autofac mvc 4)

If you are absolutely new to autofac and inversion of control, I would strongly recommend reading up on these two articles before you proceed

C# Dependency Injection tutorial
Introduction to AutoFac


In this article I will create a simple MVC4 application first without Autofac and then I will introduce Autofac (version 2.6.3.862) into the application. All this application does is display this page below. This application has been simplified to focus more on Autofac. Ideally this is how an MVC application should be laid out.













If you have already played around with autofac, you can directly skip to bootstrap.cs (Its towards the bottom of the article)


Application Without Autofac 

Create an empty MVC4 application called UI.


To the solution, add a C# class library project called Objects:















In this project include a class file called Person.cs



using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Objects
{
    public class Person
    {
        public string Name { get; set; }
        public int Age { get; set; }
        public string SocialSecurityNumber { get; set; }
    }
}



Add a C# class library called DataAccessLayer.:













 Add a reference to the Objects project added above.
 Add this class file called DAL.cs. We will pretend that this class returns data from a database.


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Objects;

namespace DataAccessLayer
{
    public class DAL
    {

        public Person GetAPerson()
        {
            var p = new Person { Name = "Jack", Age = 27, SocialSecurityNumber = "999-99-9999" };

            return p;

        }
    }
}




MVC Project UI:
























In the MVC4 project called UI, add references to both the Objects and the DataAccessLayer Projects created above.This UI project has the following three files HomeController.cs,PersonViewModel.cs, People.cshtml

HomeController.cs


using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using DataAccessLayer;
using UI.Models;
namespace UI.Controllers
{
    public class HomeController : Controller
    {
        public ActionResult People()
        {
            var dal = new DAL();
            var person = dal.GetAPerson();
            var personViewModel = new PersonViewModel(person);

            return View(personViewModel);
        }


    }
}



PersonViewModel.cs


using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Objects;

namespace UI.Models
{
    public class PersonViewModel
    {
        public string Name { get; set; }
        public int Age { get; set; }

        public PersonViewModel(Person p)
        {
            Name = p.Name;
            Age = p.Age;
        }

    }
}



People.cshtml


@model UI.Models.PersonViewModel

@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>People</title>
</head>
<body>
    <div>
       @Model.Name, @Model.Age
    </div>
</body>
</html>



Go ahead and run the app. It should correctly display a page that says Jack,27

------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------




Application With Autofac 

What we are going to do here is, in the application start code in global.asax.cs, we will call the code (BootStrap class) that sets up all the dependencies. Here in the BootStrap class, we tell the DI container (autofac) two things
  1. Which implementation of an interface to use (Object composition)
  2. When should that instance be disposed (Object Lifetime)
The second aspect (that is lifetime of the object) is something that would take a little more reading to understand and is outside the scope of this article. This is an excellent resource to understand how to set up the object lifetimes in autofac.


Modify the Objects Project:

Add a file called IDAL.cs to the Objects project.


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Objects
{
   public interface IDAL
    {

        Person GetAPerson();
    }
}


Modify the DataAccessLayer project:

Modify DAL.cs so that it inherits from the interface IDAL

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Objects;

namespace DataAccessLayer
{
    public class DAL:IDAL
    {

        public Person GetAPerson()
        {
            var p = new Person { Name = "Jack", Age = 27,SocialSecurityNumber="999-99-9999" };

            return p;

        }
    }
}



Modify the UI project

Use nuget to add Autofac,Autofac.Configuration and Autofac.Integration.Mvc dlls to the UI project. Use these nuget commands to do that

Install-Package Autofac -Version 2.6.3.862
Install-Package Autofac.Mvc4 -Version 2.6.2.859

Bootstrap.cs:

Add a file called bootstrap.cs to the UI project.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Autofac;
using System.Web.Mvc;
using Autofac.Integration.Mvc;
using DataAccessLayer;
using Objects;
using System.Reflection;

namespace UI
{
    public class BootStrap
    {

        public IContainer myContainer { get; private set; }

        public void Configure()
        {
            ContainerBuilder builder = new ContainerBuilder();
            OnConfigure(builder);

            if (this.myContainer == null)
            {
                this.myContainer = builder.Build();
            }
            else
            {
                builder.Update(this.myContainer);
            }

            //This tells the MVC application to use myContainer as its dependency resolver
           DependencyResolver.SetResolver(new AutofacDependencyResolver(this.myContainer));
        }


        protected virtual void OnConfigure(ContainerBuilder builder)
        {
            //This is where you register all dependencies

            //The line below tells autofac, when a controller is initialized, pass into its constructor, the implementations of the required interfaces
            builder.RegisterControllers(Assembly.GetExecutingAssembly());

            //The line below tells autofac, everytime an implementation IDAL is needed, pass in an instance of the class DAL
            builder.RegisterType<DAL>().As<IDAL>().InstancePerLifetimeScope();         


        }
    }

}


Modify Application_Start() in global.asax.cs: 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Http;
using System.Web.Mvc;
using System.Web.Routing;

namespace UI
{

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

            WebApiConfig.Register(GlobalConfiguration.Configuration);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);

            var bootstrap = new BootStrap();
            bootstrap.Configure();

        }

    }
}


Modify Homecontroller.cs:




using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using DataAccessLayer;
using UI.Models;
using Objects;
namespace UI.Controllers
{
    public class HomeController : Controller
    {

        private IDAL _dal;

        public HomeController(IDAL dal)
        {
            _dal = dal;
        }

        public ActionResult People()
        {

            var person = _dal.GetAPerson();
            var personViewModel = new PersonViewModel(person);

            return View(personViewModel);
        }


    }
}


Go ahead and run the app. It should run without any errors.








6 comments:

  1. Great tutorial. I used SimpleInjector MVC instead of AutoFac, and works like a charm.

    ReplyDelete
  2. Thanks for including the entire .cs file. I'm just getting started with DI and for the most part I understood what some other tutorials were doing I but had no idea where to put the code im my solutions.

    ReplyDelete
  3. Use these PM commands, if developing this sample with ASP.NET MVC 5.1

    Install-Package Autofac
    Install-Package Autofac.Mvc5

    ReplyDelete
  4. Thanks for great explanation........

    ReplyDelete
  5. Just Wonderful and simple and easy to understand. God Bless

    ReplyDelete
  6. Can you explain how it knows what to resolve without calling container.Resolve()? How does HomeControllers now get called with a parameter IDAL? I mean when I hit the URL /home/People, where is dal coming from?

    ReplyDelete

Comments will appear once they have been approved by the moderator