Introduction

In this article, we will describe how we can implement Dependency Injection (DI), using Autofac. The idea of this post is to show the steps to configure Autofac in Web API. In this example, we will create a Web API controller named customer and it contains only a Service, which is able to retrieve the data from the database.

What’s Autofac?

Autofac is an addictive IoC container for Microsoft .NET 4.5, Silverlight 5, Windows Store apps and Windows Phone 8 apps. It manages the dependencies between the classes, so that the applications stay easy to change, as they grow in size and complexity. This is achieved by treating regular .NET classes as the components.

autofac

Prerequisites

As I said before, to achieve our requirement, you must have Visual Studio 2015 (.NET Framework 4.5.2) and SQL Server.

In this article, we are going to

SQL database part

Here, you can find the scripts to create a database and table.

Create a database

  1. USE [master]
  2. GO
  3. /****** Object: Database [DBCustomer] Script Date: 3/19/2017 3:54:44 AM ******/
  4. CREATE DATABASE [DBCustomer]
  5. CONTAINMENT = NONE
  6. ON PRIMARY
  7. ( NAME = N'DBCustomer', FILENAME = N'c:\Program Files (x86)\Microsoft SQL Server\MSSQL11.MSSQLSERVER\MSSQL\DATA\DBCustomer.mdf' , SIZE = 3072KB , MAXSIZE = UNLIMITED, FILEGROWTH = 1024KB )
  8. LOG ON
  9. ( NAME = N'DBCustomer_log', FILENAME = N'c:\Program Files (x86)\Microsoft SQL Server\MSSQL11.MSSQLSERVER\MSSQL\DATA\DBCustomer_log.ldf' , SIZE = 1024KB , MAXSIZE = 2048GB , FILEGROWTH = 10%)
  10. GO
  11. ALTER DATABASE [DBCustomer] SET COMPATIBILITY_LEVEL = 110
  12. GO
  13. IF (1 = FULLTEXTSERVICEPROPERTY('IsFullTextInstalled'))
  14. begin
  15. EXEC [DBCustomer].[dbo].[sp_fulltext_database] @action = 'enable'
  16. end
  17. GO
  18. ALTER DATABASE [DBCustomer] SET ANSI_NULL_DEFAULT OFF
  19. GO
  20. ALTER DATABASE [DBCustomer] SET ANSI_NULLS OFF
  21. GO
  22. ALTER DATABASE [DBCustomer] SET ANSI_PADDING OFF
  23. GO
  24. ALTER DATABASE [DBCustomer] SET ANSI_WARNINGS OFF
  25. GO
  26. ALTER DATABASE [DBCustomer] SET ARITHABORT OFF
  27. GO
  28. ALTER DATABASE [DBCustomer] SET AUTO_CLOSE OFF
  29. GO
  30. ALTER DATABASE [DBCustomer] SET AUTO_CREATE_STATISTICS ON
  31. GO
  32. ALTER DATABASE [DBCustomer] SET AUTO_SHRINK OFF
  33. GO
  34. ALTER DATABASE [DBCustomer] SET AUTO_UPDATE_STATISTICS ON
  35. GO
  36. ALTER DATABASE [DBCustomer] SET CURSOR_CLOSE_ON_COMMIT OFF
  37. GO
  38. ALTER DATABASE [DBCustomer] SET CURSOR_DEFAULT GLOBAL
  39. GO
  40. ALTER DATABASE [DBCustomer] SET CONCAT_NULL_YIELDS_NULL OFF
  41. GO
  42. ALTER DATABASE [DBCustomer] SET NUMERIC_ROUNDABORT OFF
  43. GO
  44. ALTER DATABASE [DBCustomer] SET QUOTED_IDENTIFIER OFF
  45. GO
  46. ALTER DATABASE [DBCustomer] SET RECURSIVE_TRIGGERS OFF
  47. GO
  48. ALTER DATABASE [DBCustomer] SET DISABLE_BROKER
  49. GO
  50. ALTER DATABASE [DBCustomer] SET AUTO_UPDATE_STATISTICS_ASYNC OFF
  51. GO
  52. ALTER DATABASE [DBCustomer] SET DATE_CORRELATION_OPTIMIZATION OFF
  53. GO
  54. ALTER DATABASE [DBCustomer] SET TRUSTWORTHY OFF
  55. GO
  56. ALTER DATABASE [DBCustomer] SET ALLOW_SNAPSHOT_ISOLATION OFF
  57. GO
  58. ALTER DATABASE [DBCustomer] SET PARAMETERIZATION SIMPLE
  59. GO
  60. ALTER DATABASE [DBCustomer] SET READ_COMMITTED_SNAPSHOT OFF
  61. GO
  62. ALTER DATABASE [DBCustomer] SET HONOR_BROKER_PRIORITY OFF
  63. GO
  64. ALTER DATABASE [DBCustomer] SET RECOVERY SIMPLE
  65. GO
  66. ALTER DATABASE [DBCustomer] SET MULTI_USER
  67. GO
  68. ALTER DATABASE [DBCustomer] SET PAGE_VERIFY CHECKSUM
  69. GO
  70. ALTER DATABASE [DBCustomer] SET DB_CHAINING OFF
  71. GO
  72. ALTER DATABASE [DBCustomer] SET FILESTREAM( NON_TRANSACTED_ACCESS = OFF )
  73. GO
  74. ALTER DATABASE [DBCustomer] SET TARGET_RECOVERY_TIME = 0 SECONDS
  75. GO
  76. ALTER DATABASE [DBCustomer] SET READ_WRITE
  77. GO
  78. Create Tables
  79. USE [DBCustomer]
  80. GO
  81. /****** Object: Table [dbo].[Customer] Script Date: 3/19/2017 3:55:15 AM ******/
  82. SET ANSI_NULLS ON
  83. GO
  84. SET QUOTED_IDENTIFIER ON
  85. GO
  86. SET ANSI_PADDING ON
  87. GO
  88. CREATE TABLE [dbo].[Customer](
  89. [CustID] [int] IDENTITY(1,1) NOT NULL,
  90. [FirstName] [varchar](50) NULL,
  91. [LastName] [varchar](50) NULL,
  92. [Email] [varchar](50) NULL,
  93. [Country] [varchar](50) NULL,
  94. CONSTRAINT [PK_Customer] PRIMARY KEY CLUSTERED
  95. (
  96. [CustID] ASC
  97. )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
  98. ) ON [PRIMARY]
  99. GO
  100. SET ANSI_PADDING OFF
  101. GO

Create your MVC application

Open Visual Studio and select File >> New Project.

New Project Window will pop up. Select ASP.NET Web Application (.NET Framework), name your project and click OK.

ASP.NET

Now, new dialog will pop up to select the template. We are going to choose Web API template and click OK button.

ASP.NET

Now, we need to create a class library. To do this, right click on the project name > Add > New Item > select class library.

ASP.NET

After creating our class library, we are going to add ADO.NET Entity Data Model.

Adding ADO.NET Entity Data Model

For this, right click on the class library name, click Add > Add New Item. The dialog box will pop up inside Visual C#, select Data, followed by ADO.NET Entity Data Model and enter the name for your DbContext model as CustomerModel. finally click Add.

ASP.NET

At this stage, we are going to choose EF Designer from the database, as given below.

ASP.NET

In the snapshot given below, we need to select your Server name, then via dropdown list in connect to a database section, you should choose your database name, finally click OK button.

ASP.NET

ASP.NET

As given above, the dialog Entity Data Model Wizard will pop up to choose an object, which is used in the demo. In this example, we are going to select Customer table and click Finish button.

Finally, we see that EDMX model generates Customer entity, as shown below.

ASP.NET

Now, we are going to create generic repository, which contains the method used to return all the data from customer table. I would like to say that the following repository can also include any other methods like (CRUD, etc.)

First of all, we are creating Db Factory class, which returns the instance of DbContext.

IDbFactory.cs

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. namespace AutoFacWithWebAPI.Repository.Common
  7. {
  8. public interface IDbFactory
  9. {
  10. DBCustomerEntities Init();
  11. }
  12. }

DbFactory.cs

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. namespace AutoFacWithWebAPI.Repository.Common
  7. {
  8. public class DbFactory : IDbFactory
  9. {
  10. DBCustomerEntities dbContext;
  11. public DBCustomerEntities Init()
  12. {
  13. return dbContext ?? (dbContext = new DBCustomerEntities());
  14. }
  15. }
  16. }

IGenericRepository.cs

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. namespace AutoFacWithWebAPI.Repository.Common
  7. {
  8. public interface IGenericRepository<T> where T : class
  9. {
  10. IQueryable<T> GetAll();
  11. }
  12. }

GenericRepository.cs

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. namespace AutoFacWithWebAPI.Repository.Common
  7. {
  8. public class GenericRepository<T> : IGenericRepository<T> where T : class
  9. {
  10. private DBCustomerEntities dbContext;
  11. protected IDbFactory DbFactory
  12. {
  13. get;
  14. private set;
  15. }
  16. protected DBCustomerEntities DbContext
  17. {
  18. get { return dbContext ?? (dbContext = DbFactory.Init()); }
  19. }
  20. public GenericRepository(IDbFactory dbFactory)
  21. {
  22. DbFactory = dbFactory;
  23. }
  24. public IQueryable<T> GetAll()
  25. {
  26. return DbContext.Set<T>();
  27. }
  28. }
  29. }

After implementing generic repository, we are adding reference of our class library to Web API project. To do this, right click on References > Add Reference.

ASP.NET

Installing Autofac

It’s simple to add Autofac. We can do this by using NuGet Packages or Package Manager Console. In this example, I used NuGet Packages. Thus, right click on References > Manage NuGet Packages.

First, we are installing Autofac. Subsequently, install Autofac.integration.WebAPI, as shown below.

ASP.NET

ASP.NET

Note

Please make sure that the references given below have been added successfully.

ASP.NET

Create a controller

Now, we are going to create a controller. Right click on the controllers folder > Add > Controller> selecting Web API 2 Controller – Empty > click Add.

ASP.NET

Enter Controller name (‘CustomerController’).

ASP.NET

CustomerController.cs

  1. using AutoFacWithWebAPI.Repository;
  2. using AutoFacWithWebAPI.Repository.Common;
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Linq;
  6. using System.Net;
  7. using System.Net.Http;
  8. using System.Web.Http;
  9. namespace AutoFacWithWebAPI.Controllers
  10. {
  11. public class CustomerController : ApiController
  12. {
  13. private readonly IGenericRepository<Customer> _customerRepository;
  14. public CustomerController(IGenericRepository<Customer> customerRepository)
  15. {
  16. _customerRepository = customerRepository;
  17. }
  18. public IQueryable<Customer> GetCustomerList()
  19. {
  20. return _customerRepository.GetAll();
  21. }
  22. }
  23. }

As you can see, we have injected our customer repository within constructor, and then we have defined method called Get Customer List which returns Customer list.

Configuring Autofac

At this point, from Solution Explorer section, we are going to add 2 classes, as shown below.

AutofacWebapiConfig.cs

  1. using Autofac;
  2. using Autofac.Integration.WebApi;
  3. using AutoFacWithWebAPI.Repository;
  4. using AutoFacWithWebAPI.Repository.Common;
  5. using System;
  6. using System.Collections.Generic;
  7. using System.Data.Entity;
  8. using System.Linq;
  9. using System.Reflection;
  10. using System.Web;
  11. using System.Web.Http;
  12. namespace AutoFacWithWebAPI.App_Start
  13. {
  14. public class AutofacWebapiConfig
  15. {
  16. public static IContainer Container;
  17. public static void Initialize(HttpConfiguration config)
  18. {
  19. Initialize(config, RegisterServices(new ContainerBuilder()));
  20. }
  21. public static void Initialize(HttpConfiguration config, IContainer container)
  22. {
  23. config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
  24. }
  25. private static IContainer RegisterServices(ContainerBuilder builder)
  26. {
  27. //Register your Web API controllers.
  28. builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
  29. builder.RegisterType<DBCustomerEntities>()
  30. .As<DbContext>()
  31. .InstancePerRequest();
  32. builder.RegisterType<DbFactory>()
  33. .As<IDbFactory>()
  34. .InstancePerRequest();
  35. builder.RegisterGeneric(typeof(GenericRepository<>))
  36. .As(typeof(IGenericRepository<>))
  37. .InstancePerRequest();
  38. //Set the dependency resolver to be Autofac.
  39. Container = builder.Build();
  40. return Container;
  41. }
  42. }
  43. }

Here, you register the components with Autofac by creating a container builder, which components expose, which services.

In RegisterServices() method, we have registered all the needed types that expose interfaces. Now, build the container to finalize the registrations and prepare for the object resolution.

In Initialize() method, after building your container, we need to pass it into new instance of the AutofacWebApiDependencyResolver class. Attach the new resolver to your config.DependencyResolver to allow Web API know that it should locate the Services, using the AutofacWebApiDependencyResolver.

Bootstrapper.cs

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Web;
  5. using System.Web.Http;
  6. namespace AutoFacWithWebAPI.App_Start
  7. {
  8. public class Bootstrapper
  9. {
  10. public static void Run()
  11. {
  12. //Configure AutoFac
  13. AutofacWebapiConfig.Initialize(GlobalConfiguration.Configuration);
  14. }
  15. }
  16. }

Note

Please make sure that Run() has been added in Application_Start() method.

Global.asax.cs

  1. using AutoFacWithWebAPI.App_Start;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using System.Web;
  6. using System.Web.Http;
  7. using System.Web.Mvc;
  8. using System.Web.Optimization;
  9. using System.Web.Routing;
  10. namespace AutoFacWithWebAPI
  11. {
  12. public class WebApiApplication : System.Web.HttpApplication
  13. {
  14. protected void Application_Start()
  15. {
  16. AreaRegistration.RegisterAllAreas();
  17. Bootstrapper.Run();
  18. GlobalConfiguration.Configure(WebApiConfig.Register);
  19. FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
  20. RouteConfig.RegisterRoutes(RouteTable.Routes);
  21. BundleConfig.RegisterBundles(BundleTable.Bundles);
  22. }
  23. }
  24. }

Output

Now, you can run your Application and let’s see the output.

ASP.NET